xref: /inferno-os/utils/c2l/dpchk.c (revision 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a)
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