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