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