Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

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