Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#define VARMAC 0x80
2
 
3
long
4
getnsn(void)
5
{
6
	long n;
7
	int c;
8
 
9
	c = getnsc();
10
	if(c < '0' || c > '9')
11
		return -1;
12
	n = 0;
13
	while(c >= '0' && c <= '9') {
14
		n = n*10 + c-'0';
15
		c = getc();
16
	}
17
	unget(c);
18
	return n;
19
}
20
 
21
Sym*
22
getsym(void)
23
{
24
	int c;
25
	char *cp;
26
 
27
	c = getnsc();
28
	if(!isalpha(c) && c != '_' && c < Runeself) {
29
		unget(c);
30
		return S;
31
	}
32
	for(cp = symb;;) {
33
		if(cp <= symb+NSYMB-4)
34
			*cp++ = c;
35
		c = getc();
36
		if(isalnum(c) || c == '_' || c >= Runeself)
37
			continue;
38
		unget(c);
39
		break;
40
	}
41
	*cp = 0;
42
	if(cp > symb+NSYMB-4)
43
		yyerror("symbol too large: %s", symb);
44
	return lookup();
45
}
46
 
47
Sym*
48
getsymdots(int *dots)
49
{
50
	int c;
51
	Sym *s;
52
 
53
	s = getsym();
54
	if(s != S)
55
		return s;
56
 
57
	c = getnsc();
58
	if(c != '.'){
59
		unget(c);
60
		return S;
61
	}
62
	if(getc() != '.' || getc() != '.')
63
		yyerror("bad dots in macro");
64
	*dots = 1;
65
	return slookup("__VA_ARGS__");
66
}
67
 
68
int
69
getcom(void)
70
{
71
	int c;
72
 
73
	for(;;) {
74
		c = getnsc();
75
		if(c != '/')
76
			break;
77
		c = getc();
78
		if(c == '/') {
79
			while(c != '\n')
80
				c = getc();
81
			break;
82
		}
83
		if(c != '*')
84
			break;
85
		c = getc();
86
		for(;;) {
87
			if(c == '*') {
88
				c = getc();
89
				if(c != '/')
90
					continue;
91
				c = getc();
92
				break;
93
			}
94
			if(c == '\n') {
95
				yyerror("comment across newline");
96
				break;
97
			}
98
			c = getc();
99
		}
100
		if(c == '\n')
101
			break;
102
	}
103
	return c;
104
}
105
 
106
void
107
dodefine(char *cp)
108
{
109
	Sym *s;
110
	char *p;
111
	long l;
112
 
113
	strcpy(symb, cp);
114
	p = strchr(symb, '=');
115
	if(p) {
116
		*p++ = 0;
117
		s = lookup();
118
		l = strlen(p) + 2;	/* +1 null, +1 nargs */
119
		while(l & 3)
120
			l++;
121
		while(nhunk < l)
122
			gethunk();
123
		*hunk = 0;
124
		strcpy(hunk+1, p);
125
		s->macro = hunk;
126
		hunk += l;
127
		nhunk -= l;
128
	} else {
129
		s = lookup();
130
		s->macro = "\0001";	/* \000 is nargs */
131
	}
132
	if(debug['m'])
133
		print("#define (-D) %s %s\n", s->name, s->macro+1);
134
}
135
 
136
struct
137
{
138
	char	*macname;
139
	void	(*macf)(void);
140
} mactab[] =
141
{
142
	"ifdef",	0,	/* macif(0) */
143
	"ifndef",	0,	/* macif(1) */
144
	"else",		0,	/* macif(2) */
145
 
146
	"line",		maclin,
147
	"define",	macdef,
148
	"include",	macinc,
149
	"undef",	macund,
150
 
151
	"pragma",	macprag,
152
	"endif",	macend,
153
 
154
};
155
 
156
void
157
domacro(void)
158
{
159
	int i;
160
	Sym *s;
161
 
162
	s = getsym();
163
	if(s == S)
164
		s = slookup("endif");
165
	for(i=0; mactab[i].macname; i++)
166
		if(strcmp(s->name, mactab[i].macname) == 0) {
167
			if(mactab[i].macf)
168
				(*mactab[i].macf)();
169
			else
170
				macif(i);
171
			return;
172
		}
173
	yyerror("unknown #: %s", s->name);
174
	macend();
175
}
176
 
