Annotation of 43BSDTahoe/ucb/pascal/utilities/pc3.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1980 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  */
                      6: 
                      7: #ifndef lint
                      8: char copyright[] =
                      9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\
                     10:  All rights reserved.\n";
                     11: #endif not lint
                     12: 
                     13: #ifndef lint
                     14: static char sccsid[] = "@(#)pc3.c      5.1 (Berkeley) 6/5/85";
                     15: #endif not lint
                     16: 
                     17:     /*
                     18:      *      Pc3 is a pass in the Berkeley Pascal compilation
                     19:      * process that is performed just prior to linking Pascal
                     20:      * object files.  Its purpose is to enforce the rules of
                     21:      * separate compilation for Berkeley Pascal.  Pc3 is called
                     22:      * with the same argument list of object files that is sent to
                     23:      * the loader.  These checks are performed by pc3 by examining
                     24:      * the symbol tables of the object files:
                     25:      * (1)  All .o files must be up to date with respect to the
                     26:      *      runtime libraries.
                     27:      * (2)  Each global Pascal symbol (label, constant, type,
                     28:      *      variable, procedure, or function name) must be uniquely
                     29:      *      declared, i.e. declared in only one included file or
                     30:      *      source file.
                     31:      * (3)  Each external function (or procedure) may be resolved
                     32:      *      at most once in a source file which included the
                     33:      *      external declaration of the function.
                     34:      * 
                     35:      *      The symbol table of each object file is scanned and
                     36:      * each global Pascal symbol is placed in a hashed symbol
                     37:      * table.  The Pascal compiler has been modified to emit all
                     38:      * Pascal global symbols to the object file symbol table.  The
                     39:      * information stored in the symbol table for each such symbol
                     40:      * is:
                     41:      * 
                     42:      *    - the name of the symbol;
                     43:      *    - a subtype descriptor;
                     44:      *    - the file which logically contains the declaration of
                     45:      *      the symbol or which caused the inclusion of an include file.
                     46:      *    - for included files:
                     47:      *         - a checksum;
                     48:      *    - for symbols:
                     49:      *         - the file which textually contains the declaration of
                     50:      *           the symbol (possibly an include file);
                     51:      *         - the line number at which the symbol is declared;
                     52:      *         - the file which contains the resolution of the symbol.
                     53:      *         - the line number at which the symbol is resolved;
                     54:      * 
                     55:      *      If a symbol has been previously entered into the symbol
                     56:      * table, a check is made that the current declaration is of
                     57:      * the same type and from the same include file as the previous
                     58:      * one.  Except for files and functions and procedures, it is
                     59:      * an error for a symbol declaration to be encountered more
                     60:      * than once, unless the re-declarations come from the same
                     61:      * included file as the original.
                     62:      * 
                     63:      *      As an include file symbol is encountered in a source
                     64:      * file, the symbol table entry of each symbol declared in that
                     65:      * include file is modified to reflect its new logical
                     66:      * inclusion in the source file.  File symbols are also
                     67:      * encountered as an included file ends, signaling the
                     68:      * continuation of the enclosing file.
                     69:      * 
                     70:      *      Functions and procedures which have been declared
                     71:      * external may be resolved by declarations from source files
                     72:      * which included the external declaration of the function.
                     73:      * Functions and procedures may be resolved at most once across
                     74:      * a set of object files.  The loader will complain if a
                     75:      * function is not resolved at least once.
                     76:      */
                     77: 
                     78: char   program[] = "pc";
                     79: 
                     80: #include <sys/types.h>
                     81: #include <sys/stat.h>
                     82: #include <ar.h>
                     83: #include <stdio.h>
                     84: #include <ctype.h>
                     85: #include <a.out.h>
                     86: #include <stab.h>
                     87: #include "pstab.h"
                     88: #include "pc3.h"
                     89: 
                     90: int    errors = NONE;
                     91: BOOL   wflag = FALSE;  
                     92: 
                     93:     /*
                     94:      * check each of the argument .o files (or archives of .o files).
                     95:      */
                     96: main( argc , argv )
                     97:     int                argc;
                     98:     char       **argv;
                     99:     {
                    100:        struct fileinfo ofile;
                    101: 
                    102:        for ( argv++ ; *argv != 0 && **argv == '-' ; argv++ ) {
                    103:            (*argv)++;
                    104:            switch ( **argv ) {
                    105:                default:
                    106:                    error( FATAL , "pc3: bad flag -%c\n" , **argv );
                    107:                case 'w':
                    108:                    wflag = TRUE;
                    109:                    break;
                    110:            }
                    111:        }
                    112:        for ( /* void */ ; *argv != 0 ; argv++ ) {
                    113: #          ifdef DEBUG
                    114:                fprintf( stderr , "[main] *argv = %s\n" , *argv );
                    115: #          endif DEBUG
                    116:            ofile.name = *argv;
                    117:            checkfile( &ofile );
                    118:        }
                    119:        exit( errors );
                    120:     }
                    121: 
                    122:     /*
                    123:      * check the namelist of a file, or all namelists of an archive.
                    124:      */
                    125: checkfile( ofilep )
                    126:     struct fileinfo    *ofilep;
                    127:     {
                    128:        union {
                    129:            char        mag_armag[ SARMAG + 1 ];
                    130:            struct exec mag_exec;
                    131:        }               mag_un;
                    132:        int             red;
                    133:        struct stat     filestat;
                    134: 
                    135:        ofilep -> file = fopen( ofilep -> name , "r" );
                    136:        if ( ofilep -> file == NULL ) {
                    137:            error( ERROR , "cannot open: %s" , ofilep -> name );
                    138:            return;
                    139:        }
                    140:        fstat( fileno( ofilep -> file ) , &filestat );
                    141:        red = fread( (char *) &mag_un , 1 , sizeof mag_un , ofilep -> file );
                    142:        if ( red != sizeof mag_un ) {
                    143:            error( ERROR , "cannot read header: %s" , ofilep -> name );
                    144:            return;
                    145:        }
                    146:        if ( mag_un.mag_exec.a_magic == OARMAG ) {
                    147:            error( WARNING , "old archive: %s" , ofilep -> name );
                    148:            return;
                    149:        }
                    150:        if ( strncmp( mag_un.mag_armag , ARMAG , SARMAG ) == 0 ) {
                    151:                /* archive, iterate through elements */
                    152: #          ifdef DEBUG
                    153:                fprintf( stderr , "[checkfile] archive %s\n" , ofilep -> name );
                    154: #          endif DEBUG
                    155:            ofilep -> nextoffset = SARMAG;
                    156:            while ( nextelement( ofilep ) ) {
                    157:                checknl( ofilep );
                    158:            }
                    159:        } else if ( N_BADMAG( mag_un.mag_exec ) ) {
                    160:                /* not a file.o */
                    161:            error( ERROR , "bad format: %s" , ofilep -> name );
                    162:            return;
                    163:        } else {
                    164:                /* a file.o */
                    165: #          ifdef DEBUG
                    166:                fprintf( stderr , "[checkfile] .o file %s\n" , ofilep -> name );
                    167: #          endif DEBUG
                    168:            fseek( ofilep -> file , 0L , 0 );
                    169:            ofilep -> nextoffset = filestat.st_size;
                    170:            checknl( ofilep );
                    171:        }
                    172:        fclose( ofilep -> file );
                    173:     }
                    174: 
                    175:     /*
                    176:      * check the namelist of this file for conflicts with
                    177:      * previously entered symbols.
                    178:      */
                    179: checknl( ofilep )
                    180:     register struct fileinfo   *ofilep;
                    181:     {
                    182:     
                    183:        long                    red;
                    184:        struct exec             oexec;
                    185:        off_t                   symoff;
                    186:        long                    numsyms;
                    187:        register struct nlist   *nlp;
                    188:        register char           *stringp;
                    189:        long                    strsize;
                    190:        long                    sym;
                    191: 
                    192:        red = fread( (char *) &oexec , 1 , sizeof oexec , ofilep -> file );
                    193:        if ( red != sizeof oexec ) {
                    194:            error( ERROR , "error reading struct exec: %s"
                    195:                    , ofilep -> name );
                    196:            return;
                    197:        }
                    198:        if ( N_BADMAG( oexec ) ) {
                    199:            return;
                    200:        }
                    201:        symoff = N_SYMOFF( oexec ) - sizeof oexec;
                    202:        fseek( ofilep -> file , symoff , 1 );
                    203:        numsyms = oexec.a_syms / sizeof ( struct nlist );
                    204:        if ( numsyms == 0 ) {
                    205:            error( WARNING , "no name list: %s" , ofilep -> name );
                    206:            return;
                    207:        }
                    208:        nlp = (struct nlist *) calloc( numsyms , sizeof ( struct nlist ) );
                    209:        if ( nlp == 0 ) {
                    210:            error( FATAL , "no room for %d nlists" , numsyms );
                    211:        }
                    212:        red = fread( ( char * ) nlp , numsyms , sizeof ( struct nlist )
                    213:                    , ofilep -> file );
                    214:        if (   ftell( ofilep -> file ) + sizeof ( off_t )
                    215:            >= ofilep -> nextoffset ) {
                    216:            error( WARNING , "no string table (old format .o?)"
                    217:                    , ofilep -> name );
                    218:            return;
                    219:        }
                    220:        red = fread( (char *) &strsize , sizeof strsize , 1
                    221:                    , ofilep -> file );
                    222:        if ( red != 1 ) {
                    223:            error( WARNING , "no string table (old format .o?)"
                    224:                    , ofilep -> name );
                    225:            return;
                    226:        }
                    227:        stringp  = ( char * ) malloc( strsize );
                    228:        if ( stringp == 0 ) {
                    229:            error( FATAL , "no room for %d bytes of strings" , strsize );
                    230:        }
                    231:        red = fread( stringp + sizeof strsize
                    232:                    , strsize - sizeof ( strsize ) , 1 , ofilep -> file );
                    233:        if ( red != 1 ) {
                    234:            error( WARNING , "error reading string table: %s"
                    235:                    , ofilep -> name );
                    236:        }
                    237: #      ifdef DEBUG
                    238:            fprintf( stderr , "[checknl] %s: %d symbols\n"
                    239:                    , ofilep -> name , numsyms );
                    240: #      endif DEBUG
                    241:        for ( sym = 0 ; sym < numsyms ; sym++) {
                    242:            if ( nlp[ sym ].n_un.n_strx ) {
                    243:                nlp[ sym ].n_un.n_name = stringp + nlp[ sym ].n_un.n_strx;
                    244:            } else {
                    245:                nlp[ sym ].n_un.n_name = "";
                    246:            }
                    247:            checksymbol( &nlp[ sym ] , ofilep );
                    248:        }
                    249:        if ( nlp ) {
                    250:            free( nlp );
                    251:        }
                    252:        if ( stringp ) {
                    253:            free( stringp );
                    254:        }
                    255:     }
                    256: 
                    257:     /*
                    258:      * check a symbol.
                    259:      * look it up in the hashed symbol table,
                    260:      * entering it if necessary.
                    261:      * this maintains a state of which .p and .i files
                    262:      * it is currently in the midst from the nlist entries
                    263:      * for source and included files.
                    264:      * if we are inside a .p but not a .i, pfilep == ifilep.
                    265:      */
                    266: checksymbol( nlp , ofilep )
                    267:     struct nlist       *nlp;
                    268:     struct fileinfo    *ofilep;
                    269:     {
                    270:        static struct symbol    *pfilep = NIL;
                    271:        static struct symbol    *ifilep = NIL;
                    272:        register struct symbol  *symbolp;
                    273:        int                     errtype;
                    274: 
                    275: #      ifdef DEBUG
                    276:            if ( pfilep && ifilep ) {
                    277:                fprintf( stderr , "[checksymbol] pfile %s ifile %s\n"
                    278:                        , pfilep -> name , ifilep -> name );
                    279:            }
                    280:            fprintf( stderr , "[checksymbol] ->name %s ->n_desc %x (%s)\n"
                    281:                    , nlp -> n_un.n_name , nlp -> n_desc
                    282:                    , classify( nlp -> n_desc ) );
                    283: #      endif DEBUG
                    284:        if ( nlp -> n_type != N_PC ) {
                    285:                /* don't care about the others */
                    286:            return;
                    287:        }
                    288:        symbolp = entersymbol( nlp -> n_un.n_name );
                    289:        if ( symbolp -> lookup == NEW ) {
                    290: #          ifdef DEBUG
                    291:                fprintf( stderr , "[checksymbol] ->name %s is NEW\n"
                    292:                        , symbolp -> name );
                    293: #          endif DEBUG
                    294:            symbolp -> desc = nlp -> n_desc;
                    295:            symbolp -> fromp = pfilep;
                    296:            switch ( symbolp -> desc ) {
                    297:                default:
                    298:                        error( FATAL , "panic: [checksymbol] NEW" );
                    299:                case N_PGLABEL:
                    300:                case N_PGCONST:
                    301:                case N_PGTYPE:
                    302:                case N_PGVAR:
                    303:                case N_PGFUNC:
                    304:                case N_PGPROC:
                    305:                case N_PLDATA:
                    306:                case N_PLTEXT:
                    307:                        symbolp -> sym_un.sym_str.rfilep = ifilep;
                    308:                        symbolp -> sym_un.sym_str.rline = nlp -> n_value;
                    309:                        symbolp -> sym_un.sym_str.fromi = ifilep;
                    310:                        symbolp -> sym_un.sym_str.iline = nlp -> n_value;
                    311:                        return;
                    312:                case N_PEFUNC:
                    313:                case N_PEPROC:
                    314:                        symbolp -> sym_un.sym_str.rfilep = NIL;
                    315:                        symbolp -> sym_un.sym_str.rline = 0;
                    316:                            /*
                    317:                             *  functions can only be declared external
                    318:                             *  in included files.
                    319:                             */
                    320:                        if ( pfilep == ifilep ) {
                    321:                            error( WARNING
                    322:                                    , "%s, line %d: %s %s must be declared in included file"
                    323:                                    , pfilep -> name , nlp -> n_value
                    324:                                    , classify( symbolp -> desc )
                    325:                                    , symbolp -> name );
                    326:                        }
                    327:                        symbolp -> sym_un.sym_str.fromi = ifilep;
                    328:                        symbolp -> sym_un.sym_str.iline = nlp -> n_value;
                    329:                        return;
                    330:                case N_PSO:
                    331:                        if ( nlp -> n_value < N_FLAGCHECKSUM ) {
                    332:                            error( WARNING,
                    333:                                "%s is out of date and should be recompiled",
                    334:                                ofilep -> name );
                    335:                        }
                    336:                        pfilep = symbolp;
                    337:                        ifilep = symbolp;
                    338:                        symbolp -> sym_un.checksum = N_FLAGCHECKSUM;
                    339:                        return;
                    340:                case N_PSOL:
                    341:                        ifilep = symbolp;
                    342:                        symbolp -> sym_un.checksum = nlp -> n_value;
                    343:                        return;
                    344:            }
                    345:        } else {
                    346: #          ifdef DEBUG
                    347:                fprintf( stderr , "[checksymbol] ->name %s is OLD\n"
                    348:                        , symbolp -> name );
                    349: #          endif DEBUG
                    350:            errtype = ERROR;
                    351:            switch ( symbolp -> desc ) {
                    352:                default:
                    353:                        error( FATAL , "panic [checksymbol] OLD" );
                    354:                        return;
                    355:                case N_PSO:
                    356:                            /*
                    357:                             *  finding a file again means you are back
                    358:                             *  in it after finishing an include file.
                    359:                             */
                    360:                        if ( symbolp -> desc != nlp -> n_desc ) {
                    361:                            error( FATAL , "panic [checksymbol] PSO" );
                    362:                            return;
                    363:                        }
                    364:                        pfilep = symbolp;
                    365:                        ifilep = symbolp;
                    366:                        return;
                    367:                case N_PSOL:
                    368:                            /*
                    369:                             *  include files can be seen more than once,
                    370:                             *  but their checksums are checked if they are
                    371:                             *  greater than N_FLAGCHECKSUM.
                    372:                             *  PSOL's are seen with checksums as the
                    373:                             *  include file is entered, and with
                    374:                             *  N_FLAGCHECKSUM as we are back in an
                    375:                             *  included file from a nested include.
                    376:                             */
                    377:                        if ( symbolp -> desc != nlp -> n_desc ) {
                    378:                            error( FATAL , "panic [checksymbol] PSOL" );
                    379:                            return;
                    380:                        }
                    381:                        if ((unsigned) symbolp->sym_un.checksum > N_FLAGCHECKSUM
                    382:                           && (unsigned) nlp -> n_value > N_FLAGCHECKSUM
                    383:                           && symbolp -> sym_un.checksum != nlp -> n_value ) {
                    384:                            error( ERROR,
                    385:                            "%s included in %s differs from %s included in %s",
                    386:                                symbolp -> name, pfilep -> name,
                    387:                                symbolp -> name, symbolp -> fromp -> name );
                    388:                        }
                    389:                        ifilep = symbolp;
                    390:                        return;
                    391:                case N_PEFUNC:
                    392:                case N_PEPROC:
                    393:                            /*
                    394:                             *  this might be the resolution of the external
                    395:                             *  has to match func/proc of external
                    396:                             *  and has to have included external
                    397:                             *  and has to not have been previously resolved.
                    398:                             */
                    399:                        if (  (  ( symbolp -> desc == N_PEFUNC
                    400:                                 && nlp -> n_desc == N_PGFUNC )
                    401:                              || ( symbolp -> desc == N_PEPROC
                    402:                                 && nlp -> n_desc == N_PGPROC ) )
                    403:                           && ( symbolp -> fromp == pfilep )
                    404:                           && ( symbolp -> sym_un.sym_str.rfilep == NIL ) ) {
                    405:                                /*
                    406:                                 *      resolve external
                    407:                                 */
                    408: #                          ifdef DEBUG
                    409:                                fprintf( stderr , "[checksymbol] resolving external\n" );
                    410: #                          endif DEBUG
                    411:                            symbolp -> sym_un.sym_str.rfilep = ifilep;
                    412:                            symbolp -> sym_un.sym_str.rline = nlp -> n_value;
                    413:                            return;
                    414:                        }
                    415:                            /*
                    416:                             *  otherwise, it might be another external,
                    417:                             *  which is okay if it's
                    418:                             *  the same type and from the same include file
                    419:                             */
                    420:                        if (  (  ( symbolp -> desc == N_PEFUNC
                    421:                                 && nlp -> n_desc == N_PEFUNC )
                    422:                              || ( symbolp -> desc == N_PEPROC
                    423:                                 && nlp -> n_desc == N_PEPROC ) )
                    424:                           && ( symbolp -> sym_un.sym_str.fromi == ifilep ) ) {
                    425:                                /*
                    426:                                 *      just another pretty external
                    427:                                 *      make it look like it comes from here.
                    428:                                 */
                    429: #                          ifdef DEBUG
                    430:                                fprintf( stderr , "[checksymbol] just another pretty external\n" );
                    431: #                          endif DEBUG
                    432:                            symbolp -> fromp = pfilep;
                    433:                            return;
                    434:                        }
                    435:                            /*
                    436:                             *  something is wrong
                    437:                             *  if it's not resolved, use the header file
                    438:                             *  otherwise, it's just a regular error
                    439:                             */
                    440:                        if ( symbolp -> sym_un.sym_str.rfilep == NIL ) {
                    441:                            error( ERROR ,
                    442:                    "%s, line %d: %s is already defined\n\t(%s, line %d)." ,
                    443:                                ifilep -> name , nlp -> n_value , 
                    444:                                nlp -> n_un.n_name , 
                    445:                                symbolp -> sym_un.sym_str.fromi -> name ,
                    446:                                symbolp -> sym_un.sym_str.iline );
                    447:                            return;
                    448:                        }
                    449:                        break;
                    450:                case N_PGFUNC:
                    451:                case N_PGPROC:
                    452:                            /*
                    453:                             *  functions may not be seen more than once.
                    454:                             *  the loader will complain about
                    455:                             *  `multiply defined', but we can, too.
                    456:                             */
                    457:                        break;
                    458:                case N_PGLABEL:
                    459:                case N_PGCONST:
                    460:                case N_PGTYPE:
                    461:                case N_PGVAR:
                    462:                            /*
                    463:                             *  labels, constants, types, variables
                    464:                             *  and external declarations
                    465:                             *  may be seen as many times as they want,
                    466:                             *  as long as they come from the same include file.
                    467:                             *  make it look like they come from this .p file.
                    468:                             */
                    469: included:
                    470:                        if (  nlp -> n_desc != symbolp -> desc
                    471:                           || symbolp -> sym_un.sym_str.fromi != ifilep ) {
                    472:                            break;
                    473:                        }
                    474:                        symbolp -> fromp = pfilep;
                    475:                        return;
                    476:                case N_PLDATA:
                    477:                case N_PLTEXT:
                    478:                        switch ( nlp -> n_desc ) {
                    479:                            default:
                    480:                                error( FATAL , "pc3: unknown stab 0x%x"
                    481:                                        , nlp -> n_desc );
                    482:                                return;
                    483:                            case N_PSO:
                    484:                            case N_PSOL:
                    485:                            case N_PGCONST:
                    486:                            case N_PGTYPE:
                    487:                                /* these won't conflict with library */
                    488:                                return;
                    489:                            case N_PGLABEL:
                    490:                            case N_PGVAR:
                    491:                            case N_PGFUNC:
                    492:                            case N_PGPROC:
                    493:                            case N_PEFUNC:
                    494:                            case N_PEPROC:
                    495:                            case N_PLDATA:
                    496:                            case N_PLTEXT:
                    497:                                errtype = WARNING;
                    498:                                break;
                    499:                        }
                    500:                        break;
                    501:            }
                    502:                /*
                    503:                 *      this is the breaks
                    504:                 */
                    505:            error( errtype
                    506:                , "%s, line %d: %s %s is already defined\n\t%s%s (%s, line %d)."
                    507:                , ifilep -> name
                    508:                , nlp -> n_value
                    509:                , classify( nlp -> n_desc )
                    510:                , nlp -> n_un.n_name
                    511:                , ( symbolp -> desc == nlp -> n_desc ? "" : " as " )
                    512:                , ( symbolp -> desc == nlp -> n_desc
                    513:                        ? "" : article( symbolp -> desc ) )
                    514:                , symbolp -> sym_un.sym_str.rfilep -> name
                    515:                , symbolp -> sym_un.sym_str.rline );
                    516:        }
                    517:     }
                    518: 
                    519:     /*
                    520:      * quadratically hashed symbol table.
                    521:      * things are never deleted from the hash symbol table.
                    522:      * as more hash table is needed,
                    523:      * a new one is alloc'ed and chained to the end.
                    524:      * search is by rehashing within each table,
                    525:      * traversing chains to next table if unsuccessful.
                    526:      */
                    527: struct symbol *
                    528: entersymbol( name )
                    529:     char       *name;
                    530:     {
                    531:        static struct symboltableinfo   symboltable;
                    532:        char                            *enteredname;
                    533:        long                            hashindex;
                    534:        register struct symboltableinfo *tablep;
                    535:        register struct symbol          **herep;
                    536:        register struct symbol          **limitp;
                    537:        register long                   increment;
                    538: 
                    539:        enteredname = enterstring( name );
                    540:        hashindex = SHORT_ABS( ( long ) enteredname ) % SYMBOLPRIME;
                    541:        for ( tablep = &symboltable ; /*return*/ ; tablep = tablep -> chain ) {
                    542:            if ( tablep == NIL ) {
                    543: #              ifdef SPACEDEBUG
                    544:                    fprintf( stderr ,
                    545:                            "[entersymbol] calloc'ing table for %d symbols\n" , 
                    546:                            SYMBOLPRIME );
                    547: #              endif SPACEDEBUG
                    548:                for ( tablep = &symboltable
                    549:                    ; tablep->chain != NIL
                    550:                    ; tablep = tablep->chain ) {
                    551:                        continue;
                    552:                }
                    553:                tablep->chain = ( struct symboltableinfo * )
                    554:                            calloc( 1 , sizeof ( struct symboltableinfo ) );
                    555:                if ( tablep->chain == NIL ) {
                    556:                    error( FATAL , "ran out of memory (entersymbol)" );
                    557:                }
                    558:                tablep = tablep->chain;
                    559:            }
                    560:            herep = &( tablep -> entry[ hashindex ] );
                    561:            limitp = &( tablep -> entry[ SYMBOLPRIME ] );
                    562:            increment = 1;
                    563:            do {
                    564:                if ( *herep == NIL ) {
                    565:                        /* empty */
                    566:                    if ( tablep -> used > ( ( SYMBOLPRIME / 4 ) * 3 ) ) {
                    567:                            /* too full, break for next table */
                    568:                        break;
                    569:                    }
                    570:                    tablep -> used++;
                    571:                    *herep = symbolalloc();
                    572:                    ( *herep ) -> name = enteredname;
                    573:                    ( *herep ) -> lookup = NEW;
                    574: #                  ifdef HASHDEBUG
                    575:                        fprintf( stderr ,
                    576:                                "[entersymbol] name %s NEW after %d\n" ,
                    577:                                enteredname , increment / 2 );
                    578: #                  endif HASHDEBUG
                    579:                    return *herep;
                    580:                }
                    581:                    /* a find? */
                    582:                if ( ( *herep ) -> name == enteredname ) {
                    583:                    ( *herep ) -> lookup = OLD;
                    584: #                  ifdef HASHDEBUG
                    585:                        fprintf( stderr , "[entersymbol] name %s OLD at %d\n" ,
                    586:                                enteredname , increment / 2 );
                    587: #                  endif HASHDEBUG
                    588:                    return *herep;
                    589:                }
                    590:                herep += increment;
                    591:                if ( herep >= limitp ) {
                    592:                    herep -= SYMBOLPRIME;
                    593:                }
                    594:                increment += 2;
                    595:            } while ( increment < SYMBOLPRIME );
                    596: #          ifdef HASHDEBUG
                    597:                fprintf( stderr , "[entersymbol] next symboltable\n" );
                    598: #          endif HASHDEBUG
                    599:        }
                    600:     }
                    601: 
                    602:     /*
                    603:      * allocate a symbol from the dynamically allocated symbol table.
                    604:      */
                    605: struct symbol *
                    606: symbolalloc()
                    607:     {
                    608:        static struct symbol    *nextsymbol = NIL;
                    609:        static long             symbolsleft = 0;
                    610:        struct symbol           *newsymbol;
                    611: 
                    612:        if ( symbolsleft <= 0 ) {
                    613: #          ifdef SPACEDEBUG
                    614:                fprintf( stderr ,
                    615:                        "[symbolalloc] malloc space for %d symbols\n" ,
                    616:                        SYMBOLALLOC / sizeof( struct symbol ) );
                    617: #          endif SPACEDEBUG
                    618:            nextsymbol = ( struct symbol * ) malloc( SYMBOLALLOC );
                    619:            if ( nextsymbol == 0 ) {
                    620:                error( FATAL , "ran out of memory (symbolalloc)" );
                    621:            }
                    622:            symbolsleft = SYMBOLALLOC / sizeof( struct symbol );
                    623:        }
                    624:        newsymbol = nextsymbol;
                    625:        nextsymbol++;
                    626:        symbolsleft--;
                    627:        return newsymbol;
                    628:     }
                    629: 
                    630:     /*
                    631:      * hash a string based on all of its characters.
                    632:      */
                    633: long
                    634: hashstring( string )
                    635:     char       *string;
                    636:     {
                    637:        register char   *cp;
                    638:        register long   value;
                    639: 
                    640:        value = 0;
                    641:        for ( cp = string ; *cp ; cp++ ) {
                    642:            value = ( value * 2 ) + *cp;
                    643:        }
                    644:        return value;
                    645:     }
                    646: 
                    647:     /*
                    648:      * quadratically hashed string table.
                    649:      * things are never deleted from the hash string table.
                    650:      * as more hash table is needed,
                    651:      * a new one is alloc'ed and chained to the end.
                    652:      * search is by rehashing within each table,
                    653:      * traversing chains to next table if unsuccessful.
                    654:      */
                    655: char *
                    656: enterstring( string )
                    657:     char       *string;
                    658:     {
                    659:        static struct stringtableinfo   stringtable;
                    660:        long                            hashindex;
                    661:        register struct stringtableinfo *tablep;
                    662:        register char                   **herep;
                    663:        register char                   **limitp;
                    664:        register long                   increment;
                    665: 
                    666:        hashindex = SHORT_ABS( hashstring( string ) ) % STRINGPRIME;
                    667:        for ( tablep = &stringtable ; /*return*/ ; tablep = tablep -> chain ) {
                    668:            if ( tablep == NIL ) {
                    669: #              ifdef SPACEDEBUG
                    670:                    fprintf( stderr ,
                    671:                            "[enterstring] calloc space for %d strings\n" ,
                    672:                            STRINGPRIME );
                    673: #              endif SPACEDEBUG
                    674:                for ( tablep = &stringtable
                    675:                    ; tablep->chain != NIL
                    676:                    ; tablep = tablep->chain ) {
                    677:                        continue;
                    678:                }
                    679:                tablep->chain = ( struct stringtableinfo * )
                    680:                            calloc( 1 , sizeof ( struct stringtableinfo ) );
                    681:                if ( tablep->chain == NIL ) {
                    682:                    error( FATAL , "ran out of memory (enterstring)" );
                    683:                }
                    684:                tablep = tablep->chain;
                    685:            }
                    686:            herep = &( tablep -> entry[ hashindex ] );
                    687:            limitp = &( tablep -> entry[ STRINGPRIME ] );
                    688:            increment = 1;
                    689:            do {
                    690:                if ( *herep == NIL ) {
                    691:                        /* empty */
                    692:                    if ( tablep -> used > ( ( STRINGPRIME / 4 ) * 3 ) ) {
                    693:                            /* too full, break for next table */
                    694:                        break;
                    695:                    }
                    696:                    tablep -> used++;
                    697:                    *herep = charalloc( strlen( string ) );
                    698:                    strcpy( *herep , string );
                    699: #                  ifdef HASHDEBUG
                    700:                        fprintf( stderr ,
                    701:                                "[enterstring] string %s copied after %d\n" , 
                    702:                                *herep , increment / 2 );
                    703: #                  endif HASHDEBUG
                    704:                    return *herep;
                    705:                }
                    706:                    /* quick, check the first chars and then the rest */
                    707:                if ( **herep == *string && strcmp( *herep , string ) == 0 ) {
                    708: #                  ifdef HASHDEBUG
                    709:                        fprintf( stderr ,
                    710:                                "[enterstring] string %s found after %d\n" ,
                    711:                                *herep , increment / 2 );
                    712: #                  endif HASHDEBUG
                    713:                    return *herep;
                    714:                }
                    715:                herep += increment;
                    716:                if ( herep >= limitp ) {
                    717:                    herep -= STRINGPRIME;
                    718:                }
                    719:                increment += 2;
                    720:            } while ( increment < STRINGPRIME );
                    721: #          ifdef HASHDEBUG
                    722:                fprintf( stderr , "[enterstring] next stringtable\n" );
                    723: #          endif HASHDEBUG
                    724:        }
                    725:     }
                    726: 
                    727:     /*
                    728:      * copy a string to the dynamically allocated character table.
                    729:      */
                    730: char *
                    731: charalloc( length )
                    732:     register long      length;
                    733:     {
                    734:        static char     *nextchar = NIL;
                    735:        static long     charsleft = 0;
                    736:        register long   lengthplus1 = length + 1;
                    737:        register long   askfor;
                    738:        char            *newstring;
                    739: 
                    740:        if ( charsleft < lengthplus1 ) {
                    741:            askfor = lengthplus1 > CHARALLOC ? lengthplus1 : CHARALLOC;
                    742: #          ifdef SPACEDEBUG
                    743:                fprintf( stderr , "[charalloc] malloc space for %d chars\n" 
                    744:                        , askfor );
                    745: #          endif SPACEDEBUG
                    746:            nextchar = ( char * ) malloc( askfor );
                    747:            if ( nextchar == 0 ) {
                    748:                error( FATAL , "no room for %d characters" , askfor );
                    749:            }
                    750:            charsleft = askfor;
                    751:        }
                    752:        newstring = nextchar;
                    753:        nextchar += lengthplus1;
                    754:        charsleft -= lengthplus1;
                    755:        return newstring;
                    756:     }
                    757: 
                    758:     /*
                    759:      * read an archive header for the next element
                    760:      * and find the offset of the one after this. 
                    761:      */
                    762: BOOL
                    763: nextelement( ofilep )
                    764:     struct fileinfo    *ofilep;
                    765:     {
                    766:        register char   *cp;
                    767:        register long   red;
                    768:        register off_t  arsize;
                    769:        struct ar_hdr   archdr;
                    770: 
                    771:        fseek( ofilep -> file , ofilep -> nextoffset , 0 );
                    772:        red = fread( (char *) &archdr , 1 , sizeof archdr , ofilep -> file );
                    773:        if ( red != sizeof archdr ) {
                    774:            return FALSE;
                    775:        }
                    776:            /* null terminate the blank-padded name */
                    777:        cp = &archdr.ar_name[ ( sizeof archdr.ar_name ) - 1 ];
                    778:        *cp = '\0';
                    779:        while ( *--cp == ' ' ) {
                    780:            *cp = '\0';
                    781:        }
                    782:            /* set up the address of the beginning of next element */
                    783:        arsize = atol( archdr.ar_size );
                    784:            /* archive elements are aligned on 0 mod 2 boundaries */
                    785:        if ( arsize & 1 ) {
                    786:            arsize += 1;
                    787:        }
                    788:        ofilep -> nextoffset = ftell( ofilep -> file ) + arsize;
                    789:            /* say we had one */
                    790:        return TRUE;
                    791:     }
                    792: 
                    793:     /*
                    794:      * variable number of arguments to error, like printf.
                    795:      */
                    796: error( type , message , arg1 , arg2 , arg3 , arg4 , arg5 , arg6 , arg7 , arg8 )
                    797:     int                type;
                    798:     char       *message;
                    799:     {
                    800:        errors = type > errors ? type : errors;
                    801:        if ( wflag && type == WARNING ) {
                    802:            return;
                    803:        }
                    804:        fprintf( stderr , "%s: " , program );
                    805:        switch ( type ) {
                    806:            case WARNING:
                    807:                    fprintf( stderr , "Warning: " );
                    808:                    break;
                    809:            case ERROR:
                    810:                    fprintf( stderr , "Error: " );
                    811:                    break;
                    812:            case FATAL:
                    813:                    fprintf( stderr , "Fatal: " );
                    814:                    break;
                    815:            default:
                    816:                    fprintf( stderr , "Ooops: " );
                    817:                    break;
                    818:        }
                    819:        fprintf( stderr , message , arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8 );
                    820:        fprintf( stderr , "\n" );
                    821:        if ( type == FATAL ) {
                    822:            exit( FATAL );
                    823:        }
                    824:     }
                    825: 
                    826: char *
                    827: classify( type )
                    828:     unsigned char      type;
                    829:     {
                    830:        switch ( type ) {
                    831:            case N_PSO:
                    832:                return "source file";
                    833:            case N_PSOL:
                    834:                return "include file";
                    835:            case N_PGLABEL:
                    836:                return "label";
                    837:            case N_PGCONST:
                    838:                return "constant";
                    839:            case N_PGTYPE:
                    840:                return "type";
                    841:            case N_PGVAR:
                    842:                return "variable";
                    843:            case N_PGFUNC:
                    844:                return "function";
                    845:            case N_PGPROC:
                    846:                return "procedure";
                    847:            case N_PEFUNC:
                    848:                return "external function";
                    849:            case N_PEPROC:
                    850:                return "external procedure";
                    851:            case N_PLDATA:
                    852:                return "library variable";
                    853:            case N_PLTEXT:
                    854:                return "library routine";
                    855:            default:
                    856:                return "unknown symbol";
                    857:        }
                    858:     }
                    859: 
                    860: char *
                    861: article( type )
                    862:     unsigned char      type;
                    863:     {
                    864:        switch ( type ) {
                    865:            case N_PSO:
                    866:                return "a source file";
                    867:            case N_PSOL:
                    868:                return "an include file";
                    869:            case N_PGLABEL:
                    870:                return "a label";
                    871:            case N_PGCONST:
                    872:                return "a constant";
                    873:            case N_PGTYPE:
                    874:                return "a type";
                    875:            case N_PGVAR:
                    876:                return "a variable";
                    877:            case N_PGFUNC:
                    878:                return "a function";
                    879:            case N_PGPROC:
                    880:                return "a procedure";
                    881:            case N_PEFUNC:
                    882:                return "an external function";
                    883:            case N_PEPROC:
                    884:                return "an external procedure";
                    885:            case N_PLDATA:
                    886:                return "a library variable";
                    887:            case N_PLTEXT:
                    888:                return "a library routine";
                    889:            default:
                    890:                return "an unknown symbol";
                    891:        }
                    892:     }

unix.superglobalmegacorp.com

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