Annotation of 41BSD/cmd/pascal/pc3.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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