ncc: don't change operand order for const ops
[neatcc/cc.git] / cpp.c
blob8def1c89d9faf55553e2a40a11c37df14ea33b24
1 #include <ctype.h>
2 #include <fcntl.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include "tok.h"
7 #include "tab.h"
9 static char *buf;
10 static int len;
11 static int cur;
13 #define MAXDEFS (1 << 12)
14 #define MACROLEN (1 << 10)
15 #define MAXARGS (1 << 5)
16 #define NBUCKET (MAXDEFS << 1)
18 static struct macro {
19 char name[NAMELEN];
20 char def[MACROLEN];
21 char args[MAXARGS][NAMELEN];
22 int nargs;
23 int isfunc;
24 } macros[MAXDEFS];
25 static int nmacros;
26 /* macro hash table */
27 static struct tab mtab;
29 #define MAXBUFS (1 << 5)
30 #define BUF_FILE 0
31 #define BUF_MACRO 1
32 #define BUF_EVAL 2
33 #define BUF_TEMP 3
35 static struct buf {
36 char buf[BUFSIZE];
37 char name[NAMELEN];
38 int len;
39 int cur;
40 int type;
41 } bufs[MAXBUFS];
42 static int nbufs;
44 static void buf_new(int type, char *name)
46 if (nbufs) {
47 bufs[nbufs - 1].cur = cur;
48 bufs[nbufs - 1].len = len;
50 if (nbufs >= MAXBUFS)
51 die("nomem: MAXBUFS reached!\n");
52 nbufs++;
53 cur = 0;
54 len = 0;
55 buf = bufs[nbufs - 1].buf;
56 bufs[nbufs - 1].type = type;
57 strcpy(bufs[nbufs -1].name, name ? name : "");
60 static void buf_pop(void)
62 nbufs--;
63 if (nbufs) {
64 cur = bufs[nbufs - 1].cur;
65 len = bufs[nbufs - 1].len;
66 buf = bufs[nbufs - 1].buf;
70 static int buf_iseval(void)
72 int i;
73 for (i = 0; i < nbufs; i++)
74 if (bufs[i].type == BUF_EVAL)
75 return 1;
76 return 0;
79 static int buf_expanding(char *macro)
81 int i;
82 for (i = 0; i < nbufs; i++)
83 if (bufs[i].type == BUF_MACRO && !strcmp(macro, bufs[i].name))
84 return 1;
85 return 0;
88 static int include_file(char *path)
90 int fd = open(path, O_RDONLY);
91 int n = 0;
92 if (fd == -1)
93 return -1;
94 buf_new(BUF_FILE, path);
95 while ((n = read(fd, buf + len, BUFSIZE - len)) > 0)
96 len += n;
97 close(fd);
98 return 0;
101 int cpp_init(char *path)
103 cpp_define("__STDC__", "");
104 cpp_define("__x86_64__", "");
105 cpp_define("__linux__", "");
106 return include_file(path);
109 static void jumpws(void)
111 while (cur < len && isspace(buf[cur]))
112 cur++;
115 static void read_word(char *dst)
117 jumpws();
118 while (cur < len && (isalnum(buf[cur]) || buf[cur] == '_'))
119 *dst++ = buf[cur++];
120 *dst = '\0';
123 static void jumpcomment(void)
125 while (++cur < len) {
126 if (buf[cur] == '*' && buf[cur + 1] == '/') {
127 cur += 2;
128 break;
133 static void read_tilleol(char *dst)
135 while (cur < len && isspace(buf[cur]) && buf[cur] != '\n')
136 cur++;
137 while (cur < len && buf[cur] != '\n') {
138 if (buf[cur] == '\\')
139 cur += 2;
140 else if (buf[cur] == '/' && buf[cur + 1] == '*')
141 jumpcomment();
142 else
143 *dst++ = buf[cur++];
145 *dst = '\0';
148 static char *putstr(char *d, char *s)
150 while (*s)
151 *d++ = *s++;
152 *d = '\0';
153 return d;
156 #define MAXLOCS (1 << 10)
158 static char *locs[MAXLOCS] = {"/usr/include"};
159 static int nlocs = 1;
161 void cpp_addpath(char *s)
163 locs[nlocs++] = s;
166 static int include_find(char *name, int std)
168 int i;
169 for (i = std ? nlocs - 1 : nlocs; i >= 0; i--) {
170 char path[1 << 10];
171 char *s;
172 s = path;
173 if (locs[i]) {
174 s = putstr(s, locs[i]);
175 *s++ = '/';
177 s = putstr(s, name);
178 if (!include_file(path))
179 return 0;
181 return -1;
184 static void jumpstr(void)
186 if (buf[cur] == '\'') {
187 while (cur < len && buf[++cur] != '\'')
188 if (buf[cur] == '\\')
189 cur++;
190 cur++;
191 return;
193 if (buf[cur] == '"') {
194 while (cur < len && buf[++cur] != '"')
195 if (buf[cur] == '\\')
196 cur++;
197 cur++;
198 return;
202 static void readarg(char *s)
204 int depth = 0;
205 int beg = cur;
206 while (cur < len && (depth || buf[cur] != ',' && buf[cur] != ')')) {
207 switch (buf[cur]) {
208 case '(':
209 case '[':
210 case '{':
211 cur++;
212 depth++;
213 break;
214 case ')':
215 case ']':
216 case '}':
217 cur++;
218 depth--;
219 break;
220 case '\'':
221 case '"':
222 jumpstr();
223 break;
224 default:
225 if (buf[cur] == '/' && buf[cur + 1] == '*')
226 jumpcomment();
227 else
228 cur++;
231 memcpy(s, buf + beg, cur - beg);
232 s[cur - beg] = '\0';
235 static int macro_find(char *name)
237 char *n = tab_get(&mtab, name);
238 if (!n)
239 return -1;
240 return container(n, struct macro, name) - macros;
243 static void macro_undef(char *name)
245 int i = macro_find(name);
246 if (i >= 0)
247 tab_del(&mtab, macros[i].name);
250 static int macro_new(char *name)
252 int i = macro_find(name);
253 if (i >= 0)
254 return i;
255 if (nmacros >= MAXDEFS)
256 die("nomem: MAXDEFS reached!\n");
257 i = nmacros++;
258 strcpy(macros[i].name, name);
259 tab_add(&mtab, macros[i].name);
260 return i;
263 static void macro_define(void)
265 char name[NAMELEN];
266 struct macro *d;
267 read_word(name);
268 d = &macros[macro_new(name)];
269 d->isfunc = 0;
270 d->nargs = 0;
271 if (buf[cur] == '(') {
272 cur++;
273 jumpws();
274 while (cur < len && buf[cur] != ')') {
275 readarg(d->args[d->nargs++]);
276 jumpws();
277 if (buf[cur++] != ',')
278 break;
279 jumpws();
281 d->isfunc = 1;
283 read_tilleol(d->def);
286 int cpp_read(char *buf);
288 static char ebuf[BUFSIZE];
289 static int elen;
290 static int ecur;
292 static long evalexpr(void);
294 static int cpp_eval(void)
296 int bufid;
297 int ret;
298 char evalbuf[BUFSIZE];
299 read_tilleol(evalbuf);
300 buf_new(BUF_EVAL, NULL);
301 strcpy(buf, evalbuf);
302 len = strlen(evalbuf);
303 bufid = nbufs;
304 elen = 0;
305 ecur = 0;
306 while (bufid < nbufs || cur < len)
307 elen += cpp_read(ebuf + elen);
308 ret = evalexpr();
309 buf_pop();
310 return ret;
313 static void jumpifs(int jumpelse)
315 int depth = 0;
316 while (cur < len) {
317 if (buf[cur] == '#') {
318 char cmd[NAMELEN];
319 cur++;
320 read_word(cmd);
321 if (!strcmp("else", cmd))
322 if (!depth && !jumpelse)
323 break;
324 if (!strcmp("elif", cmd))
325 if (!depth && !jumpelse && cpp_eval())
326 break;
327 if (!strcmp("endif", cmd)) {
328 if (!depth)
329 break;
330 else
331 depth--;
333 if (!strcmp("ifdef", cmd) || !strcmp("ifndef", cmd) ||
334 !strcmp("if", cmd))
335 depth++;
336 continue;
338 if (buf[cur] == '/' && buf[cur + 1] == '*') {
339 jumpcomment();
340 continue;
342 if (buf[cur] == '\'' || buf[cur] == '"') {
343 jumpstr();
344 continue;
346 cur++;
350 static void cpp_cmd(void)
352 char cmd[NAMELEN];
353 cur++;
354 read_word(cmd);
355 if (!strcmp("define", cmd)) {
356 macro_define();
357 return;
359 if (!strcmp("undef", cmd)) {
360 char name[NAMELEN];
361 read_word(name);
362 macro_undef(name);
363 return;
365 if (!strcmp("ifdef", cmd) || !strcmp("ifndef", cmd) ||
366 !strcmp("if", cmd)) {
367 char name[NAMELEN];
368 int matched = 0;
369 if (cmd[2]) {
370 int not = cmd[2] == 'n';
371 read_word(name);
372 matched = not ? macro_find(name) < 0 :
373 macro_find(name) >= 0;
374 } else {
375 matched = cpp_eval();
377 if (!matched)
378 jumpifs(0);
379 return;
381 if (!strcmp("else", cmd) || !strcmp("elif", cmd)) {
382 jumpifs(1);
383 return;
385 if (!strcmp("endif", cmd))
386 return;
387 if (!strcmp("include", cmd)) {
388 char file[NAMELEN];
389 char *s, *e;
390 jumpws();
391 s = buf + cur + 1;
392 e = strchr(buf + cur + 1, buf[cur] == '"' ? '"' : '>');
393 memcpy(file, s, e - s);
394 file[e - s] = '\0';
395 cur += e - s + 2;
396 if (include_find(file, *e == '>') == -1)
397 die("cannot include file\n");
398 return;
402 static int macro_arg(struct macro *m, char *arg)
404 int i;
405 for (i = 0; i < m->nargs; i++)
406 if (!strcmp(arg, m->args[i]))
407 return i;
408 return -1;
411 static void macro_expand(void)
413 char name[NAMELEN];
414 char args[MAXARGS][MACROLEN];
415 int nargs = 0;
416 struct macro *m;
417 char *dst;
418 int dstlen = 0;
419 int beg;
420 read_word(name);
421 m = &macros[macro_find(name)];
422 if (!m->isfunc) {
423 buf_new(BUF_MACRO, name);
424 strcpy(buf, m->def);
425 len = strlen(m->def);
426 return;
428 jumpws();
429 if (buf[cur] == '(') {
430 cur++;
431 jumpws();
432 while (cur < len && buf[cur] != ')') {
433 readarg(args[nargs++]);
434 jumpws();
435 if (buf[cur] != ',')
436 break;
437 cur++;
438 jumpws();
440 cur++;
441 m->isfunc = 1;
443 buf_new(BUF_MACRO, name);
444 dst = buf;
445 buf = m->def;
446 len = strlen(m->def);
447 beg = cur;
448 while (cur < len) {
449 if (buf[cur] == '/' && buf[cur + 1] == '*') {
450 jumpcomment();
451 continue;
453 if (strchr("'\"", buf[cur])) {
454 jumpstr();
455 continue;
457 if (isalpha(buf[cur]) || buf[cur] == '_') {
458 int arg;
459 char word[NAMELEN];
460 read_word(word);
461 if ((arg = macro_arg(m, word)) != -1) {
462 int len = cur - beg - strlen(word);
463 char *argstr = arg > nargs ? "" : args[arg];
464 int arglen = strlen(argstr);
465 memcpy(dst + dstlen, buf + beg, len);
466 dstlen += len;
467 memcpy(dst + dstlen, argstr, arglen);
468 dstlen += arglen;
469 beg = cur;
471 continue;
473 cur++;
475 memcpy(dst + dstlen, buf + beg, len - beg);
476 dstlen += len - beg;
477 buf = dst;
478 len = dstlen;
479 cur = 0;
480 buf[len] = '\0';
483 void cpp_define(char *name, char *def)
485 char *s;
486 buf_new(BUF_TEMP, NULL);
487 s = buf;
488 s = putstr(s, name);
489 *s++ = '\t';
490 s = putstr(s, def);
491 len = s - buf;
492 macro_define();
493 buf_pop();
496 static int definedword;
498 static int hunk_off;
499 static int hunk_len;
501 int cpp_read(char *s)
503 int old;
504 if (definedword) {
505 definedword = 0;
506 macro_expand();
508 if (cur == len) {
509 if (nbufs < 2)
510 return -1;
511 buf_pop();
513 old = cur;
514 if (buf[cur] == '#') {
515 cpp_cmd();
516 return 0;
518 while (cur < len) {
519 if (buf[cur] == '#')
520 break;
521 if (buf[cur] == '/' && buf[cur + 1] == '*') {
522 jumpcomment();
523 continue;
525 if (buf[cur] == '\'' || buf[cur] == '"') {
526 jumpstr();
527 continue;
529 if (isalpha(buf[cur]) || buf[cur] == '_') {
530 char word[NAMELEN];
531 read_word(word);
532 if (!buf_expanding(word) && macro_find(word) != -1) {
533 cur -= strlen(word);
534 definedword = 1;
535 break;
537 if (buf_iseval() && !strcmp("defined", word)) {
538 int parens = 0;
539 jumpws();
540 if (buf[cur] == '(') {
541 parens = 1;
542 cur++;
544 read_word(word);
545 if (parens) {
546 jumpws();
547 cur++;
550 continue;
552 cur++;
554 memcpy(s, buf + old, cur - old);
555 s[cur - old] = '\0';
556 if (!buf_iseval()) {
557 hunk_off += hunk_len;
558 hunk_len = cur - old;
560 return cur - old;
563 /* preprocessor constant expression evaluation */
565 static char etok[NAMELEN];
566 static int enext;
568 static char *tok2[] = {
569 "<<", ">>", "&&", "||", "==", "!=", "<=", ">="
572 static int eval_tok(void)
574 char *s = etok;
575 int i;
576 while (ecur < elen) {
577 while (ecur < elen && isspace(ebuf[ecur]))
578 ecur++;
579 if (ebuf[ecur] == '/' && ebuf[ecur + 1] == '*') {
580 while (ecur < elen && (ebuf[ecur - 2] != '*' ||
581 ebuf[ecur - 1] != '/'))
582 ecur++;
583 continue;
585 break;
587 if (ecur >= elen)
588 return TOK_EOF;
589 if (isalpha(ebuf[ecur]) || ebuf[ecur] == '_') {
590 while (isalnum(ebuf[ecur]) || ebuf[ecur] == '_')
591 *s++ = ebuf[ecur++];
592 *s = '\0';
593 return TOK_NAME;
595 if (isdigit(ebuf[ecur])) {
596 while (isdigit(ebuf[ecur]))
597 *s++ = ebuf[ecur++];
598 while (tolower(ebuf[ecur]) == 'u' || tolower(ebuf[ecur]) == 'l')
599 ecur++;
600 return TOK_NUM;
602 for (i = 0; i < ARRAY_SIZE(tok2); i++)
603 if (TOK2(tok2[i]) == TOK2(ebuf + ecur)) {
604 int ret = TOK2(tok2[i]);
605 ecur += 2;
606 return ret;
608 return ebuf[ecur++];
611 static int eval_see(void)
613 if (enext == -1)
614 enext = eval_tok();
615 return enext;
618 static int eval_get(void)
620 if (enext != -1) {
621 int ret = enext;
622 enext = -1;
623 return ret;
625 return eval_tok();
628 static long eval_num(void)
630 return atol(etok);
633 static int eval_jmp(int tok)
635 if (eval_see() == tok) {
636 eval_get();
637 return 0;
639 return 1;
642 static void eval_expect(int tok)
644 eval_jmp(tok);
647 static char *eval_id(void)
649 return etok;
652 static long evalcexpr(void);
654 static long evalatom(void)
656 if (!eval_jmp(TOK_NUM))
657 return eval_num();
658 if (!eval_jmp(TOK_NAME)) {
659 int parens = !eval_jmp('(');
660 long ret;
661 eval_expect(TOK_NAME);
662 ret = macro_find(eval_id()) >= 0;
663 if (parens)
664 eval_expect(')');
665 return ret;
667 if (!eval_jmp('(')) {
668 long ret = evalcexpr();
669 eval_expect(')');
670 return ret;
672 return -1;
675 static long evalpre(void)
677 if (!eval_jmp('!'))
678 return !evalpre();
679 if (!eval_jmp('-'))
680 return -evalpre();
681 if (!eval_jmp('~'))
682 return ~evalpre();
683 return evalatom();
686 static long evalmul(void)
688 long ret = evalpre();
689 while (1) {
690 if (!eval_jmp('*')) {
691 ret *= evalpre();
692 continue;
694 if (!eval_jmp('/')) {
695 ret /= evalpre();
696 continue;
698 if (!eval_jmp('%')) {
699 ret %= evalpre();
700 continue;
702 break;
704 return ret;
707 static long evaladd(void)
709 long ret = evalmul();
710 while (1) {
711 if (!eval_jmp('+')) {
712 ret += evalmul();
713 continue;
715 if (!eval_jmp('-')) {
716 ret -= evalmul();
717 continue;
719 break;
721 return ret;
724 static long evalshift(void)
726 long ret = evaladd();
727 while (1) {
728 if (!eval_jmp(TOK2("<<"))) {
729 ret <<= evaladd();
730 continue;
732 if (!eval_jmp(TOK2(">>"))) {
733 ret >>= evaladd();
734 continue;
736 break;
738 return ret;
741 static long evalcmp(void)
743 long ret = evalshift();
744 while (1) {
745 if (!eval_jmp('<')) {
746 ret = ret < evalshift();
747 continue;
749 if (!eval_jmp('>')) {
750 ret = ret > evalshift();
751 continue;
753 if (!eval_jmp(TOK2("<="))) {
754 ret = ret <= evalshift();
755 continue;
757 if (!eval_jmp(TOK2(">="))) {
758 ret = ret >= evalshift();
759 continue;
761 break;
763 return ret;
766 static long evaleq(void)
768 long ret = evalcmp();
769 while (1) {
770 if (!eval_jmp(TOK2("=="))) {
771 ret = ret == evalcmp();
772 continue;
774 if (!eval_jmp(TOK2("!="))) {
775 ret = ret != evalcmp();
776 continue;
778 break;
780 return ret;
783 static long evalbitand(void)
785 long ret = evaleq();
786 while (!eval_jmp('&'))
787 ret &= evaleq();
788 return ret;
791 static long evalxor(void)
793 long ret = evalbitand();
794 while (!eval_jmp('^'))
795 ret ^= evalbitand();
796 return ret;
799 static long evalbitor(void)
801 long ret = evalxor();
802 while (!eval_jmp('|'))
803 ret |= evalxor();
804 return ret;
807 static long evaland(void)
809 long ret = evalbitor();
810 while (!eval_jmp(TOK2("&&")))
811 ret = ret && evalbitor();
812 return ret;
815 static long evalor(void)
817 long ret = evaland();
818 while (!eval_jmp(TOK2("||")))
819 ret = ret || evaland();
820 return ret;
823 static long evalcexpr(void)
825 long ret = evalor();
826 if (eval_jmp('?'))
827 return ret;
828 if (ret)
829 return evalor();
830 while (eval_get() != ':')
832 return evalor();
835 static long evalexpr(void)
837 enext = -1;
838 return evalcexpr();
841 static int numwidth(int n)
843 int i = 0;
844 do {
845 i++;
846 n /= 10;
847 } while (n);
848 return i;
851 static char *putnum(char *s, int n)
853 int w = numwidth(n);
854 int i;
855 for (i = 0; i < w; i++) {
856 s[w - i - 1] = !i || n ? '0' + n % 10 : ' ';
857 n /= 10;
859 return s + w;
862 static int buf_loc(char *s, int off)
864 char *e = s + off;
865 int n = 1;
866 while ((s = strchr(s, '\n')) && s < e) {
867 n++;
868 s++;
870 return n;
873 int cpp_loc(char *s, long addr)
875 int line = -1;
876 int i;
877 char *o = s;
878 for (i = nbufs - 1; i > 0; i--)
879 if (bufs[i].type == BUF_FILE)
880 break;
881 if (addr >= hunk_off && i == nbufs - 1)
882 line = buf_loc(buf, (cur - hunk_len) + (addr - hunk_off));
883 else
884 line = buf_loc(bufs[i].buf, bufs[i].cur);
885 s = putstr(s, bufs[i].name);
886 *s++ = ':';
887 s = putnum(s, line);
888 *s++ = ':';
889 *s++ = ' ';
890 return s - o;