177
void
178
macund(void)
179
{
180
	Sym *s;
181
 
182
	s = getsym();
183
	macend();
184
	if(s == S) {
185
		yyerror("syntax in #undef");
186
		return;
187
	}
188
	s->macro = 0;
189
}
190
 
191
#define	NARG	25
192
void
193
macdef(void)
194
{
195
	Sym *s, *a;
196
	char *args[NARG], *np, *base;
197
	int n, i, c, len, dots;
198
	int ischr;
199
 
200
	s = getsym();
201
	if(s == S)
202
		goto bad;
203
	if(s->macro)
204
		yyerror("macro redefined: %s", s->name);
205
	c = getc();
206
	n = -1;
207
	dots = 0;
208
	if(c == '(') {
209
		n++;
210
		c = getnsc();
211
		if(c != ')') {
212
			unget(c);
213
			for(;;) {
214
				a = getsymdots(&dots);
215
				if(a == S)
216
					goto bad;
217
				if(n >= NARG) {
218
					yyerror("too many arguments in #define: %s", s->name);
219
					goto bad;
220
				}
221
				args[n++] = a->name;
222
				c = getnsc();
223
				if(c == ')')
224
					break;
225
				if(c != ',' || dots)
226
					goto bad;
227
			}
228
		}
229
		c = getc();
230
	}
231
	if(isspace(c))
232
		if(c != '\n')
233
			c = getnsc();
234
	base = hunk;
235
	len = 1;
236
	ischr = 0;
237
	for(;;) {
238
		if(isalpha(c) || c == '_') {
239
			np = symb;
240
			*np++ = c;
241
			c = getc();
242
			while(isalnum(c) || c == '_') {
243
				*np++ = c;
244
				c = getc();
245
			}
246
			*np = 0;
247
			for(i=0; i<n; i++)
248
				if(strcmp(symb, args[i]) == 0)
249
					break;
250
			if(i >= n) {
251
				i = strlen(symb);
252
				base = allocn(base, len, i);
253
				memcpy(base+len, symb, i);
254
				len += i;
255
				continue;
256
			}
257
			base = allocn(base, len, 2);
258
			base[len++] = '#';
259
			base[len++] = 'a' + i;
260
			continue;
261
		}
262
		if(ischr){
263
			if(c == '\\'){ 
264
				base = allocn(base, len, 1);
265
				base[len++] = c;
266
				c = getc();
267
			}else if(c == ischr)
268
				ischr = 0;
269
		}else{
270
			if(c == '"' || c == '\''){
271
				base = allocn(base, len, 1);
272
				base[len++] = c;
273
				ischr = c;
274
				c = getc();
275
				continue;
276
			}
277
			if(c == '/') {
278
				c = getc();
279
				if(c == '/'){
280
					c = getc();
281
					for(;;) {
282
						if(c == '\n')
283
							break;
284
						c = getc();
285
					}
286
					continue;
287
				}
288
				if(c == '*'){
289
					c = getc();
290
					for(;;) {
291
						if(c == '*') {
292
							c = getc();
293
							if(c != '/')
294
								continue;
295
							c = getc();
296
							break;
297
						}
298
						if(c == '\n') {
299
							yyerror("comment and newline in define: %s", s->name);
300
							break;
301
						}
302
						c = getc();
303
					}
304
					continue;
305
				}
306
				base = allocn(base, len, 1);
307
				base[len++] = '/';
308
				continue;
309
			}
310
		}
311
		if(c == '\\') {
312
			c = getc();
313
			if(c == '\n') {
314
				c = getc();
315
				continue;
316
			}
317
			else if(c == '\r') {
318
				c = getc();
319
				if(c == '\n') {
320
					c = getc();
321
					continue;
322
				}
323
			}
324
			base = allocn(base, len, 1);
325
			base[len++] = '\\';
326
			continue;
327
		}
328
		if(c == '\n')
329
			break;
330
		if(c == '#')
331
		if(n > 0) {
332
			base = allocn(base, len, 1);
333
			base[len++] = c;
334
		}
335
		base = allocn(base, len, 1);
336
		base[len++] = c;
337
		c = ((--fi.c < 0)? filbuf(): (*fi.p++ & 0xff));
338
		if(c == '\n')
339
			lineno++;
340
		if(c == -1) {
341
			yyerror("eof in a macro: %s", s->name);
342
			break;
343
		}
344
	}
345
	do {
346
		base = allocn(base, len, 1);
347
		base[len++] = 0;
348
	} while(len & 3);
349
 
350
	*base = n+1;
351
	if(dots)
352
		*base |= VARMAC;
353
	s->macro = base;
354
	if(debug['m'])
355
		print("#define %s %s\n", s->name, s->macro+1);
356
	return;
357
 
358
bad:
359
	if(s == S)
360
		yyerror("syntax in #define");
361
	else
362
		yyerror("syntax in #define: %s", s->name);
363
	macend();
364
}
365
 
