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[256];
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
argflag(int c,int v)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
getflag(char * s)66 getflag(char *s)
67 {
68 Bits flag;
69 int c, f;
70 char *fmt;
71
72 fmt = fmtbuf;
73 flag = zbits;
74 nstar = 0;
75 while(c = *s++) {
76 *fmt++ = c;
77 f = flagbits[c];
78 switch(f) {
79 case Fnone:
80 argflag(c, Fverb);
81 f = flagbits[c];
82 break;
83 case Fstar:
84 nstar++;
85 case Fignor:
86 continue;
87 case Fl:
88 if(bset(flag, Fl))
89 flag = bor(flag, blsh(Fvl));
90 }
91 flag = bor(flag, blsh(f));
92 if(f >= Fverb)
93 break;
94 }
95 *fmt = 0;
96 return flag;
97 }
98
99 void
newprot(Sym * m,Type * t,char * s)100 newprot(Sym *m, Type *t, char *s)
101 {
102 Bits flag;
103 Tprot *l;
104
105 if(t == T) {
106 warn(Z, "%s: newprot: type not defined", m->name);
107 return;
108 }
109 flag = getflag(s);
110 for(l=tprot; l; l=l->link)
111 if(beq(flag, l->flag) && sametype(t, l->type))
112 return;
113 l = alloc(sizeof(*l));
114 l->type = t;
115 l->flag = flag;
116 l->link = tprot;
117 tprot = l;
118 }
119
120 void
newname(char * s,int p)121 newname(char *s, int p)
122 {
123 Tname *l;
124
125 for(l=tname; l; l=l->link)
126 if(strcmp(l->name, s) == 0) {
127 if(l->param != p)
128 yyerror("vargck %s already defined\n", s);
129 return;
130 }
131 l = alloc(sizeof(*l));
132 l->name = s;
133 l->param = p;
134 l->link = tname;
135 tname = l;
136 }
137
138 void
arginit(void)139 arginit(void)
140 {
141 int i;
142
143 lastadj = Fadj;
144 lastverb = Fverb;
145 indchar = typ(TIND, types[TCHAR]);
146
147 memset(flagbits, Fnone, sizeof(flagbits));
148
149 for(i='0'; i<='9'; i++)
150 argflag(i, Fignor);
151 argflag('.', Fignor);
152 argflag('#', Fignor);
153 argflag('u', Fignor);
154 argflag('+', Fignor);
155 argflag('-', Fignor);
156
157 argflag('*', Fstar);
158 argflag('l', Fl);
159
160 argflag('o', Fverb);
161 flagbits['x'] = flagbits['o'];
162 flagbits['X'] = flagbits['o'];
163 }
164
165 void
pragvararg(void)166 pragvararg(void)
167 {
168 Sym *s;
169 int n, c;
170 char *t;
171
172 if(1)
173 goto out;
174 s = getsym();
175 if(s && strcmp(s->name, "argpos") == 0)
176 goto ckpos;
177 if(s && strcmp(s->name, "type") == 0)
178 goto cktype;
179 yyerror("syntax in #pragma varargck");
180 goto out;
181
182 ckpos:
183 /*#pragma varargck argpos warn 2*/
184 s = getsym();
185 if(s == S)
186 goto bad;
187 n = getnsn();
188 if(n < 0)
189 goto bad;
190 newname(s->name, n);
191 goto out;
192
193 cktype:
194 /*#pragma varargck type O int*/
195 c = getnsc();
196 if(c != '"')
197 goto bad;
198 t = fmtbuf;
199 for(;;) {
200 c = getc();
201 if(c == ' ' || c == '\n')
202 goto bad;
203 if(c == '"')
204 break;
205 *t++ = c;
206 }
207 *t = 0;
208 t = strdup(fmtbuf);
209 s = getsym();
210 if(s == S)
211 goto bad;
212 c = getnsc();
213 unget(c);
214 if(c == '*')
215 newprot(s, typ(TIND, s->type), t);
216 else
217 newprot(s, s->type, t);
218 goto out;
219
220 bad:
221 yyerror("syntax in #pragma varargck");
222
223 out:
224 while(getnsc() != '\n')
225 ;
226 }
227
228 Node*
nextarg(Node * n,Node ** a)229 nextarg(Node *n, Node **a)
230 {
231 if(n == Z) {
232 *a = Z;
233 return Z;
234 }
235 if(n->op == OLIST) {
236 *a = n->left;
237 return n->right;
238 }
239 *a = n;
240 return Z;
241 }
242
243 void
checkargs(Node * nn,char * s,int pos)244 checkargs(Node *nn, char *s, int pos)
245 {
246 Node *a, *n;
247 Bits flag;
248 Tprot *l;
249
250 if(1)
251 return;
252 n = nn;
253 for(;;) {
254 s = strchr(s, '%');
255 if(s == 0) {
256 nextarg(n, &a);
257 if(a != Z)
258 warn(nn, "more arguments than format %T",
259 a->type);
260 return;
261 }
262 s++;
263 flag = getflag(s);
264 while(nstar > 0) {
265 n = nextarg(n, &a);
266 pos++;
267 nstar--;
268 if(a == Z) {
269 warn(nn, "more format than arguments %s",
270 fmtbuf);
271 return;
272 }
273 if(a->type == T)
274 continue;
275 if(!sametype(types[TINT], a->type) &&
276 !sametype(types[TUINT], a->type))
277 warn(nn, "format mismatch '*' in %s %T, arg %d",
278 fmtbuf, a->type, pos);
279 }
280 for(l=tprot; l; l=l->link)
281 if(sametype(types[TVOID], l->type)) {
282 if(beq(flag, l->flag)) {
283 s++;
284 goto loop;
285 }
286 }
287
288 n = nextarg(n, &a);
289 pos++;
290 if(a == Z) {
291 warn(nn, "more format than arguments %s",
292 fmtbuf);
293 return;
294 }
295 if(a->type == 0)
296 continue;
297 for(l=tprot; l; l=l->link)
298 if(sametype(a->type, l->type))
299 if(beq(flag, l->flag))
300 goto loop;
301 warn(nn, "format mismatch %s %T, arg %d", fmtbuf, a->type, pos);
302 loop:;
303 }
304 }
305
306 void
dpcheck(Node * n)307 dpcheck(Node *n)
308 {
309 char *s;
310 Node *a, *b;
311 Tname *l;
312 int i;
313
314 if(n == Z)
315 return;
316 b = n->left;
317 if(b == Z || b->op != ONAME)
318 return;
319 s = b->sym->name;
320 for(l=tname; l; l=l->link)
321 if(strcmp(s, l->name) == 0)
322 break;
323 if(l == 0)
324 return;
325
326 i = l->param;
327 b = n->right;
328 while(i > 0) {
329 b = nextarg(b, &a);
330 i--;
331 }
332 if(a == Z) {
333 warn(n, "cant find format arg");
334 return;
335 }
336 if(!sametype(indchar, a->type)) {
337 warn(n, "format arg type %T", a->type);
338 return;
339 }
340 if(a->op != OADDR || a->left->op != ONAME || a->left->sym != symstring) {
341 /* warn(n, "format arg not constant string");*/
342 return;
343 }
344 s = a->left->cstring;
345 checkargs(b, s, l->param);
346 }
347
348 void
praghjdicks(void)349 praghjdicks(void)
350 {
351 Sym *s;
352
353 hjdickflg = 0;
354 s = getsym();
355 if(s) {
356 hjdickflg = atoi(s->name+1);
357 if(strcmp(s->name, "on") == 0 ||
358 strcmp(s->name, "yes") == 0 ||
359 strcmp(s->name, "dick") == 0)
360 hjdickflg = 1;
361 }
362 while(getnsc() != '\n')
363 ;
364 if(0)
365 if(hjdickflg)
366 print("%4ld: hjdicks %d\n", lineno, hjdickflg);
367 else
368 print("%4ld: hjdicks off\n", lineno);
369 }
370
371 void
pragfpround(void)372 pragfpround(void)
373 {
374 Sym *s;
375
376 fproundflg = 0;
377 s = getsym();
378 if(s) {
379 hjdickflg = atoi(s->name+1);
380 if(strcmp(s->name, "on") == 0 ||
381 strcmp(s->name, "yes") == 0 ||
382 strcmp(s->name, "dick") == 0)
383 fproundflg = 1;
384 }
385 while(getnsc() != '\n')
386 ;
387 if(0)
388 if(fproundflg)
389 print("%4ld: fproundflg %d\n", lineno, fproundflg);
390 else
391 print("%4ld: fproundflg off\n", lineno);
392 }
393