]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/cc/lexbody
cc: mk clean should delete cc.a$O
[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 void
41 setinclude(char *p)
42 {
43         int i;
44
45         if(p == 0)
46                 return;
47         for(i=1; i < ninclude; i++)
48                 if(strcmp(p, include[i]) == 0)
49                         return;
50
51         if(ninclude >= nelem(include)) {
52                 yyerror("ninclude too small %d", nelem(include));
53                 exits("ninclude");
54         }
55         include[ninclude++] = p;
56 }
57
58 void
59 errorexit(void)
60 {
61
62         if(outfile)
63                 remove(outfile);
64         exits("error");
65 }
66
67 void
68 pushio(void)
69 {
70         Io *i;
71
72         i = iostack;
73         if(i == I) {
74                 yyerror("botch in pushio");
75                 errorexit();
76         }
77         i->p = fi.p;
78         i->c = fi.c;
79 }
80
81 void
82 newio(void)
83 {
84         Io *i;
85         static int pushdepth = 0;
86
87         i = iofree;
88         if(i == I) {
89                 pushdepth++;
90                 if(pushdepth > 1000) {
91                         yyerror("macro/io expansion too deep");
92                         errorexit();
93                 }
94                 i = alloc(sizeof(*i));
95         } else
96                 iofree = i->link;
97         i->c = 0;
98         i->f = -1;
99         ionext = i;
100 }
101
102 void
103 newfile(char *s, int f)
104 {
105         Io *i;
106
107         i = ionext;
108         i->link = iostack;
109         iostack = i;
110         i->f = f;
111         if(f < 0)
112                 i->f = open(s, 0);
113         if(i->f < 0) {
114                 yyerror("%Ca: %r: %s", thechar, s);
115                 errorexit();
116         }
117         fi.c = 0;
118         linehist(s, 0);
119 }
120
121 Sym*
122 slookup(char *s)
123 {
124         strncpy(symb, s, NSYMB);
125         if(symb[NSYMB-1] != '\0'){
126                 yyerror("symbol too long: %s", s);
127                 errorexit();
128         }
129         return lookup();
130 }
131
132 Sym*
133 lookup(void)
134 {
135         Sym *s;
136         ulong h;
137         char *p;
138         int c, n;
139
140         h = 0;
141         for(p=symb; *p;) {
142                 h = h * 3;
143                 h += *p++;
144         }
145         n = (p - symb) + 1;
146         if((long)h < 0)
147                 h = ~h;
148         h %= NHASH;
149         c = symb[0];
150         for(s = hash[h]; s != S; s = s->link) {
151                 if(s->name[0] != c)
152                         continue;
153                 if(strcmp(s->name, symb) == 0)
154                         return s;
155         }
156         s = alloc(sizeof(*s));
157         s->name = alloc(n);
158         memmove(s->name, symb, n);
159
160         s->link = hash[h];
161         hash[h] = s;
162         syminit(s);
163
164         return s;
165 }
166
167 long
168 yylex(void)
169 {
170         int c, c1;
171         char *cp;
172         Sym *s;
173
174         c = peekc;
175         if(c != IGN) {
176                 peekc = IGN;
177                 goto l1;
178         }
179 l0:
180         c = GETC();
181
182 l1:
183         if(c == EOF) {
184                 peekc = EOF;
185                 return -1;
186         }
187         if(isspace(c)) {
188                 if(c == '\n') {
189                         lineno++;
190                         return ';';
191                 }
192                 goto l0;
193         }
194         if(isalpha(c))
195                 goto talph;
196         if(isdigit(c))
197                 goto tnum;
198         switch(c)
199         {
200         case '\n':
201                 lineno++;
202                 return ';';
203
204         case '#':
205                 domacro();
206                 goto l0;
207
208         case '.':
209                 c = GETC();
210                 if(isalpha(c)) {
211                         cp = symb;
212                         *cp++ = '.';
213                         goto aloop;
214                 }
215                 if(isdigit(c)) {
216                         cp = symb;
217                         *cp++ = '.';
218                         goto casedot;
219                 }
220                 peekc = c;
221                 return '.';
222
223         talph:
224         case '_':
225         case '@':
226                 cp = symb;
227
228         aloop:
229                 if(cp >= &symb[NSYMB-1])
230                         goto toolong;
231                 *cp++ = c;
232                 c = GETC();
233                 if(isalpha(c) || isdigit(c) || c == '_' || c == '$')
234                         goto aloop;
235                 *cp = 0;
236                 peekc = c;
237                 s = lookup();
238                 if(s->macro) {
239                         newio();
240                         cp = ionext->b;
241                         macexpand(s, cp, sizeof(ionext->b)-1);
242                         pushio();
243                         ionext->link = iostack;
244                         iostack = ionext;
245                         fi.p = cp;
246                         fi.c = strlen(cp);
247                         if(peekc != IGN) {
248                                 cp[fi.c++] = peekc;
249                                 cp[fi.c] = 0;
250                                 peekc = IGN;
251                         }
252                         goto l0;
253                 }
254                 if(s->type == 0)
255                         s->type = LNAME;
256                 if(s->type == LNAME ||
257                    s->type == LVAR ||
258                    s->type == LLAB) {
259                         yylval.sym = s;
260                         return s->type;
261                 }
262                 yylval.lval = s->value;
263                 return s->type;
264
265         tnum:
266                 cp = symb;
267                 if(c != '0')
268                         goto dc;
269                 *cp++ = c;
270                 c = GETC();
271                 c1 = 3;
272                 if(c == 'x' || c == 'X') {
273                         c1 = 4;
274                         c = GETC();
275                 } else
276                 if(c < '0' || c > '7')
277                         goto dc;
278                 yylval.lval = 0;
279                 for(;;) {
280                         if(c >= '0' && c <= '9') {
281                                 if(c > '7' && c1 == 3)
282                                         break;
283                                 yylval.lval <<= c1;
284                                 yylval.lval += c - '0';
285                                 c = GETC();
286                                 continue;
287                         }
288                         if(c1 == 3)
289                                 break;
290                         if(c >= 'A' && c <= 'F')
291                                 c += 'a' - 'A';
292                         if(c >= 'a' && c <= 'f') {
293                                 yylval.lval <<= c1;
294                                 yylval.lval += c - 'a' + 10;
295                                 c = GETC();
296                                 continue;
297                         }
298                         break;
299                 }
300                 goto ncu;
301
302         dc:
303                 for(;;) {
304                         if(!isdigit(c))
305                                 break;
306                         if(cp >= &symb[NSYMB-1])
307                                 goto toolong;
308                         *cp++ = c;
309                         c = GETC();
310                 }
311                 if(c == '.')
312                         goto casedot;
313                 if(c == 'e' || c == 'E')
314                         goto casee;
315                 *cp = 0;
316                 if(sizeof(yylval.lval) == sizeof(vlong))
317                         yylval.lval = strtoull(symb, nil, 10);
318                 else
319                         yylval.lval = strtoul(symb, nil, 10);
320
321         ncu:
322                 while(c == 'U' || c == 'u' || c == 'l' || c == 'L')
323                         c = GETC();
324                 peekc = c;
325                 return LCONST;
326
327         casedot:
328                 for(;;) {
329                         if(cp >= &symb[NSYMB-1])
330                                 goto toolong;
331                         *cp++ = c;
332                         c = GETC();
333                         if(!isdigit(c))
334                                 break;
335                 }
336                 if(c == 'e' || c == 'E')
337                         goto casee;
338                 goto caseout;
339
340         casee:
341                 if(cp >= &symb[NSYMB-1])
342                         goto toolong;
343                 *cp++ = 'e';
344                 c = GETC();
345                 if(c == '+' || c == '-') {
346                         if(cp >= &symb[NSYMB-1])
347                                 goto toolong;
348                         *cp++ = c;
349                         c = GETC();
350                 }
351                 while(isdigit(c)) {
352                         if(cp >= &symb[NSYMB-1])
353                                 goto toolong;
354                         *cp++ = c;
355                         c = GETC();
356                 }
357
358         caseout:
359                 *cp = 0;
360                 peekc = c;
361                 if(FPCHIP) {
362                         yylval.dval = atof(symb);
363                         return LFCONST;
364                 }
365                 yyerror("assembler cannot interpret fp constants");
366                 yylval.lval = 1L;
367                 return LCONST;
368
369         case '"':
370                 memcpy(yylval.sval, nullgen.sval, sizeof(yylval.sval));
371                 cp = yylval.sval;
372                 c1 = 0;
373                 for(;;) {
374                         c = escchar('"');
375                         if(c == EOF)
376                                 break;
377                         if(c1 < sizeof(yylval.sval))
378                                 *cp++ = c;
379                         c1++;
380                 }
381                 if(c1 > sizeof(yylval.sval))
382                         yyerror("string constant too long");
383                 return LSCONST;
384
385         case '\'':
386                 c = escchar('\'');
387                 if(c == EOF)
388                         c = '\'';
389                 if(escchar('\'') != EOF)
390                         yyerror("missing '");
391                 yylval.lval = c;
392                 return LCONST;
393
394         case '/':
395                 c1 = GETC();
396                 if(c1 == '/') {
397                         for(;;) {
398                                 c = GETC();
399                                 if(c == '\n')
400                                         goto l1;
401                                 if(c == EOF) {
402                                         yyerror("eof in comment");
403                                         errorexit();
404                                 }
405                         }
406                 }
407                 if(c1 == '*') {
408                         for(;;) {
409                                 c = GETC();
410                                 while(c == '*') {
411                                         c = GETC();
412                                         if(c == '/')
413                                                 goto l0;
414                                 }
415                                 if(c == EOF) {
416                                         yyerror("eof in comment");
417                                         errorexit();
418                                 }
419                                 if(c == '\n')
420                                         lineno++;
421                         }
422                 }
423                 break;
424
425         default:
426                 return c;
427         }
428         peekc = c1;
429         return c;
430 toolong:
431         yyerror("token too long: %.*s...", utfnlen(symb, cp-symb), symb);
432         errorexit();
433         return -1;
434 }
435
436 int
437 getc(void)
438 {
439         int c;
440
441         c = peekc;
442         if(c != IGN) {
443                 peekc = IGN;
444                 if(c == '\n')
445                         lineno++;
446                 return c;
447         }
448         c = GETC();
449         if(c == '\n')
450                 lineno++;
451         if(c == EOF) {
452                 yyerror("End of file");
453                 errorexit();
454         }
455         return c;
456 }
457
458 int
459 getnsc(void)
460 {
461         int c;
462
463         for(;;) {
464                 c = getc();
465                 if(!isspace(c) || c == '\n')
466                         return c;
467         }
468 }
469
470 void
471 unget(int c)
472 {
473
474         peekc = c;
475         if(c == '\n')
476                 lineno--;
477 }
478
479 int
480 escchar(int e)
481 {
482         int c, l;
483
484 loop:
485         c = getc();
486         if(c == '\n') {
487                 yyerror("newline in string");
488                 return EOF;
489         }
490         if(c != '\\') {
491                 if(c == e)
492                         return EOF;
493                 return c;
494         }
495         c = getc();
496         if(c >= '0' && c <= '7') {
497                 l = c - '0';
498                 c = getc();
499                 if(c >= '0' && c <= '7') {
500                         l = l*8 + c-'0';
501                         c = getc();
502                         if(c >= '0' && c <= '7') {
503                                 l = l*8 + c-'0';
504                                 return l;
505                         }
506                 }
507                 peekc = c;
508                 return l;
509         }
510         switch(c)
511         {
512         case '\n':      goto loop;
513         case 'n':       return '\n';
514         case 't':       return '\t';
515         case 'b':       return '\b';
516         case 'r':       return '\r';
517         case 'f':       return '\f';
518         case 'a':       return 0x07;
519         case 'v':       return 0x0b;
520         case 'z':       return 0x00;
521         }
522         return c;
523 }
524
525 void
526 pinit(char *f)
527 {
528         int i;
529         Sym *s;
530
531         lineno = 1;
532         newio();
533         newfile(f, -1);
534         pc = 0;
535         peekc = IGN;
536         sym = 1;
537         for(i=0; i<NSYM; i++) {
538                 h[i].type = 0;
539                 h[i].sym = S;
540         }
541         for(i=0; i<NHASH; i++)
542                 for(s = hash[i]; s != S; s = s->link)
543                         s->macro = 0;
544 }
545
546 int
547 filbuf(void)
548 {
549         Io *i;
550
551 loop:
552         i = iostack;
553         if(i == I)
554                 return EOF;
555         if(i->f < 0)
556                 goto pop;
557         fi.c = read(i->f, i->b, BUFSIZ) - 1;
558         if(fi.c < 0) {
559                 close(i->f);
560                 linehist(0, 0);
561                 goto pop;
562         }
563         fi.p = i->b + 1;
564         return i->b[0];
565
566 pop:
567         iostack = i->link;
568         i->link = iofree;
569         iofree = i;
570         i = iostack;
571         if(i == I)
572                 return EOF;
573         fi.p = i->p;
574         fi.c = i->c;
575         if(--fi.c < 0)
576                 goto loop;
577         return *fi.p++;
578 }
579
580 void
581 yyerror(char *a, ...)
582 {
583         char buf[200];
584         va_list arg;
585
586         /*
587          * hack to intercept message from yaccpar
588          */
589         if(strcmp(a, "syntax error") == 0) {
590                 yyerror("syntax error, last name: %s", symb);
591                 return;
592         }
593         prfile(lineno);
594         va_start(arg, a);
595         vseprint(buf, buf+sizeof(buf), a, arg);
596         va_end(arg);
597         print("%s\n", buf);
598         nerrors++;
599         if(nerrors > 10) {
600                 print("too many errors\n");
601                 errorexit();
602         }
603 }
604
605 void
606 prfile(long l)
607 {
608         int i, n;
609         Hist a[HISTSZ], *h;
610         long d;
611
612         n = 0;
613         for(h = hist; h != H; h = h->link) {
614                 if(l < h->line)
615                         break;
616                 if(h->name) {
617                         if(h->offset == 0) {
618                                 if(n >= 0 && n < HISTSZ)
619                                         a[n] = *h;
620                                 n++;
621                                 continue;
622                         }
623                         if(n > 0 && n < HISTSZ)
624                                 if(a[n-1].offset == 0) {
625                                         a[n] = *h;
626                                         n++;
627                                 } else
628                                         a[n-1] = *h;
629                         continue;
630                 }
631                 n--;
632                 if(n >= 0 && n < HISTSZ) {
633                         d = h->line - a[n].line;
634                         for(i=0; i<n; i++)
635                                 a[i].line += d;
636                 }
637         }
638         if(n > HISTSZ)
639                 n = HISTSZ;
640         for(i=0; i<n; i++)
641                 print("%s:%ld ", a[i].name, (long)(l-a[i].line+a[i].offset+1));
642 }
643
644 void
645 ieeedtod(Ieee *ieee, double native)
646 {
647         double fr, ho, f;
648         int exp;
649
650         if(native < 0) {
651                 ieeedtod(ieee, -native);
652                 ieee->h |= 0x80000000L;
653                 return;
654         }
655         if(native == 0) {
656                 ieee->l = 0;
657                 ieee->h = 0;
658                 return;
659         }
660         fr = frexp(native, &exp);
661         f = 2097152L;           /* shouldnt use fp constants here */
662         fr = modf(fr*f, &ho);
663         ieee->h = ho;
664         ieee->h &= 0xfffffL;
665         ieee->h |= (exp+1022L) << 20;
666         f = 65536L;
667         fr = modf(fr*f, &ho);
668         ieee->l = ho;
669         ieee->l <<= 16;
670         ieee->l |= (long)(fr*f);
671 }