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