]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/cc/lexbody
merge
[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 = strtoll(symb, nil, 10);
347                 else
348                         yylval.lval = strtol(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                 return c;
462         }
463         c = GETC();
464         if(c == '\n')
465                 lineno++;
466         if(c == EOF) {
467                 yyerror("End of file");
468                 errorexit();
469         }
470         return c;
471 }
472
473 int
474 getnsc(void)
475 {
476         int c;
477
478         for(;;) {
479                 c = getc();
480                 if(!isspace(c) || c == '\n')
481                         return c;
482         }
483 }
484
485 void
486 unget(int c)
487 {
488
489         peekc = c;
490         if(c == '\n')
491                 lineno--;
492 }
493
494 int
495 escchar(int e)
496 {
497         int c, l;
498
499 loop:
500         c = getc();
501         if(c == '\n') {
502                 yyerror("newline in string");
503                 return EOF;
504         }
505         if(c != '\\') {
506                 if(c == e)
507                         return EOF;
508                 return c;
509         }
510         c = getc();
511         if(c >= '0' && c <= '7') {
512                 l = c - '0';
513                 c = getc();
514                 if(c >= '0' && c <= '7') {
515                         l = l*8 + c-'0';
516                         c = getc();
517                         if(c >= '0' && c <= '7') {
518                                 l = l*8 + c-'0';
519                                 return l;
520                         }
521                 }
522                 peekc = c;
523                 return l;
524         }
525         switch(c)
526         {
527         case '\n':      goto loop;
528         case 'n':       return '\n';
529         case 't':       return '\t';
530         case 'b':       return '\b';
531         case 'r':       return '\r';
532         case 'f':       return '\f';
533         case 'a':       return 0x07;
534         case 'v':       return 0x0b;
535         case 'z':       return 0x00;
536         }
537         return c;
538 }
539
540 void
541 pinit(char *f)
542 {
543         int i;
544         Sym *s;
545
546         lineno = 1;
547         newio();
548         newfile(f, -1);
549         pc = 0;
550         peekc = IGN;
551         sym = 1;
552         for(i=0; i<NSYM; i++) {
553                 h[i].type = 0;
554                 h[i].sym = S;
555         }
556         for(i=0; i<NHASH; i++)
557                 for(s = hash[i]; s != S; s = s->link)
558                         s->macro = 0;
559 }
560
561 int
562 filbuf(void)
563 {
564         Io *i;
565
566 loop:
567         i = iostack;
568         if(i == I)
569                 return EOF;
570         if(i->f < 0)
571                 goto pop;
572         fi.c = read(i->f, i->b, BUFSIZ) - 1;
573         if(fi.c < 0) {
574                 close(i->f);
575                 linehist(0, 0);
576                 goto pop;
577         }
578         fi.p = i->b + 1;
579         return i->b[0];
580
581 pop:
582         iostack = i->link;
583         i->link = iofree;
584         iofree = i;
585         i = iostack;
586         if(i == I)
587                 return EOF;
588         fi.p = i->p;
589         fi.c = i->c;
590         if(--fi.c < 0)
591                 goto loop;
592         return *fi.p++;
593 }
594
595 void
596 yyerror(char *a, ...)
597 {
598         char buf[200];
599         va_list arg;
600
601         /*
602          * hack to intercept message from yaccpar
603          */
604         if(strcmp(a, "syntax error") == 0) {
605                 yyerror("syntax error, last name: %s", symb);
606                 return;
607         }
608         prfile(lineno);
609         va_start(arg, a);
610         vseprint(buf, buf+sizeof(buf), a, arg);
611         va_end(arg);
612         print("%s\n", buf);
613         nerrors++;
614         if(nerrors > 10) {
615                 print("too many errors\n");
616                 errorexit();
617         }
618 }
619
620 void
621 prfile(long l)
622 {
623         int i, n;
624         Hist a[HISTSZ], *h;
625         long d;
626
627         n = 0;
628         for(h = hist; h != H; h = h->link) {
629                 if(l < h->line)
630                         break;
631                 if(h->name) {
632                         if(h->offset == 0) {
633                                 if(n >= 0 && n < HISTSZ)
634                                         a[n] = *h;
635                                 n++;
636                                 continue;
637                         }
638                         if(n > 0 && n < HISTSZ)
639                                 if(a[n-1].offset == 0) {
640                                         a[n] = *h;
641                                         n++;
642                                 } else
643                                         a[n-1] = *h;
644                         continue;
645                 }
646                 n--;
647                 if(n >= 0 && n < HISTSZ) {
648                         d = h->line - a[n].line;
649                         for(i=0; i<n; i++)
650                                 a[i].line += d;
651                 }
652         }
653         if(n > HISTSZ)
654                 n = HISTSZ;
655         for(i=0; i<n; i++)
656                 print("%s:%ld ", a[i].name, (long)(l-a[i].line+a[i].offset+1));
657 }
658
659 void
660 ieeedtod(Ieee *ieee, double native)
661 {
662         double fr, ho, f;
663         int exp;
664
665         if(native < 0) {
666                 ieeedtod(ieee, -native);
667                 ieee->h |= 0x80000000L;
668                 return;
669         }
670         if(native == 0) {
671                 ieee->l = 0;
672                 ieee->h = 0;
673                 return;
674         }
675         fr = frexp(native, &exp);
676         f = 2097152L;           /* shouldnt use fp constants here */
677         fr = modf(fr*f, &ho);
678         ieee->h = ho;
679         ieee->h &= 0xfffffL;
680         ieee->h |= (exp+1022L) << 20;
681         f = 65536L;
682         fr = modf(fr*f, &ho);
683         ieee->l = ho;
684         ieee->l <<= 16;
685         ieee->l |= (long)(fr*f);
686 }