ncc: handle empty static initializers
[neatcc.git] / cpp.c
blob57a907552b41d3c01b37871b48d2ba4da04dac90
1 #include <ctype.h>
2 #include <fcntl.h>
3 #include <stdarg.h>
4 #include <stddef.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <unistd.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include "tok.h"
12 #include "tab.h"
14 static char *buf;
15 static int len;
16 static int cur;
18 #define MAXDEFS (1 << 12)
19 #define MACROLEN (1 << 10)
20 #define MAXARGS (1 << 5)
21 #define NBUCKET (MAXDEFS << 1)
23 static struct macro {
24 char name[NAMELEN];
25 char def[MACROLEN];
26 char args[MAXARGS][NAMELEN];
27 int nargs;
28 int isfunc;
29 } macros[MAXDEFS];
30 static int nmacros;
31 /* macro hash table */
32 static struct tab mtab;
34 #define MAXBUFS (1 << 5)
35 #define BUF_FILE 0
36 #define BUF_MACRO 1
37 #define BUF_ARG 2
38 #define BUF_EVAL 3
39 #define BUF_TEMP 4
41 static struct buf {
42 char *buf;
43 int len;
44 int cur;
45 int type;
46 /* for BUF_FILE */
47 char path[NAMELEN];
48 /* for BUF_MACRO */
49 struct macro *macro;
50 char args[MAXARGS][MACROLEN]; /* arguments passed to a macro */
51 /* for BUF_ARG */
52 int arg_buf; /* the bufs index of the owning macro */
53 } bufs[MAXBUFS];
54 static int nbufs;
56 void die(char *fmt, ...)
58 va_list ap;
59 char msg[512];
60 va_start(ap, fmt);
61 vsprintf(msg, fmt, ap);
62 va_end(ap);
63 write(2, msg, strlen(msg));
64 exit(1);
67 static void buf_new(int type, char *dat, int dlen)
69 if (nbufs) {
70 bufs[nbufs - 1].buf = buf;
71 bufs[nbufs - 1].cur = cur;
72 bufs[nbufs - 1].len = len;
74 if (nbufs >= MAXBUFS)
75 die("nomem: MAXBUFS reached!\n");
76 nbufs++;
77 cur = 0;
78 buf = dat;
79 len = dlen;
80 bufs[nbufs - 1].type = type;
83 static void buf_file(char *path, char *dat, int dlen)
85 buf_new(BUF_FILE, dat, dlen);
86 strcpy(bufs[nbufs - 1].path, path ? path : "");
89 static void buf_macro(struct macro *m)
91 buf_new(BUF_MACRO, m->def, strlen(m->def));
92 bufs[nbufs - 1].macro = m;
95 static void buf_arg(char *arg, int mbuf)
97 buf_new(BUF_ARG, arg, strlen(arg));
98 bufs[nbufs - 1].arg_buf = mbuf;
101 static void buf_pop(void)
103 nbufs--;
104 if (nbufs) {
105 cur = bufs[nbufs - 1].cur;
106 len = bufs[nbufs - 1].len;
107 buf = bufs[nbufs - 1].buf;
111 static int buf_iseval(void)
113 int i;
114 for (i = nbufs - 1; i >= 0; i--)
115 if (bufs[i].type == BUF_EVAL)
116 return 1;
117 return 0;
120 static size_t file_size(int fd)
122 struct stat st;
123 if (!fstat(fd, &st))
124 return st.st_size;
125 return 0;
128 static int include_file(char *path)
130 int fd = open(path, O_RDONLY);
131 int n = 0, nr = 0;
132 char *dat;
133 int size;
134 if (fd == -1)
135 return -1;
136 size = file_size(fd) + 1;
137 dat = malloc(size);
138 while ((n = read(fd, dat + nr, size - nr)) > 0)
139 nr += n;
140 close(fd);
141 dat[nr] = '\0';
142 buf_file(path, dat, nr);
143 return 0;
146 int cpp_init(char *path)
148 return include_file(path);
151 static void jumpws(void)
153 while (cur < len && isspace(buf[cur]))
154 cur++;
157 static void read_word(char *dst)
159 jumpws();
160 while (cur < len && (isalnum(buf[cur]) || buf[cur] == '_'))
161 *dst++ = buf[cur++];
162 *dst = '\0';
165 static int jumpcomment(void)
167 if (buf[cur] == '/' && buf[cur + 1] == '*') {
168 while (++cur < len) {
169 if (buf[cur] == '*' && buf[cur + 1] == '/') {
170 cur += 2;
171 return 0;
175 if (buf[cur] == '/' && buf[cur + 1] == '/') {
176 while (++cur < len)
177 if (buf[cur] == '\n')
178 break;
179 return 0;
181 return 1;
184 static int jumpstr(void)
186 if (buf[cur] == '\'') {
187 while (cur < len && buf[++cur] != '\'')
188 if (buf[cur] == '\\')
189 cur++;
190 cur++;
191 return 0;
193 if (buf[cur] == '"') {
194 while (cur < len && buf[++cur] != '"')
195 if (buf[cur] == '\\')
196 cur++;
197 cur++;
198 return 0;
200 return 1;
203 static void read_tilleol(char *dst)
205 while (cur < len && isspace(buf[cur]) && buf[cur] != '\n')
206 cur++;
207 while (cur < len && buf[cur] != '\n') {
208 int last = cur;
209 if (buf[cur] == '\\' && buf[cur + 1] == '\n') {
210 cur += 2;
211 } else if (jumpcomment()) {
212 *dst++ = buf[cur++];
213 } else if (jumpstr()) {
214 memcpy(dst, buf + last, cur - last);
215 dst += cur - last;
218 *dst = '\0';
221 static char *putstr(char *d, char *s)
223 while (*s)
224 *d++ = *s++;
225 *d = '\0';
226 return d;
229 #define MAXLOCS (1 << 10)
231 static char *locs[MAXLOCS] = {};
232 static int nlocs = 0;
234 void cpp_addpath(char *s)
236 locs[nlocs++] = s;
239 static int include_find(char *name, int std)
241 int i;
242 for (i = std ? nlocs - 1 : nlocs; i >= 0; i--) {
243 char path[1 << 10];
244 char *s;
245 s = path;
246 if (locs[i]) {
247 s = putstr(s, locs[i]);
248 *s++ = '/';
250 s = putstr(s, name);
251 if (!include_file(path))
252 return 0;
254 return -1;
257 static void readarg(char *s)
259 int depth = 0;
260 int beg = cur;
261 while (cur < len && (depth || buf[cur] != ',' && buf[cur] != ')')) {
262 if (!jumpstr() || !jumpcomment())
263 continue;
264 switch (buf[cur++]) {
265 case '(':
266 case '[':
267 case '{':
268 depth++;
269 break;
270 case ')':
271 case ']':
272 case '}':
273 depth--;
274 break;
277 if (s) {
278 memcpy(s, buf + beg, cur - beg);
279 s[cur - beg] = '\0';
283 static int macro_find(char *name)
285 char *n = tab_get(&mtab, name);
286 if (!n)
287 return -1;
288 return container(n, struct macro, name) - macros;
291 static void macro_undef(char *name)
293 int i = macro_find(name);
294 if (i >= 0)
295 tab_del(&mtab, macros[i].name);
298 static int macro_new(char *name)
300 int i = macro_find(name);
301 if (i >= 0)
302 return i;
303 if (nmacros >= MAXDEFS)
304 die("nomem: MAXDEFS reached!\n");
305 i = nmacros++;
306 strcpy(macros[i].name, name);
307 tab_add(&mtab, macros[i].name);
308 return i;
311 static void macro_define(void)
313 char name[NAMELEN];
314 struct macro *d;
315 read_word(name);
316 d = &macros[macro_new(name)];
317 d->isfunc = 0;
318 d->nargs = 0;
319 if (buf[cur] == '(') {
320 cur++;
321 jumpws();
322 while (cur < len && buf[cur] != ')') {
323 readarg(d->args[d->nargs++]);
324 jumpws();
325 if (buf[cur] != ',')
326 break;
327 cur++;
328 jumpws();
330 cur++;
331 d->isfunc = 1;
333 read_tilleol(d->def);
336 int cpp_read(char *buf);
338 static char ebuf[BUFSIZE];
339 static int elen;
340 static int ecur;
342 static long evalexpr(void);
344 static int cpp_eval(void)
346 int bufid;
347 int ret;
348 char evalbuf[BUFSIZE];
349 read_tilleol(evalbuf);
350 buf_new(BUF_EVAL, evalbuf, strlen(evalbuf));
351 bufid = nbufs;
352 elen = 0;
353 ecur = 0;
354 while (bufid < nbufs || (bufid == nbufs && cur < len))
355 elen += cpp_read(ebuf + elen);
356 ret = evalexpr();
357 buf_pop();
358 return ret;
361 static void jumpifs(int jumpelse)
363 int depth = 0;
364 while (cur < len) {
365 if (buf[cur] == '#') {
366 char cmd[NAMELEN];
367 cur++;
368 read_word(cmd);
369 if (!strcmp("else", cmd))
370 if (!depth && !jumpelse)
371 break;
372 if (!strcmp("elif", cmd))
373 if (!depth && !jumpelse && cpp_eval())
374 break;
375 if (!strcmp("endif", cmd)) {
376 if (!depth)
377 break;
378 else
379 depth--;
381 if (!strcmp("ifdef", cmd) || !strcmp("ifndef", cmd) ||
382 !strcmp("if", cmd))
383 depth++;
384 continue;
386 if (!jumpcomment())
387 continue;
388 if (!jumpstr())
389 continue;
390 cur++;
394 static int cpp_cmd(void)
396 char cmd[NAMELEN];
397 cur++;
398 read_word(cmd);
399 if (!strcmp("define", cmd)) {
400 macro_define();
401 return 0;
403 if (!strcmp("undef", cmd)) {
404 char name[NAMELEN];
405 read_word(name);
406 macro_undef(name);
407 return 0;
409 if (!strcmp("ifdef", cmd) || !strcmp("ifndef", cmd) ||
410 !strcmp("if", cmd)) {
411 char name[NAMELEN];
412 int matched = 0;
413 if (cmd[2]) {
414 int not = cmd[2] == 'n';
415 read_word(name);
416 matched = not ? macro_find(name) < 0 :
417 macro_find(name) >= 0;
418 } else {
419 matched = cpp_eval();
421 if (!matched)
422 jumpifs(0);
423 return 0;
425 if (!strcmp("else", cmd) || !strcmp("elif", cmd)) {
426 jumpifs(1);
427 return 0;
429 if (!strcmp("endif", cmd))
430 return 0;
431 if (!strcmp("include", cmd)) {
432 char file[NAMELEN];
433 char *s, *e;
434 jumpws();
435 s = buf + cur + 1;
436 e = strchr(buf + cur + 1, buf[cur] == '"' ? '"' : '>');
437 memcpy(file, s, e - s);
438 file[e - s] = '\0';
439 cur += e - s + 2;
440 if (include_find(file, *e == '>') == -1)
441 die("cannot include <%s>\n", file);
442 return 0;
444 return 1;
447 static int macro_arg(struct macro *m, char *arg)
449 int i;
450 for (i = 0; i < m->nargs; i++)
451 if (!strcmp(arg, m->args[i]))
452 return i;
453 return -1;
456 static int buf_arg_find(char *name)
458 int i;
459 for (i = nbufs - 1; i >= 0; i--) {
460 struct buf *mbuf = &bufs[i];
461 struct macro *m = mbuf->macro;
462 if (mbuf->type == BUF_MACRO && macro_arg(m, name) >= 0)
463 return i;
464 if (mbuf->type == BUF_ARG)
465 i = mbuf->arg_buf;
467 return -1;
470 static void macro_expand(void)
472 char name[NAMELEN];
473 struct macro *m;
474 int mbuf;
475 read_word(name);
476 if ((mbuf = buf_arg_find(name)) >= 0) {
477 int arg = macro_arg(bufs[mbuf].macro, name);
478 char *dat = bufs[mbuf].args[arg];
479 buf_arg(dat, mbuf);
480 return;
482 m = &macros[macro_find(name)];
483 if (!m->isfunc) {
484 buf_macro(m);
485 return;
487 jumpws();
488 if (buf[cur] == '(') {
489 int i = 0;
490 struct buf *mbuf = &bufs[nbufs];
491 cur++;
492 jumpws();
493 while (cur < len && buf[cur] != ')') {
494 readarg(mbuf->args[i++]);
495 jumpws();
496 if (buf[cur] != ',')
497 break;
498 cur++;
499 jumpws();
501 while (i < m->nargs)
502 mbuf->args[i++][0] = '\0';
503 cur++;
504 buf_macro(m);
508 static int buf_expanding(char *macro)
510 int i;
511 for (i = nbufs - 1; i >= 0; i--) {
512 if (bufs[i].type == BUF_ARG)
513 return 0;
514 if (bufs[i].type == BUF_MACRO &&
515 !strcmp(macro, bufs[i].macro->name))
516 return 1;
518 return 0;
521 static int expandable(char *word)
523 if (buf_arg_find(word) >= 0)
524 return 1;
525 return !buf_expanding(word) && macro_find(word) != -1;
528 void cpp_define(char *name, char *def)
530 char tmp_buf[MACROLEN];
531 char *s = tmp_buf;
532 s = putstr(s, name);
533 *s++ = '\t';
534 s = putstr(s, def);
535 buf_new(BUF_TEMP, tmp_buf, s - tmp_buf);
536 macro_define();
537 buf_pop();
540 static int seen_macro;
542 static int hunk_off;
543 static int hunk_len;
545 int cpp_read(char *s)
547 int old;
548 if (seen_macro) {
549 seen_macro = 0;
550 macro_expand();
552 if (cur == len) {
553 struct buf *cbuf = &bufs[nbufs - 1];
554 if (nbufs < 2)
555 return -1;
556 if (cbuf->type & BUF_FILE)
557 free(buf);
558 buf_pop();
560 old = cur;
561 if (buf[cur] == '#')
562 if (!cpp_cmd())
563 return 0;
564 while (cur < len) {
565 if (buf[cur] == '#')
566 break;
567 if (!jumpcomment())
568 continue;
569 if (!jumpstr())
570 continue;
571 if (isalpha(buf[cur]) || buf[cur] == '_') {
572 char word[NAMELEN];
573 read_word(word);
574 if (expandable(word)) {
575 cur -= strlen(word);
576 seen_macro = 1;
577 break;
579 if (buf_iseval() && !strcmp("defined", word)) {
580 int parens = 0;
581 jumpws();
582 if (buf[cur] == '(') {
583 parens = 1;
584 cur++;
586 read_word(word);
587 if (parens) {
588 jumpws();
589 cur++;
592 continue;
594 cur++;
596 memcpy(s, buf + old, cur - old);
597 s[cur - old] = '\0';
598 if (!buf_iseval()) {
599 hunk_off += hunk_len;
600 hunk_len = cur - old;
602 return cur - old;
605 /* preprocessor constant expression evaluation */
607 static char etok[NAMELEN];
608 static int enext;
610 static char *tok2[] = {
611 "<<", ">>", "&&", "||", "==", "!=", "<=", ">="
614 static int eval_tok(void)
616 char *s = etok;
617 int i;
618 while (ecur < elen) {
619 while (ecur < elen && isspace(ebuf[ecur]))
620 ecur++;
621 if (ebuf[ecur] == '/' && ebuf[ecur + 1] == '*') {
622 while (ecur < elen && (ebuf[ecur - 2] != '*' ||
623 ebuf[ecur - 1] != '/'))
624 ecur++;
625 continue;
627 break;
629 if (ecur >= elen)
630 return TOK_EOF;
631 if (isalpha(ebuf[ecur]) || ebuf[ecur] == '_') {
632 while (isalnum(ebuf[ecur]) || ebuf[ecur] == '_')
633 *s++ = ebuf[ecur++];
634 *s = '\0';
635 return TOK_NAME;
637 if (isdigit(ebuf[ecur])) {
638 while (isdigit(ebuf[ecur]))
639 *s++ = ebuf[ecur++];
640 while (tolower(ebuf[ecur]) == 'u' || tolower(ebuf[ecur]) == 'l')
641 ecur++;
642 return TOK_NUM;
644 for (i = 0; i < ARRAY_SIZE(tok2); i++)
645 if (TOK2(tok2[i]) == TOK2(ebuf + ecur)) {
646 int ret = TOK2(tok2[i]);
647 ecur += 2;
648 return ret;
650 return ebuf[ecur++];
653 static int eval_see(void)
655 if (enext == -1)
656 enext = eval_tok();
657 return enext;
660 static int eval_get(void)
662 if (enext != -1) {
663 int ret = enext;
664 enext = -1;
665 return ret;
667 return eval_tok();
670 static long eval_num(void)
672 return atol(etok);
675 static int eval_jmp(int tok)
677 if (eval_see() == tok) {
678 eval_get();
679 return 0;
681 return 1;
684 static void eval_expect(int tok)
686 eval_jmp(tok);
689 static char *eval_id(void)
691 return etok;
694 static long evalcexpr(void);
696 static long evalatom(void)
698 if (!eval_jmp(TOK_NUM))
699 return eval_num();
700 if (!eval_jmp(TOK_NAME)) {
701 int parens = !eval_jmp('(');
702 long ret;
703 eval_expect(TOK_NAME);
704 ret = macro_find(eval_id()) >= 0;
705 if (parens)
706 eval_expect(')');
707 return ret;
709 if (!eval_jmp('(')) {
710 long ret = evalcexpr();
711 eval_expect(')');
712 return ret;
714 return -1;
717 static long evalpre(void)
719 if (!eval_jmp('!'))
720 return !evalpre();
721 if (!eval_jmp('-'))
722 return -evalpre();
723 if (!eval_jmp('~'))
724 return ~evalpre();
725 return evalatom();
728 static long evalmul(void)
730 long ret = evalpre();
731 while (1) {
732 if (!eval_jmp('*')) {
733 ret *= evalpre();
734 continue;
736 if (!eval_jmp('/')) {
737 ret /= evalpre();
738 continue;
740 if (!eval_jmp('%')) {
741 ret %= evalpre();
742 continue;
744 break;
746 return ret;
749 static long evaladd(void)
751 long ret = evalmul();
752 while (1) {
753 if (!eval_jmp('+')) {
754 ret += evalmul();
755 continue;
757 if (!eval_jmp('-')) {
758 ret -= evalmul();
759 continue;
761 break;
763 return ret;
766 static long evalshift(void)
768 long ret = evaladd();
769 while (1) {
770 if (!eval_jmp(TOK2("<<"))) {
771 ret <<= evaladd();
772 continue;
774 if (!eval_jmp(TOK2(">>"))) {
775 ret >>= evaladd();
776 continue;
778 break;
780 return ret;
783 static long evalcmp(void)
785 long ret = evalshift();
786 while (1) {
787 if (!eval_jmp('<')) {
788 ret = ret < evalshift();
789 continue;
791 if (!eval_jmp('>')) {
792 ret = ret > evalshift();
793 continue;
795 if (!eval_jmp(TOK2("<="))) {
796 ret = ret <= evalshift();
797 continue;
799 if (!eval_jmp(TOK2(">="))) {
800 ret = ret >= evalshift();
801 continue;
803 break;
805 return ret;
808 static long evaleq(void)
810 long ret = evalcmp();
811 while (1) {
812 if (!eval_jmp(TOK2("=="))) {
813 ret = ret == evalcmp();
814 continue;
816 if (!eval_jmp(TOK2("!="))) {
817 ret = ret != evalcmp();
818 continue;
820 break;
822 return ret;
825 static long evalbitand(void)
827 long ret = evaleq();
828 while (!eval_jmp('&'))
829 ret &= evaleq();
830 return ret;
833 static long evalxor(void)
835 long ret = evalbitand();
836 while (!eval_jmp('^'))
837 ret ^= evalbitand();
838 return ret;
841 static long evalbitor(void)
843 long ret = evalxor();
844 while (!eval_jmp('|'))
845 ret |= evalxor();
846 return ret;
849 static long evaland(void)
851 long ret = evalbitor();
852 while (!eval_jmp(TOK2("&&")))
853 ret = ret && evalbitor();
854 return ret;
857 static long evalor(void)
859 long ret = evaland();
860 while (!eval_jmp(TOK2("||")))
861 ret = ret || evaland();
862 return ret;
865 static long evalcexpr(void)
867 long ret = evalor();
868 if (eval_jmp('?'))
869 return ret;
870 if (ret)
871 return evalor();
872 while (eval_get() != ':')
874 return evalor();
877 static long evalexpr(void)
879 enext = -1;
880 return evalcexpr();
883 static int buf_loc(char *s, int off)
885 char *e = s + off;
886 int n = 1;
887 while ((s = strchr(s, '\n')) && s < e) {
888 n++;
889 s++;
891 return n;
894 char *cpp_loc(long addr)
896 static char loc[256];
897 int line = -1;
898 int i;
899 for (i = nbufs - 1; i > 0; i--)
900 if (bufs[i].type == BUF_FILE)
901 break;
902 if (addr >= hunk_off && i == nbufs - 1)
903 line = buf_loc(buf, (cur - hunk_len) + (addr - hunk_off));
904 else
905 line = buf_loc(bufs[i].buf, bufs[i].cur);
906 sprintf(loc, "%s:%d", bufs[i].path, line);
907 return loc;