366
void
367
macexpand(Sym *s, char *b)
368
{
369
	char buf[2000];
370
	int n, l, c, nargs;
371
	char *arg[NARG], *cp, *ob, *ecp, dots;
372
 
373
	ob = b;
374
	if(*s->macro == 0) {
375
		strcpy(b, s->macro+1);
376
		if(debug['m'])
377
			print("#expand %s %s\n", s->name, ob);
378
		return;
379
	}
380
 
381
	nargs = (char)(*s->macro & ~VARMAC) - 1;
382
	dots = *s->macro & VARMAC;
383
 
384
	c = getnsc();
385
	if(c != '(')
386
		goto bad;
387
	n = 0;
388
	c = getc();
389
	if(c != ')') {
390
		unget(c);
391
		l = 0;
392
		cp = buf;
393
		ecp = cp + sizeof(buf)-4;
394
		arg[n++] = cp;
395
		for(;;) {
396
			if(cp >= ecp)
397
				goto toobig;
398
			c = getc();
399
			if(c == '"')
400
				for(;;) {
401
					if(cp >= ecp)
402
						goto toobig;
403
					*cp++ = c;
404
					c = getc();
405
					if(c == '\\') {
406
						*cp++ = c;
407
						c = getc();
408
						continue;
409
					}
410
					if(c == '\n')
411
						goto bad;
412
					if(c == '"')
413
						break;
414
				}
415
			if(c == '\'')
416
				for(;;) {
417
					if(cp >= ecp)
418
						goto toobig;
419
					*cp++ = c;
420
					c = getc();
421
					if(c == '\\') {
422
						*cp++ = c;
423
						c = getc();
424
						continue;
425
					}
426
					if(c == '\n')
427
						goto bad;
428
					if(c == '\'')
429
						break;
430
				}
431
			if(c == '/') {
432
				c = getc();
433
				switch(c) {
434
				case '*':
435
					for(;;) {
436
						c = getc();
437
						if(c == '*') {
438
							c = getc();
439
							if(c == '/')
440
								break;
441
						}
442
					}
443
					*cp++ = ' ';
444
					continue;
445
				case '/':
446
					while((c = getc()) != '\n')
447
						;
448
					break;
449
				default:
450
					unget(c);
451
					c = '/';
452
				}
453
			}
454
			if(l == 0) {
455
				if(c == ',') {
456
					if(n == nargs && dots) {
457
						*cp++ = ',';
458
						continue;
459
					}
460
					*cp++ = 0;
461
					arg[n++] = cp;
462
					if(n > nargs)
463
						break;
464
					continue;
465
				}
466
				if(c == ')')
467
					break;
468
			}
469
			if(c == '\n')
470
				c = ' ';
471
			*cp++ = c;
472
			if(c == '(')
473
				l++;
474
			if(c == ')')
475
				l--;
476
		}
477
		*cp = 0;
478
	}
479
	if(n != nargs) {
480
		yyerror("argument mismatch expanding: %s", s->name);
481
		*b = 0;
482
		return;
483
	}
484
	cp = s->macro+1;
485
	for(;;) {
486
		c = *cp++;
487
		if(c == '\n')
488
			c = ' ';
489
		if(c != '#') {
490
			*b++ = c;
491
			if(c == 0)
492
				break;
493
			continue;
494
		}
495
		c = *cp++;
496
		if(c == 0)
497
			goto bad;
498
		if(c == '#') {
499
			*b++ = c;
500
			continue;
501
		}
502
		c -= 'a';
503
		if(c < 0 || c >= n)
504
			continue;
505
		strcpy(b, arg[c]);
506
		b += strlen(arg[c]);
507
	}
508
	*b = 0;
509
	if(debug['m'])
510
		print("#expand %s %s\n", s->name, ob);
511
	return;
512
 
513
bad:
514
	yyerror("syntax in macro expansion: %s", s->name);
515
	*b = 0;
516
	return;
517
 
518
toobig:
519
	yyerror("too much text in macro expansion: %s", s->name);
520
	*b = 0;
521
}
522
 
