Commit | Line | Data |
---|---|---|
42d6e430 BJ |
1 | # include "mfile1" |
2 | ||
3 | # include "lmanifest" | |
4 | ||
5 | # include <ctype.h> | |
6 | ||
7 | # define VAL 0 | |
8 | # define EFF 1 | |
9 | ||
10 | /* these are appropriate for the -p flag */ | |
11 | int SZCHAR = 8; | |
12 | int SZINT = 16; | |
13 | int SZFLOAT = 32; | |
14 | int SZDOUBLE = 64; | |
15 | int SZLONG = 32; | |
16 | int SZSHORT = 16; | |
17 | int SZPOINT = 16; | |
18 | int ALCHAR = 8; | |
19 | int ALINT = 16; | |
20 | int ALFLOAT = 32; | |
21 | int ALDOUBLE = 64; | |
22 | int ALLONG = 32; | |
23 | int ALSHORT = 16; | |
24 | int ALPOINT = 16; | |
25 | int ALSTRUCT = 16; | |
26 | ||
27 | int vflag = 1; /* tell about unused argments */ | |
28 | int xflag = 0; /* tell about unused externals */ | |
29 | int argflag = 0; /* used to turn off complaints about arguments */ | |
30 | int libflag = 0; /* used to generate library descriptions */ | |
31 | int vaflag = -1; /* used to signal functions with a variable number of args */ | |
32 | int aflag = 0; /* used th check precision of assignments */ | |
33 | ||
34 | char *flabel = "xxx"; | |
35 | ||
36 | # define LNAMES 100 | |
37 | ||
38 | struct lnm { | |
39 | short lid, flgs; | |
40 | } lnames[LNAMES], *lnp; | |
41 | ||
42 | contx( p, down, pl, pr ) register NODE *p; register *pl, *pr; { | |
43 | ||
44 | *pl = *pr = VAL; | |
45 | switch( p->op ){ | |
46 | ||
47 | case ANDAND: | |
48 | case OROR: | |
49 | case QUEST: | |
50 | *pr = down; | |
51 | break; | |
52 | ||
53 | case SCONV: | |
54 | case PCONV: | |
55 | case COLON: | |
56 | *pr = *pl = down; | |
57 | break; | |
58 | ||
59 | case COMOP: | |
60 | *pl = EFF; | |
61 | *pr = down; | |
62 | ||
63 | case FORCE: | |
64 | case INIT: | |
65 | case UNARY CALL: | |
66 | case STCALL: | |
67 | case UNARY STCALL: | |
68 | case CALL: | |
69 | case UNARY FORTCALL: | |
70 | case FORTCALL: | |
71 | case CBRANCH: | |
72 | break; | |
73 | ||
74 | default: | |
75 | if( asgop(p->op) ) break; | |
76 | if( p->op == UNARY MUL && ( p->type == STRTY || p->type == UNIONTY) ) { | |
77 | break; /* the compiler does this... */ | |
78 | } | |
79 | if( down == EFF && hflag ) werror( "null effect" ); | |
80 | ||
81 | } | |
82 | } | |
83 | ||
84 | ecode( p ) NODE *p; { | |
85 | /* compile code for p */ | |
86 | ||
87 | fwalk( p, contx, EFF ); | |
88 | lnp = lnames; | |
89 | lprt( p, EFF, 0 ); | |
90 | } | |
91 | ||
92 | ejobcode( flag ){ | |
93 | /* called after processing each job */ | |
94 | /* flag is nonzero if errors were detected */ | |
95 | register k; | |
96 | register struct symtab *p; | |
97 | ||
98 | for( p=stab; p< &stab[SYMTSZ]; ++p ){ | |
99 | ||
100 | if( p->stype != TNULL ) { | |
101 | ||
102 | if( p->stype == STRTY || p->stype == UNIONTY ){ | |
103 | if( dimtab[p->sizoff+1] < 0 ){ /* never defined */ | |
104 | if( hflag ) werror( "struct/union %.7s never defined", p->sname ); | |
105 | } | |
106 | } | |
107 | ||
108 | switch( p->sclass ){ | |
109 | ||
110 | case STATIC: | |
111 | if( p->suse > 0 ){ | |
112 | k = lineno; | |
113 | lineno = p->suse; | |
114 | uerror( "static variable %s unused", | |
115 | p->sname ); | |
116 | lineno = k; | |
117 | break; | |
118 | } | |
119 | ||
120 | case EXTERN: | |
121 | case USTATIC: | |
122 | /* with the xflag, worry about externs not used */ | |
123 | /* the filename may be wrong here... */ | |
124 | if( xflag && p->suse >= 0 && !libflag ){ | |
125 | printf( "%.7s\t%03d\t%o\t%d\t", p->sname, LDX, p->stype, 0 ); | |
126 | /* we don't really know the file number; we know only the line | |
127 | number, so we put only that out */ | |
128 | printf( "\"???\"\t%d\t%s\n", p->suse, flabel ); | |
129 | } | |
130 | ||
131 | case EXTDEF: | |
132 | if( p->suse < 0 ){ /* used */ | |
133 | printf( "%.7s\t%03d\t%o\t%d\t", exname(p->sname), LUM, p->stype, 0 ); | |
134 | fident( -p->suse ); | |
135 | } | |
136 | break; | |
137 | } | |
138 | ||
139 | } | |
140 | ||
141 | } | |
142 | exit( 0 ); | |
143 | } | |
144 | ||
145 | fident( line ){ /* like ident, but lineno = line */ | |
146 | register temp; | |
147 | temp = lineno; | |
148 | lineno = line; | |
149 | ident(); | |
150 | lineno = temp; | |
151 | } | |
152 | ||
153 | ident(){ /* write out file and line identification */ | |
154 | printf( "%s\t%d\t%s\n", ftitle, lineno, flabel ); | |
155 | } | |
156 | ||
157 | bfcode( a, n ) int a[]; { | |
158 | /* code for the beginning of a function; a is an array of | |
159 | indices in stab for the arguments; n is the number */ | |
160 | /* this must also set retlab */ | |
161 | register i; | |
162 | register struct symtab *cfp; | |
163 | register unsigned t; | |
164 | ||
165 | retlab = 1; | |
166 | cfp = &stab[curftn]; | |
167 | ||
168 | /* if variable number of arguments, only print the ones which will be checked */ | |
169 | if( vaflag > 0 ){ | |
170 | if( n < vaflag ) werror( "declare the VARARGS arguments you want checked!" ); | |
171 | else n = vaflag; | |
172 | } | |
173 | printf( "%.7s\t%03d\t%o\t%d\t", exname(cfp->sname), libflag?LIB:LDI, | |
174 | cfp->stype, vaflag>=0?-n:n ); | |
175 | vaflag = -1; | |
176 | ||
177 | for( i=0; i<n; ++i ) { | |
178 | switch( t = stab[a[i]].stype ){ | |
179 | ||
180 | case ULONG: | |
181 | break; | |
182 | ||
183 | case CHAR: | |
184 | case SHORT: | |
185 | t = INT; | |
186 | break; | |
187 | ||
188 | case UCHAR: | |
189 | case USHORT: | |
190 | case UNSIGNED: | |
191 | t = UNSIGNED; | |
192 | break; | |
193 | ||
194 | } | |
195 | ||
196 | printf( "%o\t", t ); | |
197 | } | |
198 | ident(); | |
199 | } | |
200 | ||
201 | ctargs( p ) NODE *p; { | |
202 | /* count arguments; p points to at least one */ | |
203 | /* the arguemnts are a tower of commasto the left */ | |
204 | register c; | |
205 | c = 1; /* count the rhs */ | |
206 | while( p->op == CM ){ | |
207 | ++c; | |
208 | p = p->left; | |
209 | } | |
210 | return( c ); | |
211 | } | |
212 | ||
213 | lpta( p ) NODE *p; { | |
214 | TWORD t; | |
215 | ||
216 | if( p->op == CM ){ | |
217 | lpta( p->left ); | |
218 | p = p->right; | |
219 | } | |
220 | switch( t = p->type ){ | |
221 | ||
222 | case CHAR: | |
223 | case SHORT: | |
224 | t = INT; | |
225 | case LONG: | |
226 | case ULONG: | |
227 | case INT: | |
228 | case UNSIGNED: | |
229 | break; | |
230 | ||
231 | case UCHAR: | |
232 | case USHORT: | |
233 | t = UNSIGNED; | |
234 | break; | |
235 | ||
236 | case FLOAT: | |
237 | printf( "%o\t", DOUBLE ); | |
238 | return; | |
239 | ||
240 | default: | |
241 | printf( "%o\t", p->type ); | |
242 | return; | |
243 | } | |
244 | ||
245 | if( p->op == ICON ) printf( "%o<1\t", t ); | |
246 | else printf( "%o\t", t ); | |
247 | } | |
248 | ||
249 | # define VALSET 1 | |
250 | # define VALUSED 2 | |
251 | # define VALASGOP 4 | |
252 | # define VALADDR 8 | |
253 | ||
254 | lprt( p, down, uses ) register NODE *p; { | |
255 | register struct symtab *q; | |
256 | register id; | |
257 | register acount; | |
258 | register down1, down2; | |
259 | register use1, use2; | |
260 | register struct lnm *np1, *np2; | |
261 | ||
262 | /* first, set variables which are set... */ | |
263 | ||
264 | use1 = use2 = VALUSED; | |
265 | if( p->op == ASSIGN ) use1 = VALSET; | |
266 | else if( p->op == UNARY AND ) use1 = VALADDR; | |
267 | else if( asgop( p->op ) ){ /* =ops */ | |
268 | use1 = VALUSED|VALSET; | |
269 | if( down == EFF ) use1 |= VALASGOP; | |
270 | } | |
271 | ||
272 | ||
273 | /* print the lines for lint */ | |
274 | ||
275 | down2 = down1 = VAL; | |
276 | acount = 0; | |
277 | ||
278 | switch( p->op ){ | |
279 | ||
280 | case EQ: | |
281 | case NE: | |
282 | case GT: | |
283 | case GE: | |
284 | case LT: | |
285 | case LE: | |
286 | if( p->left->type == CHAR && p->right->op==ICON && p->right->lval < 0 ){ | |
287 | werror( "nonportable character comparison" ); | |
288 | } | |
289 | if( (p->op==EQ || p->op==NE ) && ISUNSIGNED(p->left->type) && p->right->op == ICON ){ | |
290 | if( p->right->lval < 0 && p->right->rval == NONAME && !ISUNSIGNED(p->right->type) ){ | |
291 | werror( "comparison of unsigned with negative constant" ); | |
292 | } | |
293 | } | |
294 | break; | |
295 | ||
296 | case UGE: | |
297 | case ULT: | |
298 | if( p->right->op == ICON && p->right->lval == 0 && p->right->rval == NONAME ){ | |
299 | werror( "unsigned comparison with 0?" ); | |
300 | break; | |
301 | } | |
302 | case UGT: | |
303 | case ULE: | |
304 | if( p->right->op == ICON && p->right->lval <= 0 && !ISUNSIGNED(p->right->type) && p->right->rval == NONAME ){ | |
305 | werror( "degenerate unsigned comparison" ); | |
306 | } | |
307 | break; | |
308 | ||
309 | case COMOP: | |
310 | down1 = EFF; | |
311 | ||
312 | case ANDAND: | |
313 | case OROR: | |
314 | case QUEST: | |
315 | down2 = down; | |
316 | /* go recursively left, then right */ | |
317 | np1 = lnp; | |
318 | lprt( p->left, down1, use1 ); | |
319 | np2 = lnp; | |
320 | lprt( p->right, down2, use2 ); | |
321 | lmerge( np1, np2, 0 ); | |
322 | return; | |
323 | ||
324 | case SCONV: | |
325 | case PCONV: | |
326 | case COLON: | |
327 | down1 = down2 = down; | |
328 | break; | |
329 | ||
330 | case CALL: | |
331 | case STCALL: | |
332 | case FORTCALL: | |
333 | acount = ctargs( p->right ); | |
334 | case UNARY CALL: | |
335 | case UNARY STCALL: | |
336 | case UNARY FORTCALL: | |
337 | if( p->left->op == ICON && (id=p->left->rval) != NONAME ){ /* used to be &name */ | |
338 | printf( "%.7s\t%03d\t%o\t%d\t", | |
339 | exname(stab[id].sname), | |
340 | down==EFF ? LUE : LUV, | |
341 | DECREF(p->left->type), acount ); | |
342 | if( acount ) lpta( p->right ); | |
343 | ident(); | |
344 | } | |
345 | break; | |
346 | ||
347 | case ICON: | |
348 | /* look for &name case */ | |
349 | if( (id = p->rval) >= 0 && id != NONAME ){ | |
350 | q = &stab[id]; | |
351 | q->sflags |= (SREF|SSET); | |
352 | } | |
353 | return; | |
354 | ||
355 | case NAME: | |
356 | if( (id = p->rval) >= 0 && id != NONAME ){ | |
357 | q = &stab[id]; | |
358 | if( (uses&VALUSED) && !(q->sflags&SSET) ){ | |
359 | if( q->sclass == AUTO || q->sclass == REGISTER ){ | |
360 | if( !ISARY(q->stype ) && !ISFTN(q->stype) && q->stype!=STRTY ){ | |
361 | werror( "%.7s may be used before set", q->sname ); | |
362 | q->sflags |= SSET; | |
363 | } | |
364 | } | |
365 | } | |
366 | if( uses & VALASGOP ) break; /* not a real use */ | |
367 | if( uses & VALSET ) q->sflags |= SSET; | |
368 | if( uses & VALUSED ) q->sflags |= SREF; | |
369 | if( uses & VALADDR ) q->sflags |= (SREF|SSET); | |
370 | if( p->lval == 0 ){ | |
371 | lnp->lid = id; | |
372 | lnp->flgs = (uses&VALADDR)?0:((uses&VALSET)?VALSET:VALUSED); | |
373 | if( ++lnp >= &lnames[LNAMES] ) --lnp; | |
374 | } | |
375 | } | |
376 | return; | |
377 | ||
378 | } | |
379 | ||
380 | /* recurse, going down the right side first if we can */ | |
381 | ||
382 | switch( optype(p->op) ){ | |
383 | ||
384 | case BITYPE: | |
385 | np1 = lnp; | |
386 | lprt( p->right, down2, use2 ); | |
387 | case UTYPE: | |
388 | np2 = lnp; | |
389 | lprt( p->left, down1, use1 ); | |
390 | } | |
391 | ||
392 | if( optype(p->op) == BITYPE ){ | |
393 | if( p->op == ASSIGN && p->left->op == NAME ){ /* special case for a = .. a .. */ | |
394 | lmerge( np1, np2, 0 ); | |
395 | } | |
396 | else lmerge( np1, np2, p->op != COLON ); | |
397 | /* look for assignments to fields, and complain */ | |
398 | if( p->op == ASSIGN && p->left->op == FLD && p->right->op == ICON ) fldcon( p ); | |
399 | } | |
400 | ||
401 | } | |
402 | ||
403 | lmerge( np1, np2, flag ) struct lnm *np1, *np2; { | |
404 | /* np1 and np2 point to lists of lnm members, for the two sides | |
405 | * of a binary operator | |
406 | * flag is 1 if commutation is possible, 0 otherwise | |
407 | * lmerge returns a merged list, starting at np1, resetting lnp | |
408 | * it also complains, if appropriate, about side effects | |
409 | */ | |
410 | ||
411 | register struct lnm *npx, *npy; | |
412 | ||
413 | for( npx = np2; npx < lnp; ++npx ){ | |
414 | ||
415 | /* is it already there? */ | |
416 | for( npy = np1; npy < np2; ++npy ){ | |
417 | if( npx->lid == npy->lid ){ /* yes */ | |
418 | if( npx->flgs == 0 || npx->flgs == (VALSET|VALUSED) ) | |
419 | ; /* do nothing */ | |
420 | else if( (npx->flgs|npy->flgs)== (VALSET|VALUSED) || | |
421 | (npx->flgs&npy->flgs&VALSET) ){ | |
422 | if( flag ) werror( "%.8s evaluation order undefined", stab[npy->lid].sname ); | |
423 | } | |
424 | if( npy->flgs == 0 ) npx->flgs = 0; | |
425 | else npy->flgs |= npx->flgs; | |
426 | goto foundit; | |
427 | } | |
428 | } | |
429 | ||
430 | /* not there: update entry */ | |
431 | np2->lid = npx->lid; | |
432 | np2->flgs = npx->flgs; | |
433 | ++np2; | |
434 | ||
435 | foundit: ; | |
436 | } | |
437 | ||
438 | /* all finished: merged list is at np1 */ | |
439 | lnp = np2; | |
440 | } | |
441 | ||
442 | efcode(){ | |
443 | /* code for the end of a function */ | |
444 | register struct symtab *cfp; | |
445 | ||
446 | cfp = &stab[curftn]; | |
447 | if( retstat & RETVAL ){ | |
448 | printf( "%.7s\t%03d\t%o\t%d\t", exname(cfp->sname), | |
449 | LRV, DECREF( cfp->stype), 0 ); | |
450 | ident(); | |
451 | } | |
452 | if( !vflag ){ | |
453 | vflag = argflag; | |
454 | argflag = 0; | |
455 | } | |
456 | if( retstat == RETVAL+NRETVAL ) | |
457 | werror( "function %.8s has return(e); and return;", cfp->sname); | |
458 | } | |
459 | ||
460 | aocode(p) struct symtab *p; { | |
461 | /* called when automatic p removed from stab */ | |
462 | register struct symtab *cfs; | |
463 | cfs = &stab[curftn]; | |
464 | if(p->suse>0 && !(p->sflags&SMOS) ){ | |
465 | if( p->sclass == PARAM ){ | |
466 | if( vflag ) werror( "argument %.7s unused in function %.7s", | |
467 | p->sname, | |
468 | cfs->sname ); | |
469 | } | |
470 | else { | |
471 | if( p->sclass != TYPEDEF ) werror( "%.7s unused in function %.7s", | |
472 | p->sname, cfs->sname ); | |
473 | } | |
474 | } | |
475 | ||
476 | if( p->suse < 0 && (p->sflags & (SSET|SREF|SMOS)) == SSET && | |
477 | !ISARY(p->stype) && !ISFTN(p->stype) ){ | |
478 | ||
479 | werror( "%.7s set but not used in function %.7s", p->sname, cfs->sname ); | |
480 | } | |
481 | ||
482 | if( p->stype == STRTY || p->stype == UNIONTY || p->stype == ENUMTY ){ | |
483 | if( dimtab[p->sizoff+1] < 0 ) werror( "structure %.7s never defined", p->sname ); | |
484 | } | |
485 | ||
486 | } | |
487 | ||
488 | defnam( p ) register struct symtab *p; { | |
489 | /* define the current location as the name p->sname */ | |
490 | ||
491 | if( p->sclass == STATIC && p->slevel>1 ) return; | |
492 | ||
493 | if( !ISFTN( p->stype ) ){ | |
494 | printf( "%.7s\t%03d\t%o\t%d\t", | |
495 | exname(p->sname), libflag?LIB:LDI, p->stype, 0 ); | |
496 | ident(); | |
497 | } | |
498 | } | |
499 | ||
500 | zecode( n ){ | |
501 | /* n integer words of zeros */ | |
502 | OFFSZ temp; | |
503 | temp = n; | |
504 | inoff += temp*SZINT; | |
505 | ; | |
506 | } | |
507 | ||
508 | andable( p ) NODE *p; { /* p is a NAME node; can it accept & ? */ | |
509 | register r; | |
510 | ||
511 | if( p->op != NAME ) cerror( "andable error" ); | |
512 | ||
513 | if( (r = p->rval) < 0 ) return(1); /* labels are andable */ | |
514 | ||
515 | if( stab[r].sclass == AUTO || stab[r].sclass == PARAM ) return(0); | |
516 | return(1); | |
517 | } | |
518 | ||
519 | NODE * | |
520 | clocal(p) NODE *p; { | |
521 | ||
522 | /* this is called to do local transformations on | |
523 | an expression tree preparitory to its being | |
524 | written out in intermediate code. | |
525 | */ | |
526 | ||
527 | /* the major essential job is rewriting the | |
528 | automatic variables and arguments in terms of | |
529 | REG and OREG nodes */ | |
530 | /* conversion ops which are not necessary are also clobbered here */ | |
531 | /* in addition, any special features (such as rewriting | |
532 | exclusive or) are easily handled here as well */ | |
533 | ||
534 | register o; | |
535 | register unsigned t, tl; | |
536 | ||
537 | switch( o = p->op ){ | |
538 | ||
539 | case SCONV: | |
540 | case PCONV: | |
541 | if( p->left->type==ENUMTY ){ | |
542 | p->left = pconvert( p->left ); | |
543 | } | |
544 | /* assume conversion takes place; type is inherited */ | |
545 | t = p->type; | |
546 | tl = p->left->type; | |
547 | if( aflag && (tl==LONG||tl==ULONG) && (t!=LONG&&t!=ULONG) ){ | |
548 | werror( "long assignment may lose accuracy" ); | |
549 | } | |
550 | if( ISPTR(tl) && ISPTR(t) ){ | |
551 | tl = DECREF(tl); | |
552 | t = DECREF(t); | |
553 | switch( ISFTN(t) + ISFTN(tl) ){ | |
554 | ||
555 | case 0: /* neither is a function pointer */ | |
556 | if( talign(t,p->csiz) > talign(tl,p->left->csiz) ){ | |
557 | if( hflag||pflag ) werror( "possible pointer alignment problem" ); | |
558 | } | |
559 | break; | |
560 | ||
561 | case 1: | |
562 | werror( "questionable conversion of function pointer" ); | |
563 | ||
564 | case 2: | |
565 | ; | |
566 | } | |
567 | } | |
568 | p->left->type = p->type; | |
569 | p->left->cdim = p->cdim; | |
570 | p->left->csiz = p->csiz; | |
571 | p->op = FREE; | |
572 | return( p->left ); | |
573 | ||
574 | case PVCONV: | |
575 | case PMCONV: | |
576 | if( p->right->op != ICON ) cerror( "bad conversion"); | |
577 | p->op = FREE; | |
578 | return( buildtree( o==PMCONV?MUL:DIV, p->left, p->right ) ); | |
579 | ||
580 | } | |
581 | ||
582 | return(p); | |
583 | } | |
584 | ||
585 | NODE * | |
586 | offcon( off, t, d, s ) OFFSZ off; TWORD t;{ /* make a structure offset node */ | |
587 | register NODE *p; | |
588 | p = bcon(0); | |
589 | p->lval = off/SZCHAR; | |
590 | return(p); | |
591 | } | |
592 | ||
593 | noinit(){ | |
594 | /* storage class for such as "int a;" */ | |
595 | return( pflag ? EXTDEF : EXTERN ); | |
596 | } | |
597 | ||
598 | ||
599 | cinit( p, sz ) NODE *p; { /* initialize p into size sz */ | |
600 | inoff += sz; | |
601 | if( p->op == INIT ){ | |
602 | if( p->left->op == ICON ) return; | |
603 | if( p->left->op == NAME && p->left->type == MOE ) return; | |
604 | } | |
605 | uerror( "illegal initialization" ); | |
606 | } | |
607 | ||
608 | char * | |
609 | exname( p ) char *p; { | |
610 | /* make a name look like an external name in the local machine */ | |
611 | static char aa[8]; | |
612 | register int i; | |
613 | ||
614 | if( !pflag ) return(p); | |
615 | for( i=0; i<6; ++i ){ | |
616 | if( isupper(*p ) ) aa[i] = tolower( *p ); | |
617 | else aa[i] = *p; | |
618 | if( *p ) ++p; | |
619 | } | |
620 | aa[6] = '\0'; | |
621 | return( aa ); | |
622 | } | |
623 | ||
624 | where(f){ /* print true location of error */ | |
625 | if( f == 'u' && nerrors>1 ) --nerrors; /* don't get "too many errors" */ | |
626 | fprintf( stderr, "%s, line %d: ", ftitle, lineno ); | |
627 | } | |
628 | ||
629 | /* a number of dummy routines, unneeded by lint */ | |
630 | ||
631 | branch(n){;} | |
632 | defalign(n){;} | |
633 | deflab(n){;} | |
634 | bycode(t,i){;} | |
635 | cisreg(t){return(1);} /* everyting is a register variable! */ | |
636 | ||
637 | fldty(p) struct symtab *p; { | |
638 | ; /* all types are OK here... */ | |
639 | } | |
640 | ||
641 | fldal(t) unsigned t; { /* field alignment... */ | |
642 | if( t == ENUMTY ) return( ALCHAR ); /* this should be thought through better... */ | |
643 | if( ISPTR(t) ){ /* really for the benefit of honeywell (and someday IBM) */ | |
644 | if( pflag ) uerror( "nonportable field type" ); | |
645 | } | |
646 | else uerror( "illegal field type" ); | |
647 | return(ALINT); | |
648 | } | |
649 | ||
650 | main( argc, argv ) char *argv[]; { | |
651 | char *p; | |
652 | ||
653 | /* handle options */ | |
654 | ||
655 | for( p=argv[1]; *p; ++p ){ | |
656 | ||
657 | switch( *p ){ | |
658 | ||
659 | case '-': | |
660 | continue; | |
661 | ||
662 | case 'L': /* produced by driver program */ | |
663 | flabel = p; | |
664 | goto break2; | |
665 | ||
666 | case '\0': | |
667 | break; | |
668 | ||
669 | case 'b': | |
670 | brkflag = 1; | |
671 | continue; | |
672 | ||
673 | case 'p': | |
674 | pflag = 1; | |
675 | continue; | |
676 | ||
677 | case 'c': | |
678 | cflag = 1; | |
679 | continue; | |
680 | ||
681 | case 's': | |
682 | /* for the moment, -s triggers -h */ | |
683 | ||
684 | case 'h': | |
685 | hflag = 1; | |
686 | continue; | |
687 | ||
688 | case 'v': | |
689 | vflag = 0; | |
690 | continue; | |
691 | ||
692 | case 'x': | |
693 | xflag = 1; | |
694 | continue; | |
695 | ||
696 | case 'a': | |
697 | aflag = 1; | |
698 | case 'u': /* done in second pass */ | |
699 | case 'n': /* done in shell script */ | |
700 | continue; | |
701 | ||
702 | case 't': | |
703 | werror( "option %c now default: see `man 6 lint'", *p ); | |
704 | continue; | |
705 | ||
706 | default: | |
707 | uerror( "illegal option: %c", *p ); | |
708 | continue; | |
709 | ||
710 | } | |
711 | } | |
712 | ||
713 | break2: | |
714 | if( !pflag ){ /* set sizes to sizes of target machine */ | |
715 | # ifdef gcos | |
716 | SZCHAR = ALCHAR = 9; | |
717 | # else | |
718 | SZCHAR = ALCHAR = 8; | |
719 | # endif | |
720 | SZINT = ALINT = sizeof(int)*SZCHAR; | |
721 | SZFLOAT = ALFLOAT = sizeof(float)*SZCHAR; | |
722 | SZDOUBLE = ALDOUBLE = sizeof(double)*SZCHAR; | |
723 | SZLONG = ALLONG = sizeof(long)*SZCHAR; | |
724 | SZSHORT = ALSHORT = sizeof(short)*SZCHAR; | |
725 | SZPOINT = ALPOINT = sizeof(int *)*SZCHAR; | |
726 | ALSTRUCT = ALINT; | |
727 | /* now, fix some things up for various machines (I wish we had "alignof") */ | |
728 | ||
729 | # ifdef pdp11 | |
730 | ALLONG = ALDOUBLE = ALFLOAT = ALINT; | |
731 | #endif | |
732 | # ifdef ibm | |
733 | ALSTRUCT = ALCHAR; | |
734 | #endif | |
735 | } | |
736 | ||
737 | return( mainp1( argc, argv ) ); | |
738 | } | |
739 | ||
740 | ctype( type ) unsigned type; { /* are there any funny types? */ | |
741 | return( type ); | |
742 | } | |
743 | ||
744 | commdec( i ){ | |
745 | /* put out a common declaration */ | |
746 | register struct symtab *p; | |
747 | p = &stab[i]; | |
748 | printf( "%.7s\t%03d\t%o\t%d\t", exname(p->sname), libflag?LIB:LDC, p->stype, 0 ); | |
749 | ident(); | |
750 | } | |
751 | ||
752 | isitfloat ( s ) char *s; { | |
753 | /* s is a character string; | |
754 | if floating point is implemented, set dcon to the value of s */ | |
755 | /* lint version | |
756 | */ | |
757 | dcon = atof( s ); | |
758 | return( FCON ); | |
759 | } | |
760 | ||
761 | fldcon( p ) register NODE *p; { | |
762 | /* p is an assignment of a constant to a field */ | |
763 | /* check to see if the assignment is going to overflow, or otherwise cause trouble */ | |
764 | register s; | |
765 | CONSZ v; | |
766 | ||
767 | if( !hflag & !pflag ) return; | |
768 | ||
769 | s = UPKFSZ(p->left->rval); | |
770 | v = p->right->lval; | |
771 | ||
772 | switch( p->left->type ){ | |
773 | ||
774 | case CHAR: | |
775 | case INT: | |
776 | case SHORT: | |
777 | case LONG: | |
778 | case ENUMTY: | |
779 | if( v>=0 && (v>>(s-1))==0 ) return; | |
780 | werror( "precision lost in assignment to (possibly sign-extended) field" ); | |
781 | default: | |
782 | return; | |
783 | ||
784 | case UNSIGNED: | |
785 | case UCHAR: | |
786 | case USHORT: | |
787 | case ULONG: | |
788 | if( v<0 || (v>>s)!=0 ) werror( "precision lost in field assignment" ); | |
789 | ||
790 | return; | |
791 | } | |
792 | ||
793 | } |