xref: /plan9-contrib/sys/src/cmd/cc/lexbody (revision 183e6fd711797f00777ca42f9c4f8f07249f1b3d)
1/*
2 * common code for all the assemblers
3 */
4
5void
6pragpack(void)
7{
8	while(getnsc() != '\n')
9		;
10}
11
12void
13pragvararg(void)
14{
15	while(getnsc() != '\n')
16		;
17}
18
19void
20pragfpround(void)
21{
22	while(getnsc() != '\n')
23		;
24}
25
26void
27pragprofile(void)
28{
29	while(getnsc() != '\n')
30		;
31}
32
33void
34pragincomplete(void)
35{
36	while(getnsc() != '\n')
37		;
38}
39
40/*
41 * real allocs
42 */
43void*
44alloc(long n)
45{
46	void *p;
47
48	while((uintptr)hunk & MAXALIGN) {
49		hunk++;
50		nhunk--;
51	}
52	while(nhunk < n)
53		gethunk();
54	p = hunk;
55	nhunk -= n;
56	hunk += n;
57	return p;
58}
59
60void*
61allocn(void *p, long on, long n)
62{
63	void *q;
64
65	q = (uchar*)p + on;
66	if(q != hunk || nhunk < n) {
67		while(nhunk < on+n)
68			gethunk();
69		memmove(hunk, p, on);
70		p = hunk;
71		hunk += on;
72		nhunk -= on;
73	}
74	hunk += n;
75	nhunk -= n;
76	return p;
77}
78
79void
80setinclude(char *p)
81{
82	int i;
83
84	if(p == 0)
85		return;
86	for(i=1; i < ninclude; i++)
87		if(strcmp(p, include[i]) == 0)
88			return;
89
90	if(ninclude >= nelem(include)) {
91		yyerror("ninclude too small %d", nelem(include));
92		exits("ninclude");
93	}
94	include[ninclude++] = p;
95}
96
97void
98errorexit(void)
99{
100
101	if(outfile)
102		remove(outfile);
103	exits("error");
104}
105
106void
107pushio(void)
108{
109	Io *i;
110
111	i = iostack;
112	if(i == I) {
113		yyerror("botch in pushio");
114		errorexit();
115	}
116	i->p = fi.p;
117	i->c = fi.c;
118}
119
120void
121newio(void)
122{
123	Io *i;
124	static int pushdepth = 0;
125
126	i = iofree;
127	if(i == I) {
128		pushdepth++;
129		if(pushdepth > 1000) {
130			yyerror("macro/io expansion too deep");
131			errorexit();
132		}
133		i = alloc(sizeof(*i));
134	} else
135		iofree = i->link;
136	i->c = 0;
137	i->f = -1;
138	ionext = i;
139}
140
141void
142newfile(char *s, int f)
143{
144	Io *i;
145
146	i = ionext;
147	i->link = iostack;
148	iostack = i;
149	i->f = f;
150	if(f < 0)
151		i->f = open(s, 0);
152	if(i->f < 0) {
153		yyerror("%ca: %r: %s", thechar, s);
154		errorexit();
155	}
156	fi.c = 0;
157	linehist(s, 0);
158}
159
160Sym*
161slookup(char *s)
162{
163
164	strcpy(symb, s);
165	return lookup();
166}
167
168Sym*
169lookup(void)
170{
171	Sym *s;
172	long h;
173	char *p;
174	int c, l;
175
176	h = 0;
177	for(p=symb; c = *p; p++)
178		h = h+h+h + c;
179	l = (p - symb) + 1;
180	if(h < 0)
181		h = ~h;
182	h %= NHASH;
183	c = symb[0];
184	for(s = hash[h]; s != S; s = s->link) {
185		if(s->name[0] != c)
186			continue;
187		if(memcmp(s->name, symb, l) == 0)
188			return s;
189	}
190	s = alloc(sizeof(*s));
191	s->name = alloc(l);
192	memmove(s->name, symb, l);
193
194	s->link = hash[h];
195	hash[h] = s;
196	syminit(s);
197	return s;
198}
199
200long
201yylex(void)
202{
203	int c, c1;
204	char *cp;
205	Sym *s;
206
207	c = peekc;
208	if(c != IGN) {
209		peekc = IGN;
210		goto l1;
211	}
212l0:
213	c = GETC();
214
215l1:
216	if(c == EOF) {
217		peekc = EOF;
218		return -1;
219	}
220	if(isspace(c)) {
221		if(c == '\n') {
222			lineno++;
223			return ';';
224		}
225		goto l0;
226	}
227	if(isalpha(c))
228		goto talph;
229	if(isdigit(c))
230		goto tnum;
231	switch(c)
232	{
233	case '\n':
234		lineno++;
235		return ';';
236
237	case '#':
238		domacro();
239		goto l0;
240
241	case '.':
242		c = GETC();
243		if(isalpha(c)) {
244			cp = symb;
245			*cp++ = '.';
246			goto aloop;
247		}
248		if(isdigit(c)) {
249			cp = symb;
250			*cp++ = '.';
251			goto casedot;
252		}
253		peekc = c;
254		return '.';
255
256	talph:
257	case '_':
258	case '@':
259		cp = symb;
260
261	aloop:
262		*cp++ = c;
263		c = GETC();
264		if(isalpha(c) || isdigit(c) || c == '_' || c == '$')
265			goto aloop;
266		*cp = 0;
267		peekc = c;
268		s = lookup();
269		if(s->macro) {
270			newio();
271			cp = ionext->b;
272			macexpand(s, cp);
273			pushio();
274			ionext->link = iostack;
275			iostack = ionext;
276			fi.p = cp;
277			fi.c = strlen(cp);
278			if(peekc != IGN) {
279				cp[fi.c++] = peekc;
280				cp[fi.c] = 0;
281				peekc = IGN;
282			}
283			goto l0;
284		}
285		if(s->type == 0)
286			s->type = LNAME;
287		if(s->type == LNAME ||
288		   s->type == LVAR ||
289		   s->type == LLAB) {
290			yylval.sym = s;
291			return s->type;
292		}
293		yylval.lval = s->value;
294		return s->type;
295
296	tnum:
297		cp = symb;
298		if(c != '0')
299			goto dc;
300		*cp++ = c;
301		c = GETC();
302		c1 = 3;
303		if(c == 'x' || c == 'X') {
304			c1 = 4;
305			c = GETC();
306		} else
307		if(c < '0' || c > '7')
308			goto dc;
309		yylval.lval = 0;
310		for(;;) {
311			if(c >= '0' && c <= '9') {
312				if(c > '7' && c1 == 3)
313					break;
314				yylval.lval <<= c1;
315				yylval.lval += c - '0';
316				c = GETC();
317				continue;
318			}
319			if(c1 == 3)
320				break;
321			if(c >= 'A' && c <= 'F')
322				c += 'a' - 'A';
323			if(c >= 'a' && c <= 'f') {
324				yylval.lval <<= c1;
325				yylval.lval += c - 'a' + 10;
326				c = GETC();
327				continue;
328			}
329			break;
330		}
331		goto ncu;
332
333	dc:
334		for(;;) {
335			if(!isdigit(c))
336				break;
337			*cp++ = c;
338			c = GETC();
339		}
340		if(c == '.')
341			goto casedot;
342		if(c == 'e' || c == 'E')
343			goto casee;
344		*cp = 0;
345		if(sizeof(yylval.lval) == sizeof(vlong))
346			yylval.lval = strtoll(symb, nil, 10);
347		else
348			yylval.lval = strtol(symb, nil, 10);
349
350	ncu:
351		while(c == 'U' || c == 'u' || c == 'l' || c == 'L')
352			c = GETC();
353		peekc = c;
354		return LCONST;
355
356	casedot:
357		for(;;) {
358			*cp++ = c;
359			c = GETC();
360			if(!isdigit(c))
361				break;
362		}
363		if(c == 'e' || c == 'E')
364			goto casee;
365		goto caseout;
366
367	casee:
368		*cp++ = 'e';
369		c = GETC();
370		if(c == '+' || c == '-') {
371			*cp++ = c;
372			c = GETC();
373		}
374		while(isdigit(c)) {
375			*cp++ = c;
376			c = GETC();
377		}
378
379	caseout:
380		*cp = 0;
381		peekc = c;
382		if(FPCHIP) {
383			yylval.dval = atof(symb);
384			return LFCONST;
385		}
386		yyerror("assembler cannot interpret fp constants");
387		yylval.lval = 1L;
388		return LCONST;
389
390	case '"':
391		memcpy(yylval.sval, nullgen.sval, sizeof(yylval.sval));
392		cp = yylval.sval;
393		c1 = 0;
394		for(;;) {
395			c = escchar('"');
396			if(c == EOF)
397				break;
398			if(c1 < sizeof(yylval.sval))
399				*cp++ = c;
400			c1++;
401		}
402		if(c1 > sizeof(yylval.sval))
403			yyerror("string constant too long");
404		return LSCONST;
405
406	case '\'':
407		c = escchar('\'');
408		if(c == EOF)
409			c = '\'';
410		if(escchar('\'') != EOF)
411			yyerror("missing '");
412		yylval.lval = c;
413		return LCONST;
414
415	case '/':
416		c1 = GETC();
417		if(c1 == '/') {
418			for(;;) {
419				c = GETC();
420				if(c == '\n')
421					goto l1;
422				if(c == EOF) {
423					yyerror("eof in comment");
424					errorexit();
425				}
426			}
427		}
428		if(c1 == '*') {
429			for(;;) {
430				c = GETC();
431				while(c == '*') {
432					c = GETC();
433					if(c == '/')
434						goto l0;
435				}
436				if(c == EOF) {
437					yyerror("eof in comment");
438					errorexit();
439				}
440				if(c == '\n')
441					lineno++;
442			}
443		}
444		break;
445
446	default:
447		return c;
448	}
449	peekc = c1;
450	return c;
451}
452
453int
454getc(void)
455{
456	int c;
457
458	c = peekc;
459	if(c != IGN) {
460		peekc = IGN;
461		return c;
462	}
463	c = GETC();
464	if(c == '\n')
465		lineno++;
466	if(c == EOF) {
467		yyerror("End of file");
468		errorexit();
469	}
470	return c;
471}
472
473int
474getnsc(void)
475{
476	int c;
477
478	for(;;) {
479		c = getc();
480		if(!isspace(c) || c == '\n')
481			return c;
482	}
483}
484
485void
486unget(int c)
487{
488
489	peekc = c;
490	if(c == '\n')
491		lineno--;
492}
493
494int
495escchar(int e)
496{
497	int c, l;
498
499loop:
500	c = getc();
501	if(c == '\n') {
502		yyerror("newline in string");
503		return EOF;
504	}
505	if(c != '\\') {
506		if(c == e)
507			return EOF;
508		return c;
509	}
510	c = getc();
511	if(c >= '0' && c <= '7') {
512		l = c - '0';
513		c = getc();
514		if(c >= '0' && c <= '7') {
515			l = l*8 + c-'0';
516			c = getc();
517			if(c >= '0' && c <= '7') {
518				l = l*8 + c-'0';
519				return l;
520			}
521		}
522		peekc = c;
523		return l;
524	}
525	switch(c)
526	{
527	case '\n':	goto loop;
528	case 'n':	return '\n';
529	case 't':	return '\t';
530	case 'b':	return '\b';
531	case 'r':	return '\r';
532	case 'f':	return '\f';
533	case 'a':	return 0x07;
534	case 'v':	return 0x0b;
535	case 'z':	return 0x00;
536	}
537	return c;
538}
539
540void
541pinit(char *f)
542{
543	int i;
544	Sym *s;
545
546	lineno = 1;
547	newio();
548	newfile(f, -1);
549	pc = 0;
550	peekc = IGN;
551	sym = 1;
552	for(i=0; i<NSYM; i++) {
553		h[i].type = 0;
554		h[i].sym = S;
555	}
556	for(i=0; i<NHASH; i++)
557		for(s = hash[i]; s != S; s = s->link)
558			s->macro = 0;
559}
560
561int
562filbuf(void)
563{
564	Io *i;
565
566loop:
567	i = iostack;
568	if(i == I)
569		return EOF;
570	if(i->f < 0)
571		goto pop;
572	fi.c = read(i->f, i->b, BUFSIZ) - 1;
573	if(fi.c < 0) {
574		close(i->f);
575		linehist(0, 0);
576		goto pop;
577	}
578	fi.p = i->b + 1;
579	return i->b[0];
580
581pop:
582	iostack = i->link;
583	i->link = iofree;
584	iofree = i;
585	i = iostack;
586	if(i == I)
587		return EOF;
588	fi.p = i->p;
589	fi.c = i->c;
590	if(--fi.c < 0)
591		goto loop;
592	return *fi.p++;
593}
594
595void
596yyerror(char *a, ...)
597{
598	char buf[200];
599	va_list arg;
600
601	/*
602	 * hack to intercept message from yaccpar
603	 */
604	if(strcmp(a, "syntax error") == 0) {
605		yyerror("syntax error, last name: %s", symb);
606		return;
607	}
608	prfile(lineno);
609	va_start(arg, a);
610	vseprint(buf, buf+sizeof(buf), a, arg);
611	va_end(arg);
612	print("%s\n", buf);
613	nerrors++;
614	if(nerrors > 10) {
615		print("too many errors\n");
616		errorexit();
617	}
618}
619
620void
621prfile(long l)
622{
623	int i, n;
624	Hist a[HISTSZ], *h;
625	long d;
626
627	n = 0;
628	for(h = hist; h != H; h = h->link) {
629		if(l < h->line)
630			break;
631		if(h->name) {
632			if(h->offset == 0) {
633				if(n >= 0 && n < HISTSZ)
634					a[n] = *h;
635				n++;
636				continue;
637			}
638			if(n > 0 && n < HISTSZ)
639				if(a[n-1].offset == 0) {
640					a[n] = *h;
641					n++;
642				} else
643					a[n-1] = *h;
644			continue;
645		}
646		n--;
647		if(n >= 0 && n < HISTSZ) {
648			d = h->line - a[n].line;
649			for(i=0; i<n; i++)
650				a[i].line += d;
651		}
652	}
653	if(n > HISTSZ)
654		n = HISTSZ;
655	for(i=0; i<n; i++)
656		print("%s:%ld ", a[i].name, (long)(l-a[i].line+a[i].offset+1));
657}
658
659void
660ieeedtod(Ieee *ieee, double native)
661{
662	double fr, ho, f;
663	int exp;
664
665	if(native < 0) {
666		ieeedtod(ieee, -native);
667		ieee->h |= 0x80000000L;
668		return;
669	}
670	if(native == 0) {
671		ieee->l = 0;
672		ieee->h = 0;
673		return;
674	}
675	fr = frexp(native, &exp);
676	f = 2097152L;		/* shouldnt use fp constants here */
677	fr = modf(fr*f, &ho);
678	ieee->h = ho;
679	ieee->h &= 0xfffffL;
680	ieee->h |= (exp+1022L) << 20;
681	f = 65536L;
682	fr = modf(fr*f, &ho);
683	ieee->l = ho;
684	ieee->l <<= 16;
685	ieee->l |= (long)(fr*f);
686}
687