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