12 #define MAXDEFS (1 << 12)
13 #define MACROLEN (1 << 10)
14 #define MAXARGS (1 << 5)
19 char args
[MAXARGS
][NAMELEN
];
25 #define MAXBUFS (1 << 5)
40 static void buf_new(int type
, char *name
)
43 bufs
[nbufs
- 1].cur
= cur
;
44 bufs
[nbufs
- 1].len
= len
;
47 die("nomem: MAXBUFS reached!\n");
51 buf
= bufs
[nbufs
- 1].buf
;
52 bufs
[nbufs
- 1].type
= type
;
53 strcpy(bufs
[nbufs
-1].name
, name
? name
: "");
56 static void buf_pop(void)
60 cur
= bufs
[nbufs
- 1].cur
;
61 len
= bufs
[nbufs
- 1].len
;
62 buf
= bufs
[nbufs
- 1].buf
;
66 static int buf_iseval(void)
69 for (i
= 0; i
< nbufs
; i
++)
70 if (bufs
[i
].type
== BUF_EVAL
)
75 static int buf_expanding(char *macro
)
78 for (i
= 0; i
< nbufs
; i
++)
79 if (bufs
[i
].type
== BUF_MACRO
&& !strcmp(macro
, bufs
[i
].name
))
84 static void include(int fd
)
87 buf_new(BUF_FILE
, NULL
);
88 while ((n
= read(fd
, buf
+ len
, BUFSIZE
- len
)) > 0)
94 cpp_define("__STDC__", "");
95 cpp_define("__x86_64__", "");
96 cpp_define("__linux__", "");
100 static void jumpws(void)
102 while (cur
< len
&& isspace(buf
[cur
]))
106 static void read_word(char *dst
)
109 while (cur
< len
&& (isalnum(buf
[cur
]) || buf
[cur
] == '_'))
114 static void jumpcomment(void)
116 while (++cur
< len
) {
117 if (buf
[cur
] == '*' && buf
[cur
+ 1] == '/') {
124 static void read_tilleol(char *dst
)
126 while (cur
< len
&& isspace(buf
[cur
]) && buf
[cur
] != '\n')
128 while (cur
< len
&& buf
[cur
] != '\n') {
129 if (buf
[cur
] == '\\')
131 else if (buf
[cur
] == '/' && buf
[cur
+ 1] == '*')
139 static char *putstr(char *d
, char *s
)
147 #define MAXLOCS (1 << 10)
149 static char *locs
[MAXLOCS
] = {"/usr/include"};
150 static int nlocs
= 1;
152 void cpp_addpath(char *s
)
157 static int include_find(char *name
, int std
)
161 for (i
= std
? nlocs
- 1 : nlocs
; i
>= 0; i
--) {
166 s
= putstr(s
, locs
[i
]);
170 fd
= open(path
, O_RDONLY
);
177 static void jumpstr(void)
179 if (buf
[cur
] == '\'') {
180 while (cur
< len
&& buf
[++cur
] != '\'')
181 if (buf
[cur
] == '\\')
186 if (buf
[cur
] == '"') {
187 while (cur
< len
&& buf
[++cur
] != '"')
188 if (buf
[cur
] == '\\')
195 static void readarg(char *s
)
199 while (cur
< len
&& (depth
|| buf
[cur
] != ',' && buf
[cur
] != ')')) {
218 if (buf
[cur
] == '/' && buf
[cur
+ 1] == '*')
224 memcpy(s
, buf
+ beg
, cur
- beg
);
228 static int macro_find(char *name
)
231 for (i
= 0; i
< nmacros
; i
++)
232 if (!strcmp(name
, macros
[i
].name
))
237 static int macro_new(char *name
)
240 for (i
= 0; i
< nmacros
; i
++) {
241 if (!strcmp(name
, macros
[i
].name
))
243 if (!*macros
[i
].name
) {
244 strcpy(macros
[i
].name
, name
);
248 if (nmacros
>= MAXDEFS
)
249 die("nomem: MAXDEFS reached!\n");
250 strcpy(macros
[nmacros
++].name
, name
);
254 static void macro_define(void)
259 d
= ¯os
[macro_new(name
)];
261 if (buf
[cur
] == '(') {
264 while (cur
< len
&& buf
[cur
] != ')') {
265 readarg(d
->args
[d
->nargs
++]);
267 if (buf
[cur
++] != ',')
273 read_tilleol(d
->def
);
276 int cpp_read(char *buf
);
278 static char ebuf
[BUFSIZE
];
282 static long evalexpr(void);
284 static int cpp_eval(void)
288 char evalbuf
[BUFSIZE
];
289 read_tilleol(evalbuf
);
290 buf_new(BUF_EVAL
, NULL
);
291 strcpy(buf
, evalbuf
);
292 len
= strlen(evalbuf
);
296 while (bufid
< nbufs
|| cur
< len
)
297 elen
+= cpp_read(ebuf
+ elen
);
303 static void jumpifs(int jumpelse
)
307 if (buf
[cur
] == '#') {
311 if (!strcmp("else", cmd
))
312 if (!depth
&& !jumpelse
)
314 if (!strcmp("elif", cmd
))
315 if (!depth
&& !jumpelse
&& cpp_eval())
317 if (!strcmp("endif", cmd
)) {
323 if (!strcmp("ifdef", cmd
) || !strcmp("ifndef", cmd
) ||
328 if (buf
[cur
] == '/' && buf
[cur
+ 1] == '*') {
332 if (buf
[cur
] == '\'' || buf
[cur
] == '"') {
340 static void cpp_cmd(void)
345 if (!strcmp("define", cmd
)) {
349 if (!strcmp("undef", cmd
)) {
353 idx
= macro_find(name
);
355 strcpy(macros
[idx
].name
, "");
358 if (!strcmp("ifdef", cmd
) || !strcmp("ifndef", cmd
) ||
359 !strcmp("if", cmd
)) {
363 int not = cmd
[2] == 'n';
365 matched
= not ? macro_find(name
) < 0 :
366 macro_find(name
) >= 0;
368 matched
= cpp_eval();
374 if (!strcmp("else", cmd
) || !strcmp("elif", cmd
)) {
378 if (!strcmp("endif", cmd
))
380 if (!strcmp("include", cmd
)) {
386 e
= strchr(buf
+ cur
+ 1, buf
[cur
] == '"' ? '"' : '>');
387 memcpy(file
, s
, e
- s
);
390 fd
= include_find(file
, *e
== '>');
399 static int macro_arg(struct macro
*m
, char *arg
)
402 for (i
= 0; i
< m
->nargs
; i
++)
403 if (!strcmp(arg
, m
->args
[i
]))
408 static void macro_expand(void)
411 char args
[MAXARGS
][MACROLEN
];
418 m
= ¯os
[macro_find(name
)];
420 buf_new(BUF_MACRO
, name
);
422 len
= strlen(m
->def
);
426 if (buf
[cur
] == '(') {
429 while (cur
< len
&& buf
[cur
] != ')') {
430 readarg(args
[nargs
++]);
440 buf_new(BUF_MACRO
, name
);
443 len
= strlen(m
->def
);
446 if (buf
[cur
] == '/' && buf
[cur
+ 1] == '*') {
450 if (strchr("'\"", buf
[cur
])) {
454 if (isalpha(buf
[cur
]) || buf
[cur
] == '_') {
458 if ((arg
= macro_arg(m
, word
)) != -1) {
459 int len
= cur
- beg
- strlen(word
);
460 char *argstr
= arg
> nargs
? "" : args
[arg
];
461 int arglen
= strlen(argstr
);
462 memcpy(dst
+ dstlen
, buf
+ beg
, len
);
464 memcpy(dst
+ dstlen
, argstr
, arglen
);
472 memcpy(dst
+ dstlen
, buf
+ beg
, len
- beg
);
480 void cpp_define(char *name
, char *def
)
483 buf_new(BUF_TEMP
, NULL
);
493 static int definedword
;
495 int cpp_read(char *s
)
508 if (buf
[cur
] == '#') {
515 if (buf
[cur
] == '/' && buf
[cur
+ 1] == '*') {
519 if (buf
[cur
] == '\'' || buf
[cur
] == '"') {
523 if (isalpha(buf
[cur
]) || buf
[cur
] == '_') {
526 if (!buf_expanding(word
) && macro_find(word
) != -1) {
531 if (buf_iseval() && !strcmp("defined", word
)) {
534 if (buf
[cur
] == '(') {
548 memcpy(s
, buf
+ old
, cur
- old
);
553 /* preprocessor constant expression evaluation */
555 static char etok
[NAMELEN
];
558 static char *tok2
[] = {
559 "<<", ">>", "&&", "||", "==", "!=", "<=", ">="
562 static int eval_tok(void)
566 while (ecur
< elen
) {
567 while (ecur
< elen
&& isspace(ebuf
[ecur
]))
569 if (ebuf
[ecur
] == '/' && ebuf
[ecur
+ 1] == '*') {
570 while (ecur
< elen
&& (ebuf
[ecur
- 2] != '*' ||
571 ebuf
[ecur
- 1] != '/'))
579 if (isalpha(ebuf
[ecur
]) || ebuf
[ecur
] == '_') {
580 while (isalnum(ebuf
[ecur
]) || ebuf
[ecur
] == '_')
585 if (isdigit(ebuf
[ecur
])) {
586 while (isdigit(ebuf
[ecur
]))
588 while (tolower(ebuf
[ecur
]) == 'u' || tolower(ebuf
[ecur
]) == 'l')
592 for (i
= 0; i
< ARRAY_SIZE(tok2
); i
++)
593 if (TOK2(tok2
[i
]) == TOK2(ebuf
+ ecur
)) {
594 int ret
= TOK2(tok2
[i
]);
601 static int eval_see(void)
608 static int eval_get(void)
618 static long eval_num(void)
623 static int eval_jmp(int tok
)
625 if (eval_see() == tok
) {
632 static void eval_expect(int tok
)
637 static char *eval_id(void)
642 static long evalcexpr(void);
644 static long evalatom(void)
646 if (!eval_jmp(TOK_NUM
))
648 if (!eval_jmp(TOK_NAME
)) {
649 int parens
= !eval_jmp('(');
651 eval_expect(TOK_NAME
);
652 ret
= macro_find(eval_id()) >= 0;
657 if (!eval_jmp('(')) {
658 long ret
= evalcexpr();
665 static long evalpre(void)
676 static long evalmul(void)
678 long ret
= evalpre();
680 if (!eval_jmp('*')) {
684 if (!eval_jmp('/')) {
688 if (!eval_jmp('%')) {
697 static long evaladd(void)
699 long ret
= evalmul();
701 if (!eval_jmp('+')) {
705 if (!eval_jmp('-')) {
714 static long evalshift(void)
716 long ret
= evaladd();
718 if (!eval_jmp(TOK2("<<"))) {
722 if (!eval_jmp(TOK2(">>"))) {
731 static long evalcmp(void)
733 long ret
= evalshift();
735 if (!eval_jmp('<')) {
736 ret
= ret
< evalshift();
739 if (!eval_jmp('>')) {
740 ret
= ret
> evalshift();
743 if (!eval_jmp(TOK2("<="))) {
744 ret
= ret
<= evalshift();
747 if (!eval_jmp(TOK2(">="))) {
748 ret
= ret
>= evalshift();
756 static long evaleq(void)
758 long ret
= evalcmp();
760 if (!eval_jmp(TOK2("=="))) {
761 ret
= ret
== evalcmp();
764 if (!eval_jmp(TOK2("!="))) {
765 ret
= ret
!= evalcmp();
773 static long evalbitand(void)
776 while (!eval_jmp('&'))
781 static long evalxor(void)
783 long ret
= evalbitand();
784 while (!eval_jmp('^'))
789 static long evalbitor(void)
791 long ret
= evalxor();
792 while (!eval_jmp('|'))
797 static long evaland(void)
799 long ret
= evalbitor();
800 while (!eval_jmp(TOK2("&&")))
801 ret
= ret
&& evalbitor();
805 static long evalor(void)
807 long ret
= evaland();
808 while (!eval_jmp(TOK2("||")))
809 ret
= ret
|| evaland();
813 static long evalcexpr(void)
820 while (eval_get() != ':')
825 static long evalexpr(void)