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