|
|
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.