xref: /inferno-os/utils/0a/lex.c (revision 9dbf735d35c339c90deaed43fc0ae17f16c122f7)
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