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
charalloc defined in line 730; used 2 times
checkfile defined in line 125; used 1 times
checknl defined in line 179; used 2 times
checksymbol defined in line 266; used 1 times
classify defined in line 826; used 4 times
enterstring defined in line 655; used 2 times
entersymbol defined in line 527; used 2 times
error defined in line 796; used 26 times
hashstring defined in line 633; used 1 times
main defined in line 96; never used
nextelement defined in line 762; used 2 times
symbolalloc defined in line 605; used 2 times

Defined variables

copyright defined in line 8; never used
errors defined in line 90; used 4 times
program defined in line 78; used 1 times
sccsid defined in line 14; never used
Last modified: 1985-06-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2469
Valid CSS Valid XHTML 1.0 Strict