]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/cc/dpchk.c
disk/format: implement long name support
[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                 if(c == 0 || c >= nelem(flagbits))
80                         break;
81                 fmt += runetochar(fmt, &c);
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         argflag('z', ewidth[TVLONG]==ewidth[TIND] ? Fvl : Fl);
169
170         argflag('o', Fverb);
171         flagbits['x'] = flagbits['o'];
172         flagbits['X'] = flagbits['o'];
173 }
174
175 void
176 pragvararg(void)
177 {
178         Sym *s;
179         int n, c;
180         char *t, *e;
181         Rune r;
182         Type *ty;
183
184         if(!debug['F'])
185                 goto out;
186         s = getsym();
187         if(s && strcmp(s->name, "argpos") == 0)
188                 goto ckpos;
189         if(s && strcmp(s->name, "type") == 0)
190                 goto cktype;
191         if(s && strcmp(s->name, "flag") == 0)
192                 goto ckflag;
193         yyerror("syntax in #pragma varargck");
194         goto out;
195
196 ckpos:
197 /*#pragma       varargck        argpos  warn    2*/
198         s = getsym();
199         if(s == S)
200                 goto bad;
201         n = getnsn();
202         if(n < 0)
203                 goto bad;
204         newname(s->name, n);
205         goto out;
206
207 ckflag:
208 /*#pragma       varargck        flag    'c'*/
209         c = getnsc();
210         if(c != '\'')
211                 goto bad;
212         c = getr();
213         if(c == '\\')
214                 c = getr();
215         else if(c == '\'')
216                 goto bad;
217         if(c == '\n')
218                 goto bad;
219         if(getc() != '\'')
220                 goto bad;
221         argflag(c, Fignor);
222         goto out;
223
224 cktype:
225 /*#pragma       varargck        type    O       int*/
226         c = getnsc();
227         if(c != '"')
228                 goto bad;
229         t = fmtbuf;
230         e = t + sizeof(fmtbuf)-1;
231         for(;;) {
232                 r = getr();
233                 if(r == ' ' || r == '\n')
234                         goto bad;
235                 if(r == '"')
236                         break;
237                 if(t >= e)
238                         goto bad;
239                 t += runetochar(t, &r);
240         }
241         *t = 0;
242         t = strdup(fmtbuf);
243         s = getsym();
244         if(s == S)
245                 goto bad;
246         ty = s->type;
247         while((c = getnsc()) == '*')
248                 ty = typ(TIND, ty);
249         unget(c);
250         newprot(s, ty, t);
251         goto out;
252
253 bad:
254         yyerror("syntax in #pragma varargck");
255
256 out:
257         while(getnsc() != '\n')
258                 ;
259 }
260
261 Node*
262 nextarg(Node *n, Node **a)
263 {
264         if(n == Z) {
265                 *a = Z;
266                 return Z;
267         }
268         if(n->op == OLIST) {
269                 *a = n->left;
270                 return n->right;
271         }
272         *a = n;
273         return Z;
274 }
275
276 void
277 checkargs(Node *nn, char *s, int pos)
278 {
279         Node *a, *n;
280         Bits flag;
281         Tprot *l;
282
283         if(!debug['F'])
284                 return;
285         n = nn;
286         for(;;) {
287                 s = strchr(s, '%');
288                 if(s == 0) {
289                         nextarg(n, &a);
290                         if(a != Z)
291                                 warn(nn, "more arguments than format %T",
292                                         a->type);
293                         return;
294                 }
295                 s++;
296                 flag = getflag(s);
297                 while(nstar > 0) {
298                         n = nextarg(n, &a);
299                         pos++;
300                         nstar--;
301                         if(a == Z) {
302                                 warn(nn, "more format than arguments %s",
303                                         fmtbuf);
304                                 return;
305                         }
306                         if(a->type == T)
307                                 continue;
308                         if(!sametype(types[TINT], a->type) &&
309                            !sametype(types[TUINT], a->type))
310                                 warn(nn, "format mismatch '*' in %s %T, arg %d",
311                                         fmtbuf, a->type, pos);
312                 }
313                 for(l=tprot; l; l=l->link)
314                         if(sametype(types[TVOID], l->type)) {
315                                 if(beq(flag, l->flag)) {
316                                         s++;
317                                         goto loop;
318                                 }
319                         }
320
321                 n = nextarg(n, &a);
322                 pos++;
323                 if(a == Z) {
324                         warn(nn, "more format than arguments %s",
325                                 fmtbuf);
326                         return;
327                 }
328                 if(a->type == 0)
329                         continue;
330                 for(l=tprot; l; l=l->link)
331                         if(sametype(a->type, l->type)) {
332 /*print("checking %T/%ulx %T/%ulx\n", a->type, flag.b[0], l->type, l->flag.b[0]);*/
333                                 if(beq(flag, l->flag))
334                                         goto loop;
335                         }
336                 warn(nn, "format mismatch %s %T, arg %d", fmtbuf, a->type, pos);
337         loop:;
338         }
339 }
340
341 void
342 dpcheck(Node *n)
343 {
344         char *s;
345         Node *a, *b;
346         Tname *l;
347         int i;
348
349         if(n == Z)
350                 return;
351         b = n->left;
352         if(b == Z || b->op != ONAME)
353                 return;
354         s = b->sym->name;
355         for(l=tname; l; l=l->link)
356                 if(strcmp(s, l->name) == 0)
357                         break;
358         if(l == 0)
359                 return;
360
361         i = l->param;
362         b = n->right;
363         while(i > 0) {
364                 b = nextarg(b, &a);
365                 i--;
366         }
367         if(a == Z) {
368                 warn(n, "cant find format arg");
369                 return;
370         }
371         if(!sametype(indchar, a->type)) {
372                 warn(n, "format arg type %T", a->type);
373                 return;
374         }
375         if(a->op != OADDR || a->left->op != ONAME || a->left->sym != symstring) {
376 /*              warn(n, "format arg not constant string");*/
377                 return;
378         }
379         s = a->left->cstring;
380         checkargs(b, s, l->param);
381 }
382
383 void
384 pragpack(void)
385 {
386         Sym *s;
387
388         packflg = 0;
389         s = getsym();
390         if(s) {
391                 packflg = atoi(s->name+1);
392                 if(strcmp(s->name, "on") == 0 ||
393                    strcmp(s->name, "yes") == 0)
394                         packflg = 1;
395         }
396         while(getnsc() != '\n')
397                 ;
398         if(debug['f'])
399                 if(packflg)
400                         print("%4ld: pack %d\n", lineno, packflg);
401                 else
402                         print("%4ld: pack off\n", lineno);
403 }
404
405 void
406 pragfpround(void)
407 {
408         Sym *s;
409
410         fproundflg = 0;
411         s = getsym();
412         if(s) {
413                 fproundflg = atoi(s->name+1);
414                 if(strcmp(s->name, "on") == 0 ||
415                    strcmp(s->name, "yes") == 0)
416                         fproundflg = 1;
417         }
418         while(getnsc() != '\n')
419                 ;
420         if(debug['f'])
421                 if(fproundflg)
422                         print("%4ld: fproundflg %d\n", lineno, fproundflg);
423                 else
424                         print("%4ld: fproundflg off\n", lineno);
425 }
426
427 void
428 pragprofile(void)
429 {
430         Sym *s;
431
432         profileflg = 0;
433         s = getsym();
434         if(s) {
435                 profileflg = atoi(s->name+1);
436                 if(strcmp(s->name, "on") == 0 ||
437                    strcmp(s->name, "yes") == 0)
438                         profileflg = 1;
439         }
440         while(getnsc() != '\n')
441                 ;
442         if(debug['f'])
443                 if(profileflg)
444                         print("%4ld: profileflg %d\n", lineno, profileflg);
445                 else
446                         print("%4ld: profileflg off\n", lineno);
447 }
448
449 void
450 pragincomplete(void)
451 {
452         Sym *s;
453         Type *t;
454         int istag, w, et;
455
456         istag = 0;
457         s = getsym();
458         if(s == nil)
459                 goto out;
460         et = 0;
461         w = s->lexical;
462         if(w == LSTRUCT)
463                 et = TSTRUCT;
464         else if(w == LUNION)
465                 et = TUNION;
466         if(et != 0){
467                 s = getsym();
468                 if(s == nil){
469                         yyerror("missing struct/union tag in pragma incomplete");
470                         goto out;
471                 }
472                 if(s->lexical != LNAME && s->lexical != LTYPE){
473                         yyerror("invalid struct/union tag: %s", s->name);
474                         goto out;
475                 }
476                 dotag(s, et, 0);
477                 istag = 1;
478         }else if(strcmp(s->name, "_off_") == 0){
479                 debug['T'] = 0;
480                 goto out;
481         }else if(strcmp(s->name, "_on_") == 0){
482                 debug['T'] = 1;
483                 goto out;
484         }
485         t = s->type;
486         if(istag)
487                 t = s->suetag;
488         if(t == T)
489                 yyerror("unknown type %s in pragma incomplete", s->name);
490         else if(!typesu[t->etype])
491                 yyerror("not struct/union type in pragma incomplete: %s", s->name);
492         else
493                 t->garb |= GINCOMPLETE;
494 out:
495         while(getnsc() != '\n')
496                 ;
497         if(debug['f'])
498                 print("%s incomplete\n", s->name);
499 }