int: load constant call arguments as late as possible
[neatcc.git] / cpp.c
blob73df6ccf73032bcb7441e5490e401d1c85903e0c
1 /* neatcc preprocessor */
2 #include <ctype.h>
3 #include <fcntl.h>
4 #include <stdarg.h>
5 #include <stddef.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <unistd.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include "ncc.h"
14 static char *buf;
15 static long len;
16 static long cur;
18 static struct macro {
19 char name[NAMELEN]; /* macro name */
20 char def[MDEFLEN]; /* macro definition */
21 char args[NARGS][NAMELEN];
22 int nargs; /* number of arguments */
23 int isfunc; /* macro is a function */
24 int undef; /* macro is removed */
25 } macros[NDEFS];
26 static int mcount = 1; /* number of macros */
27 static int mhead[256]; /* macro hash table heads */
28 static int mnext[NDEFS]; /* macro hash table next entries */
30 #define BUF_FILE 0
31 #define BUF_MACRO 1
32 #define BUF_ARG 2
33 #define BUF_EVAL 3
34 #define BUF_TEMP 4
36 /* preprocessing input buffers for files, macros and macro arguments */
37 static struct buf {
38 char *buf;
39 long len;
40 long cur;
41 int type;
42 /* for BUF_FILE */
43 char path[NAMELEN];
44 /* for BUF_MACRO */
45 struct macro *macro;
46 char args[NARGS][MARGLEN]; /* arguments passed to a macro */
47 /* for BUF_ARG */
48 int arg_buf; /* the bufs index of the owning macro */
49 } bufs[NBUFS];
50 static int bufs_n;
51 static int bufs_limit = 0; /* cpp_read() limit; useful in cpp_eval() */
53 void die(char *fmt, ...)
55 va_list ap;
56 char msg[512];
57 va_start(ap, fmt);
58 vsprintf(msg, fmt, ap);
59 va_end(ap);
60 write(2, msg, strlen(msg));
61 exit(1);
64 static void buf_new(int type, char *dat, long dlen)
66 if (bufs_n) {
67 bufs[bufs_n - 1].buf = buf;
68 bufs[bufs_n - 1].cur = cur;
69 bufs[bufs_n - 1].len = len;
71 if (bufs_n >= NBUFS)
72 die("nomem: NBUFS reached!\n");
73 bufs_n++;
74 cur = 0;
75 buf = dat;
76 len = dlen;
77 bufs[bufs_n - 1].type = type;
80 static void buf_file(char *path, char *dat, int dlen)
82 buf_new(BUF_FILE, dat, dlen);
83 strcpy(bufs[bufs_n - 1].path, path ? path : "");
86 static void buf_macro(struct macro *m)
88 buf_new(BUF_MACRO, m->def, strlen(m->def));
89 bufs[bufs_n - 1].macro = m;
92 static void buf_arg(char *arg, int mbuf)
94 buf_new(BUF_ARG, arg, strlen(arg));
95 bufs[bufs_n - 1].arg_buf = mbuf;
98 static void buf_pop(void)
100 bufs_n--;
101 if (bufs[bufs_n].type == BUF_FILE)
102 free(buf);
103 if (bufs_n) {
104 cur = bufs[bufs_n - 1].cur;
105 len = bufs[bufs_n - 1].len;
106 buf = bufs[bufs_n - 1].buf;
110 static int buf_iseval(void)
112 int i;
113 for (i = bufs_n - 1; i >= 0; i--)
114 if (bufs[i].type == BUF_EVAL)
115 return 1;
116 return 0;
119 static size_t file_size(int fd)
121 struct stat st;
122 if (!fstat(fd, &st))
123 return st.st_size;
124 return 0;
127 static int include_file(char *path)
129 int fd = open(path, O_RDONLY);
130 int n = 0, nr = 0;
131 char *dat;
132 int size;
133 if (fd == -1)
134 return -1;
135 size = file_size(fd) + 1;
136 dat = malloc(size);
137 while ((n = read(fd, dat + nr, size - nr)) > 0)
138 nr += n;
139 close(fd);
140 dat[nr] = '\0';
141 buf_file(path, dat, nr);
142 return 0;
145 int cpp_init(char *path)
147 return include_file(path);
150 static int jumpws(void)
152 int old = cur;
153 while (cur < len && isspace(buf[cur]))
154 cur++;
155 return cur == old;
158 static void read_word(char *dst)
160 jumpws();
161 while (cur < len && (isalnum(buf[cur]) || buf[cur] == '_'))
162 *dst++ = buf[cur++];
163 *dst = '\0';
166 static int jumpcomment(void)
168 if (buf[cur] == '/' && buf[cur + 1] == '*') {
169 while (++cur < len) {
170 if (buf[cur] == '*' && buf[cur + 1] == '/') {
171 cur += 2;
172 return 0;
176 if (buf[cur] == '/' && buf[cur + 1] == '/') {
177 while (++cur < len && buf[cur] != '\n')
178 if (buf[cur] == '\\')
179 cur++;
180 return 0;
182 return 1;
185 static int jumpstr(void)
187 if (buf[cur] == '\'') {
188 while (++cur < len && buf[cur] != '\'')
189 if (buf[cur] == '\\')
190 cur++;
191 cur++;
192 return 0;
194 if (buf[cur] == '"') {
195 while (++cur < len && buf[cur] != '"')
196 if (buf[cur] == '\\')
197 cur++;
198 cur++;
199 return 0;
201 return 1;
204 static void read_tilleol(char *dst)
206 while (cur < len && isspace(buf[cur]) && buf[cur] != '\n')
207 cur++;
208 while (cur < len && buf[cur] != '\n') {
209 int last = cur;
210 if (buf[cur] == '\\' && buf[cur + 1] == '\n') {
211 cur += 2;
212 continue;
214 if (!jumpstr()) {
215 memcpy(dst, buf + last, cur - last);
216 dst += cur - last;
217 continue;
219 if (!jumpcomment())
220 continue;
221 *dst++ = buf[cur++];
223 *dst = '\0';
226 static char *locs[NLOCS] = {};
227 static int nlocs = 0;
229 /* header directory */
230 void cpp_path(char *s)
232 locs[nlocs++] = s;
235 static int include_find(char *name, int std)
237 int i;
238 for (i = std ? nlocs - 1 : nlocs; i >= 0; i--) {
239 char path[1 << 10];
240 if (locs[i])
241 sprintf(path, "%s/%s", locs[i], name);
242 else
243 strcpy(path, name);
244 if (!include_file(path))
245 return 0;
247 return -1;
250 static void readarg(char *s)
252 int depth = 0;
253 int beg = cur;
254 while (cur < len && (depth || (buf[cur] != ',' && buf[cur] != ')'))) {
255 if (!jumpstr() || !jumpcomment())
256 continue;
257 switch (buf[cur++]) {
258 case '(':
259 case '[':
260 case '{':
261 depth++;
262 break;
263 case ')':
264 case ']':
265 case '}':
266 depth--;
267 break;
270 if (s) {
271 memcpy(s, buf + beg, cur - beg);
272 s[cur - beg] = '\0';
276 /* find a macro; if undef is nonzero, search #undef-ed macros too */
277 static int macro_find(char *name, int undef)
279 int i = mhead[(unsigned char) name[0]];
280 while (i > 0) {
281 if (!strcmp(name, macros[i].name))
282 if (!macros[i].undef || undef)
283 return i;
284 i = mnext[i];
286 return -1;
289 static void macro_undef(char *name)
291 int i = macro_find(name, 0);
292 if (i >= 0)
293 macros[i].undef = 1;
296 static int macro_new(char *name)
298 int i = macro_find(name, 1);
299 if (i >= 0)
300 return i;
301 if (mcount >= NDEFS)
302 die("nomem: NDEFS reached!\n");
303 i = mcount++;
304 strcpy(macros[i].name, name);
305 mnext[i] = mhead[(unsigned char) name[0]];
306 mhead[(unsigned char) name[0]] = i;
307 return i;
310 static void macro_define(void)
312 char name[NAMELEN];
313 struct macro *d;
314 read_word(name);
315 d = &macros[macro_new(name)];
316 d->isfunc = 0;
317 d->nargs = 0;
318 d->undef = 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 static char ebuf[MARGLEN];
337 static int elen;
338 static int ecur;
340 static long evalexpr(void);
342 static long cpp_eval(void)
344 char evalbuf[MARGLEN];
345 int old_limit;
346 long ret, clen;
347 char *cbuf;
348 read_tilleol(evalbuf);
349 buf_new(BUF_EVAL, evalbuf, strlen(evalbuf));
350 elen = 0;
351 ecur = 0;
352 old_limit = bufs_limit;
353 bufs_limit = bufs_n;
354 while (!cpp_read(&cbuf, &clen)) {
355 memcpy(ebuf + elen, cbuf, clen);
356 elen += clen;
358 bufs_limit = old_limit;
359 ret = evalexpr();
360 buf_pop();
361 return ret;
364 static void jumpifs(int jumpelse)
366 int depth = 0;
367 while (cur < len) {
368 if (buf[cur] == '#') {
369 char cmd[NAMELEN];
370 cur++;
371 read_word(cmd);
372 if (!strcmp("else", cmd))
373 if (!depth && !jumpelse)
374 break;
375 if (!strcmp("elif", cmd))
376 if (!depth && !jumpelse && cpp_eval())
377 break;
378 if (!strcmp("endif", cmd)) {
379 if (!depth)
380 break;
381 else
382 depth--;
384 if (!strcmp("ifdef", cmd) || !strcmp("ifndef", cmd) ||
385 !strcmp("if", cmd))
386 depth++;
387 continue;
389 if (!jumpcomment())
390 continue;
391 if (!jumpstr())
392 continue;
393 cur++;
397 static int cpp_cmd(void)
399 char cmd[NAMELEN];
400 cur++;
401 read_word(cmd);
402 if (!strcmp("define", cmd)) {
403 macro_define();
404 return 0;
406 if (!strcmp("undef", cmd)) {
407 char name[NAMELEN];
408 read_word(name);
409 macro_undef(name);
410 return 0;
412 if (!strcmp("ifdef", cmd) || !strcmp("ifndef", cmd) ||
413 !strcmp("if", cmd)) {
414 char name[NAMELEN];
415 int matched = 0;
416 if (cmd[2]) {
417 int not = cmd[2] == 'n';
418 read_word(name);
419 matched = not ? macro_find(name, 0) < 0 :
420 macro_find(name, 0) >= 0;
421 } else {
422 matched = cpp_eval();
424 if (!matched)
425 jumpifs(0);
426 return 0;
428 if (!strcmp("else", cmd) || !strcmp("elif", cmd)) {
429 jumpifs(1);
430 return 0;
432 if (!strcmp("endif", cmd))
433 return 0;
434 if (!strcmp("include", cmd)) {
435 char file[NAMELEN];
436 char *s, *e;
437 jumpws();
438 s = buf + cur + 1;
439 e = strchr(buf + cur + 1, buf[cur] == '"' ? '"' : '>');
440 memcpy(file, s, e - s);
441 file[e - s] = '\0';
442 cur += e - s + 2;
443 if (include_find(file, *e == '>') == -1)
444 err("cannot include <%s>\n", file);
445 return 0;
447 err("unknown directive <%s>\n", cmd);
448 return 1;
451 static int macro_arg(struct macro *m, char *arg)
453 int i;
454 for (i = 0; i < m->nargs; i++)
455 if (!strcmp(arg, m->args[i]))
456 return i;
457 return -1;
460 static int buf_arg_find(char *name)
462 int i;
463 for (i = bufs_n - 1; i >= 0; i--) {
464 struct buf *mbuf = &bufs[i];
465 struct macro *m = mbuf->macro;
466 if (mbuf->type == BUF_MACRO && macro_arg(m, name) >= 0)
467 return i;
468 if (mbuf->type == BUF_ARG)
469 i = mbuf->arg_buf;
471 return -1;
474 static void macro_expand(char *name)
476 struct macro *m;
477 int mbuf;
478 if ((mbuf = buf_arg_find(name)) >= 0) {
479 int arg = macro_arg(bufs[mbuf].macro, name);
480 char *dat = bufs[mbuf].args[arg];
481 buf_arg(dat, mbuf);
482 return;
484 m = &macros[macro_find(name, 0)];
485 if (!m->isfunc) {
486 buf_macro(m);
487 return;
489 jumpws();
490 if (buf[cur] == '(') {
491 int i = 0;
492 struct buf *mbuf = &bufs[bufs_n];
493 cur++;
494 jumpws();
495 while (cur < len && buf[cur] != ')') {
496 readarg(mbuf->args[i++]);
497 jumpws();
498 if (buf[cur] != ',')
499 break;
500 cur++;
501 jumpws();
503 while (i < m->nargs)
504 mbuf->args[i++][0] = '\0';
505 cur++;
506 buf_macro(m);
510 static int buf_expanding(char *macro)
512 int i;
513 for (i = bufs_n - 1; i >= 0; i--) {
514 if (bufs[i].type == BUF_ARG)
515 return 0;
516 if (bufs[i].type == BUF_MACRO &&
517 !strcmp(macro, bufs[i].macro->name))
518 return 1;
520 return 0;
523 /* return 1 for plain macros and arguments and 2 for function macros */
524 static int expandable(char *word)
526 int i;
527 if (buf_arg_find(word) >= 0)
528 return 1;
529 if (buf_expanding(word))
530 return 0;
531 i = macro_find(word, 0);
532 return i >= 0 ? macros[i].isfunc + 1 : 0;
535 void cpp_define(char *name, char *def)
537 char tmp_buf[MDEFLEN];
538 sprintf(tmp_buf, "%s\t%s", name, def);
539 buf_new(BUF_TEMP, tmp_buf, strlen(tmp_buf));
540 macro_define();
541 buf_pop();
544 static int seen_macro; /* seen a macro; 2 if a function macro */
545 static char seen_name[NAMELEN]; /* the name of the last macro */
547 static int hunk_off;
548 static int hunk_len;
550 int cpp_read(char **obuf, long *olen)
552 int old, end;
553 int jump_name = 0;
554 *olen = 0;
555 *obuf = "";
556 if (seen_macro == 1) {
557 macro_expand(seen_name);
558 seen_macro = 0;
560 if (cur == len) {
561 if (bufs_n < bufs_limit + 1)
562 return 1;
563 buf_pop();
565 old = cur;
566 if (cur < len && buf[cur] == '#')
567 if (!cpp_cmd())
568 return 0;
569 while (cur < len) {
570 if (!jumpws())
571 continue;
572 if (buf[cur] == '#')
573 break;
574 if (!jumpcomment())
575 continue;
576 if (seen_macro == 2) {
577 if (buf[cur] == '(')
578 macro_expand(seen_name);
579 seen_macro = 0;
580 old = cur;
581 continue;
583 if (!jumpstr())
584 continue;
585 if (isalnum(buf[cur]) || buf[cur] == '_') {
586 char word[NAMELEN];
587 read_word(word);
588 seen_macro = expandable(word);
589 if (seen_macro) {
590 strcpy(seen_name, word);
591 jump_name = 1;
592 break;
594 if (buf_iseval() && !strcmp("defined", word)) {
595 int parens = 0;
596 jumpws();
597 if (buf[cur] == '(') {
598 parens = 1;
599 cur++;
601 read_word(word);
602 if (parens) {
603 jumpws();
604 cur++;
607 continue;
609 cur++;
611 /* macros are expanded later; ignoring their names */
612 end = jump_name ? cur - strlen(seen_name) : cur;
613 if (!buf_iseval()) {
614 hunk_off += hunk_len;
615 hunk_len = end - old;
617 *obuf = buf + old;
618 *olen = end - old;
619 return 0;
622 /* preprocessor constant expression evaluation */
624 #define TOK2(a) ((a)[0] << 16 | (a)[1] << 8)
625 #define TOK_NAME 256
626 #define TOK_NUM 257
627 #define TOK_EOF -1
629 static char etok[NAMELEN];
630 static int enext;
632 static char *tok2[] = {
633 "<<", ">>", "&&", "||", "==", "!=", "<=", ">="
636 static int eval_tok(void)
638 char *s = etok;
639 int i;
640 while (ecur < elen) {
641 while (ecur < elen && isspace(ebuf[ecur]))
642 ecur++;
643 if (ebuf[ecur] == '/' && ebuf[ecur + 1] == '*') {
644 while (ecur < elen && (ebuf[ecur - 2] != '*' ||
645 ebuf[ecur - 1] != '/'))
646 ecur++;
647 continue;
649 break;
651 if (ecur >= elen)
652 return TOK_EOF;
653 if (isalpha(ebuf[ecur]) || ebuf[ecur] == '_') {
654 while (isalnum(ebuf[ecur]) || ebuf[ecur] == '_')
655 *s++ = ebuf[ecur++];
656 *s = '\0';
657 return TOK_NAME;
659 if (isdigit(ebuf[ecur])) {
660 while (isdigit(ebuf[ecur]))
661 *s++ = ebuf[ecur++];
662 while (tolower(ebuf[ecur]) == 'u' || tolower(ebuf[ecur]) == 'l')
663 ecur++;
664 *s = '\0';
665 return TOK_NUM;
667 for (i = 0; i < LEN(tok2); i++)
668 if (TOK2(tok2[i]) == TOK2(ebuf + ecur)) {
669 int ret = TOK2(tok2[i]);
670 ecur += 2;
671 return ret;
673 return ebuf[ecur++];
676 static int eval_see(void)
678 if (enext == -1)
679 enext = eval_tok();
680 return enext;
683 static int eval_get(void)
685 if (enext != -1) {
686 int ret = enext;
687 enext = -1;
688 return ret;
690 return eval_tok();
693 static long eval_num(void)
695 return atol(etok);
698 static int eval_jmp(int tok)
700 if (eval_see() == tok) {
701 eval_get();
702 return 0;
704 return 1;
707 static void eval_expect(int tok)
709 eval_jmp(tok);
712 static char *eval_id(void)
714 return etok;
717 static long evalcexpr(void);
719 static long evalatom(void)
721 if (!eval_jmp(TOK_NUM))
722 return eval_num();
723 if (!eval_jmp(TOK_NAME)) {
724 int parens = !eval_jmp('(');
725 long ret;
726 eval_expect(TOK_NAME);
727 ret = macro_find(eval_id(), 0) >= 0;
728 if (parens)
729 eval_expect(')');
730 return ret;
732 if (!eval_jmp('(')) {
733 long ret = evalcexpr();
734 eval_expect(')');
735 return ret;
737 return -1;
740 static long evalpre(void)
742 if (!eval_jmp('!'))
743 return !evalpre();
744 if (!eval_jmp('-'))
745 return -evalpre();
746 if (!eval_jmp('~'))
747 return ~evalpre();
748 return evalatom();
751 static long evalmul(void)
753 long ret = evalpre();
754 while (1) {
755 if (!eval_jmp('*')) {
756 ret *= evalpre();
757 continue;
759 if (!eval_jmp('/')) {
760 ret /= evalpre();
761 continue;
763 if (!eval_jmp('%')) {
764 ret %= evalpre();
765 continue;
767 break;
769 return ret;
772 static long evaladd(void)
774 long ret = evalmul();
775 while (1) {
776 if (!eval_jmp('+')) {
777 ret += evalmul();
778 continue;
780 if (!eval_jmp('-')) {
781 ret -= evalmul();
782 continue;
784 break;
786 return ret;
789 static long evalshift(void)
791 long ret = evaladd();
792 while (1) {
793 if (!eval_jmp(TOK2("<<"))) {
794 ret <<= evaladd();
795 continue;
797 if (!eval_jmp(TOK2(">>"))) {
798 ret >>= evaladd();
799 continue;
801 break;
803 return ret;
806 static long evalcmp(void)
808 long ret = evalshift();
809 while (1) {
810 if (!eval_jmp('<')) {
811 ret = ret < evalshift();
812 continue;
814 if (!eval_jmp('>')) {
815 ret = ret > evalshift();
816 continue;
818 if (!eval_jmp(TOK2("<="))) {
819 ret = ret <= evalshift();
820 continue;
822 if (!eval_jmp(TOK2(">="))) {
823 ret = ret >= evalshift();
824 continue;
826 break;
828 return ret;
831 static long evaleq(void)
833 long ret = evalcmp();
834 while (1) {
835 if (!eval_jmp(TOK2("=="))) {
836 ret = ret == evalcmp();
837 continue;
839 if (!eval_jmp(TOK2("!="))) {
840 ret = ret != evalcmp();
841 continue;
843 break;
845 return ret;
848 static long evalbitand(void)
850 long ret = evaleq();
851 while (!eval_jmp('&'))
852 ret &= evaleq();
853 return ret;
856 static long evalxor(void)
858 long ret = evalbitand();
859 while (!eval_jmp('^'))
860 ret ^= evalbitand();
861 return ret;
864 static long evalbitor(void)
866 long ret = evalxor();
867 while (!eval_jmp('|'))
868 ret |= evalxor();
869 return ret;
872 static long evaland(void)
874 long ret = evalbitor();
875 while (!eval_jmp(TOK2("&&")))
876 ret = ret && evalbitor();
877 return ret;
880 static long evalor(void)
882 long ret = evaland();
883 while (!eval_jmp(TOK2("||")))
884 ret = ret || evaland();
885 return ret;
888 static long evalcexpr(void)
890 long ret = evalor();
891 if (eval_jmp('?'))
892 return ret;
893 if (ret)
894 return evalor();
895 while (eval_get() != ':')
897 return evalor();
900 static long evalexpr(void)
902 enext = -1;
903 return evalcexpr();
906 static int buf_loc(char *s, int off)
908 char *e = s + off;
909 int n = 1;
910 while ((s = strchr(s, '\n')) && s < e) {
911 n++;
912 s++;
914 return n;
917 char *cpp_loc(long addr)
919 static char loc[256];
920 int line = -1;
921 int i;
922 for (i = bufs_n - 1; i > 0; i--)
923 if (bufs[i].type == BUF_FILE)
924 break;
925 if (addr >= hunk_off && i == bufs_n - 1)
926 line = buf_loc(buf, (cur - hunk_len) + (addr - hunk_off));
927 else
928 line = buf_loc(bufs[i].buf, bufs[i].cur);
929 sprintf(loc, "%s:%d", bufs[i].path, line);
930 return loc;