]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/cc/lexbody
ip/ipconfig: use ewrite() to enable routing command for sendra
[plan9front.git] / sys / src / cmd / cc / lexbody
1 /*
2  * common code for all the assemblers
3  */
4
5 void
6 pragpack(void)
7 {
8         while(getnsc() != '\n')
9                 ;
10 }
11
12 void
13 pragvararg(void)
14 {
15         while(getnsc() != '\n')
16                 ;
17 }
18
19 void
20 pragfpround(void)
21 {
22         while(getnsc() != '\n')
23                 ;
24 }
25
26 void
27 pragprofile(void)
28 {
29         while(getnsc() != '\n')
30                 ;
31 }
32
33 void
34 pragincomplete(void)
35 {
36         while(getnsc() != '\n')
37                 ;
38 }
39
40 /*
41  * real allocs
42  */
43 void*
44 alloc(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
60 void*
61 allocn(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
79 void
80 setinclude(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
97 void
98 errorexit(void)
99 {
100
101         if(outfile)
102                 remove(outfile);
103         exits("error");
104 }
105
106 void
107 pushio(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
120 void
121 newio(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
141 void
142 newfile(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
160 Sym*
161 slookup(char *s)
162 {
163
164         strcpy(symb, s);
165         return lookup();
166 }
167
168 Sym*
169 lookup(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
200 long
201 yylex(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         }
212 l0:
213         c = GETC();
214
215 l1:
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 = strtoull(symb, nil, 10);
347                 else
348                         yylval.lval = strtoul(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                                         goto l1;
422                                 if(c == EOF) {
423                                         yyerror("eof in comment");
424                                         errorexit();
425                                 }
426                         }
427                 }
428                 if(c1 == '*') {
429                         for(;;) {
430                                 c = GETC();
431                                 while(c == '*') {
432                                         c = GETC();
433                                         if(c == '/')
434                                                 goto l0;
435                                 }
436                                 if(c == EOF) {
437                                         yyerror("eof in comment");
438                                         errorexit();
439                                 }
440                                 if(c == '\n')
441                                         lineno++;
442                         }
443                 }
444                 break;
445
446         default:
447                 return c;
448         }
449         peekc = c1;
450         return c;
451 }
452
453 int
454 getc(void)
455 {
456         int c;
457
458         c = peekc;
459         if(c != IGN) {
460                 peekc = IGN;
461                 if(c == '\n')
462                         lineno++;
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
475 int
476 getnsc(void)
477 {
478         int c;
479
480         for(;;) {
481                 c = getc();
482                 if(!isspace(c) || c == '\n')
483                         return c;
484         }
485 }
486
487 void
488 unget(int c)
489 {
490
491         peekc = c;
492         if(c == '\n')
493                 lineno--;
494 }
495
496 int
497 escchar(int e)
498 {
499         int c, l;
500
501 loop:
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
542 void
543 pinit(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
563 int
564 filbuf(void)
565 {
566         Io *i;
567
568 loop:
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
583 pop:
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
597 void
598 yyerror(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
622 void
623 prfile(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
661 void
662 ieeedtod(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 }