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