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