523
void
524
macinc(void)
525
{
526
	int c0, c, i, f;
527
	char str[STRINGSZ], *hp;
528
 
529
	c0 = getnsc();
530
	if(c0 != '"') {
531
		c = c0;
532
		if(c0 != '<')
533
			goto bad;
534
		c0 = '>';
535
	}
536
	for(hp = str;;) {
537
		c = getc();
538
		if(c == c0)
539
			break;
540
		if(c == '\n')
541
			goto bad;
542
		*hp++ = c;
543
	}
544
	*hp = 0;
545
 
546
	c = getcom();
547
	if(c != '\n')
548
		goto bad;
549
 
550
	f = -1;
551
	for(i=0; i<ninclude; i++) {
552
		if(i == 0 && c0 == '>')
553
			continue;
554
		strcpy(symb, include[i]);
555
		strcat(symb, "/");
556
		if(strcmp(symb, "./") == 0)
557
			symb[0] = 0;
558
		strcat(symb, str);
559
		f = open(symb, 0);
560
		if(f >= 0)
561
			break;
562
	}
563
	if(f < 0)
564
		strcpy(symb, str);
565
	c = strlen(symb) + 1;
566
	while(c & 3)
567
		c++;
568
	while(nhunk < c)
569
		gethunk();
570
	hp = hunk;
571
	memcpy(hunk, symb, c);
572
	nhunk -= c;
573
	hunk += c;
574
	newio();
575
	pushio();
576
	newfile(hp, f);
577
	return;
578
 
579
bad:
580
	unget(c);
581
	yyerror("syntax in #include");
582
	macend();
583
}
584
 
585
void
586
maclin(void)
587
{
588
	char *cp;
589
	int c;
590
	long n;
591
 
592
	n = getnsn();
593
	c = getc();
594
	if(n < 0)
595
		goto bad;
596
 
597
	for(;;) {
598
		if(c == ' ' || c == '\t') {
599
			c = getc();
600
			continue;
601
		}
602
		if(c == '"')
603
			break;
604
		if(c == '\n') {
605
			strcpy(symb, "<noname>");
606
			goto nn;
607
		}
608
		goto bad;
609
	}
610
	cp = symb;
611
	for(;;) {
612
		c = getc();
613
		if(c == '"')
614
			break;
615
		*cp++ = c;
616
	}
617
	*cp = 0;
618
	c = getcom();
619
	if(c != '\n')
620
		goto bad;
621
 
622
nn:
623
	c = strlen(symb) + 1;
624
	while(c & 3)
625
		c++;
626
	while(nhunk < c)
627
		gethunk();
628
	cp = hunk;
629
	memcpy(hunk, symb, c);
630
	nhunk -= c;
631
	hunk += c;
632
	linehist(cp, n);
633
	return;
634
 
635
bad:
636
	unget(c);
637
	yyerror("syntax in #line");
638
	macend();
639
}
640
 
641
void
642
macif(int f)
643
{
644
	int c, l, bol;
645
	Sym *s;
646
 
647
	if(f == 2)
648
		goto skip;
649
	s = getsym();
650
	if(s == S)
651
		goto bad;
652
	if(getcom() != '\n')
653
		goto bad;
654
	if((s->macro != 0) ^ f)
655
		return;
656
 
657
skip:
658
	bol = 1;
659
	l = 0;
660
	for(;;) {
661
		c = getc();
662
		if(c != '#') {
663
			if(!isspace(c))
664
				bol = 0;
665
			if(c == '\n')
666
				bol = 1;
667
			continue;
668
		}
669
		if(!bol)
670
			continue;
671
		s = getsym();
672
		if(s == S)
673
			continue;
674
		if(strcmp(s->name, "endif") == 0) {
675
			if(l) {
676
				l--;
677
				continue;
678
			}
679
			macend();
680
			return;
681
		}
682
		if(strcmp(s->name, "ifdef") == 0 || strcmp(s->name, "ifndef") == 0) {
683
			l++;
684
			continue;
685
		}
686
		if(l == 0 && f != 2 && strcmp(s->name, "else") == 0) {
687
			macend();
688
			return;
689
		}
690
	}
691
 
692
bad:
693
	yyerror("syntax in #if(n)def");
694
	macend();
695
}
696
 
