]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/cc/lex.c
cc: promote integer constants according to c99 spec.
[plan9front.git] / sys / src / cmd / cc / lex.c
1 #include        "cc.h"
2 #include        "y.tab.h"
3
4 #ifndef CPP
5 #define CPP     "/bin/cpp"
6 #endif
7
8 /*
9  * known debug flags
10  * flags without a description may be exclusive to certain architectures
11  *      -.              Inhibit search for includes in source directory
12  *      -0
13  *      -4
14  *      -8
15  *      -<
16
17  *      -A              !B
18  *      -B              non ANSI
19  *      -C
20  *      -D name         define
21  *      -F              format specification check
22  *      -G
23  *      -H
24  *      -I path         include
25  *      -L              print every NAME symbol
26  *      -M              constant multiplication
27  *      -N
28  *      -P              peephole
29  *      -Q
30  *      -R              print registerization
31  *      -S              print assembly
32  *      -T
33  *      -V              enable void* conversion warnings
34  *      -W
35  *      -X              abort on error
36  *      -Y
37  *      -Z
38
39  *      -a              acid declaration output
40  *      -c
41  *      -d              print declarations
42  *      -e
43  *      -f
44  *      -g
45  *      -h
46  *      -i              print initialization
47  *      -l              generate little-endian code
48  *      -m              print add/sub/mul trees
49  *      -n              print acid to file (%.c=%.acid) (with -a or -aa)
50  *      -o file         output file
51  *      -p              use standard cpp ANSI preprocessor (not on windows)
52  *      -s              print structure offsets (with -a or -aa)
53  *      -t              print type trees
54  *      -v              verbose printing
55  *      -w              print warnings
56  *      -x
57  *      -y
58  */
59
60 void
61 main(int argc, char *argv[])
62 {
63         char **defs, *p;
64         int nproc, nout, status, i, c, ndef;
65
66         memset(debug, 0, sizeof(debug));
67         tinit();
68         cinit();
69         ginit();
70         arginit();
71
72         profileflg = 1; /* #pragma can turn it off */
73         tufield = simplet((1L<<tfield->etype) | BUNSIGNED);
74         defs = 0;
75         ndef = 0;
76         outfile = 0;
77         include[ninclude++] = ".";
78         ARGBEGIN {
79         default:
80                 c = ARGC();
81                 if(c >= 0 && c < sizeof(debug))
82                         debug[c]++;
83                 break;
84
85         case 'l':                       /* for little-endian mips */
86                 if(thechar != 'v'){
87                         print("can only use -l with vc");
88                         errorexit();
89                 }
90                 thechar = '0';
91                 thestring = "spim";
92                 break;
93
94         case 'o':
95                 outfile = ARGF();
96                 break;
97
98         case 'D':
99                 p = ARGF();
100                 if(p) {
101                         if((ndef & 15) == 0)
102                                 defs = allocn(defs, ndef*sizeof(defs[0]), 16*sizeof(defs[0]));
103                         defs[ndef++] = p;
104                         dodefine(p);
105                 }
106                 break;
107
108         case 'I':
109                 p = ARGF();
110                 if(p)
111                         setinclude(p);
112                 break;
113         } ARGEND
114         if(argc < 1 && outfile == 0) {
115                 print("usage: %Cc [-options] files\n", thechar);
116                 errorexit();
117         }
118         if(argc > 1 && systemtype(Windows)){
119                 print("can't compile multiple files on windows\n");
120                 errorexit();
121         }
122         if(argc > 1 && !systemtype(Windows)) {
123                 nproc = 1;
124                 /*
125                  * if we're writing acid to standard output, don't compile
126                  * concurrently, to avoid interleaving output.
127                  */
128                 if(((!debug['a'] && !debug['Z']) || debug['n']) &&
129                     (p = getenv("NPROC")) != nil)
130                         nproc = atol(p);        /* */
131                 c = 0;
132                 nout = 0;
133                 for(;;) {
134                         while(nout < nproc && argc > 0) {
135                                 i = myfork();
136                                 if(i < 0) {
137                                         i = mywait(&status);
138                                         if(i < 0) {
139                                                 print("cannot create a process\n");
140                                                 errorexit();
141                                         }
142                                         if(status)
143                                                 c++;
144                                         nout--;
145                                         continue;
146                                 }
147                                 if(i == 0) {
148                                         fprint(2, "%s:\n", *argv);
149                                         if (compile(*argv, defs, ndef))
150                                                 errorexit();
151                                         exits(0);
152                                 }
153                                 nout++;
154                                 argc--;
155                                 argv++;
156                         }
157                         i = mywait(&status);
158                         if(i < 0) {
159                                 if(c)
160                                         errorexit();
161                                 exits(0);
162                         }
163                         if(status)
164                                 c++;
165                         nout--;
166                 }
167         }
168
169         if(argc == 0)
170                 c = compile("stdin", defs, ndef);
171         else
172                 c = compile(argv[0], defs, ndef);
173
174         if(c)
175                 errorexit();
176         exits(0);
177 }
178
179 int
180 compile(char *file, char **defs, int ndef)
181 {
182         char *ofile, *p, **av;
183         int i, c, fd[2];
184         static int first = 1;
185
186         ofile = strdup(file);
187         p = utfrrune(ofile, pathchar());
188         if(p) {
189                 *p++ = 0;
190                 if(!debug['.'])
191                         include[0] = strdup(ofile);
192         } else
193                 p = ofile;
194
195         if(outfile == 0) {
196                 if(p) {
197                         outfile = p;
198                         if(p = utfrrune(outfile, '.'))
199                                 if(p[1] == 'c' && p[2] == 0)
200                                         p[0] = 0;
201                         if(debug['a'] && debug['n'])
202                                 outfile = smprint("%s.acid", outfile);
203                         else if(debug['Z'] && debug['n'])
204                                 outfile = smprint("%s_pickle.c", outfile);
205                         else
206                                 outfile = smprint("%s.%C", outfile, thechar);
207                 } else
208                         outfile = "/dev/null";
209         }
210
211         if(p = getenv("INCLUDE")) {
212                 setinclude(p);
213         } else {
214                 if(systemtype(Plan9)) {
215                         setinclude(smprint("/%s/include", thestring));
216                         setinclude("/sys/include");
217                 }
218         }
219         if (first)
220                 Binit(&diagbuf, 1, OWRITE);
221         /*
222          * if we're writing acid to standard output, don't keep scratching
223          * outbuf.
224          */
225         if((debug['a'] || debug['Z']) && !debug['n']) {
226                 if (first) {
227                         outfile = 0;
228                         Binit(&outbuf, dup(1, -1), OWRITE);
229                         dup(2, 1);
230                 }
231         } else {
232                 c = mycreat(outfile, 0664);
233                 if(c < 0) {
234                         diag(Z, "cannot open %s - %r", outfile);
235                         outfile = 0;
236                         errorexit();
237                 }
238                 Binit(&outbuf, c, OWRITE);
239         }
240         newio();
241         first = 0;
242
243         /* Use an ANSI preprocessor */
244         if(debug['p']) {
245                 if(systemtype(Windows)) {
246                         diag(Z, "-p option not supported on windows");
247                         errorexit();
248                 }
249                 if(myaccess(file) < 0) {
250                         diag(Z, "%s does not exist", file);
251                         errorexit();
252                 }
253                 if(mypipe(fd) < 0) {
254                         diag(Z, "pipe failed");
255                         errorexit();
256                 }
257                 switch(myfork()) {
258                 case -1:
259                         diag(Z, "fork failed");
260                         errorexit();
261                 case 0:
262                         close(fd[0]);
263                         mydup(fd[1], 1);
264                         close(fd[1]);
265
266                         i = 8+ndef+ninclude;
267                         av = alloc(i*sizeof(av[0]));
268
269                         i = 0;
270                         av[i++] = CPP;
271                         av[i++] = "-+";
272                         if(debug['.'])
273                                 av[i++] = "-.";
274                         for(c = 0; c < ndef; c++)
275                                 av[i++] = smprint("-D%s", defs[c]);
276                         for(c = 0; c < ninclude; c++)
277                                 av[i++] = smprint("-I%s", include[c]);
278                         if(strcmp(file, "stdin") != 0)
279                                 av[i++] = file;
280                         av[i] = 0;
281                         if(debug['p'] > 1) {
282                                 for(c = 0; c < i; c++)
283                                         fprint(2, "%s ", av[c]);
284                                 fprint(2, "\n");
285                         }
286                         myexec(av[0], av);
287                         fprint(2, "can't exec C preprocessor %s: %r\n", CPP);
288                         errorexit();
289                 default:
290                         close(fd[1]);
291                         newfile(file, fd[0]);
292                         break;
293                 }
294         } else {
295                 if(strcmp(file, "stdin") == 0)
296                         newfile(file, 0);
297                 else
298                         newfile(file, -1);
299         }
300         yyparse();
301         if(!debug['a'] && !debug['Z'])
302                 gclean();
303         return nerrors;
304 }
305
306 void
307 errorexit(void)
308 {
309         if(outfile)
310                 remove(outfile);
311         exits("error");
312 }
313
314 void
315 pushio(void)
316 {
317         Io *i;
318
319         i = iostack;
320         if(i == I) {
321                 yyerror("botch in pushio");
322                 errorexit();
323         }
324         i->p = fi.p;
325         i->c = fi.c;
326 }
327
328 void
329 newio(void)
330 {
331         Io *i;
332         static int pushdepth = 0;
333
334         i = iofree;
335         if(i == I) {
336                 pushdepth++;
337                 if(pushdepth > 1000) {
338                         yyerror("macro/io expansion too deep");
339                         errorexit();
340                 }
341                 i = alloc(sizeof(*i));
342         } else
343                 iofree = i->link;
344         i->c = 0;
345         i->f = -1;
346         ionext = i;
347 }
348
349 void
350 newfile(char *s, int f)
351 {
352         Io *i;
353
354         if(debug['e'])
355                 print("%L: %s\n", lineno, s);
356
357         i = ionext;
358         i->link = iostack;
359         iostack = i;
360         i->f = f;
361         if(f < 0)
362                 i->f = open(s, 0);
363         if(i->f < 0) {
364                 yyerror("%Cc: %r: %s", thechar, s);
365                 errorexit();
366         }
367         fi.c = 0;
368         linehist(s, 0);
369 }
370
371 Sym*
372 slookup(char *s)
373 {
374         strncpy(symb, s, NSYMB);
375         if(symb[NSYMB-1] != '\0'){
376                 yyerror("symbol too long: %s", s);
377                 errorexit();
378         }
379         return lookup();
380 }
381
382 Sym*
383 lookup(void)
384 {
385         Sym *s;
386         ulong h;
387         char *p;
388         int c, n;
389
390         h = 0;
391         for(p=symb; *p;) {
392                 h = h * 3;
393                 h += *p++;
394         }
395         n = (p - symb) + 1;
396         if((long)h < 0)
397                 h = ~h;
398         h %= NHASH;
399         c = symb[0];
400         for(s = hash[h]; s != S; s = s->link) {
401                 if(s->name[0] != c)
402                         continue;
403                 if(strcmp(s->name, symb) == 0)
404                         return s;
405         }
406         s = alloc(sizeof(*s));
407         s->name = alloc(n);
408         memmove(s->name, symb, n);
409
410         s->link = hash[h];
411         hash[h] = s;
412         syminit(s);
413
414         return s;
415 }
416
417 void
418 syminit(Sym *s)
419 {
420         s->lexical = LNAME;
421         s->block = 0;
422         s->offset = 0;
423         s->type = T;
424         s->suetag = T;
425         s->class = CXXX;
426         s->aused = 0;
427         s->sig = SIGNONE;
428 }
429
430 #define EOF     (-1)
431 #define IGN     (-2)
432 #define ESC     (1<<20)
433
434 enum
435 {
436         Numdec          = 1<<0,
437         Numlong         = 1<<1,
438         Numuns          = 1<<2,
439         Numvlong        = 1<<3,
440         Numflt          = 1<<4,
441 };
442
443 long
444 yylex(void)
445 {
446         vlong vv;
447         long c, c1, t, w;
448         char *cp;
449         Rune rune;
450         Sym *s;
451
452         if(peekc != IGN) {
453                 c = peekc;
454                 peekc = IGN;
455                 goto l1;
456         }
457 l0:
458         c = GETC();
459
460 l1:
461         if(c >= Runeself) {
462                 /*
463                  * extension --
464                  *      all multibyte runes are alpha
465                  */
466                 cp = symb;
467                 goto talph;
468         }
469         if(isspace(c)) {
470                 if(c == '\n')
471                         lineno++;
472                 goto l0;
473         }
474         if(isalpha(c)) {
475                 cp = symb;
476                 if(c != 'L')
477                         goto talph;
478                 *cp++ = c;
479                 c = GETC();
480                 if(c == '\'') {
481                         /* L'x' */
482                         c = escchar('\'', 1, 0);
483                         if(c == EOF)
484                                 c = '\'';
485                         c1 = escchar('\'', 1, 0);
486                         if(c1 != EOF) {
487                                 yyerror("missing '");
488                                 peekc = c1;
489                         }
490                         yylval.vval = convvtox(c, TRUNE);
491                         return LUCONST;
492                 }
493                 if(c == '"') {
494                         goto caselq;
495                 }
496                 goto talph;
497         }
498         if(isdigit(c))
499                 goto tnum;
500         switch(c)
501         {
502
503         case EOF:
504                 peekc = EOF;
505                 return -1;
506
507         case '_':
508                 cp = symb;
509                 goto talph;
510
511         case '#':
512                 domacro();
513                 goto l0;
514
515         case '.':
516                 c1 = GETC();
517                 if(isdigit(c1)) {
518                         cp = symb;
519                         *cp++ = c;
520                         c = c1;
521                         c1 = 0;
522                         goto casedot;
523                 }
524                 break;
525
526         case '"':
527                 strcpy(symb, "\"<string>\"");
528                 cp = alloc(0);
529                 c1 = 0;
530
531                 /* "..." */
532                 for(;;) {
533                         c = escchar('"', 0, 1);
534                         if(c == EOF)
535                                 break;
536                         if(c & ESC) {
537                                 cp = allocn(cp, c1, 1);
538                                 cp[c1++] = c;
539                         } else {
540                                 rune = c;
541                                 c = runelen(rune);
542                                 cp = allocn(cp, c1, c);
543                                 runetochar(cp+c1, &rune);
544                                 c1 += c;
545                         }
546                 }
547                 yylval.sval.l = c1;
548                 do {
549                         cp = allocn(cp, c1, 1);
550                         cp[c1++] = 0;
551                 } while(c1 & MAXALIGN);
552                 yylval.sval.s = cp;
553                 return LSTRING;
554
555         caselq:
556                 /* L"..." */
557                 strcpy(symb, "\"L<string>\"");
558                 cp = alloc(0);
559                 c1 = 0;
560                 for(;;) {
561                         c = escchar('"', 1, 0);
562                         if(c == EOF)
563                                 break;
564                         cp = allocn(cp, c1, sizeof(Rune));
565                         *(Rune*)(cp + c1) = c;
566                         c1 += sizeof(Rune);
567                 }
568                 yylval.sval.l = c1;
569                 do {
570                         cp = allocn(cp, c1, sizeof(Rune));
571                         *(Rune*)(cp + c1) = 0;
572                         c1 += sizeof(Rune);
573                 } while(c1 & MAXALIGN);
574                 yylval.sval.s = cp;
575                 return LLSTRING;
576
577         case '\'':
578                 /* '.' */
579                 c = escchar('\'', 0, 0);
580                 if(c == EOF)
581                         c = '\'';
582                 c1 = escchar('\'', 0, 0);
583                 if(c1 != EOF) {
584                         yyerror("missing '");
585                         peekc = c1;
586                 }
587                 vv = c;
588                 yylval.vval = convvtox(vv, TUCHAR);
589                 if(yylval.vval != vv)
590                         yyerror("overflow in character constant: 0x%lx", c);
591                 else
592                 if(c & 0x80){
593                         nearln = lineno;
594                         warn(Z, "sign-extended character constant");
595                 }
596                 yylval.vval = convvtox(vv, TCHAR);
597                 return LCONST;
598
599         case '/':
600                 c1 = GETC();
601                 if(c1 == '*') {
602                         for(;;) {
603                                 c = getr();
604                                 while(c == '*') {
605                                         c = getr();
606                                         if(c == '/')
607                                                 goto l0;
608                                 }
609                                 if(c == EOF) {
610                                         yyerror("eof in comment");
611                                         errorexit();
612                                 }
613                         }
614                 }
615                 if(c1 == '/') {
616                         for(;;) {
617                                 c = getr();
618                                 if(c == '\n')
619                                         goto l0;
620                                 if(c == EOF) {
621                                         yyerror("eof in comment");
622                                         errorexit();
623                                 }
624                         }
625                 }
626                 if(c1 == '=')
627                         return LDVE;
628                 break;
629
630         case '*':
631                 c1 = GETC();
632                 if(c1 == '=')
633                         return LMLE;
634                 break;
635
636         case '%':
637                 c1 = GETC();
638                 if(c1 == '=')
639                         return LMDE;
640                 break;
641
642         case '+':
643                 c1 = GETC();
644                 if(c1 == '+')
645                         return LPP;
646                 if(c1 == '=')
647                         return LPE;
648                 break;
649
650         case '-':
651                 c1 = GETC();
652                 if(c1 == '-')
653                         return LMM;
654                 if(c1 == '=')
655                         return LME;
656                 if(c1 == '>')
657                         return LMG;
658                 break;
659
660         case '>':
661                 c1 = GETC();
662                 if(c1 == '>') {
663                         c = LRSH;
664                         c1 = GETC();
665                         if(c1 == '=')
666                                 return LRSHE;
667                         break;
668                 }
669                 if(c1 == '=')
670                         return LGE;
671                 break;
672
673         case '<':
674                 c1 = GETC();
675                 if(c1 == '<') {
676                         c = LLSH;
677                         c1 = GETC();
678                         if(c1 == '=')
679                                 return LLSHE;
680                         break;
681                 }
682                 if(c1 == '=')
683                         return LLE;
684                 break;
685
686         case '=':
687                 c1 = GETC();
688                 if(c1 == '=')
689                         return LEQ;
690                 break;
691
692         case '!':
693                 c1 = GETC();
694                 if(c1 == '=')
695                         return LNE;
696                 break;
697
698         case '&':
699                 c1 = GETC();
700                 if(c1 == '&')
701                         return LANDAND;
702                 if(c1 == '=')
703                         return LANDE;
704                 break;
705
706         case '|':
707                 c1 = GETC();
708                 if(c1 == '|')
709                         return LOROR;
710                 if(c1 == '=')
711                         return LORE;
712                 break;
713
714         case '^':
715                 c1 = GETC();
716                 if(c1 == '=')
717                         return LXORE;
718                 break;
719
720         default:
721                 return c;
722         }
723         peekc = c1;
724         return c;
725
726 talph:
727         /*
728          * cp is set to symb and some
729          * prefix has been stored
730          */
731         for(;;) {
732                 if(cp >= &symb[NSYMB-UTFmax-1])
733                         goto toolong;
734                 if(c >= Runeself) {
735                         for(c1=0;;) {
736                                 cp[c1++] = c;
737                                 if(fullrune(cp, c1))
738                                         break;
739                                 c = GETC();
740                         }
741                         cp += c1;
742                         c = GETC();
743                         continue;
744                 }
745                 if(!isalnum(c) && c != '_')
746                         break;
747                 *cp++ = c;
748                 c = GETC();
749         }
750         *cp = 0;
751         if(debug['L'])
752                 print("%L: %s\n", lineno, symb);
753         peekc = c;
754         s = lookup();
755         if(s->macro) {
756                 newio();
757                 cp = ionext->b;
758                 macexpand(s, cp, sizeof(ionext->b)-1);
759                 pushio();
760                 ionext->link = iostack;
761                 iostack = ionext;
762                 fi.p = cp;
763                 fi.c = strlen(cp);
764                 if(peekc != IGN) {
765                         cp[fi.c++] = peekc;
766                         cp[fi.c] = 0;
767                         peekc = IGN;
768                 }
769                 goto l0;
770         }
771         yylval.sym = s;
772         if(s->class == CTYPEDEF || s->class == CTYPESTR)
773                 return LTYPE;
774         return s->lexical;
775
776 tnum:
777         c1 = 0;
778         cp = symb;
779         if(c != '0') {
780                 c1 |= Numdec;
781                 for(;;) {
782                         if(cp >= &symb[NSYMB-1])
783                                 goto toolong;
784                         *cp++ = c;
785                         c = GETC();
786                         if(isdigit(c))
787                                 continue;
788                         goto dc;
789                 }
790         }
791         *cp++ = c;
792         c = GETC();
793         if(c == 'x' || c == 'X')
794                 for(;;) {
795                         if(cp >= &symb[NSYMB-1])
796                                 goto toolong;
797                         *cp++ = c;
798                         c = GETC();
799                         if(isdigit(c))
800                                 continue;
801                         if(c >= 'a' && c <= 'f')
802                                 continue;
803                         if(c >= 'A' && c <= 'F')
804                                 continue;
805                         if(cp == symb+2)
806                                 yyerror("malformed hex constant");
807                         goto ncu;
808                 }
809         if(c < '0' || c > '7')
810                 goto dc;
811         for(;;) {
812                 if(c >= '0' && c <= '7') {
813                         if(cp >= &symb[NSYMB-1])
814                                 goto toolong;
815                         *cp++ = c;
816                         c = GETC();
817                         continue;
818                 }
819                 goto ncu;
820         }
821
822 dc:
823         if(c == '.')
824                 goto casedot;
825         if(c == 'e' || c == 'E')
826                 goto casee;
827
828 ncu:
829         if((c == 'U' || c == 'u') && !(c1 & Numuns)) {
830                 c = GETC();
831                 c1 |= Numuns;
832                 goto ncu;
833         }
834         if((c == 'L' || c == 'l') && !(c1 & Numvlong)) {
835                 c = GETC();
836                 if(c1 & Numlong)
837                         c1 |= Numvlong;
838                 c1 |= Numlong;
839                 goto ncu;
840         }
841         *cp = 0;
842         peekc = c;
843         if(mpatov(symb, &yylval.vval))
844                 yyerror("overflow in constant");
845
846         vv = yylval.vval;
847         /*
848          * c99 is silly: decimal constants stay signed,
849          * hex and octal go unsigned before widening.
850          */
851         w = 32;
852         if((c1 & (Numdec|Numuns)) == Numdec)
853                 w = 31;
854         if(c1 & Numvlong || (c1 & Numlong) == 0 && (uvlong)vv >= 1ULL<<w){
855                 if((c1&(Numdec|Numvlong)) == Numdec && vv < 1ULL<<32)
856                         warn(Z, "int constant widened to vlong: %s", symb);
857                 if((c1 & Numuns) || convvtox(vv, TVLONG) < 0) {
858                         c = LUVLCONST;
859                         t = TUVLONG;
860                         goto nret;
861                 }
862                 c = LVLCONST;
863                 t = TVLONG;
864                 goto nret;
865         }
866         if(c1 & Numlong) {
867                 if((c1 & Numuns) || convvtox(vv, TLONG) < 0) {
868                         c = LULCONST;
869                         t = TULONG;
870                         goto nret;
871                 }
872                 c = LLCONST;
873                 t = TLONG;
874                 goto nret;
875         }
876         if((c1 & Numuns) || convvtox(vv, TINT) < 0) {
877                 c = LUCONST;
878                 t = TUINT;
879                 goto nret;
880         }
881         c = LCONST;
882         t = TINT;
883         goto nret;
884
885 nret:
886         yylval.vval = convvtox(vv, t);
887         if(yylval.vval != vv){
888                 nearln = lineno;
889                 warn(Z, "truncated constant: %T %s", types[t], symb);
890         }
891         return c;
892
893 casedot:
894         for(;;) {
895                 if(cp >= &symb[NSYMB-1])
896                         goto toolong;
897                 *cp++ = c;
898                 c = GETC();
899                 if(!isdigit(c))
900                         break;
901         }
902         if(c != 'e' && c != 'E')
903                 goto caseout;
904
905 casee:
906         if(cp >= &symb[NSYMB-2])
907                 goto toolong;
908         *cp++ = 'e';
909         c = GETC();
910         if(c == '+' || c == '-') {
911                 *cp++ = c;
912                 c = GETC();
913         }
914         if(!isdigit(c))
915                 yyerror("malformed fp constant exponent");
916         while(isdigit(c)) {
917                 if(cp >= &symb[NSYMB-1])
918                         goto toolong;
919                 *cp++ = c;
920                 c = GETC();
921         }
922
923 caseout:
924         if(c == 'L' || c == 'l') {
925                 c = GETC();
926                 c1 |= Numlong;
927         } else
928         if(c == 'F' || c == 'f') {
929                 c = GETC();
930                 c1 |= Numflt;
931         }
932         *cp = 0;
933         peekc = c;
934         yylval.dval = strtod(symb, nil);
935         if(isInf(yylval.dval, 1) || isInf(yylval.dval, -1)) {
936                 yyerror("overflow in float constant");
937                 yylval.dval = 0;
938         }
939         if(c1 & Numflt)
940                 return LFCONST;
941         return LDCONST;
942
943 toolong:
944         yyerror("token too long: %.*s...", utfnlen(symb, cp-symb), symb);
945         errorexit();
946         return -1;
947 }
948
949 /*
950  * convert a string, s, to vlong in *v
951  * return conversion overflow.
952  * required syntax is [0[x]]d*
953  */
954 int
955 mpatov(char *s, vlong *v)
956 {
957         vlong n, nn;
958         int c;
959
960         n = 0;
961         c = *s;
962         if(c == '0')
963                 goto oct;
964         while(c = *s++) {
965                 if(c >= '0' && c <= '9')
966                         nn = n*10 + c-'0';
967                 else
968                         goto bad;
969                 if(n < 0 && nn >= 0)
970                         goto bad;
971                 n = nn;
972         }
973         goto out;
974
975 oct:
976         s++;
977         c = *s;
978         if(c == 'x' || c == 'X')
979                 goto hex;
980         while(c = *s++) {
981                 if(c >= '0' || c <= '7')
982                         nn = n*8 + c-'0';
983                 else
984                         goto bad;
985                 if(n < 0 && nn >= 0)
986                         goto bad;
987                 n = nn;
988         }
989         goto out;
990
991 hex:
992         s++;
993         while(c = *s++) {
994                 if(c >= '0' && c <= '9')
995                         c += 0-'0';
996                 else
997                 if(c >= 'a' && c <= 'f')
998                         c += 10-'a';
999                 else
1000                 if(c >= 'A' && c <= 'F')
1001                         c += 10-'A';
1002                 else
1003                         goto bad;
1004                 nn = n*16 + c;
1005                 if(n < 0 && nn >= 0)
1006                         goto bad;
1007                 n = nn;
1008         }
1009 out:
1010         *v = n;
1011         return 0;
1012
1013 bad:
1014         *v = ~0;
1015         return 1;
1016 }
1017
1018 int
1019 getc(void)
1020 {
1021         int c;
1022
1023         if(peekc != IGN) {
1024                 c = peekc;
1025                 peekc = IGN;
1026         } else
1027                 c = GETC();
1028         if(c == '\n')
1029                 lineno++;
1030         if(c == EOF) {
1031                 yyerror("End of file");
1032                 errorexit();
1033         }
1034         return c;
1035 }
1036
1037 long
1038 getr(void)
1039 {
1040         int c, i;
1041         char str[UTFmax+1];
1042         Rune rune;
1043
1044
1045         c = getc();
1046         if(c < Runeself)
1047                 return c;
1048         i = 0;
1049         str[i++] = c;
1050
1051 loop:
1052         c = getc();
1053         str[i++] = c;
1054         if(!fullrune(str, i))
1055                 goto loop;
1056         c = chartorune(&rune, str);
1057         if(rune == Runeerror && c == 1) {
1058                 nearln = lineno;
1059                 diag(Z, "illegal rune in string");
1060                 for(c=0; c<i; c++)
1061                         print(" %.2x", *(uchar*)(str+c));
1062                 print("\n");
1063         }
1064         return rune;
1065 }
1066
1067 int
1068 getnsc(void)
1069 {
1070         int c;
1071
1072         if(peekc != IGN) {
1073                 c = peekc;
1074                 peekc = IGN;
1075         } else
1076                 c = GETC();
1077         for(;;) {
1078                 if(c >= Runeself || !isspace(c))
1079                         return c;
1080                 if(c == '\n') {
1081                         lineno++;
1082                         return c;
1083                 }
1084                 c = GETC();
1085         }
1086 }
1087
1088 void
1089 unget(int c)
1090 {
1091
1092         peekc = c;
1093         if(c == '\n')
1094                 lineno--;
1095 }
1096
1097 long
1098 escchar(long e, int longflg, int escflg)
1099 {
1100         long c, l;
1101         int i;
1102
1103 loop:
1104         c = getr();
1105         if(c == '\n') {
1106                 yyerror("newline in string");
1107                 return EOF;
1108         }
1109         if(c != '\\') {
1110                 if(c == e)
1111                         c = EOF;
1112                 return c;
1113         }
1114         c = getr();
1115         if(c == 'x') {
1116                 /*
1117                  * note this is not ansi,
1118                  * supposed to only accept 2 hex
1119                  */
1120                 i = 2;
1121                 if(longflg)
1122                         i = 6;
1123                 l = 0;
1124                 for(; i>0; i--) {
1125                         c = getc();
1126                         if(c >= '0' && c <= '9') {
1127                                 l = l*16 + c-'0';
1128                                 continue;
1129                         }
1130                         if(c >= 'a' && c <= 'f') {
1131                                 l = l*16 + c-'a' + 10;
1132                                 continue;
1133                         }
1134                         if(c >= 'A' && c <= 'F') {
1135                                 l = l*16 + c-'A' + 10;
1136                                 continue;
1137                         }
1138                         unget(c);
1139                         break;
1140                 }
1141                 if(escflg)
1142                         l |= ESC;
1143                 return l;
1144         }
1145         if(c >= '0' && c <= '7') {
1146                 /*
1147                  * note this is not ansi,
1148                  * supposed to only accept 3 oct
1149                  */
1150                 i = 2;
1151                 if(longflg)
1152                         i = 6;
1153                 l = c - '0';
1154                 for(; i>0; i--) {
1155                         c = getc();
1156                         if(c >= '0' && c <= '7') {
1157                                 l = l*8 + c-'0';
1158                                 continue;
1159                         }
1160                         unget(c);
1161                 }
1162                 if(escflg)
1163                         l |= ESC;
1164                 return l;
1165         }
1166         switch(c)
1167         {
1168         case '\n':      goto loop;
1169         case 'n':       return '\n';
1170         case 't':       return '\t';
1171         case 'b':       return '\b';
1172         case 'r':       return '\r';
1173         case 'f':       return '\f';
1174         case 'a':       return '\a';
1175         case 'v':       return '\v';
1176         }
1177         return c;
1178 }
1179
1180 struct
1181 {
1182         char    *name;
1183         ushort  lexical;
1184         ushort  type;
1185 } itab[] =
1186 {
1187         "auto",         LAUTO,          0,
1188         "break",        LBREAK,         0,
1189         "case",         LCASE,          0,
1190         "char",         LCHAR,          TCHAR,
1191         "const",        LCONSTNT,       0,
1192         "continue",     LCONTINUE,      0,
1193         "default",      LDEFAULT,       0,
1194         "do",           LDO,            0,
1195         "double",       LDOUBLE,        TDOUBLE,
1196         "else",         LELSE,          0,
1197         "enum",         LENUM,          0,
1198         "extern",       LEXTERN,        0,
1199         "float",        LFLOAT,         TFLOAT,
1200         "for",          LFOR,           0,
1201         "goto",         LGOTO,          0,
1202         "if",           LIF,            0,
1203         "inline",       LINLINE,        0,
1204         "int",          LINT,           TINT,
1205         "long",         LLONG,          TLONG,
1206         "register",     LREGISTER,      0,
1207         "restrict",     LRESTRICT,      0,
1208         "return",       LRETURN,        0,
1209         "SET",          LSET,           0,
1210         "short",        LSHORT,         TSHORT,
1211         "signed",       LSIGNED,        0,
1212         "signof",       LSIGNOF,        0,
1213         "sizeof",       LSIZEOF,        0,
1214         "static",       LSTATIC,        0,
1215         "struct",       LSTRUCT,        0,
1216         "switch",       LSWITCH,        0,
1217         "typedef",      LTYPEDEF,       0,
1218         "typestr",      LTYPESTR,       0,
1219         "union",        LUNION,         0,
1220         "unsigned",     LUNSIGNED,      0,
1221         "USED",         LUSED,          0,
1222         "void",         LVOID,          TVOID,
1223         "volatile",     LVOLATILE,      0,
1224         "while",        LWHILE,         0,
1225         0
1226 };
1227
1228 void
1229 cinit(void)
1230 {
1231         Sym *s;
1232         int i;
1233         Type *t;
1234
1235         nerrors = 0;
1236         lineno = 1;
1237         iostack = I;
1238         iofree = I;
1239         peekc = IGN;
1240
1241         types[TXXX] = T;
1242         types[TCHAR] = typ(TCHAR, T);
1243         types[TUCHAR] = typ(TUCHAR, T);
1244         types[TSHORT] = typ(TSHORT, T);
1245         types[TUSHORT] = typ(TUSHORT, T);
1246         types[TINT] = typ(TINT, T);
1247         types[TUINT] = typ(TUINT, T);
1248         types[TLONG] = typ(TLONG, T);
1249         types[TULONG] = typ(TULONG, T);
1250         types[TVLONG] = typ(TVLONG, T);
1251         types[TUVLONG] = typ(TUVLONG, T);
1252         types[TFLOAT] = typ(TFLOAT, T);
1253         types[TDOUBLE] = typ(TDOUBLE, T);
1254         types[TVOID] = typ(TVOID, T);
1255         types[TENUM] = typ(TENUM, T);
1256         types[TFUNC] = typ(TFUNC, types[TINT]);
1257         types[TIND] = typ(TIND, types[TVOID]);
1258
1259         for(i=0; i<NHASH; i++)
1260                 hash[i] = S;
1261         for(i=0; itab[i].name; i++) {
1262                 s = slookup(itab[i].name);
1263                 s->lexical = itab[i].lexical;
1264                 if(itab[i].type != 0)
1265                         s->type = types[itab[i].type];
1266         }
1267         blockno = 0;
1268         autobn = 0;
1269         autoffset = 0;
1270
1271         t = typ(TARRAY, types[TCHAR]);
1272         t->width = 0;
1273         symstring = slookup(".string");
1274         symstring->class = CSTATIC;
1275         symstring->type = t;
1276
1277         t = typ(TARRAY, types[TCHAR]);
1278         t->width = 0;
1279
1280         nodproto = new(OPROTO, Z, Z);
1281         dclstack = D;
1282
1283         pathname = allocn(pathname, 0, 100);
1284         if(mygetwd(pathname, 99) == 0) {
1285                 pathname = allocn(pathname, 100, 900);
1286                 if(mygetwd(pathname, 999) == 0)
1287                         strcpy(pathname, "/???");
1288         }
1289
1290         fmtinstall('O', Oconv);
1291         fmtinstall('T', Tconv);
1292         fmtinstall('F', FNconv);
1293         fmtinstall('L', Lconv);
1294         fmtinstall('Q', Qconv);
1295         fmtinstall('|', VBconv);
1296 }
1297
1298 int
1299 filbuf(void)
1300 {
1301         Io *i;
1302
1303 loop:
1304         i = iostack;
1305         if(i == I)
1306                 return EOF;
1307         if(i->f < 0)
1308                 goto pop;
1309         fi.c = read(i->f, i->b, BUFSIZ) - 1;
1310         if(fi.c < 0) {
1311                 close(i->f);
1312                 linehist(0, 0);
1313                 goto pop;
1314         }
1315         fi.p = i->b + 1;
1316         return i->b[0] & 0xff;
1317
1318 pop:
1319         iostack = i->link;
1320         i->link = iofree;
1321         iofree = i;
1322         i = iostack;
1323         if(i == I)
1324                 return EOF;
1325         fi.p = i->p;
1326         fi.c = i->c;
1327         if(--fi.c < 0)
1328                 goto loop;
1329         return *fi.p++ & 0xff;
1330 }
1331
1332 int
1333 Oconv(Fmt *fp)
1334 {
1335         int a;
1336
1337         a = va_arg(fp->args, int);
1338         if(a < OXXX || a > OEND)
1339                 return fmtprint(fp, "***badO %d***", a);
1340
1341         return fmtstrcpy(fp, onames[a]);
1342 }
1343
1344 int
1345 Lconv(Fmt *fp)
1346 {
1347         Hist *h;
1348         struct
1349         {
1350                 Hist*   incl;   /* start of this include file */
1351                 long    idel;   /* delta line number to apply to include */
1352                 Hist*   line;   /* start of this #line directive */
1353                 long    ldel;   /* delta line number to apply to #line */
1354         } a[HISTSZ];
1355         long l, d;
1356         int i, n;
1357
1358         l = va_arg(fp->args, long);
1359         n = 0;
1360         for(h = hist; h != H; h = h->link) {
1361                 if(l < h->line)
1362                         break;
1363                 if(h->name) {
1364                         if(h->offset != 0) {            /* #line directive, not #pragma */
1365                                 if(n > 0 && n < HISTSZ && h->offset >= 0) {
1366                                         a[n-1].line = h;
1367                                         a[n-1].ldel = h->line - h->offset + 1;
1368                                 }
1369                         } else {
1370                                 if(n < HISTSZ) {        /* beginning of file */
1371                                         a[n].incl = h;
1372                                         a[n].idel = h->line;
1373                                         a[n].line = 0;
1374                                 }
1375                                 n++;
1376                         }
1377                         continue;
1378                 }
1379                 n--;
1380                 if(n > 0 && n < HISTSZ) {
1381                         d = h->line - a[n].incl->line;
1382                         a[n-1].ldel += d;
1383                         a[n-1].idel += d;
1384                 }
1385         }
1386         if(n > HISTSZ)
1387                 n = HISTSZ;
1388         if(n == 0)
1389                 return fmtprint(fp, "<eof>");
1390         for(i=n-1; i>=0; i--) {
1391                 if(i != n-1) {
1392                         if(fp->flags & ~(FmtWidth|FmtPrec))     /* BUG ROB - was f3 */
1393                                 break;
1394                         fmtrune(fp, ' ');
1395                 }
1396                 if(a[i].line)
1397                         fmtprint(fp, "%s:%ld[%s:%ld]",
1398                                 a[i].line->name, l-a[i].ldel+1,
1399                                 a[i].incl->name, l-a[i].idel+1);
1400                 else
1401                         fmtprint(fp, "%s:%ld",
1402                                 a[i].incl->name, l-a[i].idel+1);
1403                 l = a[i].incl->line - 1;        /* now print out start of this file */
1404         }
1405         return 0;
1406 }
1407
1408 int
1409 Tconv(Fmt *fp)
1410 {
1411         Type *t, *t1;
1412         int et;
1413         long n;
1414
1415         t = va_arg(fp->args, Type*);
1416         while(t != T) {
1417                 if(t->garb&~GINCOMPLETE)
1418                         fmtprint(fp, "%s ", gnames[t->garb&~GINCOMPLETE]);
1419                 et = t->etype;
1420                 fmtprint(fp, "%s", tnames[et]);
1421                 if(et == TFUNC && (t1 = t->down) != T) {
1422                         fmtprint(fp, "(%T", t1);
1423                         while((t1 = t1->down) != T)
1424                                 fmtprint(fp, ", %T", t1);
1425                         fmtprint(fp, ")");
1426                 }
1427                 if(et == TARRAY) {
1428                         n = t->width;
1429                         if(t->link != T && t->link->width)
1430                                 n /= t->link->width;
1431                         fmtprint(fp, "[%ld]", n);
1432                 }
1433                 if(t->nbits)
1434                         fmtprint(fp, " %d:%d", t->shift, t->nbits);
1435                 if(typesu[et]) {
1436                         fmtprint(fp, " %s", t->tag? t->tag->name: "{}");
1437                         break;
1438                 }
1439                 if((t = t->link) == T)
1440                         break;
1441                 fmtrune(fp, ' ');
1442         }
1443         return 0;
1444 }
1445
1446 int
1447 FNconv(Fmt *fp)
1448 {
1449         char *str;
1450         Node *n;
1451
1452         n = va_arg(fp->args, Node*);
1453         str = "<indirect>";
1454         if(n != Z && (n->op == ONAME || n->op == ODOT || n->op == OELEM))
1455                 str = n->sym->name;
1456         return fmtstrcpy(fp, str);
1457 }
1458
1459 int
1460 Qconv(Fmt *fp)
1461 {
1462         long b;
1463         int i;
1464
1465         b = va_arg(fp->args, long);
1466         while(b) {
1467                 i = bitno(b);
1468                 b &= ~(1L << i);
1469                 fmtprint(fp, "%s%s", qnames[i], b? " ": "");
1470         }
1471         return 0;
1472 }
1473
1474 int
1475 VBconv(Fmt *fp)
1476 {
1477         int n, t, pc;
1478
1479         n = va_arg(fp->args, int);
1480         pc = 0; /* BUG: was printcol */
1481         while(pc < n) {
1482                 t = (pc+4) & ~3;
1483                 if(t <= n) {
1484                         fmtrune(fp, '\t');
1485                         pc = t;
1486                 } else {
1487                         fmtrune(fp, ' ');
1488                         pc++;
1489                 }
1490         }
1491         return 0;
1492 }
1493
1494 void
1495 setinclude(char *p)
1496 {
1497         int i;
1498         char *e;
1499
1500         while(*p != 0) {
1501                 e = strchr(p, ' ');
1502                 if(e != 0)
1503                         *e = '\0';
1504
1505                 for(i=1; i < ninclude; i++)
1506                         if(strcmp(p, include[i]) == 0)
1507                                 break;
1508
1509                 if(i >= ninclude){
1510                         if(ninclude >= nelem(include)) {
1511                                 diag(Z, "ninclude too small %d", nelem(include));
1512                                 exits("ninclude");
1513                         }
1514                         include[ninclude++] = p;
1515                 }
1516
1517                 if(e == 0)
1518                         break;
1519                 p = e+1;
1520         }
1521 }