Annotation of 42BSD/ucb/pascal/utilities/pc3.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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