# 2.11BSD#431 - /usr/src/ucb/PORT/pascal/utilities/pc3.c

##### Functions

    article           X
    charalloc         X
    checkfile         X
    checknl           X
    checksymbol       X
    classify          X
    enterstring       X
    entersymbol       X
    error             X
    hashstring        X
    main              X
    nextelement       X
    symbolalloc       X

##### Variables

    copyright         X
    errors            X
    program           X

       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:     }

#### Defined functions

article defined in line 860; used 2 times

- in line 513
- in /usr/src/ucb/PORT/pascal/utilities/pc3.h line 132

charalloc defined in line 730; used 2 times

- in line 697
- in /usr/src/ucb/PORT/pascal/utilities/pc3.h line 128

checkfile defined in line 125; used 1 times

- in line 117

checknl defined in line 179; used 2 times

- in line 157, 170

checksymbol defined in line 266; used 1 times

- in line 247

classify defined in line 826; used 4 times

- in line 282, 324, 509
- in /usr/src/ucb/PORT/pascal/utilities/pc3.h line 131

enterstring defined in line 655; used 2 times

- in line 539
- in /usr/src/ucb/PORT/pascal/utilities/pc3.h line 127

entersymbol defined in line 527; used 2 times

- in line 288
- in /usr/src/ucb/PORT/pascal/utilities/pc3.h line 124

error defined in line 796; used 26 times

- in line 106, 137, 143-147(2), 161, 194, 205-210(2), 216, 223, 229-234(2), 298, 321, 332, 353, 361, 378, 384, 441, 480, 505, 556, 620, 682, 748

hashstring defined in line 633; used 1 times

- in line 666

main defined in line 96; never used
nextelement defined in line 762; used 2 times

- in line 156
- in /usr/src/ucb/PORT/pascal/utilities/pc3.h line 129

symbolalloc defined in line 605; used 2 times

- in line 571
- in /usr/src/ucb/PORT/pascal/utilities/pc3.h line 125

#### Defined variables

copyright defined in line 8; never used
errors defined in line 90; used 4 times

- in line 119, 800(3)

program defined in line 78; used 1 times

- in line 804

sccsid defined in line 14; never used

Last modified: 1985-06-06 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 3336 |