xref: /inferno-os/utils/cc/lexbody (revision 45a20ab721a513710138340faff3d59a31c3e01e)
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					lineno++;
422					goto l0;
423				}
424				if(c == EOF) {
425					yyerror("eof in comment");
426					errorexit();
427				}
428			}
429		}
430		if(c1 == '*') {
431			for(;;) {
432				c = GETC();
433				while(c == '*') {
434					c = GETC();
435					if(c == '/')
436						goto l0;
437				}
438				if(c == EOF) {
439					yyerror("eof in comment");
440					errorexit();
441				}
442				if(c == '\n')
443					lineno++;
444			}
445		}
446		break;
447
448	default:
449		return c;
450	}
451	peekc = c1;
452	return c;
453}
454
455int
456getc(void)
457{
458	int c;
459
460	c = peekc;
461	if(c != IGN) {
462		peekc = IGN;
463		return c;
464	}
465	c = GETC();
466	if(c == '\n')
467		lineno++;
468	if(c == EOF) {
469		yyerror("End of file");
470		errorexit();
471	}
472	return c;
473}
474
475int
476getnsc(void)
477{
478	int c;
479
480	for(;;) {
481		c = getc();
482		if(!isspace(c) || c == '\n')
483			return c;
484	}
485}
486
487void
488unget(int c)
489{
490
491	peekc = c;
492	if(c == '\n')
493		lineno--;
494}
495
496int
497escchar(int e)
498{
499	int c, l;
500
501loop:
502	c = getc();
503	if(c == '\n') {
504		yyerror("newline in string");
505		return EOF;
506	}
507	if(c != '\\') {
508		if(c == e)
509			return EOF;
510		return c;
511	}
512	c = getc();
513	if(c >= '0' && c <= '7') {
514		l = c - '0';
515		c = getc();
516		if(c >= '0' && c <= '7') {
517			l = l*8 + c-'0';
518			c = getc();
519			if(c >= '0' && c <= '7') {
520				l = l*8 + c-'0';
521				return l;
522			}
523		}
524		peekc = c;
525		return l;
526	}
527	switch(c)
528	{
529	case '\n':	goto loop;
530	case 'n':	return '\n';
531	case 't':	return '\t';
532	case 'b':	return '\b';
533	case 'r':	return '\r';
534	case 'f':	return '\f';
535	case 'a':	return 0x07;
536	case 'v':	return 0x0b;
537	case 'z':	return 0x00;
538	}
539	return c;
540}
541
542void
543pinit(char *f)
544{
545	int i;
546	Sym *s;
547
548	lineno = 1;
549	newio();
550	newfile(f, -1);
551	pc = 0;
552	peekc = IGN;
553	sym = 1;
554	for(i=0; i<NSYM; i++) {
555		h[i].type = 0;
556		h[i].sym = S;
557	}
558	for(i=0; i<NHASH; i++)
559		for(s = hash[i]; s != S; s = s->link)
560			s->macro = 0;
561}
562
563int
564filbuf(void)
565{
566	Io *i;
567
568loop:
569	i = iostack;
570	if(i == I)
571		return EOF;
572	if(i->f < 0)
573		goto pop;
574	fi.c = read(i->f, i->b, BUFSIZ) - 1;
575	if(fi.c < 0) {
576		close(i->f);
577		linehist(0, 0);
578		goto pop;
579	}
580	fi.p = i->b + 1;
581	return i->b[0];
582
583pop:
584	iostack = i->link;
585	i->link = iofree;
586	iofree = i;
587	i = iostack;
588	if(i == I)
589		return EOF;
590	fi.p = i->p;
591	fi.c = i->c;
592	if(--fi.c < 0)
593		goto loop;
594	return *fi.p++;
595}
596
597void
598yyerror(char *a, ...)
599{
600	char buf[200];
601	va_list arg;
602
603	/*
604	 * hack to intercept message from yaccpar
605	 */
606	if(strcmp(a, "syntax error") == 0) {
607		yyerror("syntax error, last name: %s", symb);
608		return;
609	}
610	prfile(lineno);
611	va_start(arg, a);
612	vseprint(buf, buf+sizeof(buf), a, arg);
613	va_end(arg);
614	print("%s\n", buf);
615	nerrors++;
616	if(nerrors > 10) {
617		print("too many errors\n");
618		errorexit();
619	}
620}
621
622void
623prfile(long l)
624{
625	int i, n;
626	Hist a[HISTSZ], *h;
627	long d;
628
629	n = 0;
630	for(h = hist; h != H; h = h->link) {
631		if(l < h->line)
632			break;
633		if(h->name) {
634			if(h->offset == 0) {
635				if(n >= 0 && n < HISTSZ)
636					a[n] = *h;
637				n++;
638				continue;
639			}
640			if(n > 0 && n < HISTSZ)
641				if(a[n-1].offset == 0) {
642					a[n] = *h;
643					n++;
644				} else
645					a[n-1] = *h;
646			continue;
647		}
648		n--;
649		if(n >= 0 && n < HISTSZ) {
650			d = h->line - a[n].line;
651			for(i=0; i<n; i++)
652				a[i].line += d;
653		}
654	}
655	if(n > HISTSZ)
656		n = HISTSZ;
657	for(i=0; i<n; i++)
658		print("%s:%ld ", a[i].name, (long)(l-a[i].line+a[i].offset+1));
659}
660
661void
662ieeedtod(Ieee *ieee, double native)
663{
664	double fr, ho, f;
665	int exp;
666
667	if(native < 0) {
668		ieeedtod(ieee, -native);
669		ieee->h |= 0x80000000L;
670		return;
671	}
672	if(native == 0) {
673		ieee->l = 0;
674		ieee->h = 0;
675		return;
676	}
677	fr = frexp(native, &exp);
678	f = 2097152L;		/* shouldnt use fp constants here */
679	fr = modf(fr*f, &ho);
680	ieee->h = ho;
681	ieee->h &= 0xfffffL;
682	ieee->h |= (exp+1022L) << 20;
683	f = 65536L;
684	fr = modf(fr*f, &ho);
685	ieee->l = ho;
686	ieee->l <<= 16;
687	ieee->l |= (long)(fr*f);
688}
689