xref: /plan9-contrib/sys/src/cmd/6a/lex.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include <u.h>
2 #include <libc.h>
3 #include <ctype.h>
4 #include <bio.h>
5 #include "../6c/6.out.h"
6 #include "a.h"
7 #include "y.tab.h"
8 
9 void
10 main(int argc, char *argv[])
11 {
12 	char ofile[100], incfile[20], *p;
13 	int nout, nproc, status, i, c, of;
14 
15 	thechar = '6';
16 	thestring = "960";
17 	memset(debug, 0, sizeof(debug));
18 	cinit();
19 	outfile = 0;
20 	include[ninclude++] = ".";
21 	ARGBEGIN {
22 	default:
23 		c = ARGC();
24 		if(c >= 0 || c < sizeof(debug))
25 			debug[c] = 1;
26 		break;
27 
28 	case 'o':
29 		outfile = ARGF();
30 		break;
31 
32 	case 'D':
33 		p = ARGF();
34 		if(p)
35 			Dlist[nDlist++] = p;
36 		break;
37 
38 	case 'I':
39 		p = ARGF();
40 		if(p)
41 			include[ninclude++] = p;
42 		break;
43 	} ARGEND
44 	if(*argv == 0) {
45 		print("usage: %ca [-options] file.s\n", thechar);
46 		errorexit();
47 	}
48 	nproc = 3;
49 	if(p = getenv("NPROC"))
50 		nproc = atol(p);
51 	if(argc > 1) {
52 		c = 0;
53 		nout = 0;
54 		for(;;) {
55 			while(nout < nproc && argc > 0) {
56 				i = fork();
57 				if(i < 0) {
58 					i = mywait(&status);
59 					if(i < 0)
60 						errorexit();
61 					if(status)
62 						c++;
63 					nout--;
64 					continue;
65 				}
66 				if(i == 0) {
67 					print("%s:\n", *argv);
68 					goto child;
69 				}
70 				nout++;
71 				argc--;
72 				argv++;
73 			}
74 			i = mywait(&status);
75 			if(i < 0) {
76 				if(c)
77 					errorexit();
78 				exits(0);
79 			}
80 			if(status)
81 				c++;
82 			nout--;
83 		}
84 	}
85 
86 child:
87 	strcpy(ofile, *argv);
88 	if(p = strrchr(ofile, '/')) {
89 		include[0] = ofile;
90 		*p++ = 0;
91 	} else
92 		p = ofile;
93 	if(outfile == 0) {
94 		outfile = p;
95 		if(p = strrchr(outfile, '.'))
96 			if(p[1] == 's' && p[2] == 0)
97 				p[0] = 0;
98 		p = strrchr(outfile, 0);
99 		p[0] = '.';
100 		p[1] = thechar;
101 		p[2] = 0;
102 	}
103 	if(unix()) {
104 		strcpy(incfile, "/usr/%include");
105 		p = strrchr(incfile, '%');
106 		if(p)
107 			*p = thechar;
108 	} else {
109 		strcpy(incfile, "/");
110 		strcat(incfile, thestring);
111 		strcat(incfile, "/include");
112 	}
113 	include[ninclude++] = incfile;
114 	if(p = getenv("INCLUDE"))
115 		include[ninclude-1] = p;	/* */
116 	of = mycreat(outfile, 0664);
117 	if(of < 0) {
118 		yyerror("%ca: cannot create %s", thechar, outfile);
119 		errorexit();
120 	}
121 	Binit(&obuf, of, OWRITE);
122 
123 	pass = 1;
124 	pinit(*argv);
125 	for(i=0; i<nDlist; i++)
126 		dodefine(Dlist[i]);
127 	yyparse();
128 	if(nerrors) {
129 		cclean();
130 		errorexit();
131 	}
132 
133 	pass = 2;
134 	outhist();
135 	pinit(*argv);
136 	for(i=0; i<nDlist; i++)
137 		dodefine(Dlist[i]);
138 	yyparse();
139 	cclean();
140 	if(nerrors)
141 		errorexit();
142 	exits(0);
143 }
144 
145 struct
146 {
147 	char	*name;
148 	ushort	type;
149 	ushort	value;
150 } itab[] =
151 {
152 	"SP",		LSP,	D_AUTO,
153 	"SB",		LSB,	D_EXTERN,
154 	"FP",		LFP,	D_PARAM,
155 	"PC",		LPC,	D_BRANCH,
156 
157 	"R0",		LRREG,	D_R0+0,			/* 960 pfp, r0 */
158 	"R1",		LRREG,	D_R0+1,			/* 960 sp, r1 */
159 	"R2",		LRREG,	D_R0+2,			/* 960 rip, r2 */
160 	"R3",		LRREG,	D_R0+3,
161 	"R4",		LRREG,	D_R0+4,
162 	"R5",		LRREG,	D_R0+5,
163 	"R6",		LRREG,	D_R0+6,
164 	"R7",		LRREG,	D_R0+7,
165 	"R8",		LRREG,	D_R0+8,
166 	"R9",		LRREG,	D_R0+9,
167 	"R10",		LRREG,	D_R0+10,
168 	"R11",		LRREG,	D_R0+11,
169 	"R12",		LRREG,	D_R0+12,
170 	"R13",		LRREG,	D_R0+13,
171 	"R14",		LRREG,	D_R0+14,
172 	"R15",		LRREG,	D_R0+15,
173 	"R16",		LRREG,	D_R0+16,		/* g0 */
174 	"R17",		LRREG,	D_R0+17,
175 	"R18",		LRREG,	D_R0+18,
176 	"R19",		LRREG,	D_R0+19,
177 	"R20",		LRREG,	D_R0+20,
178 	"R21",		LRREG,	D_R0+21,
179 	"R22",		LRREG,	D_R0+22,
180 	"R23",		LRREG,	D_R0+23,
181 	"R24",		LRREG,	D_R0+24,
182 	"R25",		LRREG,	D_R0+25,
183 	"R26",		LRREG,	D_R0+26,
184 	"R27",		LRREG,	D_R0+27,
185 	"R28",		LRREG,	D_R0+28,		/* static register */
186 	"R29",		LRREG,	D_R0+29,		/* stack register */
187 	"R30",		LRREG,	D_R0+30,		/* link register */
188 	"R31",		LRREG,	D_R0+31,		/* 960 fp, g15 */
189 
190 	"DATA",		LTYPE1,	ADATA,
191 
192 	"ADJSP",	LTYPEX,	AADJSP,
193 	"SYSCALL",	LTYPEX,	ASYSCALL,
194 	"CALL",		LTYPEX, ACALL,
195 	"CALLS",	LTYPEX, ACALLS,
196 
197 	"GLOBL",	LTYPEB,	AGLOBL,
198 	"TEXT",		LTYPEB,	ATEXT,
199 	"LONG",		LTYPES,	ALONG,
200 	"NOP",		LTYPES,	ANOP,
201 	"RTS",		LTYPEB,	ARTS,
202 
203 	"ADDC",		LTYPEB, AADDC,
204 	"ADDI",		LTYPEB, AADDI,
205 	"ADDO",		LTYPEB, AADDO,
206 	"ALTERBIT",	LTYPEB, AALTERBIT,
207 	"AND",		LTYPEB, AAND,
208 	"ANDNOT",	LTYPEB, AANDNOT,
209 	"ATADD",	LTYPEB, AATADD,
210 	"ATMOD",	LTYPEB, AATMOD,
211 	"B",		LTYPED, AB,
212 	"BAL",		LTYPED, ABAL,
213 	"BBC",		LTYPED, ABBC,
214 	"BBS",		LTYPED, ABBS,
215 	"BE",		LTYPED, ABE,
216 	"BG",		LTYPED, ABG,
217 	"BGE",		LTYPED, ABGE,
218 	"BL",		LTYPED, ABL,
219 	"BLE",		LTYPED, ABLE,
220 	"BNE",		LTYPED, ABNE,
221 	"BNO",		LTYPED, ABNO,
222 	"BO",		LTYPED, ABO,
223 	"CHKBIT",	LTYPEB, ACHKBIT,
224 	"CLRBIT",	LTYPEB, ACLRBIT,
225 	"CMPDECI",	LTYPEB, ACMPDECI,
226 	"CMPDECO",	LTYPEB, ACMPDECO,
227 	"CMPI",		LTYPEB, ACMPI,
228 	"CMPIBE",	LTYPEB, ACMPIBE,
229 	"CMPIBG",	LTYPEB, ACMPIBG,
230 	"CMPIBGE",	LTYPEB, ACMPIBGE,
231 	"CMPIBL",	LTYPEB, ACMPIBL,
232 	"CMPIBLE",	LTYPEB, ACMPIBLE,
233 	"CMPIBNE",	LTYPEB, ACMPIBNE,
234 	"CMPIBNO",	LTYPEB, ACMPIBNO,
235 	"CMPIBO",	LTYPEB, ACMPIBO,
236 	"CMPINCI",	LTYPEB, ACMPINCI,
237 	"CMPINCO",	LTYPEB, ACMPINCO,
238 	"CMPO",		LTYPEB, ACMPO,
239 	"CMPOBE",	LTYPEB, ACMPOBE,
240 	"CMPOBG",	LTYPEB, ACMPOBG,
241 	"CMPOBGE",	LTYPEB, ACMPOBGE,
242 	"CMPOBL",	LTYPEB, ACMPOBL,
243 	"CMPOBLE",	LTYPEB, ACMPOBLE,
244 	"CMPOBNE",	LTYPEB, ACMPOBNE,
245 	"CONCMPI",	LTYPEB, ACONCMPI,
246 	"CONCMPO",	LTYPEB, ACONCMPO,
247 	"DADDC",	LTYPEB, ADADDC,
248 	"DIVI",		LTYPEB, ADIVI,
249 	"DIVO",		LTYPEB, ADIVO,
250 	"DMOVT",	LTYPEB, ADMOVT,
251 	"DSUBC",	LTYPEB, ADSUBC,
252 	"EDIV",		LTYPEB, AEDIV,
253 	"EMUL",		LTYPEB, AEMUL,
254 	"EXTRACT",	LTYPEB, AEXTRACT,
255 	"FAULTE",	LTYPEB, AFAULTE,
256 	"FAULTG",	LTYPEB, AFAULTG,
257 	"FAULTGE",	LTYPEB, AFAULTGE,
258 	"FAULTL",	LTYPEB, AFAULTL,
259 	"FAULTLE",	LTYPEB, AFAULTLE,
260 	"FAULTNE",	LTYPEB, AFAULTNE,
261 	"FAULTNO",	LTYPEB, AFAULTNO,
262 	"FAULTO",	LTYPEB, AFAULTO,
263 	"FLUSHREG",	LTYPEB, AFLUSHREG,
264 	"FMARK",	LTYPEB, AFMARK,
265 	"MARK",		LTYPEB, AMARK,
266 	"MODAC",	LTYPEB, AMODAC,
267 	"MODI",		LTYPEB, AMODI,
268 	"MODIFY",	LTYPEB, AMODIFY,
269 	"MODPC",	LTYPEB, AMODPC,
270 	"MODTC",	LTYPEB, AMODTC,
271 	"MOV",		LTYPEB, AMOV,
272 	"MOVA",		LTYPEB, AMOVA,
273 	"MOVIB",	LTYPEB, AMOVIB,
274 	"MOVIS",	LTYPEB, AMOVIS,
275 	"MOVOB",	LTYPEB, AMOVOB,
276 	"MOVOS",	LTYPEB, AMOVOS,
277 	"MOVQ",		LTYPEB, AMOVQ,
278 	"MOVT",		LTYPEB, AMOVT,
279 	"MOVV",		LTYPEB, AMOVV,
280 	"MULI",		LTYPEB, AMULI,
281 	"MULO",		LTYPEB, AMULO,
282 	"NAND",		LTYPEB, ANAND,
283 	"NOR",		LTYPEB, ANOR,
284 	"NOT",		LTYPEB, ANOT,
285 	"NOTAND",	LTYPEB, ANOTAND,
286 	"NOTBIT",	LTYPEB, ANOTBIT,
287 	"NOTOR",	LTYPEB, ANOTOR,
288 	"OR",		LTYPEB, AOR,
289 	"ORNOT",	LTYPEB, AORNOT,
290 	"REMI",		LTYPEB, AREMI,
291 	"REMO",		LTYPEB, AREMO,
292 	"RET",		LTYPEB, ARET,
293 	"ROTATE",	LTYPEB, AROTATE,
294 	"SCANBIT",	LTYPEB, ASCANBIT,
295 	"SCANBYTE",	LTYPEB, ASCANBYTE,
296 	"SETBIT",	LTYPEB, ASETBIT,
297 	"SHLI",		LTYPEB, ASHLI,
298 	"SHLO",		LTYPEB, ASHLO,
299 	"SHRDI",	LTYPEB, ASHRDI,
300 	"SHRI",		LTYPEB, ASHRI,
301 	"SHRO",		LTYPEB, ASHRO,
302 	"SPANBIT",	LTYPEB, ASPANBIT,
303 	"SUBC",		LTYPEB, ASUBC,
304 	"SUBI",		LTYPEB, ASUBI,
305 	"SUBO",		LTYPEB, ASUBO,
306 	"SYNCF",	LTYPEB, ASYNCF,
307 	"SYNMOV",	LTYPEB, ASYNMOV,
308 	"SYNMOVQ",	LTYPEB, ASYNMOVQ,
309 	"SYNMOVV",	LTYPEB, ASYNMOVV,
310 	"SYSCTL",	LTYPEB,	ASYSCTL,
311 	"TESTE",	LTYPED, ATESTE,
312 	"TESTG",	LTYPED, ATESTG,
313 	"TESTGE",	LTYPED, ATESTGE,
314 	"TESTL",	LTYPED, ATESTL,
315 	"TESTLE",	LTYPED, ATESTLE,
316 	"TESTNE",	LTYPED, ATESTNE,
317 	"TESTNO",	LTYPED, ATESTNO,
318 	"TESTO",	LTYPED, ATESTO,
319 	"XNOR",		LTYPEB, AXNOR,
320 	"XOR",		LTYPEB, AXOR,
321 
322 	0
323 };
324 
325 void
326 cinit(void)
327 {
328 	Sym *s;
329 	int i;
330 
331 	nullgen.sym = S;
332 	nullgen.offset = 0;
333 	if(FPCHIP)
334 		nullgen.dval = 0;
335 	for(i=0; i<sizeof(nullgen.sval); i++)
336 		nullgen.sval[i] = 0;
337 	nullgen.type = D_NONE;
338 	nullgen.index = D_NONE;
339 	nullgen.scale = 0;
340 
341 	nerrors = 0;
342 	iostack = I;
343 	iofree = I;
344 	peekc = IGN;
345 	nhunk = 0;
346 	for(i=0; i<NHASH; i++)
347 		hash[i] = S;
348 	for(i=0; itab[i].name; i++) {
349 		s = slookup(itab[i].name);
350 		if(s->type != LNAME)
351 			yyerror("double initialization %s", itab[i].name);
352 		s->type = itab[i].type;
353 		s->value = itab[i].value;
354 	}
355 
356 	ALLOCN(pathname, 0, 100);
357 	if(getwd(pathname, 99) == 0) {
358 		ALLOCN(pathname, 100, 900);
359 		if(getwd(pathname, 999) == 0)
360 			strcpy(pathname, "/???");
361 	}
362 }
363 
364 void
365 checkscale(int scale)
366 {
367 
368 	switch(scale) {
369 	case 1:
370 	case 2:
371 	case 4:
372 	case 8:
373 	case 16:
374 		return;
375 	}
376 	yyerror("scale must be 1<<[01234]: %d", scale);
377 }
378 
379 void
380 syminit(Sym *s)
381 {
382 
383 	s->type = LNAME;
384 	s->value = 0;
385 }
386 
387 void
388 cclean(void)
389 {
390 	Gen2 g2;
391 
392 	g2.from = nullgen;
393 	g2.to = nullgen;
394 	outcode(AEND, &g2);
395 	Bflush(&obuf);
396 }
397 
398 void
399 zname(char *n, int t, int s)
400 {
401 
402 	Bputc(&obuf, ANAME);	/* as */
403 	Bputc(&obuf, t);		/* type */
404 	Bputc(&obuf, s);		/* sym */
405 	while(*n) {
406 		Bputc(&obuf, *n);
407 		n++;
408 	}
409 	Bputc(&obuf, 0);
410 }
411 
412 void
413 zaddr(Gen *a, int s)
414 {
415 	long l;
416 	int i, t;
417 	char *n;
418 	Ieee e;
419 
420 	t = 0;
421 	if(a->index != D_NONE || a->scale != 0)
422 		t |= T_INDEX;
423 	if(s != 0)
424 		t |= T_SYM;
425 
426 	switch(a->type) {
427 	default:
428 		t |= T_TYPE;
429 	case D_NONE:
430 		if(a->offset != 0)
431 			t |= T_OFFSET;
432 		break;
433 	case D_FCONST:
434 		t |= T_FCONST;
435 		break;
436 	case D_SCONST:
437 		t |= T_SCONST;
438 		break;
439 	}
440 	Bputc(&obuf, t);
441 
442 	if(t & T_INDEX) {	/* implies index, scale */
443 		Bputc(&obuf, a->index);
444 		Bputc(&obuf, a->scale);
445 	}
446 	if(t & T_OFFSET) {	/* implies offset */
447 		l = a->offset;
448 		Bputc(&obuf, l);
449 		Bputc(&obuf, l>>8);
450 		Bputc(&obuf, l>>16);
451 		Bputc(&obuf, l>>24);
452 	}
453 	if(t & T_SYM)		/* implies sym */
454 		Bputc(&obuf, s);
455 	if(t & T_FCONST) {
456 		ieeedtod(&e, a->dval);
457 		l = e.l;
458 		Bputc(&obuf, l);
459 		Bputc(&obuf, l>>8);
460 		Bputc(&obuf, l>>16);
461 		Bputc(&obuf, l>>24);
462 		l = e.h;
463 		Bputc(&obuf, l);
464 		Bputc(&obuf, l>>8);
465 		Bputc(&obuf, l>>16);
466 		Bputc(&obuf, l>>24);
467 		return;
468 	}
469 	if(t & T_SCONST) {
470 		n = a->sval;
471 		for(i=0; i<NSNAME; i++) {
472 			Bputc(&obuf, *n);
473 			n++;
474 		}
475 		return;
476 	}
477 	if(t & T_TYPE)
478 		Bputc(&obuf, a->type);
479 }
480 
481 void
482 outcode(int a, Gen2 *g2)
483 {
484 	int sf, st, t;
485 	Sym *s;
486 
487 	if(pass == 1)
488 		goto out;
489 
490 jackpot:
491 	sf = 0;
492 	s = g2->from.sym;
493 	while(s != S) {
494 		sf = s->sym;
495 		if(sf < 0 || sf >= NSYM)
496 			sf = 0;
497 		t = g2->from.type;
498 		if(h[sf].type == t)
499 		if(h[sf].sym == s)
500 			break;
501 		zname(s->name, t, sym);
502 		s->sym = sym;
503 		h[sym].sym = s;
504 		h[sym].type = t;
505 		sf = sym;
506 		sym++;
507 		if(sym >= NSYM)
508 			sym = 1;
509 		break;
510 	}
511 	st = 0;
512 	s = g2->to.sym;
513 	while(s != S) {
514 		st = s->sym;
515 		if(st < 0 || st >= NSYM)
516 			st = 0;
517 		t = g2->to.type;
518 		if(h[st].type == t)
519 		if(h[st].sym == s)
520 			break;
521 		zname(s->name, t, sym);
522 		s->sym = sym;
523 		h[sym].sym = s;
524 		h[sym].type = t;
525 		st = sym;
526 		sym++;
527 		if(sym >= NSYM)
528 			sym = 1;
529 		if(st == sf)
530 			goto jackpot;
531 		break;
532 	}
533 	Bputc(&obuf, a);
534 	Bputc(&obuf, lineno);
535 	Bputc(&obuf, lineno>>8);
536 	Bputc(&obuf, lineno>>16);
537 	Bputc(&obuf, lineno>>24);
538 	switch(t = g2->type) {
539 	case D_NONE:
540 		t = 0;			/* 0 D_NONE */
541 		break;
542 
543 	default:
544 		if(t < D_R0 || t >= D_R0+32) {
545 			yyerror("bad type in outcode: %d", t);
546 			t = D_R0;
547 		}
548 		t = (t - D_R0) + 1;	/* 1-32 D_R0+ */
549 		break;
550 
551 	case D_CONST:
552 		t = g2->offset;
553 		if(t >= 32) {
554 			yyerror("bad offset in outcode", t);
555 			t = 0;
556 		}
557 		t = (t - 0) + 33;	/* 33-64 D_CONST+ */
558 		break;
559 	}
560 	Bputc(&obuf, t);
561 	zaddr(&g2->from, sf);
562 	zaddr(&g2->to, st);
563 
564 out:
565 	if(a != AGLOBL && a != ADATA)
566 		pc++;
567 }
568 
569 void
570 outhist(void)
571 {
572 	Gen g;
573 	Hist *h;
574 	char *p, *q, *op;
575 	int n;
576 
577 	g = nullgen;
578 	for(h = hist; h != H; h = h->link) {
579 		p = h->name;
580 		op = 0;
581 		if(p && p[0] != '/' && h->offset == 0 && pathname && pathname[0] == '/') {
582 			op = p;
583 			p = pathname;
584 		}
585 		while(p) {
586 			q = strchr(p, '/');
587 			if(q) {
588 				n = q-p;
589 				if(n == 0)
590 					n = 1;	/* leading "/" */
591 				q++;
592 			} else {
593 				n = strlen(p);
594 				q = 0;
595 			}
596 			if(n) {
597 				Bputc(&obuf, ANAME);
598 				Bputc(&obuf, D_FILE);	/* type */
599 				Bputc(&obuf, 1);	/* sym */
600 				Bputc(&obuf, '<');
601 				Bwrite(&obuf, p, n);
602 				Bputc(&obuf, 0);
603 			}
604 			p = q;
605 			if(p == 0 && op) {
606 				p = op;
607 				op = 0;
608 			}
609 		}
610 		g.offset = h->offset;
611 
612 		Bputc(&obuf, AHISTORY);
613 		Bputc(&obuf, h->line);
614 		Bputc(&obuf, h->line>>8);
615 		Bputc(&obuf, h->line>>16);
616 		Bputc(&obuf, h->line>>24);
617 		Bputc(&obuf, 0);			/* reg */
618 		zaddr(&nullgen, 0);
619 		zaddr(&g, 0);
620 	}
621 }
622 
623 #include "../cc/lexbody"
624 #include "../cc/macbody"
625