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