C:/Users/Dennis/src/lang/russell.orig/src/root/rc.c

Go to the documentation of this file.
00001 /*
00002  *               Russell compiler driver
00003  *
00004  *  Syntax: rc [-flags] file [file.o ...]
00005  *
00006  *  File names ending in ".o" are assumed to be (non-Russell) object
00007  * files to be linked in. 
00008  *
00009  *  Flags:
00010  *      B   - Debugging flag: see rc
00011  *      D   - Debugging flag: see rc
00012  *      i   - initialize compiler (implies -U, unless -I is present)
00013  *      d   - identical to i except generates demand loadable initialized
00014  *            compiler on the VAX.
00015  *      I   - invoke the initialized compiler (default)
00016  *      U   - invoke the uninitialized compiler
00017  *      a   - generate abstract syntax instead of VAX code (defunct)
00018  *      A   - generate alternate machine code - VAX on a SUN, or SUN
00019  *            on a VAX
00020  *      m   - generate ML abstract machine code (defunct)
00021  *      G   - produce general, machine independent, intermediate code
00022  *      O   - invoke the "optimizer".  Repeated to invoke the
00023  *            intermediate code optimizer.  Tripled to unroll loops once.
00024  *      c   - generate a .o file with signature information, which can
00025  *            be linked into another program.
00026  *      S   - do not assemble the object program.  Leave it around
00027  *            as a .s file
00028  *      r   - leave the result relocatable (passed on to loader)
00029  *      p   - run the standard C preprocessor on the source
00030  *      L   - interpret import rule Liberally.  Allow functions
00031  *            with trailing var Void argument to import variables
00032  *      P   - enable execution profiling
00033  *      T   - enable tracing
00034  *      V   - print known call graph and opt. info to stdout
00035  *      N   - no use of Callcc
00036  *      f   - generate intermediate code that does not explicitly
00037  *            update the stack pointer.
00038  *            However, a deallocation instruction preceded by HINT
00039  *            ONS is assumed to turn into a noop, at least if the
00040  *            size is blatantly constant.
00041  *            (Used for RIC to C translator.)
00042  *      F   - same as f, but also arrange that all GAR instructions
00043  *            precede any real code, and that BSF functions
00044  *            don't access the global frame pointer.  No assumptions
00045  *            are made about HINT ONS.
00046  *            (Used for RIC to ILOC translator.)
00047  *      R   - generate intermediate code that maintains identifier
00048  *            bindings in virtual registers whenever possible.  Probably
00049  *            useful only in the presence of a good global register
00050  *            allocator for the target machine.
00051  *      l<name>
00052  *          - each instance in the command line of this option is passed
00053  *            on to ld (this is a library link)
00054  *      o <name>
00055  *          - put the result in file named <name> instead of a.out
00056  *      C   - (cleanup) remove any .s or .G files created
00057  *      h   - heap allocate all variables and allocation records
00058  *            (only useful to measure the impact of these optimizations)
00059  *      u   - Use a user supplied version of rc.x or Grc.x, the main
00060  *            compiler executable.
00061  *      X   - Generate C callable functions for components of the type
00062  *            denoted by the expression in the source file.
00063  *      x   - generate executable compatible with Xerox Portable Common
00064  *            Runtime.  All heap allocation is done with explicit calls.
00065  *            
00066  *
00067  *  If the intermediate code generator is used, in the most general case,
00068  * the sequence of activated processes is:
00069  *
00070  *      1) C preprocessor
00071  *      2) Grc.x, the body of the compiler
00072  *      3) RICfilter, a local optimizer for Russell Intermediate Code (with -O)
00073  *      4) RICopt, a static garbage collector (with -OO)
00074  *      5) cg, a final code generator
00075  *      6) as
00076  *      7) ld
00077  *
00078  */
00079 
00080 # include <stdio.h>
00081 # include <signal.h>
00082 # include <a.out.h>
00083 # include <sys/file.h>
00084 # include <sys/types.h>
00085 # include <sys/stat.h>
00086 # include "../parm.h"
00087 # include "mesg.h"
00088 
00089 # ifdef malloc
00090 #   undef malloc    /* We want the real one */
00091 #   undef free
00092 # endif
00093 
00094 # define DEBUG DEBUG
00095 
00096 
00097 char *ppname; 
00098 char *rcname;
00099 char *optname;
00100 char *RICoptname;
00101 char *RICfiltername;
00102 char *cgname;
00103 
00104 /* Unique names for temporary files */
00105 char *rctmp0name;   /* Preprocessor output */
00106 char *rctmp1name;   /* Optimizer input */
00107 char *rctmp2name;   /* Signature and Rc optimization info out */
00108 char *rctmp3name;   /* Intermediate code optimizer data flow info in  */
00109 char *rctmp4name;   /* intermediate code optimizer data flow info out */
00110                     /* also used as input file to RICfilter           */
00111 
00112 /* Flag variables.
00113  */
00114 boolean aflag;              /* generate abstract syntax */
00115 boolean oflag;              /* rename a.out as given file name */
00116 boolean Oflag;              /* optimize for execution speed */
00117 boolean OOflag;             /* invoke RIC optimizer */
00118 boolean OOOflag;            /* unroll loops once */
00119 boolean Sflag;              /* do not assemble */
00120 boolean cflag;              /* incomplete program */
00121 boolean rflag;              /* relocatable object file */
00122 boolean pflag;              /* Run C preprocessor */
00123 boolean Pflag;              /* Execution profiling */
00124 boolean Gflag;              /* Intermediate code */
00125 boolean CGflag;             /* Run separate code generator */
00126 boolean Cflag;              /* clean up afterwards */
00127 boolean fflag;              /* No stack pointer updates */
00128 boolean Fflag;              /* RT style stack frames */
00129 boolean Rflag;              /* Locals in registers */
00130 boolean Xflag;              /* Externally callable code */
00131 boolean xflag;              /* PCR code */
00132 boolean uflag;              /* Use rc.x from current directory */
00133 boolean Vflag;              /* Print optimization info */
00134 
00135 boolean take_next= FALSE;   /* next argument is final_name */
00136 char *lppflags = "";        /* Legal preprocessor flags. */
00137 char *lpmnflags  = "BDidaMpLPTVNfFRhx"; /* Legal Rc flags.            */
00138                                         /* G,c are handled separately */
00139 char *lprtflags  = "IUOGcSArlCXOu";  /* legal flags, used only by   */
00140                                      /* the root process.           */
00141 char appflags[100];         /* Actual preprocessor flags. */
00142 char apmnflags[100];        /* Actual rc flags. */
00143 
00144 char *objfiles[MAXNOBJFILES];     /* object files that need to be linked */
00145                                   /* with this program                   */
00146 int nobjfiles = 0;       /* number of valid entries in objfiles */
00147 
00148 char *libraries[MAXNLIBRARIES];   /* libraries needed for linking */
00149 int nlibraries = 0;      /* number of valid entries on libraries */
00150 
00151 char * malloc();
00152 
00153 int intr_handler();
00154 
00155 /* Add a copy of the file name ofile to the list of object files to be loaded */
00156 void add_objfile(ofile)
00157 char * ofile;
00158 {
00159     char * nfn = malloc(strlen(ofile)+1);
00160     int i;
00161     boolean duplicate = FALSE;
00162 
00163     if (nobjfiles >= MAXNOBJFILES) {
00164         fprintf(stderr, "Too many object files\n");
00165         exit(1);
00166     }
00167     strcpy(nfn,ofile);
00168     for (i = 0; i < nobjfiles; i++) {
00169         if (strcmp(nfn, objfiles[i]) == 0) {
00170 /*
00171             fprintf(stderr,
00172                     "Warning: External file %s mentioned twice\n",
00173                     nfn);
00174 */
00175             duplicate = TRUE;
00176         }
00177     }
00178     if (!duplicate) {
00179       objfiles[nobjfiles++] = nfn;
00180     }
00181 }
00182 
00183 /* Name of Rc to execute. */
00184 char Rcname[15] = "";
00185 
00186 /* Name of code file produced by main pass or RICfilter, if invoked */
00187 char * codefilename;
00188 
00189 /* Name of code file produced by main compiler pass */
00190 char * main_out_fname;
00191 
00192 char * outfilename();
00193 char * mktemp();
00194 
00195 boolean dloadflag = FALSE;  /* generate a demand loadable initialized */
00196                             /* compiler.                              */
00197 
00198 main(argc,argv)
00199 int argc;
00200 char **argv;
00201 {   int argf;   /* After all flags are                              */
00202                 /* are read argv[argf] is the file name.            */
00203     int status;
00204     extern exit();
00205     boolean compile_only = FALSE;
00206     int argn;
00207 
00208     /* If quit is sent, just exit (w/o core dump). */
00209         signal(SIGQUIT, exit);
00210 
00211     /* Clean up after SIGINT */
00212         signal(SIGINT, intr_handler);
00213 
00214     ppname = PPNAME;
00215     rcname = RCNAME;
00216     optname = OPTNAME;
00217     cgname = CGNAME;
00218     RICoptname = RICOPTNAME;
00219     RICfiltername = RICFILTERNAME;
00220 
00221     argf = -1;
00222 
00223 #   ifndef VAX
00224       /* Initialize to use separate code generator */
00225         Gflag = TRUE;
00226         CGflag = TRUE;
00227 #   endif
00228     /* Process any flag options. */
00229         strcpy(appflags, "-");
00230         strcpy(apmnflags, "-");
00231         for (argn = 1; argn < argc; argn++) {
00232          if (take_next) {
00233           int al = strlen(argv[argn]);
00234           if (strcmp(argv[argn]+al-2,".o")==0 || 
00235               strcmp(argv[argn]+al-2,".r")==0) {
00236            fprintf(stderr,"Questionable -o usage: Might overwrite %s.\n",
00237                                                                 argv[argn]);
00238            goto usage;
00239           } else {
00240            add_objfile(argv[argn]);
00241            take_next = FALSE;
00242           }
00243          } else if ( argv[argn][0] == '-' ) {
00244           char *flagp;
00245           char *farg = "0";
00246           switch( argv[argn][1] ) {     /* may be special or just flag */
00247 
00248            case 'l' :           /* library */
00249             if (nlibraries >= MAXNLIBRARIES) {
00250                 fprintf(stderr, "Too many libraries\n");
00251                 exit(1);
00252             }
00253             libraries[nlibraries++] = argv[argn];
00254             break;
00255 
00256            case 'o' :           /* put output in file argv[argn+1] */
00257             oflag = TRUE;
00258             add_objfile(argv[argn]);    /* make -o option an obj file */
00259             take_next = TRUE;
00260             break;
00261 
00262            default:
00263 
00264             for (flagp = &(argv[argn][1]); *flagp != 0; flagp++) {
00265                 farg[0] = *flagp;
00266                 if ( index(lppflags, *flagp) != 0 ) {
00267                     strcat(appflags, farg);
00268                 } else if ( index(lpmnflags, *flagp) != 0 ) {
00269                     strcat(apmnflags, farg);
00270                 } else if ( index(lprtflags, *flagp) == 0 ) {
00271                     fprintf(stderr, "Bad flag: %c\n", *flagp);
00272                 }
00273                 switch ( *flagp ) {
00274                     case 'd' :
00275                         dloadflag = TRUE;
00276                         /* Otherwise identical to i */
00277                     case 'i' :
00278                         /* Unless otherwise specified, use Rc. */
00279                             if ( strcmp(Rcname, "") == 0 )
00280                                 strcpy(Rcname, "Rc");
00281                         compile_only = TRUE;
00282                         break;
00283                     case 'I':
00284                         if (Gflag) {
00285                           strcpy(Rcname, "rc.x");
00286                         } else {
00287                           strcpy(Rcname, "Grc.x");
00288                         }
00289                         break;
00290                     case 'C':
00291                         Cflag = TRUE;
00292                         break;
00293                     case 'U':
00294                         strcpy(Rcname, "Rc");
00295                         break;
00296                     case 'a':
00297                         aflag = TRUE;
00298                         break;
00299                     case 'A':
00300                         Sflag = TRUE;
00301 #                       ifdef VAX
00302                           CGflag = TRUE;
00303                           Gflag = TRUE;
00304 #                       else
00305                           CGflag = FALSE;
00306                           Gflag = FALSE;
00307 #                       endif
00308                         break;
00309                     case 'O':
00310                         if (OOflag) {
00311                           OOOflag = TRUE;
00312                         } else if (Oflag) {
00313                           OOflag = TRUE;
00314                         } else {
00315                           Oflag = TRUE;
00316                         }
00317                         break;
00318                     case 'c':
00319                         if (nobjfiles != 0) {
00320                           fprintf(stderr, "Warning: .o files ignored with -c\n");
00321                         }
00322                         cflag = TRUE;
00323                         break;
00324                     case 'X':
00325                         Xflag = TRUE;
00326                         break;
00327                     case 'S':
00328                         Sflag = TRUE;
00329                         break;
00330                     case 'r':
00331                         rflag = TRUE;
00332                         break;
00333                     case 'p':
00334                         pflag = TRUE;
00335                         break;
00336                     case 'P':
00337                         Pflag = TRUE;
00338                         break;
00339                     case 'G':
00340                         Gflag = TRUE;
00341                         CGflag = FALSE;
00342                         compile_only = TRUE;
00343                         break;
00344                     case 'f':
00345                         fflag = TRUE;
00346                         break;
00347                     case 'F':
00348                         fflag = TRUE;
00349                         Fflag = TRUE;
00350                         break;
00351                     case 'R':
00352                         Rflag = TRUE;
00353                         break;
00354                     case 'u':
00355                         uflag = TRUE;
00356                         break;
00357                     case 'x':
00358                         xflag = TRUE;
00359                         break;
00360                     case 'V':
00361                         Vflag = TRUE;
00362                         break;
00363                 } /* end switch (*flagp) */
00364             } /* end for (flagp...) */
00365           } /* end switch( argv...) */
00366          } else {
00367             /* argv[argn] not flag argument */
00368             int arg_len = strlen(argv[argn]);
00369             if (argv[argn][arg_len-1] == 'o'
00370                 && argv[argn][arg_len-2] == '.') {
00371                 if (cflag) {
00372                     fprintf(stderr, "Warning: .o files ignored with -c\n");
00373                 }
00374                 add_objfile(argv[argn]);
00375             } else { /* Russell source file */
00376                 if (argf == -1) { /* first one */
00377                     argf = argn;
00378                 } else {
00379                     fprintf(stderr, "One source file at a time, please!\n");
00380                     goto usage;
00381                 }
00382             } /* end if (argv...) */
00383          } /* end if (argv[argn][0] == '-')... */
00384         } /* end for (argn...) */
00385 
00386     if (argf == -1) {
00387         fprintf(stderr, "No Russell source file\n");
00388         goto usage;
00389     }
00390 
00391     if (cflag && Gflag && !CGflag) {
00392         fprintf(stderr, "Warning: -G suppresses -c\n");
00393         cflag = FALSE;
00394     }
00395 
00396 
00397     if (Xflag && cflag) {
00398         fprintf(stderr, "Warning: -X suppresses -c\n");
00399         cflag = FALSE;
00400     }
00401 
00402 #   ifdef RT
00403 #     ifndef GEN_C
00404        /* -f is mandatory for RT code generator  */
00405         if (CGflag) {
00406             if (!Fflag) {
00407                 strcat(apmnflags, "F");
00408             }
00409             Fflag = TRUE;
00410         }
00411 #     endif
00412 #   endif
00413 
00414 #   ifdef GEN_C
00415       /* RIC-to-C translator expects at least -f */
00416         if (CGflag) {
00417             if (!Fflag) {
00418                 strcat(apmnflags, "f");
00419             }
00420         }
00421 #   endif
00422 
00423     if (Gflag) {
00424         strcat(apmnflags, "G");
00425         if (Rcname[0] != 'R') {
00426             /* Haven't seen -U */
00427             strcpy(Rcname, "Grc.x");
00428         }
00429     }
00430 
00431 
00432     if (Xflag) {
00433         strcat(apmnflags, "X");
00434     }
00435 
00436     if (cflag) {
00437         strcat(apmnflags, "c");
00438     }
00439 
00440     if (Oflag) {
00441         strcat(apmnflags, "O");
00442     }
00443 
00444     if (OOflag) {
00445         if (!Gflag) {
00446             fprintf(stderr, "-OO was ignored - works only in conjunction with intermediate code generator\n");
00447         } else if (OOOflag) {
00448             strcat(apmnflags, "OO");
00449         } else {
00450             strcat(apmnflags, "O");
00451         }
00452     }
00453 
00454     /* Generate temp file names */
00455         rctmp0name = mktemp("/tmp/rctmp0XXXXXX");
00456         rctmp1name = mktemp("/tmp/rctmp1XXXXXX");
00457         rctmp2name = mktemp("/tmp/rctmp2XXXXXX");
00458         if (Gflag & Oflag) {
00459           rctmp4name = mktemp("/tmp/rctmp4XXXXXX");
00460         }
00461         if (OOflag) {
00462           rctmp3name = mktemp("/tmp/rctmp3XXXXXX");
00463         }
00464 
00465     /* Remove old object file list */
00466         unlink(OBJFILELIST);
00467 
00468     /* Generate file name for code output from main compiler or RICfilter */
00469         if (OOflag || Oflag && ! Gflag) {
00470             codefilename = rctmp1name;
00471         } else {
00472             codefilename = outfilename(argv[argf], (Gflag? 'G' : 's'));
00473         }
00474 
00475     /* Generate file name for code output from main compiler */
00476         if (Oflag & Gflag) {
00477             main_out_fname = rctmp4name;
00478         } else {
00479             main_out_fname = codefilename;
00480         }
00481 
00482     if (pflag) {
00483       /* Fork and exec preprocessor with stdout going to rctmp0 */
00484         if( rfork() == 0 ) {
00485             fclose(stdout);
00486             if( fopen( rctmp0name, "w" ) == NULL ) {
00487                 fprintf(stderr, "Cannot create %s\n", rctmp0name);
00488                 exit(1);
00489             }
00490             execl(ppname, "cpp", appflags, argv[argf], 0 );
00491             /* exit */
00492 
00493             fprintf(stderr, "Can't exec preprocessor\n");
00494             exit(1);
00495         }
00496 
00497       /* Wait for preprocessor to finish, then report its status. */
00498         wait( &status );
00499         if( status != 0 ) {
00500             fprintf(stderr, "Compilation terminated after preprocessing.\n");
00501             printstatus(status);
00502             rmfiles();
00503             exit(1);
00504         }
00505     }
00506 
00507     /* Fork and exec rc */
00508         if( rfork() == 0 ) {
00509             char fullrcname[150];
00510 
00511             if (uflag) {
00512                 fullrcname[0] = '\0';
00513             } else {
00514                 strcpy(fullrcname, rcname);
00515             }
00516             if (Rcname[0] == 0)
00517                 strcat(fullrcname, "rc.x");
00518             else
00519                 strcat(fullrcname, Rcname);
00520 #           if vax
00521               if(dloadflag) {
00522                 /* Check that current version of Rc is demand loadable */
00523                     int rcdescr;
00524                     long magic_n;   /* magic number of Rc file */
00525 
00526                     if ((rcdescr = open(fullrcname,0)) == -1 ||
00527                          read(rcdescr, &magic_n, sizeof (long)) <= 0) {
00528                             fprintf(stderr,"Can't read %s\n", fullrcname);
00529                             rmfiles();
00530                             exit(1);
00531                     }
00532                     if (magic_n != ZMAGIC && magic_n != NMAGIC) {
00533                         fprintf (stderr,"Can't generate demand loadable file from old format a.out file\n");
00534                     }
00535                     close(rcdescr);
00536               }
00537 #           endif
00538             if (cflag && OOflag) {
00539               execl(fullrcname, "Rc", argv[argf],
00540                     apmnflags, pflag? rctmp0name : argv[argf],
00541                     main_out_fname,
00542                     rctmp2name, rctmp3name, 0 );
00543             } else if (cflag) {
00544               execl(fullrcname, "Rc", argv[argf],
00545                     apmnflags, pflag? rctmp0name : argv[argf],
00546                     main_out_fname,
00547                     rctmp2name, 0 );
00548             } else if (OOflag) {
00549               execl(fullrcname, "Rc", argv[argf],
00550                     apmnflags, pflag? rctmp0name : argv[argf],
00551                     main_out_fname,
00552                     rctmp3name, 0 );
00553             } else {
00554               execl(fullrcname, "Rc", argv[argf],
00555                     apmnflags, pflag? rctmp0name : argv[argf],
00556                     main_out_fname, 0 );
00557             }
00558             /* exit */
00559 
00560             fprintf(stderr, "Can't exec %s\n", fullrcname);
00561             rmfiles();
00562             exit(1);
00563         }
00564 
00565     /* Wait for rc to finish then report its status. */
00566         wait( &status );
00567         if( status != 0 ) {
00568             fprintf(stderr, "Compilation terminated prematurely.\n");
00569             printstatus(status);
00570             rmfiles();
00571             exit(1);
00572         }
00573 
00574     /* Add object files to list */
00575       {
00576 #       define MAXFILELEN 100
00577         FILE * objfilelist  = fopen(OBJFILELIST, "r");
00578         char namebuf[MAXFILELEN+1];
00579         int len;
00580         int retcode;
00581 
00582         if (objfilelist != NULL) {
00583             while (!feof(objfilelist)) {
00584                 retcode = (int) fgets(namebuf, MAXFILELEN, objfilelist);
00585                 /* delete trailing newline */
00586                   {
00587                     len = strlen(namebuf);
00588                     if (namebuf[len-1] == '\n') {
00589                       namebuf[--len] = 0;
00590                     }
00591                   }
00592                 if (retcode != NULL && len != 0) {
00593                     add_objfile(namebuf);
00594                 }
00595             }
00596         }
00597       }
00598 
00599     if (Oflag && !Gflag) {
00600       /* Fork and exec Vax "optimizer" */
00601         if( rfork() == 0 ) {
00602             char * optfilename = outfilename(argv[argf], 's');
00603 
00604             if( freopen( optfilename, "w", stdout ) == NULL ) {
00605                 fprintf(stderr, "Cannot create %s\n", optfilename);
00606                 exit(1);
00607             }
00608             execl("/bin/awk", "awk", "-f", OPTNAME,
00609                   codefilename, 0);
00610             /* exit */
00611 
00612             fprintf(stderr, "Can't exec /bin/awk\n");
00613             exit(1);
00614         }
00615 
00616         /* Wait for optimizer to finish, then report its status. */
00617           wait( &status );
00618           if( status != 0 ) {
00619             fprintf(stderr, "Optimization failed\n");
00620             printstatus(status);
00621             rmfiles();
00622             exit(1);
00623           }
00624     } /* if (Oflag && !Gflag) ... */
00625 
00626     if (Oflag && Gflag) {
00627       /* Fork and exec RICfilter */
00628         if( rfork() == 0 ) {
00629             if( freopen( codefilename, "w", stdout ) == NULL ) {
00630                 fprintf(stderr, "Cannot create %s\n", codefilename);
00631                 exit(1);
00632             }
00633             if( freopen( main_out_fname, "r", stdin ) == NULL ) {
00634                 fprintf(stderr, "Cannot create %s\n", main_out_fname);
00635                 exit(1);
00636             }
00637             execl(RICfiltername, "RICfilter", 0);
00638             /* exit */
00639 
00640             fprintf(stderr, "Can't exec %s\n", RICfiltername);
00641             exit(1);
00642         }
00643 
00644         /* Wait for RICfilter to finish, then report its status. */
00645           wait( &status );
00646           if( status != 0 ) {
00647             fprintf(stderr, "Local RIC optimization failed\n");
00648             printstatus(status);
00649             rmfiles();
00650             exit(1);
00651           }
00652     } /* if (Oflag && Gflag) ... */
00653 
00654     if (OOflag) {
00655       /* Fork and exec RIC optimizer */
00656         if( rfork() == 0 ) {
00657             char * optfilename = outfilename(argv[argf], 'G');
00658 
00659             execl(RICoptname, "RICopt", (Vflag? "-verbose" : "-"),
00660                   codefilename, optfilename, rctmp3name,
00661                   cflag? rctmp4name : "/dev/null", 0);
00662             /* exit */
00663 
00664             fprintf(stderr, "Can't exec %s\n", RICoptname);
00665             exit(1);
00666         }
00667 
00668         /* Wait for optimizer to finish, then report its status. */
00669           wait( &status );
00670           if( status != 0 ) {
00671             fprintf(stderr, "Optimization failed\n");
00672             printstatus(status);
00673             rmfiles();
00674             exit(1);
00675           }
00676     } /* if (OOflag) ... */
00677 
00678     if (compile_only) {
00679         rmfiles();
00680         exit(0);
00681     }
00682 
00683     if (CGflag) {
00684       char * gf_name;
00685       char * global_ar_name();
00686       
00687       if (xflag && !cflag) {
00688           /* This is a top level file destined to be run in a */
00689           /* multi-threaded world.  Storing the global frame  */
00690           /* pointer in a single global variable wont do.     */
00691           /* instead we set things up so that each function   */
00692           /* will know to get GF from the right place.  This  */
00693           /* isn't necessary in subsidiary compilations,      */
00694           /* they only see a part of the global frame that    */
00695           /* should be identical for everybody.               */
00696           gf_name = global_ar_name(argv[argf]);
00697       } else {
00698           gf_name = "global_ar";
00699       }
00700       /* Fork and exec final code generator */
00701         if( rfork() == 0 ) {
00702             if (Oflag) {
00703               execl(cgname, cgname,
00704                     (xflag? "-Ox" : "-O"),
00705                     outfilename(argv[argf], 'G'),
00706 #               ifndef RT
00707                     outfilename(argv[argf], 's'),
00708 #               endif
00709 #               ifdef GEN_C
00710                     gf_name,
00711 #               endif
00712                     0);
00713             } else if (xflag) {
00714               execl(cgname, cgname,
00715                     "-x",
00716                     outfilename(argv[argf], 'G'),
00717 #               ifndef RT
00718                     outfilename(argv[argf], 's'),
00719 #               endif
00720 #               ifdef GEN_C
00721                     gf_name,
00722 #               endif
00723                     0);
00724             } else {
00725               execl(cgname, cgname,
00726                     outfilename(argv[argf], 'G'),
00727 #               ifndef RT
00728                     outfilename(argv[argf], 's'),
00729 #               endif
00730 #               ifdef GEN_C
00731                     gf_name,
00732 #               endif
00733               0);
00734             }
00735             /* exit */
00736 
00737             fprintf(stderr, "Can't exec %s\n", cgname);
00738             rmfiles();
00739             exit(1);
00740         }
00741 
00742         /* Wait for code generator to finish, then report its status. */
00743           wait( &status );
00744           if( status != 0 ) {
00745             fprintf(stderr, "Final code generation failed\n");
00746             printstatus(status);
00747             rmfiles();
00748             exit(1);
00749           }
00750     } /* if (CGflag) ... */
00751 
00752     if (!Sflag) {
00753       /* assemble the result */
00754         if (rfork() == 0) {
00755             execl("/bin/as", "as", "-o", outfilename(argv[argf], 'o'),
00756                                          outfilename(argv[argf], 's'), 0);
00757             fprintf(stderr, "Can't exec /bin/as\n");
00758             rmfiles();
00759             exit(1);
00760         }
00761         wait(&status);
00762         if (status != 0) {
00763             fprintf(stderr, "Assembly failed\n");
00764             printstatus(status);
00765             rmfiles();
00766             exit(1);
00767         }
00768 
00769         if (!cflag && !Xflag) {
00770           char * ld_argv[MAXNOBJFILES + 10];
00771           int ld_argc = 0;
00772           int i;
00773 
00774           /* Add current file and standard files to list to be loaded */
00775             add_objfile(outfilename(argv[argf], 'o'));
00776             if (!rflag) {
00777 #               ifdef RT
00778                   add_objfile(strcat(RROOT, "/rt_runtime/rrt0.o"));
00779 #               else
00780                   add_objfile(strcat(RROOT, "/runtime/rrt0.o"));
00781 #               endif
00782               /* Add C library to list of libraries */
00783                 if (nlibraries >= MAXNLIBRARIES) {
00784                   fprintf(stderr, "Too many libraries\n");
00785                   exit(1);
00786                 }
00787                 if (Pflag) {
00788                   libraries[nlibraries++] = "/usr/lib/libc_p.a";
00789                 } else {
00790                   libraries[nlibraries++] = "/lib/libc.a";
00791                 }
00792             }
00793 
00794           /* build argument vector for ld command */
00795             ld_argv[ld_argc++] = "ld";
00796             if (rflag) {
00797               /* Make object file relocatable */
00798                 ld_argv[ld_argc++] = "-r";
00799             } else {
00800                 ld_argv[ld_argc++] = "-e";
00801                 ld_argv[ld_argc++] = "start";
00802                 if (Pflag) {
00803                     ld_argv[ld_argc++] = "/lib/gcrt0.o";
00804                 } else {
00805                     ld_argv[ld_argc++] = "/lib/crt0.o";
00806                 }
00807             }
00808             for (i = 0; i < nobjfiles; i++) {
00809                 ld_argv[ld_argc++] = objfiles[i];
00810             }
00811             for (i = 0; i < nlibraries; i++) {
00812                 ld_argv[ld_argc++] = libraries[i];
00813             }
00814             ld_argv[ld_argc++] = 0;
00815           /* Fork and exec ld command */
00816             if (rfork() == 0) {
00817               execv("/bin/ld", ld_argv);
00818               fprintf(stderr, "Can't exec /bin/ld\n");
00819               rmfiles();
00820               exit(1);
00821             }
00822             wait(&status);
00823             if (status != 0 && (!rflag /* needed due to ld misfeature */)) {
00824               fprintf(stderr, "Linking failed\n");
00825               printstatus(status);
00826             }
00827         } else if (cflag) {
00828           /* append signature and optimization information to end of .o file */
00829             FILE * rctmp2 = fopen(rctmp2name,"r");
00830             FILE * ofile = fopen(outfilename(argv[argf], 'o'), "r+");
00831             long strsize;
00832             struct exec header;
00833             extern char * etext;
00834             char c;
00835 #           if defined(SUN) && defined(EXTRA_MAGIC)
00836               struct extra_sections es;
00837               unsigned long es_start;   /* Start position of extra section */
00838                                         /* header.                         */
00839               unsigned long es_length;
00840 #           endif
00841 
00842             if (ofile == NULL) {
00843                 fprintf(stderr, "Can't open %s\n",
00844                                 outfilename(argv[argf], 'o'));
00845                 rmfiles();
00846                 exit(1);
00847             }
00848             if (rctmp2 == NULL) {
00849                 fprintf(stderr, "Can't open %s\n", rctmp2);
00850                 rmfiles();
00851                 exit(1);
00852             }
00853             fread(&header, sizeof (struct exec), 1, ofile);
00854             fseek(ofile, N_STROFF(header), 0);
00855             fread(&strsize, sizeof (long), 1, ofile);
00856             fseek(ofile, N_STROFF(header) + strsize, 0);
00857             
00858 #           if defined(SUN) && defined(EXTRA_MAGIC)
00859               /* Leave space for extra section header and length */
00860                 es_start = ftell(ofile);
00861                 fseek(ofile, sizeof (struct extra_sections) + sizeof(int), 1);
00862 #           endif
00863 
00864             if (OOflag) {
00865                 /* Copy file of data flow info, preceded by its size */
00866                 struct stat buf;
00867                 FILE * rctmp4 = fopen(rctmp4name,"r");
00868                 int count;
00869 
00870                 if (rctmp4 == NULL) {
00871                     fprintf(stderr, "Optimizer failed to write flow info\n");
00872                     putw(0, ofile);
00873                 } else {
00874                     fstat(fileno(rctmp4), &buf);
00875                     putw(buf.st_size, ofile);
00876                     count = 0;
00877                     while (c = getc(rctmp4), !feof(rctmp4)) {
00878                         putc(c, ofile); count ++;
00879                     }
00880                     if (count != buf.st_size) {
00881                         fprintf(stderr, "Stat returned incorrect size for %s\n",
00882                                 rctmp4name);
00883                         abort(count, buf.st_size);
00884                     }
00885                 }
00886             } else {
00887                 putw(0, ofile);
00888             }
00889             /* Copy file consisting of &etext, objfilelist, and signature */
00890               while (c = getc(rctmp2), !feof(rctmp2)) {
00891                 putc(c, ofile);
00892               }
00893 #           if defined(SUN) && defined(EXTRA_MAGIC)
00894               /* Write the extra section header and length */
00895                 es_length = ftell(ofile) - es_start
00896                             - sizeof (struct extra_sections)
00897                             - sizeof(int);
00898                 fseek(ofile, es_start, 0);
00899                 es.extra_magic = EXTRA_MAGIC;
00900                 es.extra_nsects = 1;
00901                 if (!fwrite(&es, sizeof (struct extra_sections), 1, ofile)) {
00902                     fprintf(stderr, "Couldnt write extra sections hdr\n");
00903                 }
00904                 putw(es_length, ofile);
00905 #           endif
00906 
00907             fclose(ofile);
00908             fclose(rctmp2);
00909         }
00910     }
00911 
00912     if (Cflag) {
00913       if (!Gflag || CGflag) {
00914         unlink(outfilename(argv[argf],'G'));
00915       }
00916       if (!Sflag) {
00917         unlink(outfilename(argv[argf],'s'));
00918       }
00919 #     ifdef GEN_C
00920         unlink(outfilename(argv[argf],'c')); 
00921 #     endif  
00922       unlink(OBJFILELIST);
00923     }
00924     rmfiles();
00925     exit(0);
00926 
00927 usage:
00928         fprintf(stderr, "Usage: rc [-%s%s%s] filename\n",
00929                 lppflags, lpmnflags, lprtflags);
00930         exit(1);
00931 }
00932 
00933 
00934 /*
00935  *  Convert a ___.r filename into a ___.x filename
00936  */
00937 char *outfilename(str, x)
00938 char *str;
00939 char x;
00940 {
00941 register char *p, *q;
00942 char * result;
00943 
00944     result = (char *)malloc(strlen(str) + 4);
00945     p = str; q = result;
00946     while( *p )
00947         *q++ = *p++;
00948     q--;
00949     if( (q[-1] == '.') && (q[0] == 'r') ) {
00950         *q++ = x;
00951         *q++ = 0;
00952     } else {
00953         sprintf(result, "a.%c", x);
00954     }
00955     return(result);
00956 }
00957 
00958 
00959 /*
00960  *  Given a file name, return the corresponding name for the global
00961  * activation record pointer.
00962  */
00963 char * global_ar_name(s)
00964 char *s;
00965 {
00966 register char * result = (char *)malloc(strlen(s) + 20);
00967 register char * buf = (char *)malloc(strlen(s) + 1);
00968 int len = strlen(s);
00969 
00970     strcpy(buf,s);
00971     if (buf[len-1] == 'r' && buf[len-2] == '.') {
00972         buf[len-2] = '\0';
00973     }
00974     sprintf(result, "%s_ar_save_loc", buf);
00975     free(buf);
00976     return(result);
00977 }
00978 
00979 
00980 /*
00981  * printstatus(s)
00982  *
00983  *  Give the reason the child died, if not from natural causes.
00984  */
00985 printstatus(s)
00986 unsigned s;
00987 {   unsigned e = s & 0177;
00988 
00989     if ( mesg[e] != 0 ) {
00990         fprintf(stderr, "Reason: %s", mesg[e]);
00991         if ( s & 0200 )
00992             fprintf(stderr, " -- Core was dumped\n");
00993         else
00994             fprintf(stderr, "\n");
00995     }
00996 }
00997 
00998 
00999 /*
01000  *  rfork()
01001  *
01002  *  fork() and check that it worked. Return fork() code.
01003  */
01004 rfork()
01005 {   register int forkcode;
01006     forkcode = fork();
01007     if (forkcode == -1) {
01008         fprintf(stderr, "Can't fork!!!\n");
01009         exit(1);
01010     }
01011     return(forkcode);
01012 }
01013 
01014 /*
01015  * remove temporary files
01016  */
01017 rmfiles()
01018 {
01019     unlink(rctmp0name);
01020     unlink(rctmp1name);
01021     unlink(rctmp2name);
01022     if (OOflag) {
01023       unlink(rctmp3name);
01024     }
01025     if (Oflag & Gflag) {
01026       unlink(rctmp4name);
01027     }
01028 }
01029 
01030 /*
01031  * handler for interrupt signal
01032  */
01033 intr_handler()
01034 {
01035     rmfiles();
01036     exit(1);
01037 }

Generated on Fri Jan 25 10:39:48 2008 for russell by  doxygen 1.5.4