Annotation of 42BSD/ucb/pascal/utilities/pc3.c, revision 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.