Annotation of 41BSD/cmd/as/asmain.c, revision 1.1.1.1

1.1       root        1: /* Copyright (c) 1980 Regents of the University of California */
                      2: static char sccsid[] = "@(#)asmain.c 4.8 8/20/80";
                      3: #include <stdio.h>
                      4: #include <ctype.h>
                      5: #include <signal.h>
                      6: 
                      7: #include "as.h"
                      8: #include "assyms.h"
                      9: #include "asexpr.h"
                     10: #include "asscan.h"
                     11: 
                     12: #ifdef UNIX
                     13: #define        unix_lang_name "VAX/UNIX Assembler V8/20/80 4.8"
                     14: #endif
                     15: 
                     16: #ifdef VMS
                     17: #define vms_lang_name "VAX/VMS C Assembler V1.00"
                     18: #endif VMS
                     19: 
                     20: /*
                     21:  *     variables to manage reading the assembly source files
                     22:  */
                     23: char   *dotsname;      /*the current file name; managed by the parser*/
                     24: int    lineno;         /*current line number; managed by the parser*/
                     25: char   **innames;      /*names of the files being assembled*/
                     26: int    ninfiles;       /*how many interesting files there are*/
                     27: /*
                     28:  *     Flags settable from the argv process argument list
                     29:  */
                     30: int    silent = 0;     /*don't complain about any errors*/
                     31: int    savelabels = 0; /*write the labels to the a.out file*/
                     32: int    d124 = 4;       /*default allocate 4 bytes for unknown pointers*/
                     33: int    anyerrs = 0;    /*no errors yet*/
                     34: int    orgwarn = 0;    /*Bad origins*/
                     35: int    passno = 1;     /* current pass*/
                     36: int    jxxxJUMP = 0;   /* in jxxxes that branch too far, use jmp instead of brw */
                     37: int    readonlydata = 0;       /* initialzed data -> text space */
                     38: 
                     39: #ifdef DEBUG
                     40: int    debug = 0;
                     41: int    toktrace = 0;
                     42: #endif
                     43: 
                     44: int    useVM =         /*put the temp file in virtual memory*/
                     45: #ifdef VMS
                     46:        1;              /*VMS has virtual memory (duh)*/
                     47: #endif VMS
                     48: #ifdef UNIX
                     49:        0;
                     50: #endif
                     51: 
                     52: char   *endcore;       /*where to get more symbol space*/
                     53: 
                     54: /*
                     55:  *     Managers of the a.out file.
                     56:  */
                     57: struct exec    hdr;
                     58: #define        MAGIC   0407
                     59: u_long tsize;          /* total text size */
                     60: u_long dsize;          /* total data size */
                     61: u_long datbase;        /* base of the data segment */
                     62: u_long trsize;         /* total text relocation size */
                     63: u_long drsize;         /* total data relocation size */
                     64: 
                     65: /*
                     66:  *     Information about the current segment is accumulated in
                     67:  *     usedot; the most important information stored is the
                     68:  *     accumulated size of each of the text and data segments
                     69:  *
                     70:  *     dotp points to the correct usedot expression for the current segment
                     71:  */
                     72: struct exp     usedot[NLOC+NLOC];      /* info about all segments */
                     73: struct exp     *dotp;                  /* data/text location pointer */
                     74: /*
                     75:  *     The inter pass temporary file is opened and closed by stdio, but
                     76:  *     is written to using direct read/write, as the temporary file
                     77:  *     is composed of buffers exactly BUFSIZ long.
                     78:  */
                     79: FILE   *tmpfil;                        /* interpass communication file */
                     80: /*
                     81:  *     a.out is created during the second pass.
                     82:  *     It is opened by stdio, but is filled with the parallel
                     83:  *     block I/O library
                     84:  */
                     85: char   *outfile = "a.out";
                     86: FILE   *a_out_file;                    
                     87: off_t  a_out_off;                      /* cumulative offsets for segments */
                     88: /*
                     89:  *     The logical files containing the assembled data for each of
                     90:  *     the text and data segments are
                     91:  *     managed by the parallel block I/O library.
                     92:  *     a.out is logically opened in many places at once to
                     93:  *     receive the assembled data from the various segments as
                     94:  *     it all trickles in, but is physically opened only once
                     95:  *     to minimize file overhead.
                     96:  */
                     97: BFILE  *usefile[NLOC+NLOC];            /* text/data files */
                     98: BFILE  *txtfil;                        /* current text/data file */
                     99: /*
                    100:  *     Relocation information is accumulated seperately for each
                    101:  *     segment.  This is required by the old loader (from BTL),
                    102:  *     but not by the new loader (Bill Joy).  
                    103:  *
                    104:  *     However, the size of the relocation information can not be computed
                    105:  *     during or after the 1st pass because the ''absoluteness' of values
                    106:  *     is unknown until all locally declared symbols have been seen.
                    107:  *     Thus, the size of the relocation information is only
                    108:  *     known after the second pass is finished.
                    109:  *     This obviates the use of the block I/O
                    110:  *     library, which requires knowing the exact offsets in a.out.
                    111:  *
                    112:  *     So, we save the relocation information internally (we don't
                    113:  *     go to internal files to minimize overhead).
                    114:  *
                    115:  *     Empirically, we studied 259 files composing the system,
                    116:  *     two compilers and a compiler generator: (all of which have
                    117:  *     fairly large source files)
                    118:  *     
                    119:  *     Number of files = 259
                    120:  *             Number of non zero text reloc files: 233
                    121:  *             Number of non zero data reloc files: 53
                    122:  *     Average text relocation = 889
                    123:  *     Average data relocation = 346
                    124:  *     Number of files > BUFSIZ text relocation = 71
                    125:  *     Number of files > BUFSIZ data relocation = 6
                    126:  *     
                    127:  *     For compiled C code, there is usually one text segment and two
                    128:  *     data segments; we see that allocating our own buffers and
                    129:  *     doing our internal handling of relocation information will,
                    130:  *     on the average, not use more memory than taken up by the buffers
                    131:  *     allocated for doing file I/O in parallel to a number of file.
                    132:  *     
                    133:  *     If we are assembling with the -V option, we
                    134:  *     use the left over token buffers from the 2nd pass,
                    135:  *     otherwise, we create our own.
                    136:  *
                    137:  *     When the 2nd pass is complete, closeoutrel flushes the token
                    138:  *     buffers out to a BFILE.
                    139:  *
                    140:  *     The internals to relbufdesc are known only in assyms.c
                    141:  *
                    142:  *     outrel constructs the relocation information.
                    143:  *     closeoutrel flushes the relocation information to relfil.
                    144:  */
                    145: struct relbufdesc      *rusefile[NLOC+NLOC];   
                    146: struct relbufdesc      *relfil;        /* un concatnated relocation info */
                    147: BFILE  *relocfile;                     /* concatnated relocation info */
                    148: /*
                    149:  *     Once the relocation information has been written,
                    150:  *     we can write out the symbol table using the Block I/O
                    151:  *     mechanisms, as we once again know the offsets into
                    152:  *     the a.out file.
                    153:  *
                    154:  *     We use relfil to output the symbol table information.
                    155:  */
                    156: 
                    157: char   *tmpdirprefix =
                    158: #ifdef UNIX
                    159:                        "/tmp/";
                    160: #else VMS
                    161:                        "/usr/tmp/";
                    162: #endif
                    163: 
                    164: #define                TMP_SUFFIX      "asXXXXXX"
                    165: char           tmpn1[TNAMESIZE];
                    166: 
                    167: int delexit();
                    168: 
                    169: main(argc, argv)
                    170:        int     argc;
                    171:        char    **argv;
                    172: {
                    173: 
                    174:        tmpn1[0] = 0;
                    175:        endcore = (char *)sbrk(0);
                    176: 
                    177:        argprocess(argc, argv);         /* process argument lists */
                    178:        if (anyerrs) exit(1);
                    179: 
                    180:        initialize();
                    181:        zeroorigins();                  /* set origins to zero */
                    182:        zerolocals();                   /* fix local label counters */
                    183: 
                    184:        i_pass1();                      /* open temp files, etc */
                    185:        pass1();                        /* first pass through .s files */
                    186:        testlocals();                   /* check for undefined locals */
                    187:        if (anyerrs) delexit();
                    188: 
                    189:        pass1_5();                      /* resolve jxxx */
                    190:        if (anyerrs) delexit();
                    191: 
                    192:        open_a_out();                   /* open a.out */
                    193:        roundsegments();                /* round segments to FW */
                    194:        build_hdr();                    /* build initial header, and output */
                    195:        
                    196:        i_pass2();                      /* reopen temporary file, etc */
                    197:        pass2();                        /* second pass through the virtual .s */
                    198:        if (anyerrs) delexit();
                    199: 
                    200:        fillsegments();                 /* fill segments with 0 to FW */
                    201:        reloc_syms();                   /* dump relocation and symbol table */
                    202: 
                    203:        delete();                       /* remove tmp file */
                    204:        bflush();                       /* close off block I/O view of a.out */
                    205:        fix_a_out();                    /* add in text and data reloc counts */
                    206: 
                    207:        if (anyerrs == 0 && orgwarn)
                    208:                yyerror("Caution: absolute origins.\n");
                    209:        exit(anyerrs != 0);
                    210: }      /*end of UNIX main*/
                    211: 
                    212: argprocess(argc, argv)
                    213:        int     argc;
                    214:        char    *argv[];
                    215: {
                    216:        register        char    *cp;
                    217: 
                    218:        ninfiles = 0;
                    219:        silent = 0;
                    220: #ifdef DEBUG
                    221:        debug = 0;
                    222: #endif
                    223:        innames = (char **)ClearCalloc(argc+1, sizeof (innames[0]));
                    224:        dotsname = "<argv error>";
                    225:        while (argc > 1) {
                    226:                if (argv[1][0] != '-')
                    227:                        innames[ninfiles++] = argv[1];
                    228:                else {
                    229:                        cp = argv[1] + 1;
                    230:                        /*
                    231:                         *      We can throw away single minus signs, so
                    232:                         *      that make scripts for the PDP 11 assembler work
                    233:                         *      on this assembler too
                    234:                         */
                    235:                        while (*cp){    
                    236:                                switch(*cp++){
                    237:                                 default:
                    238:                                        yyerror("Unknown flag: %c", *--cp);
                    239:                                        cp++;
                    240:                                        break;
                    241:                                 case 'd':
                    242:                                        d124 = *cp++ - '0';
                    243:                                        if ( (d124 != 1) && (d124 != 2) && 
                    244:                                             (d124 != 4)){
                    245:                                                yyerror("-d[124] only");
                    246:                                                exit(1);
                    247:                                        }
                    248:                                        break;
                    249:                                 case 'o':
                    250:                                        if (argc < 3){
                    251:                                                yyerror("-o what???");
                    252:                                                exit(1);
                    253:                                        }
                    254:                                        outfile = argv[2];
                    255:                                   bumpone:
                    256:                                        argc -= 2;
                    257:                                        argv += 2;
                    258:                                        goto nextarg;
                    259: 
                    260:                                 case 't':
                    261:                                        if (argc < 3){
                    262:                                                yyerror("-t what???");
                    263:                                                exit(1);
                    264:                                        }
                    265:                                        tmpdirprefix = argv[2];
                    266:                                        goto bumpone;
                    267:                                 
                    268:                                 case 'V':
                    269:                                        useVM = 1;
                    270:                                        break;
                    271:                                 case 'W':
                    272:                                        silent = 1;
                    273:                                        break;
                    274:                                 case 'L':
                    275:                                        savelabels = 1;
                    276:                                        break;
                    277:                                 case 'J':
                    278:                                        jxxxJUMP = 1;
                    279:                                        break;
                    280: #ifdef DEBUG
                    281:                                 case 'D':
                    282:                                        debug = 1;
                    283:                                        break;
                    284:                                 case 'T':
                    285:                                        toktrace = 1;
                    286:                                        break;
                    287: #endif
                    288:                                 case 'R':
                    289:                                        readonlydata = 1;
                    290:                                        break;
                    291:                                }       /*end of the switch*/
                    292:                        }       /*end of pulling out all arguments*/
                    293:                }       /*end of a flag argument*/
                    294:                --argc; ++argv;
                    295:           nextarg:;
                    296:        }
                    297:        /* innames[ninfiles] = 0; */
                    298: }
                    299: 
                    300: initialize()
                    301: {
                    302:        if (signal(SIGINT, SIG_IGN) != SIG_IGN)
                    303:                signal(SIGINT, delexit);
                    304:        /*
                    305:         *      Install symbols in the table
                    306:         */
                    307:        symtabinit();
                    308:        syminstall();
                    309:        /*
                    310:         *      Build the expression parser accelerator token sets
                    311:         */
                    312:        buildtokensets();               
                    313: }
                    314: 
                    315: zeroorigins()
                    316: {
                    317:        register        int     locindex;
                    318:        /*
                    319:         *      Mark usedot: the first NLOC slots are for named text segments,
                    320:         *      the next for named data segments.
                    321:         */
                    322:        for (locindex = 0; locindex < NLOC; locindex++){
                    323:                usedot[locindex].e_xtype = XTEXT;
                    324:                usedot[NLOC + locindex].e_xtype = XDATA;
                    325:                usedot[locindex].e_xvalue = 0;
                    326:                usedot[NLOC + locindex].e_xvalue = 0;
                    327:                usedot[locindex].e_yvalue = 0;
                    328:                usedot[NLOC + locindex].e_yvalue = 0;
                    329:        }
                    330: }
                    331: 
                    332: zerolocals()
                    333: {
                    334:        register        int     i;
                    335: 
                    336:        for (i = 0; i <= 9; i++) {
                    337:                lgensym[i] = 1;
                    338:                genref[i] = 0;
                    339:        }
                    340: }
                    341: 
                    342: i_pass1()
                    343: {
                    344:        if (useVM == 0){
                    345:                strcat(tmpn1, tmpdirprefix);
                    346:                if (tmpdirprefix[strlen(tmpdirprefix)-1] != '/')
                    347:                        strcat(tmpn1, "/");
                    348:                strcat(tmpn1, TMP_SUFFIX);
                    349:                mktemp(tmpn1);
                    350:                tmpfil = fopen(tmpn1, "w");
                    351:                if (tmpfil==NULL) {
                    352:                  yyerror("Bad pass 1 temporary file for writing %s", tmpn1);
                    353:                  delexit();
                    354:                }
                    355:        }
                    356: 
                    357:        inittmpfile();
                    358:        initijxxx();
                    359: }
                    360: 
                    361: pass1()
                    362: {
                    363:        register        int     i;
                    364: 
                    365:        passno = 1;
                    366:        dotp = &usedot[0];
                    367:        txtfil = (BFILE *)0;
                    368:        relfil = (struct relbufdesc *)0;
                    369: 
                    370:        if (ninfiles == 0){             /*take the input from stdin directly*/
                    371:                lineno = 1;
                    372:                dotsname = "<stdin>";
                    373: 
                    374:                yyparse();
                    375:        } else {                /*we have the names tanked*/
                    376:                for (i = 0; i < ninfiles; i++){
                    377:                        new_dot_s(innames[i]);
                    378:                        if (freopen(innames[i], "r", stdin) == NULL) {
                    379:                                yyerror( "Can't open source file %s\n",
                    380:                                        innames[i]);
                    381:                                exit(2);
                    382:                        }
                    383:                        /* stdio is NOT used to read the input characters */
                    384:                        /* we use read directly, into our own buffers */
                    385:                        yyparse();
                    386:                }
                    387:        }
                    388: 
                    389:        closetmpfile();         /*kick out the last buffered intermediate text*/
                    390: }
                    391: 
                    392: testlocals()
                    393: {
                    394:        register        int     i;
                    395:        for (i = 0; i <= 9; i++) {
                    396:                if (genref[i])
                    397:                        yyerror("Reference to undefined local label %df", i);
                    398:                lgensym[i] = 1;
                    399:                genref[i] = 0;
                    400:        }
                    401: }
                    402: 
                    403: pass1_5()
                    404: {
                    405:        sortsymtab();
                    406: #ifdef DEBUG
                    407:        if (debug) dumpsymtab();
                    408: #endif
                    409:        jxxxfix();
                    410: #ifdef DEBUG
                    411:        if (debug) dumpsymtab();
                    412: #endif
                    413: }
                    414: 
                    415: open_a_out()
                    416: {
                    417:        /*
                    418:         *      Open up the a.out file now, and get set to build
                    419:         *      up offsets into it for all of the various text,data
                    420:         *      text relocation and data relocation segments.
                    421:         */
                    422:        a_out_file = fopen(outfile, "w");
                    423:        if (a_out_file == NULL) {
                    424:                yyerror("Cannot create %s", outfile);
                    425:                delexit();
                    426:        }
                    427:        biofd = a_out_file->_file;
                    428:        a_out_off = 0;
                    429: }
                    430: 
                    431: roundsegments()
                    432: {
                    433:        register        int     locindex;
                    434:        register        long    v;
                    435:        /*
                    436:         *      round and assign text segment origins
                    437:         *      the exec header always goes in usefile[0]
                    438:         */
                    439:        tsize = 0;
                    440:        for (locindex=0; locindex<NLOC; locindex++) {
                    441:                v = round(usedot[locindex].e_xvalue, FW);
                    442:                usedot[locindex].e_xvalue = tsize;
                    443:                if ((locindex == 0) || (v != 0) ){
                    444:                        usefile[locindex] = (BFILE *)Calloc(1, sizeof(BFILE));
                    445:                        bopen(usefile[locindex], a_out_off);
                    446:                        if (locindex == 0)
                    447:                                a_out_off = sizeof (struct exec);
                    448:                } else {
                    449:                        usefile[locindex] = (BFILE *)-1;
                    450:                }
                    451:                tsize += v;
                    452:                a_out_off += v;
                    453:        }
                    454:        /*
                    455:         *              Round and assign data segment origins.
                    456:         */
                    457:        datbase = round(tsize, FW);
                    458:        for (locindex=0; locindex<NLOC; locindex++) {
                    459:                v = round(usedot[NLOC+locindex].e_xvalue, FW);
                    460:                usedot[NLOC+locindex].e_xvalue = datbase + dsize;
                    461:                if (v != 0){
                    462:                        usefile[NLOC + locindex] = (BFILE *)Calloc(1,sizeof(BFILE));
                    463:                        bopen(usefile[NLOC + locindex], a_out_off);
                    464:                } else {
                    465:                        usefile[NLOC + locindex] = (BFILE *)-1;
                    466:                }
                    467:                dsize += v;
                    468:                a_out_off += v;
                    469:        }
                    470:        /*
                    471:         *      Assign final values to symbols
                    472:         */
                    473:        hdr.a_bss = dsize;
                    474:        freezesymtab();         /* this touches hdr.a_bss */
                    475:        stabfix();
                    476:        /*
                    477:         *      Set up the relocation information "files" to
                    478:         *      be zero; outrel takes care of the rest
                    479:         */
                    480:        for (locindex = 0; locindex < NLOC + NLOC; locindex++){
                    481:                rusefile[locindex] = (struct relbufdesc *)0;
                    482:        }
                    483: }
                    484: 
                    485: build_hdr()
                    486: {
                    487:        /*
                    488:         *      Except for the text and data relocation sizes,
                    489:         *      calculate the final values for the header
                    490:         *      
                    491:         *      Write out the initial copy; we to come 
                    492:         *      back later and patch up a_trsize and a_drsize,
                    493:         *      and overwrite this first version of the header.
                    494:         */
                    495:        hdr.a_magic = MAGIC;
                    496:        hdr.a_text = tsize;
                    497:        hdr.a_data = dsize;
                    498:        hdr.a_bss -= dsize;
                    499:        hdr.a_syms = sizesymtab();      /* Does not include string pool length */
                    500:        hdr.a_entry = 0;
                    501:        hdr.a_trsize = 0;
                    502:        hdr.a_drsize = 0;
                    503: 
                    504:        bwrite((char *)&hdr, sizeof(hdr), usefile[0]);
                    505: }
                    506: 
                    507: i_pass2()
                    508: {
                    509:        if (useVM == 0) {
                    510:                fclose(tmpfil);
                    511:                tmpfil = fopen(tmpn1, "r");
                    512:                if (tmpfil==NULL) {
                    513:                   yyerror("Bad pass 2 temporary file for reading %s", tmpn1);
                    514:                   delexit();
                    515:                }
                    516:        }
                    517: }
                    518: 
                    519: pass2()
                    520: {
                    521: #ifdef DEBUG
                    522:        if (debug)
                    523:                printf("\n\n\n\t\tPASS 2\n\n\n\n");
                    524: #endif DEBUG
                    525:        passno = 2;
                    526:        lineno = 1;
                    527:        dotp = &usedot[0];
                    528:        txtfil = usefile[0];    /* already opened (always!) */
                    529:        relfil = 0;             /* outrel takes care of the rest */
                    530:        initoutrel();
                    531: 
                    532:        inittmpfile();
                    533: 
                    534:        yyparse();
                    535: 
                    536:        closetmpfile();
                    537: }
                    538: 
                    539: fillsegments()
                    540: {
                    541:        int     locindex;
                    542:        /*
                    543:         *      Round text and data segments to FW by appending zeros
                    544:         */
                    545:        for (locindex = 0; locindex < NLOC + NLOC; locindex++) {
                    546:                if (usefile[locindex]) {
                    547:                        txtfil = usefile[locindex];
                    548:                        dotp = &usedot[locindex];
                    549:                        while (usedot[locindex].e_xvalue & FW)
                    550:                                outb(0);
                    551:                }
                    552:        }
                    553: }
                    554: 
                    555: reloc_syms()
                    556: {
                    557:        u_long  closerelfil();
                    558:        /*
                    559:         *      Move the relocation information to a.out
                    560:         *      a_out_off is the offset so far:
                    561:         *      exec + text segments + data segments
                    562:         */
                    563:        relocfile = (BFILE *)Calloc(1,sizeof(BFILE));
                    564:        bopen(relocfile, a_out_off);
                    565:        a_out_off += closeoutrel(relocfile);
                    566: 
                    567:        hdr.a_trsize = trsize;
                    568:        hdr.a_drsize = drsize;
                    569:        if (readonlydata) {
                    570:                hdr.a_text += hdr.a_data;
                    571:                hdr.a_data = 0;
                    572:                hdr.a_trsize += hdr.a_drsize;
                    573:                hdr.a_drsize = 0;
                    574:        }
                    575:        /*
                    576:         *      Output the symbol table
                    577:         *      and if FLEXNAMES is set, the string pool
                    578:         */
                    579:        symwrite(relocfile);
                    580: }
                    581: 
                    582: fix_a_out()
                    583: {
                    584:        if (lseek(a_out_file->_file, 0L, 0) < 0)
                    585:                yyerror("Reposition for header rewrite fails");
                    586:        if (write(a_out_file->_file, (char *)&hdr, sizeof (struct exec)) < 0)
                    587:                yyerror("Rewrite of header fails");
                    588: }
                    589: 
                    590: delexit()
                    591: {
                    592:        delete();
                    593:        if (passno == 2){
                    594:                unlink(outfile);
                    595:        }
                    596:        exit(1);
                    597: }
                    598: 
                    599: delete()
                    600: {
                    601:        if (useVM == 0 || tmpn1[0])
                    602:                unlink(tmpn1);
                    603: }
                    604: 
                    605: sawabort()
                    606: {
                    607:        char    *fillinbuffer();
                    608:        while (fillinbuffer() != (char *)0)
                    609:                continue;
                    610:        delete();
                    611:        exit(1);        /*although the previous pass will also exit non zero*/
                    612: }
                    613: 
                    614: panic(fmt, a1, a2, a3, a4)
                    615:        char    *fmt;
                    616:        /*VARARGS 1*/
                    617: {
                    618:        yyerror("Assembler panic: bad internal data structure.");
                    619:        yyerror(fmt, a1, a2, a3, a4);
                    620:        delete();
                    621:        abort();
                    622: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.