]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/cc/dpchk.c
merge
[plan9front.git] / sys / src / cmd / cc / dpchk.c
1 #include        "cc.h"
2 #include        "y.tab.h"
3
4 enum
5 {
6         Fnone   = 0,
7         Fl,
8         Fvl,
9         Fignor,
10         Fstar,
11         Fadj,
12
13         Fverb   = 10,
14 };
15
16 typedef struct  Tprot   Tprot;
17 struct  Tprot
18 {
19         Type*   type;
20         Bits    flag;
21         Tprot*  link;
22 };
23
24 typedef struct  Tname   Tname;
25 struct  Tname
26 {
27         char*   name;
28         int     param;
29         Tname*  link;
30 };
31
32 static  Type*   indchar;
33 static  uchar   flagbits[512];
34 static  char    fmtbuf[100];
35 static  int     lastadj;
36 static  int     lastverb;
37 static  int     nstar;
38 static  Tprot*  tprot;
39 static  Tname*  tname;
40
41 void
42 argflag(int c, int v)
43 {
44
45         switch(v) {
46         case Fignor:
47         case Fstar:
48         case Fl:
49         case Fvl:
50                 flagbits[c] = v;
51                 break;
52         case Fverb:
53                 flagbits[c] = lastverb;
54 /*print("flag-v %c %d\n", c, lastadj);*/
55                 lastverb++;
56                 break;
57         case Fadj:
58                 flagbits[c] = lastadj;
59 /*print("flag-l %c %d\n", c, lastadj);*/
60                 lastadj++;
61                 break;
62         }
63 }
64
65 Bits
66 getflag(char *s)
67 {
68         Bits flag;
69         int f;
70         char *fmt, *e;
71         Rune c;
72
73         fmt = fmtbuf;
74         e = fmtbuf + sizeof(fmtbuf)-1;
75         flag = zbits;
76         nstar = 0;
77         while(fmt < e){
78                 s += chartorune(&c, s);
79                 fmt += runetochar(fmt, &c);
80                 if(c == 0 || c >= nelem(flagbits))
81                         break;
82                 f = flagbits[c];
83                 switch(f) {
84                 case Fnone:
85                         argflag(c, Fverb);
86                         f = flagbits[c];
87                         break;
88                 case Fstar:
89                         nstar++;
90                 case Fignor:
91                         continue;
92                 case Fl:
93                         if(bset(flag, Fl))
94                                 flag = bor(flag, blsh(Fvl));
95                 }
96                 flag = bor(flag, blsh(f));
97                 if(f >= Fverb)
98                         break;
99         }
100         *fmt = 0;
101         return flag;
102 }
103
104 void
105 newprot(Sym *m, Type *t, char *s)
106 {
107         Bits flag;
108         Tprot *l;
109
110         if(t == T) {
111                 warn(Z, "%s: newprot: type not defined", m->name);
112                 return;
113         }
114         flag = getflag(s);
115         for(l=tprot; l; l=l->link)
116                 if(beq(flag, l->flag) && sametype(t, l->type))
117                         return;
118         l = alloc(sizeof(*l));
119         l->type = t;
120         l->flag = flag;
121         l->link = tprot;
122         tprot = l;
123 }
124
125 void
126 newname(char *s, int p)
127 {
128         Tname *l;
129
130         for(l=tname; l; l=l->link)
131                 if(strcmp(l->name, s) == 0) {
132                         if(l->param != p)
133                                 yyerror("vargck %s already defined\n", s);
134                         return;
135                 }
136         l = alloc(sizeof(*l));
137         l->name = s;
138         l->param = p;
139         l->link = tname;
140         tname = l;
141 }
142
143 void
144 arginit(void)
145 {
146         int i;
147
148 /* debug['F'] = 1;*/
149 /* debug['w'] = 1;*/
150
151         lastadj = Fadj;
152         lastverb = Fverb;
153         indchar = typ(TIND, types[TCHAR]);
154
155         memset(flagbits, Fnone, sizeof(flagbits));
156
157         for(i='0'; i<='9'; i++)
158                 argflag(i, Fignor);
159         argflag('.', Fignor);
160         argflag('#', Fignor);
161         argflag('u', Fignor);
162         argflag('h', Fignor);
163         argflag('+', Fignor);
164         argflag('-', Fignor);
165
166         argflag('*', Fstar);
167         argflag('l', Fl);
168
169         argflag('o', Fverb);
170         flagbits['x'] = flagbits['o'];
171         flagbits['X'] = flagbits['o'];
172 }
173
174 void
175 pragvararg(void)
176 {
177         Sym *s;
178         int n, c;
179         char *t, *e;
180         Rune r;
181         Type *ty;
182
183         if(!debug['F'])
184                 goto out;
185         s = getsym();
186         if(s && strcmp(s->name, "argpos") == 0)
187                 goto ckpos;
188         if(s && strcmp(s->name, "type") == 0)
189                 goto cktype;
190         if(s && strcmp(s->name, "flag") == 0)
191                 goto ckflag;
192         yyerror("syntax in #pragma varargck");
193         goto out;
194
195 ckpos:
196 /*#pragma       varargck        argpos  warn    2*/
197         s = getsym();
198         if(s == S)
199                 goto bad;
200         n = getnsn();
201         if(n < 0)
202                 goto bad;
203         newname(s->name, n);
204         goto out;
205
206 ckflag:
207 /*#pragma       varargck        flag    'c'*/
208         c = getnsc();
209         if(c != '\'')
210                 goto bad;
211         c = getr();
212         if(c == '\\')
213                 c = getr();
214         else if(c == '\'')
215                 goto bad;
216         if(c == '\n')
217                 goto bad;
218         if(getc() != '\'')
219                 goto bad;
220         argflag(c, Fignor);
221         goto out;
222
223 cktype:
224 /*#pragma       varargck        type    O       int*/
225         c = getnsc();
226         if(c != '"')
227                 goto bad;
228         t = fmtbuf;
229         e = t + sizeof(fmtbuf)-1;
230         for(;;) {
231                 r = getr();
232                 if(r == ' ' || r == '\n')
233                         goto bad;
234                 if(r == '"')
235                         break;
236                 if(t >= e)
237                         goto bad;
238                 t += runetochar(t, &r);
239         }
240         *t = 0;
241         t = strdup(fmtbuf);
242         s = getsym();
243         if(s == S)
244                 goto bad;
245         ty = s->type;
246         while((c = getnsc()) == '*')
247                 ty = typ(TIND, ty);
248         unget(c);
249         newprot(s, ty, t);
250         goto out;
251
252 bad:
253         yyerror("syntax in #pragma varargck");
254
255 out:
256         while(getnsc() != '\n')
257                 ;
258 }
259
260 Node*
261 nextarg(Node *n, Node **a)
262 {
263         if(n == Z) {
264                 *a = Z;
265                 return Z;
266         }
267         if(n->op == OLIST) {
268                 *a = n->left;
269                 return n->right;
270         }
271         *a = n;
272         return Z;
273 }
274
275 void
276 checkargs(Node *nn, char *s, int pos)
277 {
278         Node *a, *n;
279         Bits flag;
280         Tprot *l;
281
282         if(!debug['F'])
283                 return;
284         n = nn;
285         for(;;) {
286                 s = strchr(s, '%');
287                 if(s == 0) {
288                         nextarg(n, &a);
289                         if(a != Z)
290                                 warn(nn, "more arguments than format %T",
291                                         a->type);
292                         return;
293                 }
294                 s++;
295                 flag = getflag(s);
296                 while(nstar > 0) {
297                         n = nextarg(n, &a);
298                         pos++;
299                         nstar--;
300                         if(a == Z) {
301                                 warn(nn, "more format than arguments %s",
302                                         fmtbuf);
303                                 return;
304                         }
305                         if(a->type == T)
306                                 continue;
307                         if(!sametype(types[TINT], a->type) &&
308                            !sametype(types[TUINT], a->type))
309                                 warn(nn, "format mismatch '*' in %s %T, arg %d",
310                                         fmtbuf, a->type, pos);
311                 }
312                 for(l=tprot; l; l=l->link)
313                         if(sametype(types[TVOID], l->type)) {
314                                 if(beq(flag, l->flag)) {
315                                         s++;
316                                         goto loop;
317                                 }
318                         }
319
320                 n = nextarg(n, &a);
321                 pos++;
322                 if(a == Z) {
323                         warn(nn, "more format than arguments %s",
324                                 fmtbuf);
325                         return;
326                 }
327                 if(a->type == 0)
328                         continue;
329                 for(l=tprot; l; l=l->link)
330                         if(sametype(a->type, l->type)) {
331 /*print("checking %T/%ulx %T/%ulx\n", a->type, flag.b[0], l->type, l->flag.b[0]);*/
332                                 if(beq(flag, l->flag))
333                                         goto loop;
334                         }
335                 warn(nn, "format mismatch %s %T, arg %d", fmtbuf, a->type, pos);
336         loop:;
337         }
338 }
339
340 void
341 dpcheck(Node *n)
342 {
343         char *s;
344         Node *a, *b;
345         Tname *l;
346         int i;
347
348         if(n == Z)
349                 return;
350         b = n->left;
351         if(b == Z || b->op != ONAME)
352                 return;
353         s = b->sym->name;
354         for(l=tname; l; l=l->link)
355                 if(strcmp(s, l->name) == 0)
356                         break;
357         if(l == 0)
358                 return;
359
360         i = l->param;
361         b = n->right;
362         while(i > 0) {
363                 b = nextarg(b, &a);
364                 i--;
365         }
366         if(a == Z) {
367                 warn(n, "cant find format arg");
368                 return;
369         }
370         if(!sametype(indchar, a->type)) {
371                 warn(n, "format arg type %T", a->type);
372                 return;
373         }
374         if(a->op != OADDR || a->left->op != ONAME || a->left->sym != symstring) {
375 /*              warn(n, "format arg not constant string");*/
376                 return;
377         }
378         s = a->left->cstring;
379         checkargs(b, s, l->param);
380 }
381
382 void
383 pragpack(void)
384 {
385         Sym *s;
386
387         packflg = 0;
388         s = getsym();
389         if(s) {
390                 packflg = atoi(s->name+1);
391                 if(strcmp(s->name, "on") == 0 ||
392                    strcmp(s->name, "yes") == 0)
393                         packflg = 1;
394         }
395         while(getnsc() != '\n')
396                 ;
397         if(debug['f'])
398                 if(packflg)
399                         print("%4ld: pack %d\n", lineno, packflg);
400                 else
401                         print("%4ld: pack off\n", lineno);
402 }
403
404 void
405 pragfpround(void)
406 {
407         Sym *s;
408
409         fproundflg = 0;
410         s = getsym();
411         if(s) {
412                 fproundflg = atoi(s->name+1);
413                 if(strcmp(s->name, "on") == 0 ||
414                    strcmp(s->name, "yes") == 0)
415                         fproundflg = 1;
416         }
417         while(getnsc() != '\n')
418                 ;
419         if(debug['f'])
420                 if(fproundflg)
421                         print("%4ld: fproundflg %d\n", lineno, fproundflg);
422                 else
423                         print("%4ld: fproundflg off\n", lineno);
424 }
425
426 void
427 pragprofile(void)
428 {
429         Sym *s;
430
431         profileflg = 0;
432         s = getsym();
433         if(s) {
434                 profileflg = atoi(s->name+1);
435                 if(strcmp(s->name, "on") == 0 ||
436                    strcmp(s->name, "yes") == 0)
437                         profileflg = 1;
438         }
439         while(getnsc() != '\n')
440                 ;
441         if(debug['f'])
442                 if(profileflg)
443                         print("%4ld: profileflg %d\n", lineno, profileflg);
444                 else
445                         print("%4ld: profileflg off\n", lineno);
446 }
447
448 void
449 pragincomplete(void)
450 {
451         Sym *s;
452         Type *t;
453         int istag, w, et;
454
455         istag = 0;
456         s = getsym();
457         if(s == nil)
458                 goto out;
459         et = 0;
460         w = s->lexical;
461         if(w == LSTRUCT)
462                 et = TSTRUCT;
463         else if(w == LUNION)
464                 et = TUNION;
465         if(et != 0){
466                 s = getsym();
467                 if(s == nil){
468                         yyerror("missing struct/union tag in pragma incomplete");
469                         goto out;
470                 }
471                 if(s->lexical != LNAME && s->lexical != LTYPE){
472                         yyerror("invalid struct/union tag: %s", s->name);
473                         goto out;
474                 }
475                 dotag(s, et, 0);
476                 istag = 1;
477         }else if(strcmp(s->name, "_off_") == 0){
478                 debug['T'] = 0;
479                 goto out;
480         }else if(strcmp(s->name, "_on_") == 0){
481                 debug['T'] = 1;
482                 goto out;
483         }
484         t = s->type;
485         if(istag)
486                 t = s->suetag;
487         if(t == T)
488                 yyerror("unknown type %s in pragma incomplete", s->name);
489         else if(!typesu[t->etype])
490                 yyerror("not struct/union type in pragma incomplete: %s", s->name);
491         else
492                 t->garb |= GINCOMPLETE;
493 out:
494         while(getnsc() != '\n')
495                 ;
496         if(debug['f'])
497                 print("%s incomplete\n", s->name);
498 }