/* $Id: cim.c,v 1.18 1997/01/26 14:30:21 cim Exp $ */ /* Copyright (C) 1987-1998 Sverre Hvammen Johansen, * Department of Informatics, University of Oslo. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Main for kompilatoren. */ #include #include "const.h" #include "name.h" #include "filelist.h" #include "newstr.h" #include "cimcomp.h" #include "error.h" #include "lex.h" #include "mellbuilder.h" #include "checker.h" #include "gen.h" #include "trans.h" #if STDC_HEADERS || HAVE_STRING_H #include #else /* not STDC_HEADERS and not HAVE_STRING_H */ #include #endif /* not STDC_HEADERS and not HAVE_STRING_H */ #if HAVE_UNISTD_H #include #endif #if STDC_HEADERS #include #endif #if HAVE_SIGNAL_H #include #endif #include "getopt.h" struct SENT *mainSent; FILE *ccode; char *extcodename; char *mifcodename; static char *outputname = ""; static char *exekname; static char *sourcename; static char *listname; static char *ccodename; static char *ocodename; static char *shlname; static char *ccomp; static char *ccompargs = ""; static char *linkargs = ""; static char *systemlibdir = LIBDIR; static char *tmpdir; char *includedir = INCLUDEDIR; int option_write_tokens; int option_write_mif; int option_nowarning; int option_atr; int option_line; int option_reuse_timestamp; int option_verbose; int option_init_poolsize; int option_dyn_poolsize; int option_max_poolsize; int option_bl_in_dir_line; static int option_static; static int option_pic; static int option_checkdiff; static int option_nolink; static int option_nosim; static int option_nocc; static int option_checkdif; static int option_notempdel; static int option_noexecdel; static int option_quiet; static int option_sscheck; #ifdef DEBUG static int option_lex, static int option_gen_test; static int option_declarations; static int option_expressions; static int option_msymbols; static int option_input; #endif #ifdef DEBUG static int s_out; #endif char separat_comp; /* Sier om kj|ringen er en separat * kompilering eller ikke */ char *progname; /****************************************************************************** XMALLOC */ char * xmalloc (size) unsigned int size; { char *ptr = malloc (size); if (! ptr) { fprintf (stderr, "%s: virtual memory exhausted\n", progname); exit (1); } return ptr; } /****************************************************************************** TRAP-ROUTINES */ #if HAVE_SIGFPE static RETSIGTYPE float_trap () { lerror (25); } #endif #if HAVE_SIGSEGV static RETSIGTYPE seg_trap () { lerror (26); } #endif #if HAVE_SIGILL static RETSIGTYPE illegal_trap () { lerror (28); } #endif #if HAVE_SIGTRAP static RETSIGTYPE trace_trap () { lerror (29); } #endif #if HAVE_SIGBUS static RETSIGTYPE bus_trap () { lerror (27); } #endif #if HAVE_SIGSYS static RETSIGTYPE sys_trap () { lerror (30); } #endif static init_trap_routines() { #if HAVE_SIGFPE signal (SIGFPE, float_trap); #endif #if HAVE_SIGSEGV signal (SIGSEGV, seg_trap); #endif #if HAVE_SIGILL signal (SIGILL, illegal_trap); #endif #if HAVE_SIGTRAP signal (SIGTRAP, trace_trap); #endif #if HAVE_SIGSYS signal (SIGSYS, sys_trap); #endif #if HAVE_SIGBUS signal (SIGBUS, bus_trap); #endif } /****************************************************************************** GET_ALL_ENV */ #if HAVE_GETENV extern char *getenv (); static xgetenv (name, var) char *name; char **var; { char *value; value = getenv (name); if (value != NULL) *var = newstrcat1 (value); } #endif static get_all_env() { #if HAVE_GETENV xgetenv ("CIMLIBDIR", &systemlibdir); xgetenv ("CIMINCLUDEDIR", &includedir); xgetenv ("TMPDIR", &tmpdir); xgetenv ("CIMTMPDIR", &tmpdir); #endif } /****************************************************************************** SIMCOMP */ static simcomp () { mbuilderInit(); if (initLex (sourcename)) return (TRUE); if (option_write_tokens) { scan_and_write_tokens (); return (FALSE); } #ifdef DEBUG if (option_declarations || option_expressions || option_msymbols || option_input || option_lex) { s_out = dup (stdout->_file); if (freopen (listname, "w", stdout) == NULL) { perror (newstrcat3 (progname, ": ", listname)); return (TRUE); } } #endif if ((ccode = fopen (ccodename, "w")) == NULL) { perror (newstrcat3 (progname, ": ", ccodename)); return (TRUE); } if (!option_quiet) fprintf (stderr, "Compiling %s:\n", sourcename); /* PASS 1 */ initExtspec (); init_parser (); initDecl (); yyparse (); /* PASS 2 AV KOMPILATOREN */ if (anterror == 0) { mbuilderReinit(); ebuilderInit(); sbuilderInit(); mainSent= sbuild(); reinit (); expCheckerInit (); genInit (); sentCheck (mainSent, TRUE); if (anterror == 0) { sentTrans (mainSent); sentGen (mainSent); } if (separat_comp && (anterror == 0 || option_atr)) write_all_ext (); #ifdef DEBUG if (option_declarations) dump (); #endif } fclose (ccode); #ifdef DEBUG if (option_declarations || option_expressions || option_msymbols || option_input || option_lex) { fclose (stdout); fdopen (s_out, "w"); dup2 (s_out, fileno (stdout)); } #endif if (anterror != 0) return (TRUE); else return (FALSE); } /****************************************************************************** STRINGTOUPPER */ static char * stringtoupper (s) char *s; { char *st; for (st = s; *st != '\0'; st++) if (*st >= 'a' && *st <= 'z') *st = *st - (char) 32; return (s); } /****************************************************************************** BASENAME */ static char * basename (str) char *str; { int i,j; for (i = strlen (str) - 2; i >= 0; i--) if (!strncmp (&str[i], "/", 1)) { str= &str[i + 1]; break; } str= newstrcat1 (str); i= strlen (str); if (i > 4 && !(strcmp (&str[i - 4], ".sim") && strcmp (&str[i - 4], ".SIM") && strcmp (&str[i - 4], ".cim") && strcmp (&str[i - 4], ".CIM"))) str[i - 4] = '\0'; return str; } /****************************************************************************** PRINT_HELP */ static int print_help(status)int status; { fprintf(stderr,"Usage: %s" " [-a] [--atr]" " [-b flags] [--cflags=flags]" "\n " " [-B flags] [--ldflags=flags]" " [-c] [--suppress-linking]" "\n " " [-d] [--compare]" " [-D NAME] [--define=NAME]" " [-e] [--static]" "\n " " [-E] [--preprocess]" " [-F] [--write-mif]" " [-g] [--debug]" "\n " " [-G] [--gcc]" " [-I DIR] [--includedir=DIR]" " [-h] [--help]" "\n " " [-H] [--no-lines]" " [-l LIBRARY] [--library=LIBRARY]" "\n " " [-L DIR] [--library-dir=DIR]" " [-m [N]] [--memory-pool-size[=N]]" "\n " " [-M N] [--max-memory-pool-size=N]" " [-N FILE] [--input=FILE]" "\n " " [-o FILE] [--output=FILE]" " [-O] [-ON]" " [--optimize] [--optimize=N]" "\n " " [-p] [--pic]" " [-P] [--only-link]" " [-q] [--quiet]" "\n " " [-R] [--preserve-timestamp]" " [--silent]" " [-s] [--no-simula-compile]" "\n " " [-S] [--only-simula-compile]" " [-t] [--dont-remove-temporaries]" "\n " " [-U NAME] [--undefine=NAME]" " [-v] [--verbose]" " [-V] [--version]" "\n " " [-w] [--no-warn]" " simula-file [file...]\n", progname); exit(status); } /****************************************************************************** PARSEOPTIONS */ static parseoptions (argc, argv) int argc; char *argv[]; { int c; int index; while (1) { int option_index = 0; static struct option long_options[] = { {"atr", 0, 0, 'a'}, {"cflags=", 1, 0, 'b'}, {"ldflags", 1, 0, 'B'}, {"suppress-linking", 0, 0, 'c'}, {"c-compiler", 1, 0, 'C'}, {"compare", 0, 0, 'd'}, {"define", 1, 0, 'D'}, {"static", 0, 0, 'e'}, {"preprocess", 0, 0, 'E'}, {"write-mif", 0, 0, 'F'}, {"debug", 0, 0, 'g'}, {"gcc", 0, 0, 'G'}, {"include-dir", 1, 0, 'I'}, {"help", 0, 0, 'h'}, {"no-lines", 0, 0, 'H'}, {"library", 1, 0, 'l'}, {"library-dir", 2, 0, 'L'}, {"memory-pool-size", 2, 0, 'm'}, {"max-memory-pool-size", 1, 0, 'M'}, {"input", 1, 0, 'N'}, {"output", 1, 0, 'o'}, {"optimize", 2, 0, 'O'}, {"pic", 0, 0, 'p'}, {"only-link", 0, 0, 'P'}, {"quiet", 0, 0, 'q'}, {"silent", 0, 0, 'q'}, {"preserve-timestamp", 0, 0, 'R'}, {"no-simula-compile", 0, 0, 's'}, {"only-simula-compile", 0, 0, 'S'}, {"dont-remove-temporaries", 0, 0, 't'}, {"undefine", 1, 0, 'U'}, {"verbose", 0, 0, 'v'}, {"version", 0, 0, 'V'}, {"no-warn", 0, 0, 'w'}, #ifdef DEBUG {"dd", 0, &option_declarations, 1}, {"de", 0, &option_expressions, 1}, {"dm", 0, &option_msymbols, 1}, {"di", 0, &option_input, 1}, {"dl", 0, &option_lex, 1}, {"dg", 0, &option_gen, 1}, #endif {"oc", 1, 0, 'b'}, {"ol", 1, 0, 'B'}, {0, 0, 0, 0} }; c = getopt_long_only (argc, argv, "ab:B:cC:edD:EFgGI:hHl:L::m::M:o:O::pP" "qRsStTU:vVw", long_options, &option_index); if (c == EOF) break; switch (c) { case 0: /* If this option set a flag, do nothing else now. */ break; case 'a': option_atr = TRUE; option_checkdiff = TRUE; option_reuse_timestamp = TRUE; break; case 'b': ccompargs = newstrcat3 (ccompargs, optarg, " "); break; case 'B': linkargs = newstrcat3 (linkargs, optarg, " "); break; case 'c': if (option_nolink || option_nocc) { fprintf (stderr, "%s: Option -c: Specified twise or " "in combination with -S or -C\n", progname); print_help (1); } option_nolink = TRUE; break; case 'C': ccomp = newstrcat1 (optarg); break; case 'd': option_checkdiff = TRUE; option_reuse_timestamp = TRUE; break; case 'D': defineName (tag (stringtoupper (optarg)), TRUE); break; case 'e': option_static = TRUE; break; case 'E': option_write_tokens = TRUE; break; case 'F': option_write_mif = TRUE; break; case 'g': break; case 'G': ccomp = "gcc -g -O2"; break; case 'h': print_help(0); break; case 'H': option_line = TRUE; break; case 'I': includedir = newstrcat1 (optarg); break; case 'l': new_lib (optarg); break; case 'L': insert_name_in_dirlist (optarg); break; case 'm': if (optarg) { sscanf (optarg, "%d", &option_init_poolsize); option_init_poolsize *= 1024; } else { option_dyn_poolsize = TRUE; } break; case 'M': sscanf (optarg, "%d", &option_max_poolsize); option_max_poolsize *= 1024; break; case 'N': if (sourcename != NULL) { fprintf (stderr, "%s: More than one simula-file " "are specified\n", progname); print_help (1); }; sourcename = newstrcat1 (optarg); break; case 'o': outputname = newstrcat1 (optarg); break; case 'O': if (!optarg) optarg=""; ccompargs = newstrcat4 (ccompargs, "-O", optarg, " "); break; case 'p': option_pic = TRUE; break; case 'P': if (option_nolink || option_nocc || option_nosim) { fprintf (stderr, "%s: Option -C: Specified twise or " "in combination with -s, -c or -S\n", progname); print_help (1); } option_nocc = option_nosim = TRUE; break; case 'q': option_quiet = TRUE; option_verbose = FALSE; break; case 'R': option_reuse_timestamp = TRUE; break; case 's': if (option_nocc || option_nosim) { fprintf (stderr, "%s: Option -s: Specified twise or in " "combination with -S or -C\n", progname); print_help (1); } option_nosim = TRUE; break; case 'S': if (option_nolink || option_nocc || option_nosim) { fprintf (stderr, "%s: Option -S: Specified twise or " "in combination with -s, -c or -C\n", progname); print_help (1); } option_nolink = option_nocc = TRUE; break; case 't': option_notempdel = TRUE; break; case 'u': option_bl_in_dir_line = TRUE; break; case 'U': defineName (tag (stringtoupper (optarg)), FALSE); break; case 'v': option_verbose = TRUE; option_quiet = FALSE; break; case 'V': printf ("%s-%s\n", PACKAGE_VERSION, SYSTEM_TYPE); exit (0); break; case 'w': option_nowarning = TRUE; break; case '?': return (TRUE); break; } } for (index = optind; index < argc; index++) { int l = strlen (argv[index]); if (l >= 6 && !strcmp (&argv[index][l - 6], "-atr.a")) { insert_name_in_archlist (argv[index]); insert_name_in_linklist (transform_name (argv[index], "-atr.a", ".a"), FALSE); } else if (l >= 2 && !strcmp (&argv[index][l - 2], ".a")) { insert_name_in_archlist (transform_name (argv[index], ".a", "-atr.a")); insert_name_in_linklist (argv[index], FALSE); } else if (l >= 2 && !strcmp (&argv[index][l - 2], ".o")) { insert_name_in_linklist (argv[index], FALSE); } else if (l >= 2 && argv[index][l - 2] == '.') { fprintf (stderr, "%s: Illegal extension\n", progname); print_help (1); } else { if (sourcename != NULL) { fprintf (stderr, "%s: More than one simula-files " "are specified\n", progname); print_help (1); }; if (l > 4 && !(strcmp (&argv[index][l - 4], ".sim") && strcmp (&argv[index][l - 4], ".SIM") && strcmp (&argv[index][l - 4], ".cim") && strcmp (&argv[index][l - 4], ".CIM"))) sourcename = newstrcat1 (argv[index]); else sourcename = newstrcat2 (argv[index], ".sim"); } } if (sourcename == NULL) { fprintf (stderr, "%s: No simula-file is specified\n", progname); print_help (1); }; exekname= basename (sourcename); listname= newstrcat2 (exekname, ".L"); extcodename= newstrcat2 (exekname, ".atr"); mifcodename= newstrcat2 (exekname, ".mif"); ccodename= newstrcat2 (exekname, ".c"); ocodename= newstrcat2 (exekname, ".o"); shlname= newstrcat3 ("./", exekname, ".shl"); if (!strcmp (outputname, "")) outputname = exekname; else exekname = outputname; if (strncmp (exekname, "/", 1)) exekname = newstrcat2 ("./", exekname); return (FALSE); } /****************************************************************************** MAIN */ main (argc, argv, envp) int argc; char *argv[]; char *envp[]; { char *archname; char *kom; char differ=TRUE; progname = argv[0]; initNewstr (); initFilelist (); ccomp = newstrcat3 (SCC, " ", SCFLAGS); init_trap_routines(); get_all_env(); insert_name_in_dirlist (systemlibdir); initName (); if (parseoptions (argc, argv)) return (1); new_lib ("cim"); if (option_verbose) { fprintf (stderr, "Cim Compiler (version: %s configuration name: %s).\n" "Copyright 1989-1998 by Sverre Hvammen Johansen, Stein Krogdahl," "Terje Mjøs and Free Software Foundation, Inc.\n" "Cim comes with ABSOLUTELY NO WARRANTY.\n" "This is free software, and you are welcome to redistribute it\n" "under the GNU General Public License; version 2.\n", PACKAGE_VERSION, SYSTEM_TYPE); } if(option_atr) system (newstrcat6 ("cp -f ", extcodename, " ", extcodename, ".old", " 2>/dev/null")); if(option_checkdiff) { rename (ccodename, newstrcat2 (ccodename, ".old")); } if (!option_nosim && simcomp ()) { unlink (ccodename); if(option_checkdiff) { rename (ccodename, newstrcat2 (ccodename, ".old")); } return (1); } if (option_write_tokens) return (0); if(option_atr) { char status; unlink (ccodename); status = system (newstrcat5 ("cmp -s ", extcodename, " ", extcodename, ".old 2>/dev/null")); unlink (newstrcat2 (extcodename, ".old")); if (status) { if (option_verbose) fprintf (stderr, "Atr file differ\n"); return (1); } else return (0); } if (!option_nosim) { FILE *shlfile; if ((shlfile = fopen (shlname, "w")) == NULL) { perror (newstrcat3 (progname, ": ", shlname)); return (1); } fprintf (shlfile, "#! /bin/sh\n" "\n" "CC='%s'\n" "CFLAGS='%s'\n" "CFLAGS_ADD=\n" "LDFLAGS='%s'\n" "LDFLAGS_ADD=\n" "wl='%s'\n" "link_static_flag=\"%s\"\n" "pic_flag=\"%s\"\n" "\n" "prev=\n" "for option\n" "do\n" " if test -n \"$prev\"; then\n" " eval \"$prev=\\$option\"\n" " prev=\n" " if test -n \"$CFLAGS_ADD\"; then\n" " CFLAGS=\"$CFLAGS $option\"\n" " CFLAGS_ADD=\n" " fi\n" " if test -n \"$LDFLAGS_ADD\"; then\n" " LDFLAGS=\"$LDFLAGS $option\"\n" " LDFLAGS_ADD=\n" " fi\n" " continue\n" " fi\n" "\n" " case \"$option\" in\n" " -*=*) optarg=`echo \"$option\" | " "sed 's/[-_a-zA-Z0-9]*=//'` ;;\n" " *) optarg= ;;\n" " esac\n" "\n" " case \"$option\" in\n" " -c | --suppress-linking | -suppress-linking)\n" " option_nolink=yes ;;\n" " -e | --static | -static)\n" " LDFLAGS=\"$LDFLAGS $link_static_flag\" ;;\n" " -G | --gcc | -gcc)\n" " CC='gcc -g -O2'; static_flag='-static'; \n" " pic_flag=' -fPIC' ;;\n" " -q | --quiet | --silent | -quiet | -silent)\n" " option_quiet=yes ; option_verbose= ;;\n" " -v | --verbose | -verbose) " " option_quiet= ; option_verbose=yes ;;\n" " -p | --pic | -pic)\n" " CFLAGS=\"$CFLAGS $pic_flag\" ;;\n" " -P | --only-link | -only-link)\n" " option_nocc=yes ;;\n" " -t | --dont-remove-temporaries | -dont-remove-temporaries)\n" " option_notempdel=yes ;;\n" " -s | --no-simula-compile | -no-simula-compile)\n" " option_notempdel=yes ;;\n" " -S | --only-simula-compile | -only-simula-compile)\n" " option_nolink=yes; option_nocc=yes ;;\n" " -d | --compare | -compare) " " option_checkdiff=yes; option_notempdel=yes ;;\n" "\n" " -b | --cflags | -cflags)\n" " prev=CFLAGS_ADD ;;\n" " -B | --ldflags | -ldflags)\n" " prev=LDFLAGS_ADD ;;\n" " -C | --c-compiler | -c-compiler)\n" " prev=CC ;;\n" " -b=* | --cflags=* | -cflags=*)\n" " CFLAGS=\"$CFLAGS $optarg\" ;;\n" " -B=* | --ldflags=* | -ldflags=*)\n" " LDFLAGS=\"$LDFLAGS $optarg\" ;;\n" " -C=* | --c-compiler=* | -c-compiler=*)\n" " CC=\"$optarg\" ;;\n" /* " *) { echo \"n.shl: $option: invalid option\" 1>&2; " "exit 1 };;\n"*/ " esac\n" "done\n" "\n" "differ=yes\n" "if test -z \"$option_nocc\"; then\n" " if test -n \"$option_checkdiff\"; then\n" " cmp -s %s %s.old &&\n" " differ=\n" " rm -f %s.old\n" " fi\n" "\n" " if test -n \"$differ\"; then\n" " if test -z \"$option_quiet\"; then\n" " echo $CC $CFLAGS -c %s\n" " fi\n" " $CC $CFLAGS -c %s || exit 1\n" " else\n" " if test -z\"$option_quiet\"; then\n" " echo touch %s\n" " fi\n" " touch %s\n" " fi\n" " if test -z \"$option_notempdel\"; then\n" " rm -f %s\n" " fi\n" "fi\n" "\n", ccomp, "", SLDFLAGS, WL_FLAG, LINK_STATIC_FLAG, PIC_FLAG, ccodename, ccodename, ccodename, ccodename, ccodename, ocodename, ocodename, ccodename); if (!separat_comp) { more_modules (); fprintf (shlfile, "if test -z \"$option_nolink\"; then\n" " if test -z \"$option_quiet\"; then\n" " echo $CC $LDFLAGS -o %s %s %s\n" " fi\n" "\n" " $CC $LDFLAGS -o %s %s %s %s || exit 1\n" "fi\n", outputname, ocodename, get_names_in_linklist (), outputname, ocodename, get_names_in_linklist (), SLIBS); } if (!((option_nolink && !separat_comp) || option_nocc || option_notempdel)) fprintf (shlfile, "rm -f %s\n",shlname); fclose (shlfile); system (newstrcat2 ("chmod +x ", shlname)); } argv[0]= shlname; execve (shlname, argv, envp); }