xref: /inferno-os/utils/0a/lex.c (revision e45fa0eb0763b57d6fb0649c064bc3b95ccdea6c)
1 #define	EXTERN
2 #include "a.h"
3 #include "y.tab.h"
4 #include <ctype.h>
5 
6 void
7 main(int argc, char *argv[])
8 {
9 	char *p;
10 	int nout, nproc, status, i, c;
11 
12 	thechar = '0';
13 	thestring = "spim";
14 	memset(debug, 0, sizeof(debug));
15 	cinit();
16 	outfile = 0;
17 	include[ninclude++] = ".";
18 	ARGBEGIN {
19 	default:
20 		c = ARGC();
21 		if(c >= 0 || c < sizeof(debug))
22 			debug[c] = 1;
23 		break;
24 
25 	case 'o':
26 		outfile = ARGF();
27 		break;
28 
29 	case 'D':
30 		p = ARGF();
31 		if(p)
32 			Dlist[nDlist++] = p;
33 		break;
34 
35 	case 'I':
36 		p = ARGF();
37 		setinclude(p);
38 		break;
39 	} ARGEND
40 	if(*argv == 0) {
41 		print("usage: %ca [-options] file.s\n", thechar);
42 		errorexit();
43 	}
44 	if(argc > 1 && systemtype(Windows)) {
45 		print("can't assemble multiple files on windows\n");
46 		errorexit();
47 	}
48 	if(argc > 1 && !systemtype(Windows)) {
49 		nproc = 1;
50 		if(p = getenv("NPROC"))
51 			nproc = atol(p);	/* */
52 		c = 0;
53 		nout = 0;
54 		for(;;) {
55 			while(nout < nproc && argc > 0) {
56 				i = myfork();
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 					if(assemble(*argv))
69 						errorexit();
70 					exits(0);
71 				}
72 				nout++;
73 				argc--;
74 				argv++;
75 			}
76 			i = mywait(&status);
77 			if(i < 0) {
78 				if(c)
79 					errorexit();
80 				exits(0);
81 			}
82 			if(status)
83 				c++;
84 			nout--;
85 		}
86 	}
87 	if(assemble(argv[0]))
88 		errorexit();
89 	exits(0);
90 }
91 
92 int
93 assemble(char *file)
94 {
95 	char ofile[100], incfile[20], *p;
96 	int i, of;
97 
98 	strcpy(ofile, file);
99 	p = utfrrune(ofile, '/');
100 	if(p) {
101 		include[0] = ofile;
102 		*p++ = 0;
103 	} else
104 		p = ofile;
105 	if(outfile == 0) {
106 		outfile = p;
107 		if(outfile){
108 			p = utfrrune(outfile, '.');
109 			if(p)
110 				if(p[1] == 's' && p[2] == 0)
111 					p[0] = 0;
112 			p = utfrune(outfile, 0);
113 			p[0] = '.';
114 			p[1] = thechar;
115 			p[2] = 0;
116 		} else
117 			outfile = "/dev/null";
118 	}
119 	p = getenv("INCLUDE");
120 	if(p) {
121 		setinclude(p);
122 	} else {
123 		if(systemtype(Plan9)) {
124 			sprint(incfile,"/%s/include", thestring);
125 			setinclude(strdup(incfile));
126 		}
127 	}
128 
129 	of = mycreat(outfile, 0664);
130 	if(of < 0) {
131 		yyerror("%ca: cannot create %s", thechar, outfile);
132 		errorexit();
133 	}
134 	Binit(&obuf, of, OWRITE);
135 
136 	pass = 1;
137 	pinit(file);
138 	for(i=0; i<nDlist; i++)
139 		dodefine(Dlist[i]);
140 	yyparse();
141 	if(nerrors) {
142 		cclean();
143 		return nerrors;
144 	}
145 
146 	pass = 2;
147 	outhist();
148 	pinit(file);
149 	for(i=0; i<nDlist; i++)
150 		dodefine(Dlist[i]);
151 	yyparse();
152 	cclean();
153 	return nerrors;
154 }
155 
156 struct
157 {
158 	char	*name;
159 	ushort	type;
160 	ushort	value;
161 } itab[] =
162 {
163 	"SP",		LSP,	D_AUTO,
164 	"SB",		LSB,	D_EXTERN,
165 	"FP",		LFP,	D_PARAM,
166 	"PC",		LPC,	D_BRANCH,
167 	"HI",		LHI,	D_HI,
168 	"LO",		LLO,	D_LO,
169 
170 	"R",		LR,	0,
171 	"R0",		LREG,	0,
172 	"R1",		LREG,	1,
173 	"R2",		LREG,	2,
174 	"R3",		LREG,	3,
175 	"R4",		LREG,	4,
176 	"R5",		LREG,	5,
177 	"R6",		LREG,	6,
178 	"R7",		LREG,	7,
179 	"R8",		LREG,	8,
180 	"R9",		LREG,	9,
181 	"R10",		LREG,	10,
182 	"R11",		LREG,	11,
183 	"R12",		LREG,	12,
184 	"R13",		LREG,	13,
185 	"R14",		LREG,	14,
186 	"R15",		LREG,	15,
187 	"R16",		LREG,	16,
188 	"R17",		LREG,	17,
189 	"R18",		LREG,	18,
190 	"R19",		LREG,	19,
191 	"R20",		LREG,	20,
192 	"R21",		LREG,	21,
193 	"R22",		LREG,	22,
194 	"R23",		LREG,	23,
195 	"R24",		LREG,	24,
196 	"R25",		LREG,	25,
197 	"R26",		LREG,	26,
198 	"R27",		LREG,	27,
199 	"R28",		LREG,	28,
200 	"R29",		LREG,	29,
201 	"R30",		LREG,	30,
202 	"R31",		LREG,	31,
203 
204 	"M",		LM,	0,
205 	"M0",		LMREG,	0,
206 	"M1",		LMREG,	1,
207 	"M2",		LMREG,	2,
208 	"M3",		LMREG,	3,
209 	"M4",		LMREG,	4,
210 	"M5",		LMREG,	5,
211 	"M6",		LMREG,	6,
212 	"M7",		LMREG,	7,
213 	"M8",		LMREG,	8,
214 	"M9",		LMREG,	9,
215 	"M10",		LMREG,	10,
216 	"M11",		LMREG,	11,
217 	"M12",		LMREG,	12,
218 	"M13",		LMREG,	13,
219 	"M14",		LMREG,	14,
220 	"M15",		LMREG,	15,
221 	"M16",		LMREG,	16,
222 	"M17",		LMREG,	17,
223 	"M18",		LMREG,	18,
224 	"M19",		LMREG,	19,
225 	"M20",		LMREG,	20,
226 	"M21",		LMREG,	21,
227 	"M22",		LMREG,	22,
228 	"M23",		LMREG,	23,
229 	"M24",		LMREG,	24,
230 	"M25",		LMREG,	25,
231 	"M26",		LMREG,	26,
232 	"M27",		LMREG,	27,
233 	"M28",		LMREG,	28,
234 	"M29",		LMREG,	29,
235 	"M30",		LMREG,	30,
236 	"M31",		LMREG,	31,
237 
238 	"F",		LF,	0,
239 
240 	"F0",		LFREG,	0,
241 	"F1",		LFREG,	1,
242 	"F2",		LFREG,	2,
243 	"F3",		LFREG,	3,
244 	"F4",		LFREG,	4,
245 	"F5",		LFREG,	5,
246 	"F6",		LFREG,	6,
247 	"F7",		LFREG,	7,
248 	"F8",		LFREG,	8,
249 	"F9",		LFREG,	9,
250 	"F10",		LFREG,	10,
251 	"F11",		LFREG,	11,
252 	"F12",		LFREG,	12,
253 	"F13",		LFREG,	13,
254 	"F14",		LFREG,	14,
255 	"F15",		LFREG,	15,
256 	"F16",		LFREG,	16,
257 	"F17",		LFREG,	17,
258 	"F18",		LFREG,	18,
259 	"F19",		LFREG,	19,
260 	"F20",		LFREG,	20,
261 	"F21",		LFREG,	21,
262 	"F22",		LFREG,	22,
263 	"F23",		LFREG,	23,
264 	"F24",		LFREG,	24,
265 	"F25",		LFREG,	25,
266 	"F26",		LFREG,	26,
267 	"F27",		LFREG,	27,
268 	"F28",		LFREG,	28,
269 	"F29",		LFREG,	29,
270 	"F30",		LFREG,	30,
271 	"F31",		LFREG,	31,
272 
273 	"FCR",		LFCR,	0,
274 	"FCR0",		LFCREG,	0,
275 	"FCR1",		LFCREG,	1,
276 	"FCR2",		LFCREG,	2,
277 	"FCR3",		LFCREG,	3,
278 	"FCR4",		LFCREG,	4,
279 	"FCR5",		LFCREG,	5,
280 	"FCR6",		LFCREG,	6,
281 	"FCR7",		LFCREG,	7,
282 	"FCR8",		LFCREG,	8,
283 	"FCR9",		LFCREG,	9,
284 	"FCR10",	LFCREG,	10,
285 	"FCR11",	LFCREG,	11,
286 	"FCR12",	LFCREG,	12,
287 	"FCR13",	LFCREG,	13,
288 	"FCR14",	LFCREG,	14,
289 	"FCR15",	LFCREG,	15,
290 	"FCR16",	LFCREG,	16,
291 	"FCR17",	LFCREG,	17,
292 	"FCR18",	LFCREG,	18,
293 	"FCR19",	LFCREG,	19,
294 	"FCR20",	LFCREG,	20,
295 	"FCR21",	LFCREG,	21,
296 	"FCR22",	LFCREG,	22,
297 	"FCR23",	LFCREG,	23,
298 	"FCR24",	LFCREG,	24,
299 	"FCR25",	LFCREG,	25,
300 	"FCR26",	LFCREG,	26,
301 	"FCR27",	LFCREG,	27,
302 	"FCR28",	LFCREG,	28,
303 	"FCR29",	LFCREG,	29,
304 	"FCR30",	LFCREG,	30,
305 	"FCR31",	LFCREG,	31,
306 
307 	"ADD",		LTYPE1, AADD,
308 	"ADDU",		LTYPE1, AADDU,
309 	"SUB",		LTYPE1, ASUB,	/* converted to ADD(-) in loader */
310 	"SUBU",		LTYPE1, ASUBU,
311 	"SGT",		LTYPE1, ASGT,
312 	"SGTU",		LTYPE1, ASGTU,
313 	"AND",		LTYPE1, AAND,
314 	"OR",		LTYPE1, AOR,
315 	"XOR",		LTYPE1, AXOR,
316 	"SLL",		LTYPE1, ASLL,
317 	"SRL",		LTYPE1, ASRL,
318 	"SRA",		LTYPE1, ASRA,
319 
320 	"ADDV",		LTYPE1, AADDV,
321 	"ADDVU",	LTYPE1, AADDVU,
322 	"SUBV",		LTYPE1, ASUBV,	/* converted to ADD(-) in loader */
323 	"SUBVU",	LTYPE1, ASUBVU,
324 	"SLLV",		LTYPE1, ASLLV,
325 	"SRLV",		LTYPE1, ASRLV,
326 	"SRAV",		LTYPE1, ASRAV,
327 
328 	"NOR",		LTYPE2, ANOR,
329 
330 	"MOVB",		LTYPE3, AMOVB,
331 	"MOVBU",	LTYPE3, AMOVBU,
332 	"MOVH",		LTYPE3, AMOVH,
333 	"MOVHU",	LTYPE3, AMOVHU,
334 	"MOVWL",	LTYPE3, AMOVWL,
335 	"MOVWR",	LTYPE3, AMOVWR,
336 	"MOVVL",	LTYPE3, AMOVVL,
337 	"MOVVR",	LTYPE3, AMOVVR,
338 
339 	"BREAK",	LTYPEJ, ABREAK,		/* overloaded CACHE opcode */
340 	"END",		LTYPE4, AEND,
341 	"REM",		LTYPE6, AREM,
342 	"REMU",		LTYPE6, AREMU,
343 	"RET",		LTYPE4, ARET,
344 	"SYSCALL",	LTYPE4, ASYSCALL,
345 	"TLBP",		LTYPE4, ATLBP,
346 	"TLBR",		LTYPE4, ATLBR,
347 	"TLBWI",	LTYPE4, ATLBWI,
348 	"TLBWR",	LTYPE4, ATLBWR,
349 
350 	"MOVW",		LTYPE5, AMOVW,
351 	"MOVV",		LTYPE5, AMOVV,
352 	"MOVD",		LTYPE5, AMOVD,
353 	"MOVF",		LTYPE5, AMOVF,
354 
355 	"DIV",		LTYPE6, ADIV,
356 	"DIVU",		LTYPE6, ADIVU,
357 	"MUL",		LTYPE6, AMUL,
358 	"MULU",		LTYPE6, AMULU,
359 	"DIVV",		LTYPE6, ADIVV,
360 	"DIVVU",		LTYPE6, ADIVVU,
361 	"MULV",		LTYPE6, AMULV,
362 	"MULVU",		LTYPE6, AMULVU,
363 
364 	"RFE",		LTYPE7, ARFE,
365 	"JMP",		LTYPE7, AJMP,
366 
367 	"JAL",		LTYPE8, AJAL,
368 
369 	"BEQ",		LTYPE9, ABEQ,
370 	"BNE",		LTYPE9, ABNE,
371 
372 	"BGEZ",		LTYPEA, ABGEZ,
373 	"BGEZAL",	LTYPEA, ABGEZAL,
374 	"BGTZ",		LTYPEA, ABGTZ,
375 	"BLEZ",		LTYPEA, ABLEZ,
376 	"BLTZ",		LTYPEA, ABLTZ,
377 	"BLTZAL",	LTYPEA, ABLTZAL,
378 
379 	"TEXT",		LTYPEB, ATEXT,
380 	"GLOBL",	LTYPEB, AGLOBL,
381 
382 	"DATA",		LTYPEC, ADATA,
383 
384 	"MOVDF",	LTYPE5, AMOVDF,
385 	"MOVDW",	LTYPE5, AMOVDW,
386 	"MOVFD",	LTYPE5, AMOVFD,
387 	"MOVFW",	LTYPE5, AMOVFW,
388 	"MOVWD",	LTYPE5, AMOVWD,
389 	"MOVWF",	LTYPE5, AMOVWF,
390 
391 	"ABSD",		LTYPED, AABSD,
392 	"ABSF",		LTYPED, AABSF,
393 	"ABSW",		LTYPED, AABSW,
394 	"NEGD",		LTYPED, ANEGD,
395 	"NEGF",		LTYPED, ANEGF,
396 	"NEGW",		LTYPED, ANEGW,
397 
398 	"CMPEQD",	LTYPEF, ACMPEQD,
399 	"CMPEQF",	LTYPEF, ACMPEQF,
400 	"CMPGED",	LTYPEF, ACMPGED,
401 	"CMPGEF",	LTYPEF, ACMPGEF,
402 	"CMPGTD",	LTYPEF, ACMPGTD,
403 	"CMPGTF",	LTYPEF, ACMPGTF,
404 
405 	"ADDD",		LTYPEE, AADDD,
406 	"ADDF",		LTYPEE, AADDF,
407 	"ADDW",		LTYPEE, AADDW,
408 	"DIVD",		LTYPEE, ADIVD,
409 	"DIVF",		LTYPEE, ADIVF,
410 	"DIVW",		LTYPEE, ADIVW,
411 	"MULD",		LTYPEE, AMULD,
412 	"MULF",		LTYPEE, AMULF,
413 	"MULW",		LTYPEE, AMULW,
414 	"SUBD",		LTYPEE, ASUBD,
415 	"SUBF",		LTYPEE, ASUBF,
416 	"SUBW",		LTYPEE, ASUBW,
417 
418 	"BFPT",		LTYPEG, ABFPT,
419 	"BFPF",		LTYPEG, ABFPF,
420 
421 	"WORD",		LTYPEH, AWORD,
422 	"NOP",		LTYPEI, ANOP,
423 	"SCHED",	LSCHED, 0,
424 	"NOSCHED",	LSCHED, 0x80,
425 	0
426 };
427 
428 void
429 cinit(void)
430 {
431 	Sym *s;
432 	int i;
433 
434 	nullgen.sym = S;
435 	nullgen.offset = 0;
436 	nullgen.type = D_NONE;
437 	nullgen.name = D_NONE;
438 	nullgen.reg = NREG;
439 	if(FPCHIP)
440 		nullgen.dval = 0;
441 	for(i=0; i<sizeof(nullgen.sval); i++)
442 		nullgen.sval[i] = 0;
443 
444 	nerrors = 0;
445 	iostack = I;
446 	iofree = I;
447 	peekc = IGN;
448 	nhunk = 0;
449 	for(i=0; i<NHASH; i++)
450 		hash[i] = S;
451 	for(i=0; itab[i].name; i++) {
452 		s = slookup(itab[i].name);
453 		s->type = itab[i].type;
454 		s->value = itab[i].value;
455 	}
456 
457 	pathname = alloc(100);
458 	if(mygetwd(pathname, 99) == 0) {
459 		pathname = allocn(pathname, 100, 900);
460 		if(mygetwd(pathname, 999) == 0)
461 			strcpy(pathname, "/?");
462 	}
463 }
464 
465 void
466 syminit(Sym *s)
467 {
468 
469 	s->type = LNAME;
470 	s->value = 0;
471 }
472 
473 int
474 isreg(Gen *g)
475 {
476 
477 	USED(g);
478 	return 1;
479 }
480 
481 void
482 cclean(void)
483 {
484 
485 	outcode(AEND, &nullgen, NREG, &nullgen);
486 	Bflush(&obuf);
487 }
488 
489 void
490 zname(char *n, int t, int s)
491 {
492 
493 	Bputc(&obuf, ANAME);
494 	Bputc(&obuf, t);	/* type */
495 	Bputc(&obuf, s);	/* sym */
496 	while(*n) {
497 		Bputc(&obuf, *n);
498 		n++;
499 	}
500 	Bputc(&obuf, 0);
501 }
502 
503 void
504 zaddr(Gen *a, int s)
505 {
506 	long l;
507 	int i;
508 	char *n;
509 	Ieee e;
510 
511 	Bputc(&obuf, a->type);
512 	Bputc(&obuf, a->reg);
513 	Bputc(&obuf, s);
514 	Bputc(&obuf, a->name);
515 	switch(a->type) {
516 	default:
517 		print("unknown type %d\n", a->type);
518 		exits("arg");
519 
520 	case D_NONE:
521 	case D_REG:
522 	case D_FREG:
523 	case D_MREG:
524 	case D_FCREG:
525 	case D_LO:
526 	case D_HI:
527 		break;
528 
529 	case D_OREG:
530 	case D_CONST:
531 	case D_OCONST:
532 	case D_BRANCH:
533 		l = a->offset;
534 		Bputc(&obuf, l);
535 		Bputc(&obuf, l>>8);
536 		Bputc(&obuf, l>>16);
537 		Bputc(&obuf, l>>24);
538 		break;
539 
540 	case D_SCONST:
541 		n = a->sval;
542 		for(i=0; i<NSNAME; i++) {
543 			Bputc(&obuf, *n);
544 			n++;
545 		}
546 		break;
547 
548 	case D_FCONST:
549 		ieeedtod(&e, a->dval);
550 		Bputc(&obuf, e.l);
551 		Bputc(&obuf, e.l>>8);
552 		Bputc(&obuf, e.l>>16);
553 		Bputc(&obuf, e.l>>24);
554 		Bputc(&obuf, e.h);
555 		Bputc(&obuf, e.h>>8);
556 		Bputc(&obuf, e.h>>16);
557 		Bputc(&obuf, e.h>>24);
558 		break;
559 	}
560 }
561 
562 void
563 outcode(int a, Gen *g1, int reg, Gen *g2)
564 {
565 	int sf, st, t;
566 	Sym *s;
567 
568 	if(pass == 1)
569 		goto out;
570 jackpot:
571 	sf = 0;
572 	s = g1->sym;
573 	while(s != S) {
574 		sf = s->sym;
575 		if(sf < 0 || sf >= NSYM)
576 			sf = 0;
577 		t = g1->name;
578 		if(h[sf].type == t)
579 		if(h[sf].sym == s)
580 			break;
581 		zname(s->name, t, sym);
582 		s->sym = sym;
583 		h[sym].sym = s;
584 		h[sym].type = t;
585 		sf = sym;
586 		sym++;
587 		if(sym >= NSYM)
588 			sym = 1;
589 		break;
590 	}
591 	st = 0;
592 	s = g2->sym;
593 	while(s != S) {
594 		st = s->sym;
595 		if(st < 0 || st >= NSYM)
596 			st = 0;
597 		t = g2->name;
598 		if(h[st].type == t)
599 		if(h[st].sym == s)
600 			break;
601 		zname(s->name, t, sym);
602 		s->sym = sym;
603 		h[sym].sym = s;
604 		h[sym].type = t;
605 		st = sym;
606 		sym++;
607 		if(sym >= NSYM)
608 			sym = 1;
609 		if(st == sf)
610 			goto jackpot;
611 		break;
612 	}
613 	Bputc(&obuf, a);
614 	Bputc(&obuf, reg|nosched);
615 	Bputc(&obuf, lineno);
616 	Bputc(&obuf, lineno>>8);
617 	Bputc(&obuf, lineno>>16);
618 	Bputc(&obuf, lineno>>24);
619 	zaddr(g1, sf);
620 	zaddr(g2, st);
621 
622 out:
623 	if(a != AGLOBL && a != ADATA)
624 		pc++;
625 }
626 
627 void
628 outhist(void)
629 {
630 	Gen g;
631 	Hist *h;
632 	char *p, *q, *op, c;
633 	int n;
634 
635 	g = nullgen;
636 	c = pathchar();
637 	for(h = hist; h != H; h = h->link) {
638 		p = h->name;
639 		op = 0;
640 		/* on windows skip drive specifier in pathname */
641 		if(systemtype(Windows) && p && p[1] == ':'){
642 			p += 2;
643 			c = *p;
644 		}
645 		if(p && p[0] != c && h->offset == 0 && pathname){
646 			/* on windows skip drive specifier in pathname */
647 			if(systemtype(Windows) && pathname[1] == ':') {
648 				op = p;
649 				p = pathname+2;
650 				c = *p;
651 			} else if(pathname[0] == c){
652 				op = p;
653 				p = pathname;
654 			}
655 		}
656 		while(p) {
657 			q = strchr(p, c);
658 			if(q) {
659 				n = q-p;
660 				if(n == 0){
661 					n = 1;	/* leading "/" */
662 					*p = '/';	/* don't emit "\" on windows */
663 				}
664 				q++;
665 			} else {
666 				n = strlen(p);
667 				q = 0;
668 			}
669 			if(n) {
670 				Bputc(&obuf, ANAME);
671 				Bputc(&obuf, D_FILE);	/* type */
672 				Bputc(&obuf, 1);	/* sym */
673 				Bputc(&obuf, '<');
674 				Bwrite(&obuf, p, n);
675 				Bputc(&obuf, 0);
676 			}
677 			p = q;
678 			if(p == 0 && op) {
679 				p = op;
680 				op = 0;
681 			}
682 		}
683 		g.offset = h->offset;
684 
685 		Bputc(&obuf, AHISTORY);
686 		Bputc(&obuf, 0);
687 		Bputc(&obuf, h->line);
688 		Bputc(&obuf, h->line>>8);
689 		Bputc(&obuf, h->line>>16);
690 		Bputc(&obuf, h->line>>24);
691 		zaddr(&nullgen, 0);
692 		zaddr(&g, 0);
693 	}
694 }
695 
696 #include "../cc/lexbody"
697 #include "../cc/macbody"
698