|
|
1.1 root 1: # include "manifest"
2: # include "lint.h"
3:
4: # define USED 01
5: # define VUSED 02
6: # define EUSED 04
7: # define RVAL 010
8: # define VARARGS 0100
9:
10: # define NSZ 2048
11: # define TYSZ 3500
12: # define FSZ 250
13: # define NTY 50
14:
15: typedef struct sty STYPE;
16: struct sty { ATYPE t; STYPE *next; };
17:
18: typedef struct sym {
19: #ifndef FLEXNAMES
20: char name[LCHNM];
21: #else
22: char *name;
23: #endif
24: short nargs;
25: int decflag;
26: int fline;
27: STYPE symty;
28: int fno;
29: int use;
30: } STAB;
31:
32: STAB stab[NSZ];
33: STAB *find();
34:
35: STYPE tary[TYSZ];
36: STYPE *tget();
37:
38: #ifndef FLEXNAMES
39: char fnm[FSZ][LFNM];
40: #else
41: char *fnm[FSZ];
42: #endif
43:
44: #ifdef FLEXNAMES
45: char *getstr();
46: #endif
47:
48: int tfree; /* used to allocate types */
49: int ffree; /* used to save filenames */
50:
51: struct ty atyp[NTY];
52: /* r is where all the input ends up */
53: union rec r;
54:
55: int hflag = 0;
56: int pflag = 0;
57: int xflag = 0;
58: int uflag = 1;
59: int ddddd = 0;
60:
61: int cfno; /* current file number */
62:
63: #ifdef FMTARGS
64: FILE *stmpfile; /* string tmp file pointer */
65: char *stmpname; /* string tmp file name */
66: #endif
67:
68:
69: main( argc, argv ) char *argv[]; {
70: register char *p;
71:
72: /* first argument is intermediate file */
73: /* second argument is - options */
74:
75: #ifdef FMTARGS
76: fmtinit();
77: #endif
78: for( ; argc>2 && argv[argc-1][0] == '-' ; --argc ){
79: for( p=argv[argc-1]; *p; ++p ){
80: switch( *p ){
81:
82: case 'h':
83: hflag = 1;
84: break;
85:
86: case 'p':
87: pflag = 1;
88: break;
89:
90: case 'x':
91: xflag = 1;
92: break;
93:
94: case 'X':
95: ddddd = 1;
96: break;
97:
98: case 'u':
99: uflag = 0;
100: break;
101:
102: #ifdef FMTARGS
103: case 'S':
104: for (stmpname = p + 1; p[1]; p++);
105: if (!(stmpfile = fopen (stmpname, "r"))) {
106: error ("%s: can't open", stmpname);
107: exit (1);
108: }
109: break;
110: #endif
111: }
112: }
113: }
114:
115: if( argc < 2 || !freopen( argv[1], "r", stdin ) ){
116: error( "cannot open intermediate file" );
117: exit( 1 );
118: }
119:
120: mloop( LDI|LIB );
121: rewind( stdin );
122: mloop( LDC|LDX );
123: rewind( stdin );
124: mloop( LRV|LUV|LUE|LUM );
125: cleanup();
126: return(0);
127: }
128:
129: mloop( m ){
130: /* do the main loop */
131: register STAB *q;
132:
133: while( lread(m) ){
134: q = find();
135: if( q->decflag ) chkcompat(q);
136: else setuse(q);
137: }
138: }
139:
140: lread(m){ /* read a line into r.l */
141:
142: register n;
143:
144: for(;;) {
145: if( fread( (char *)&r, sizeof(r), 1, stdin ) <= 0 ) return(0);
146: if( r.l.decflag & LFN ){
147: /* new filename */
148: #ifdef FLEXNAMES
149: r.f.fn = getstr();
150: #endif
151: setfno( r.f.fn );
152: continue;
153: }
154: #ifdef FLEXNAMES
155: r.l.name = getstr();
156: #endif
157:
158: n = r.l.nargs;
159: if( n<0 ) n = -n;
160: if( n ){
161: if( n>=NTY ) error( "more than %d args?", n );
162: fread( (char *)atyp, sizeof(ATYPE), n, stdin );
163: }
164: if( ( r.l.decflag & m ) ) return( 1 );
165: }
166: }
167:
168: setfno( s ) char *s; {
169: /* look up current file names */
170: /* first, strip backwards to the beginning or to the first / */
171: int i;
172:
173: /* now look up s */
174: for( i=0; i<ffree; ++i ){
175: #ifndef FLEXNAMES
176: if( !strncmp( s, fnm[i], LFNM ) ){
177: #else
178: if (fnm[i] == s){
179: #endif
180: cfno = i;
181: return;
182: }
183: }
184: /* make a new entry */
185: if( ffree >= FSZ ) error( "more than %d files", FSZ );
186: #ifndef FLEXNAMES
187: strncpy( fnm[ffree], s, LFNM );
188: #else
189: fnm[ffree] = s;
190: #endif
191: cfno = ffree++;
192: }
193:
194: /* VARARGS */
195: error( s, a ) char *s; {
196:
197: #ifndef FLEXNAMES
198: fprintf( stderr, "pass 2 error:(file %.*s) ", LFNM, fnm[cfno] );
199: #else
200: fprintf( stderr, "pass 2 error:(file %s) ", fnm[cfno] );
201: #endif
202: fprintf( stderr, s, a );
203: fprintf( stderr, "\n" );
204: exit(1);
205: }
206:
207: STAB *
208: find(){
209: /* for this to work, NSZ should be a power of 2 */
210: register h=0;
211: #ifndef FLEXNAMES
212: { register char *p, *q;
213: for( h=0,p=r.l.name,q=p+LCHNM; *p&&p<q; ++p) {
214: h = (h<<1)+ *p;
215: if( h>=NSZ ){
216: h = (h+1)&(NSZ-1);
217: }
218: }
219: }
220: #else
221: h = ((int)r.l.name)%NSZ;
222: #endif
223: { register STAB *p, *q;
224: for( p=q= &stab[h]; q->decflag; ){
225: /* this call to strncmp should be taken out... */
226: #ifndef FLEXNAMES
227: if( !strncmp( r.l.name, q->name, LCHNM)) return(q);
228: #else
229: if (r.l.name == q->name) return (q);
230: #endif
231: if( ++q >= &stab[NSZ] ) q = stab;
232: if( q == p ) error( "too many names defined" );
233: }
234: #ifndef FLEXNAMES
235: strncpy( q->name, r.l.name, LCHNM );
236: #else
237: q->name = r.l.name;
238: #endif
239: return( q );
240: }
241: }
242:
243: STYPE *
244: tget(){
245: if( tfree >= TYSZ ){
246: error( "too many types needed" );
247: }
248: return( &tary[tfree++] );
249: }
250:
251: chkcompat(q) STAB *q; {
252: /* are the types, etc. in r.l and q compatible */
253: register int i;
254: STYPE *qq;
255:
256: setuse(q);
257:
258: /* argument check */
259:
260: if( q->decflag & (LDI|LIB|LUV|LUE) ){
261: if( r.l.decflag & (LUV|LIB|LUE) ){
262: #ifdef FMTARGS
263: if (q->decflag & (LPF|LSF)) {
264: fmtcheck (q);
265: if(r.l.nargs > q->nargs)
266: r.l.nargs = q->nargs;
267: q->use |= VARARGS;
268: }
269: #endif
270: if( q->nargs != r.l.nargs ){
271: if( !(q->use&VARARGS) ){
272: #ifndef FLEXNAMES
273: printf( "%.8s: variable # of args.", q->name );
274: #else
275: printf( "%s: variable # of args.", q->name );
276: #endif
277: viceversa(q);
278: }
279: if( r.l.nargs > q->nargs ) r.l.nargs = q->nargs;
280: if( !(q->decflag & (LDI|LIB) ) ) {
281: q->nargs = r.l.nargs;
282: q->use |= VARARGS;
283: }
284: }
285: for( i=0,qq=q->symty.next; i<r.l.nargs; ++i,qq=qq->next){
286: if( chktype( &qq->t, &atyp[i] ) ){
287: #ifndef FLEXNAMES
288: printf( "%.8s, arg. %d used inconsistently",
289: #else
290: printf( "%s, arg. %d used inconsistently",
291: #endif
292: q->name, i+1 );
293: viceversa(q);
294: }
295: }
296: }
297: }
298:
299: if( (q->decflag&(LDI|LIB|LUV)) && r.l.decflag==LUV ){
300: if( chktype( &r.l.type, &q->symty.t ) ){
301: #ifndef FLEXNAMES
302: printf( "%.8s value used inconsistently", q->name );
303: #else
304: printf( "%s value used inconsistently", q->name );
305: #endif
306: viceversa(q);
307: }
308: }
309:
310: /* check for multiple declaration */
311:
312: if( (q->decflag&LDI) && (r.l.decflag&(LDI|LIB)) ){
313: #ifndef FLEXNAMES
314: printf( "%.8s multiply declared", q->name );
315: #else
316: printf( "%s multiply declared", q->name );
317: #endif
318: viceversa(q);
319: }
320:
321: /* do a bit of checking of definitions and uses... */
322:
323: if( (q->decflag & (LDI|LIB|LDX|LDC|LUM)) && (r.l.decflag & (LDX|LDC|LUM)) && q->symty.t.aty != r.l.type.aty ){
324: #ifndef FLEXNAMES
325: printf( "%.8s value declared inconsistently", q->name );
326: #else
327: printf( "%s value declared inconsistently", q->name );
328: #endif
329: viceversa(q);
330: }
331:
332: /* better not call functions which are declared to be structure or union returning */
333:
334: if( (q->decflag & (LDI|LIB|LDX|LDC)) && (r.l.decflag & LUE) && q->symty.t.aty != r.l.type.aty ){
335: /* only matters if the function returns union or structure */
336: TWORD ty;
337: ty = q->symty.t.aty;
338: if( ISFTN(ty) && ((ty = DECREF(ty))==STRTY || ty==UNIONTY ) ){
339: #ifndef FLEXNAMES
340: printf( "%.8s function value type must be declared before use", q->name );
341: #else
342: printf( "%s function value type must be declared before use", q->name );
343: #endif
344: viceversa(q);
345: }
346: }
347:
348: if( pflag && q->decflag==LDX && r.l.decflag == LUM && !ISFTN(q->symty.t.aty) ){
349: /* make the external declaration go away */
350: /* in effect, it was used without being defined */
351: }
352: }
353:
354: viceversa(q) STAB *q; {
355: /* print out file comparison */
356: #ifndef FLEXNAMES
357: printf( " %.*s(%d) :: %.*s(%d)\n",
358: LFNM, fnm[q->fno], q->fline,
359: LFNM, fnm[cfno], r.l.fline );
360: #else
361: printf( " %s(%d) :: %s(%d)\n",
362: fnm[q->fno], q->fline,
363: fnm[cfno], r.l.fline );
364: #endif
365: }
366:
367: /* messages for defintion/use */
368: char *
369: mess[2][2] ={
370: "",
371: #ifndef FLEXNAMES
372: "%.8s used( %.*s(%d) ), but not defined\n",
373: "%.8s defined( %.*s(%d) ), but never used\n",
374: "%.8s declared( %.*s(%d) ), but never used or defined\n"
375: #else
376: "%s used( %s(%d) ), but not defined\n",
377: "%s defined( %s(%d) ), but never used\n",
378: "%s declared( %s(%d) ), but never used or defined\n"
379: #endif
380: };
381:
382: lastone(q) STAB *q; {
383:
384: register nu, nd, uses;
385:
386: if( ddddd ) pst(q);
387:
388: nu = nd = 0;
389: uses = q->use;
390:
391: #ifdef FMTARGS
392: /* not needed anymore, right? */
393: q->decflag &= ~(LPF|LSF);
394: #endif
395:
396: if( !(uses&USED) && q->decflag != LIB ) {
397: #ifndef FLEXNAMES
398: if( strncmp(q->name,"main",7) )
399: #else
400: if (strcmp(q->name, "main"))
401: #endif
402: nu = 1;
403: }
404:
405: if( !ISFTN(q->symty.t.aty) ){
406: switch( q->decflag ){
407:
408: case LIB:
409: nu = nd = 0; /* don't complain about uses on libraries */
410: break;
411: case LDX:
412: if( !xflag ) break;
413: case LUV:
414: case LUE:
415: /* 01/04/80 */ case LUV | LUE:
416: case LUM:
417: nd = 1;
418: }
419: }
420: if( uflag && ( nu || nd ) ) printf( mess[nu][nd],
421: #ifndef FLEXNAMES
422: q->name, LFNM, fnm[q->fno], q->fline );
423: #else
424: q->name, fnm[q->fno], q->fline );
425: #endif
426:
427: if( (uses&(RVAL+EUSED)) == (RVAL+EUSED) ){
428: #ifndef FLEXNAMES
429: printf( "%.8s returns value which is %s ignored\n", q->name,
430: #else
431: printf( "%s returns value which is %s ignored\n", q->name,
432: #endif
433: uses&VUSED ? "sometimes" : "always" );
434: }
435:
436: if( (uses&(RVAL+VUSED)) == (VUSED) && (q->decflag&(LDI|LIB)) ){
437: #ifndef FLEXNAMES
438: printf( "%.8s value is used, but none returned\n", q->name );
439: #else
440: printf( "%s value is used, but none returned\n", q->name );
441: #endif
442: }
443: }
444:
445: cleanup(){ /* call lastone and die gracefully */
446: STAB *q;
447: for( q=stab; q< &stab[NSZ]; ++q ){
448: if( q->decflag ) lastone(q);
449: }
450: exit(0);
451: }
452:
453: setuse(q) STAB *q; { /* check new type to ensure that it is used */
454:
455: if( !q->decflag ){ /* new one */
456: q->decflag = r.l.decflag;
457: q->symty.t = r.l.type;
458: if( r.l.nargs < 0 ){
459: q->nargs = -r.l.nargs;
460: q->use = VARARGS;
461: }
462: else {
463: q->nargs = r.l.nargs;
464: q->use = 0;
465: }
466: q->fline = r.l.fline;
467: q->fno = cfno;
468: if( q->nargs ){
469: int i;
470: STYPE *qq;
471: for( i=0,qq= &q->symty; i<q->nargs; ++i,qq=qq->next ){
472: qq->next = tget();
473: qq->next->t = atyp[i];
474: }
475: }
476: }
477:
478: switch( r.l.decflag ){
479:
480: case LRV:
481: q->use |= RVAL;
482: return;
483: case LUV:
484: q->use |= VUSED+USED;
485: return;
486: case LUE:
487: q->use |= EUSED+USED;
488: return;
489: /* 01/04/80 */ case LUV | LUE:
490: case LUM:
491: q->use |= USED;
492: return;
493:
494: }
495: }
496:
497: chktype( pt1, pt2 ) register ATYPE *pt1, *pt2; {
498: TWORD t;
499:
500: /* check the two type words to see if they are compatible */
501: /* for the moment, enums are turned into ints, and should be checked as such */
502: if( pt1->aty == ENUMTY ) pt1->aty = INT;
503: if( pt2->aty == ENUMTY ) pt2->aty = INT;
504:
505: if( (t=BTYPE(pt1->aty)==STRTY) || t==UNIONTY ){
506: return( pt1->aty!=pt2->aty || (
507: pt1->extra!=pt2->extra ) );
508: }
509:
510: if( pt2->extra ){ /* constant passed in */
511: if( pt1->aty == UNSIGNED && pt2->aty == INT ) return( 0 );
512: else if( pt1->aty == ULONG && pt2->aty == LONG ) return( 0 );
513: }
514: else if( pt1->extra ){ /* for symmetry */
515: if( pt2->aty == UNSIGNED && pt1->aty == INT ) return( 0 );
516: else if( pt2->aty == ULONG && pt1->aty == LONG ) return( 0 );
517: }
518:
519: return( pt1->aty != pt2->aty );
520: }
521:
522: struct tb { int m; char * nm };
523: ptb( v, tp ) struct tb *tp; {
524: /* print a value from the table */
525: int flag;
526: flag = 0;
527: for( ; tp->m; ++tp ){
528: if( v&tp->m ){
529: if( flag++ ) putchar( '|' );
530: printf( "%s", tp->nm );
531: }
532: }
533: }
534:
535: pst( q ) STAB *q; {
536: /* give a debugging output for q */
537: static struct tb dfs[] = {
538: LDI, "LDI",
539: LIB, "LIB",
540: LDC, "LDC",
541: LDX, "LDX",
542: LRV, "LRV",
543: LUV, "LUV",
544: LUE, "LUE",
545: LUM, "LUM",
546: #ifdef FMTARGS
547: LPF, "printf-like",
548: LSF, "scanf-like",
549: #endif
550: 0, "" };
551:
552: static struct tb us[] = {
553: USED, "USED",
554: VUSED, "VUSED",
555: EUSED, "EUSED",
556: RVAL, "RVAL",
557: VARARGS, "VARARGS",
558: 0, 0,
559: };
560:
561: #ifndef FLEXNAMES
562: printf( "%.8s (", q->name );
563: #else
564: printf( "%s (", q->name );
565: #endif
566: ptb( q->decflag, dfs );
567: printf( "), use= " );
568: ptb( q->use, us );
569: printf( ", line %d, nargs=%d\n", q->fline, q->nargs );
570: }
571:
572: #ifdef FLEXNAMES
573:
574: pty( t, name ) TWORD t; {
575: static char * tnames[] = {
576: "void", "farg", "char", "short",
577: "int", "long", "float", "double",
578: "struct xxx", "union %s", "enum", "moety",
579: "unsigned char", "unsigned short", "unsigned", "unsigned long",
580: "?", "?"
581: };
582:
583: printf( "%s ", tnames[BTYPE(t)] );
584: pty1( t, name, (8 * sizeof (int) - BTSHIFT) / TSHIFT );
585: }
586:
587: pty1( t, name, level ) TWORD t; {
588: register TWORD u;
589:
590: if( level < 0 ){
591: printf( "%s", name );
592: return;
593: }
594: u = t >> level * TSHIFT;
595: if( ISPTR(u) ){
596: printf( "*" );
597: pty1( t, name, level-1 );
598: }
599: else if( ISFTN(u) ){
600: if( level > 0 && ISPTR(u << TSHIFT) ){
601: printf( "(" );
602: pty1( t, name, level-1 );
603: printf( ")()" );
604: }
605: else {
606: pty1( t, name, level-1 );
607: printf( "()" );
608: }
609: }
610: else if( ISARY(u) ){
611: if( level > 0 && ISPTR(u << TSHIFT) ){
612: printf( "(" );
613: pty1( t, name, level-1 );
614: printf( ")[]" );
615: }
616: else {
617: pty1( t, name, level-1 );
618: printf( "[]" );
619: }
620: }
621: else {
622: pty1( t, name, level-1 );
623: }
624: }
625:
626: char *
627: getstr()
628: {
629: char buf[BUFSIZ];
630: register char *cp = buf;
631: register int c;
632:
633: if (feof(stdin) || ferror(stdin))
634: return("");
635: while ((c = getchar()) > 0)
636: *cp++ = c;
637: if (c < 0) {
638: fprintf(stderr, "pass 2 error: intermediate file format error (getstr)");
639: exit(1);
640: }
641: *cp++ = 0;
642: return (hash(buf));
643: }
644:
645: #define NSAVETAB 4096
646: char *savetab;
647: int saveleft;
648:
649: char *
650: savestr(cp)
651: register char *cp;
652: {
653: register int len;
654:
655: len = strlen(cp) + 1;
656: if (len > saveleft) {
657: saveleft = NSAVETAB;
658: if (len > saveleft)
659: saveleft = len;
660: savetab = (char *)malloc(saveleft);
661: if (savetab == 0) {
662: fprintf(stderr, "pass 2 error: ran out of memory (savestr)");
663: exit(1);
664: }
665: }
666: strncpy(savetab, cp, len);
667: cp = savetab;
668: savetab += len;
669: saveleft -= len;
670: return (cp);
671: }
672:
673: /*
674: * The definition for the segmented hash tables.
675: */
676: #define MAXHASH 20
677: #define HASHINC 1013
678: struct ht {
679: char **ht_low;
680: char **ht_high;
681: int ht_used;
682: } htab[MAXHASH];
683:
684: char *
685: hash(s)
686: char *s;
687: {
688: register char **h;
689: register i;
690: register char *cp;
691: struct ht *htp;
692: int sh;
693:
694: /*
695: * The hash function is a modular hash of
696: * the sum of the characters with the sum
697: * doubled before each successive character
698: * is added.
699: */
700: cp = s;
701: i = 0;
702: while (*cp)
703: i = i*2 + *cp++;
704: sh = (i&077777) % HASHINC;
705: cp = s;
706: /*
707: * There are as many as MAXHASH active
708: * hash tables at any given point in time.
709: * The search starts with the first table
710: * and continues through the active tables
711: * as necessary.
712: */
713: for (htp = htab; htp < &htab[MAXHASH]; htp++) {
714: if (htp->ht_low == 0) {
715: register char **hp =
716: (char **) calloc(sizeof (char **), HASHINC);
717: if (hp == 0) {
718: fprintf(stderr, "pass 2 error: ran out of memory (hash)");
719: exit(1);
720: }
721: htp->ht_low = hp;
722: htp->ht_high = htp->ht_low + HASHINC;
723: }
724: h = htp->ht_low + sh;
725: /*
726: * quadratic rehash increment
727: * starts at 1 and incremented
728: * by two each rehash.
729: */
730: i = 1;
731: do {
732: if (*h == 0) {
733: if (htp->ht_used > (HASHINC * 3)/4)
734: break;
735: htp->ht_used++;
736: *h = savestr(cp);
737: return (*h);
738: }
739: if (**h == *cp && strcmp(*h, cp) == 0)
740: return (*h);
741: h += i;
742: i += 2;
743: if (h >= htp->ht_high)
744: h -= HASHINC;
745: } while (i < HASHINC);
746: }
747: fprintf(stderr, "pass 2 error: ran out of hash tables");
748: exit(1);
749: }
750: char *tstrbuf[1];
751: #endif
752:
753:
754: # ifdef FMTARGS
755:
756: #define FMTSIZE 256
757:
758: char *getfmt();
759:
760: static char pftab[256], /* printf */
761: pfltab[128], /* printf %l? */
762: sftab[256], /* scanf */
763: sfhtab[128], /* scanf %h? */
764: sfltab[128]; /* scanf %l? */
765:
766: typedef struct {
767: char *fm_s; /* format characters of interest */
768: char fm_ty; /* expected arg type for fm_c */
769: char fm_lty; /* expected type if preceded by `l' */
770: char fm_hty; /* expected type if preceded by `h' */
771: } Fmtinit;
772:
773:
774: static Fmtinit pinit[] = {
775: { "dox", INT, LONG },
776: { "efgEG", DOUBLE },
777: { "c", INT },
778: { "s", CHAR+PTR },
779: #ifdef USGFMT
780: { "uX", INT, LONG },
781: #else
782: { "DOX", LONG },
783: { "u", UNSIGNED, ULONG },
784: #endif
785: { 0 }
786: };
787:
788: static Fmtinit sinit[] = {
789: { "dox", INT+PTR, LONG+PTR, SHORT+PTR },
790: { "efg", FLOAT+PTR, DOUBLE+PTR },
791: { "cs[", CHAR+PTR },
792: #ifdef USGFMT
793: { "u", UNSIGNED+PTR, ULONG+PTR, USHORT+PTR },
794: #else
795: { "DOX", LONG+PTR },
796: { "EFG", DOUBLE+PTR },
797: #endif
798: { 0 }
799: };
800:
801:
802: chkprintf (q, arg, fmt)
803: STAB *q;
804: register int arg;
805: register char *fmt;
806: {
807: register int c, d;
808: register TWORD ty;
809:
810: while (c = *fmt++) {
811: if (c != '%' || (c = *fmt++) == '%')
812: continue;
813: for (; c=='-' || c=='+' || c=='#' || c==' '; c = *fmt++);
814: if (c == '*') {
815: fmtarg (q, arg++, INT, '*', 0);
816: c = *fmt++;
817: }
818: else for (; c >= '0' && c <= '9'; c = *fmt++);
819: if (c == '.')
820: if ((c = *fmt++) == '*') {
821: fmtarg (q, arg++, INT, '*', 0);
822: c = *fmt++;
823: }
824: else for (; c >= '0' && c <= '9'; c = *fmt++);
825: ty = pftab[c];
826: if (c == 'l' && pftab[c = *fmt++]) {
827: d = 'l';
828: ty = pfltab[c];
829: }
830: else d = 0;
831: if (ty)
832: fmtarg (q, arg++, ty, c, d);
833: else goto bad;
834: }
835:
836: if (arg < r.l.nargs)
837: fmterror (q, "too many args for format");
838: return;
839:
840: bad:
841: fmterror (q, "malformed format string");
842: return;
843: }
844:
845:
846: chkscanf (q, arg, fmt)
847: STAB *q;
848: register int arg;
849: register char *fmt;
850: {
851: register int c, d = 0, suppress;
852: TWORD ty;
853:
854: while (c = *fmt++) {
855: if (c != '%' || (c = *fmt++) == '%')
856: continue;
857: if (suppress = (c == '*'))
858: c = *fmt++;
859: for (; c >= '0' && c <= '9'; c = *fmt++);
860: ty = sftab[c];
861: if (c == '[') {
862: if ((c = *fmt++) == '^')
863: c = *fmt++;
864: if (c == ']')
865: c = *fmt++;
866: for (; c && c != ']'; c = *fmt++);
867: if (c != ']')
868: goto bad;
869: c = '[';
870: }
871: d = 0;
872: if (c == 'l' || c == 'h') {
873: d = c;
874: if (sftab[c = *fmt++])
875: ty = fmt[-2] == 'l' ? sfltab[c] : sfhtab[c];
876: }
877: if (!ty)
878: goto bad;
879: else if (!suppress)
880: fmtarg (q, arg++, ty, c, d);
881: }
882:
883: if (arg < r.l.nargs)
884: fmterror (q, "too many args for format");
885: return;
886:
887: bad:
888: fmterror (q, "malformed format string");
889: return;
890: }
891:
892:
893: fmtarg (q, arg, ty, c, d)
894: STAB *q;
895: char c, d;
896: int arg;
897: TWORD ty;
898: {
899: char buf[16];
900: TWORD ty2;
901:
902: if (arg >= r.l.nargs) {
903: if (arg == r.l.nargs)
904: fmterror (q, "too few args for format");
905: return;
906: }
907:
908: #define deunsign(x) (ISUNSIGNED(BTYPE(x))?((x)&~BTMASK|DEUNSIGN(BTYPE(x))):(x))
909:
910: ty = deunsign (ty);
911: ty2 = deunsign (atyp[arg].aty);
912:
913: if (ty == ty2) /* fat chance ... */
914: return;
915:
916: if (sizeof (int) == sizeof (long))
917: if ((ty & TMASK) == (ty2 & TMASK))
918: if (BTYPE (ty) == INT && BTYPE (ty2) == LONG ||
919: BTYPE (ty) == LONG && BTYPE (ty2) == INT)
920: return;
921:
922: prflex (q->name);
923: printf (": %%%.1s%c for ", &d, c);
924: sprintf (buf, "arg %d", arg+1);
925: pty (atyp[arg].aty, buf);
926: viceversa (q);
927: return;
928: }
929:
930:
931: fmtcheck (q)
932: STAB *q;
933: {
934: char *fmt;
935: int arg = q->nargs;
936:
937: if (r.l.nargs < arg) /* somebody else will complain */
938: return;
939: if (arg < 1) /* should've been caught in pass 1 */
940: return;
941: if (!(fmt = getfmt (atyp+arg-1)))
942: return;
943:
944: if (q->decflag & LPF)
945: chkprintf (q, arg, fmt);
946: else if (q->decflag & LSF)
947: chkscanf (q, arg, fmt);
948: return;
949: }
950:
951:
952: fmterror (q, msg)
953: STAB *q;
954: char *msg;
955: {
956: prflex (q->name);
957: printf (": %s", msg);
958: viceversa (q);
959: }
960:
961:
962: int
963: fmtinit()
964: {
965: char *s;
966: int i;
967:
968: for (i = 0; s = pinit[i].fm_s; i++)
969: for (; *s; s++) {
970: pftab[*s] = pinit[i].fm_ty;
971: pfltab[*s] = pinit[i].fm_lty;
972: }
973: for (i = 0; s = sinit[i].fm_s; i++)
974: for (; *s; s++) {
975: sftab[*s] = sinit[i].fm_ty;
976: sfhtab[*s] = sinit[i].fm_hty;
977: sfltab[*s] = sinit[i].fm_lty;
978: }
979: return;
980: }
981:
982:
983: char *
984: getfmt (a)
985: register ATYPE *a;
986: {
987: static char fmt[FMTSIZE];
988: register char *s = fmt;
989: register int c;
990:
991: if (a->straddr <= 0)
992: return (0); /* not a string constant */
993: if (fseek (stmpfile, a->straddr, 0))
994: error ("cannot fseek string file");
995:
996: while ((c = fgetc (stmpfile)) != EOF && c && s < fmt+FMTSIZE-1)
997: *s++ = c;
998:
999: *s = '\0';
1000: return (fmt);
1001: }
1002:
1003:
1004: prflex (name)
1005: char *name;
1006: {
1007: #ifdef FLEXNAMES
1008: printf ("%s", name);
1009: #else
1010: printf ("%.8s", name);
1011: #endif
1012: }
1013:
1014:
1015: # endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.