697
void
698
macprag(void)
699
{
700
	Sym *s;
701
	int c0, c;
702
	char *hp;
703
	Hist *h;
704
 
705
	s = getsym();
706
 
707
	if(s && strcmp(s->name, "lib") == 0)
708
		goto praglib;
709
	if(s && strcmp(s->name, "pack") == 0) {
710
		pragpack();
711
		return;
712
	}
713
	if(s && strcmp(s->name, "fpround") == 0) {
714
		pragfpround();
715
		return;
716
	}
717
	if(s && strcmp(s->name, "profile") == 0) {
718
		pragprofile();
719
		return;
720
	}
721
	if(s && strcmp(s->name, "varargck") == 0) {
722
		pragvararg();
723
		return;
724
	}
725
	if(s && strcmp(s->name, "incomplete") == 0) {
726
		pragincomplete();
727
		return;
728
	}
729
	while(getnsc() != '\n')
730
		;
731
	return;
732
 
733
praglib:
734
	c0 = getnsc();
735
	if(c0 != '"') {
736
		c = c0;
737
		if(c0 != '<')
738
			goto bad;
739
		c0 = '>';
740
	}
741
	for(hp = symb;;) {
742
		c = getc();
743
		if(c == c0)
744
			break;
745
		if(c == '\n')
746
			goto bad;
747
		*hp++ = c;
748
	}
749
	*hp = 0;
750
	c = getcom();
751
	if(c != '\n')
752
		goto bad;
753
 
754
	/*
755
	 * put pragma-line in as a funny history 
756
	 */
757
	c = strlen(symb) + 1;
758
	while(c & 3)
759
		c++;
760
	while(nhunk < c)
761
		gethunk();
762
	hp = hunk;
763
	memcpy(hunk, symb, c);
764
	nhunk -= c;
765
	hunk += c;
766
 
767
	h = alloc(sizeof(Hist));
768
	h->name = hp;
769
	h->line = lineno;
770
	h->offset = -1;
771
	h->link = H;
772
	if(ehist == H) {
773
		hist = h;
774
		ehist = h;
775
		return;
776
	}
777
	ehist->link = h;
778
	ehist = h;
779
	return;
780
 
781
bad:
782
	unget(c);
783
	yyerror("syntax in #pragma lib");
784
	macend();
785
}
786
 
787
void
788
macend(void)
789
{
790
	int c;
791
 
792
	for(;;) {
793
		c = getnsc();
794
		if(c < 0 || c == '\n')
795
			return;
796
	}
797
}
798
 
799
void
800
linehist(char *f, int offset)
801
{
802
	Hist *h;
803
 
804
	/*
805
	 * overwrite the last #line directive if
806
	 * no alloc has happened since the last one
807
	 */
808
	if(newflag == 0 && ehist != H && offset != 0 && ehist->offset != 0)
809
		if(f && ehist->name && strcmp(f, ehist->name) == 0) {
810
			ehist->line = lineno;
811
			ehist->offset = offset;
812
			return;
813
		}
814
 
815
	if(debug['f'])
816
		if(f) {
817
			if(offset)
818
				print("%4ld: %s (#line %d)\n", lineno, f, offset);
819
			else
820
				print("%4ld: %s\n", lineno, f);
821
		} else
822
			print("%4ld: <pop>\n", lineno);
823
	newflag = 0;
824
 
825
	h = alloc(sizeof(Hist));
826
	h->name = f;
827
	h->line = lineno;
828
	h->offset = offset;
829
	h->link = H;
830
	if(ehist == H) {
831
		hist = h;
832
		ehist = h;
833
		return;
834
	}
835
	ehist->link = h;
836
	ehist = h;
837
}
838
 
839
void
840
gethunk(void)
841
{
842
	char *h;
843
	long nh;
844
 
845
	nh = NHUNK;
846
	if(thunk >= 10L*NHUNK)
847
		nh = 10L*NHUNK;
848
	h = (char*)mysbrk(nh);
849
	if(h == (char*)-1) {
850
		yyerror("out of memory");
851
		errorexit();
852
	}
853
	hunk = h;
854
	nhunk = nh;
855
	thunk += nh;
856
}