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

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

unix.superglobalmegacorp.com

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