Annotation of 41BSD/cmd/pascal/pc3.c, revision 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.