16 #define MAXDEFS (1 << 12)
17 #define MACROLEN (1 << 10)
18 #define MAXARGS (1 << 5)
19 #define NBUCKET (MAXDEFS << 1)
24 char args
[MAXARGS
][NAMELEN
];
29 /* macro hash table */
30 static struct tab mtab
;
32 #define MAXBUFS (1 << 5)
48 char args
[MAXARGS
][MACROLEN
]; /* arguments passed to a macro */
50 int arg_buf
; /* the bufs index of the owning macro */
54 static void buf_new(int type
, char *dat
, int dlen
)
57 bufs
[nbufs
- 1].buf
= buf
;
58 bufs
[nbufs
- 1].cur
= cur
;
59 bufs
[nbufs
- 1].len
= len
;
62 die("nomem: MAXBUFS reached!\n");
67 bufs
[nbufs
- 1].type
= type
;
70 static void buf_file(char *path
, char *dat
, int dlen
)
72 buf_new(BUF_FILE
, dat
, dlen
);
73 strcpy(bufs
[nbufs
- 1].path
, path
? path
: "");
76 static void buf_macro(struct macro
*m
)
78 buf_new(BUF_MACRO
, m
->def
, strlen(m
->def
));
79 bufs
[nbufs
- 1].macro
= m
;
82 static void buf_arg(char *arg
, int mbuf
)
84 buf_new(BUF_ARG
, arg
, strlen(arg
));
85 bufs
[nbufs
- 1].arg_buf
= mbuf
;
88 static void buf_pop(void)
92 cur
= bufs
[nbufs
- 1].cur
;
93 len
= bufs
[nbufs
- 1].len
;
94 buf
= bufs
[nbufs
- 1].buf
;
98 static int buf_iseval(void)
101 for (i
= nbufs
- 1; i
>= 0; i
--)
102 if (bufs
[i
].type
== BUF_EVAL
)
107 static size_t file_size(int fd
)
115 static int include_file(char *path
)
117 int fd
= open(path
, O_RDONLY
);
123 size
= file_size(fd
) + 1;
125 while ((n
= read(fd
, dat
+ nr
, size
- nr
)) > 0)
129 buf_file(path
, dat
, nr
);
133 int cpp_init(char *path
)
135 cpp_define("__STDC__", "");
136 cpp_define("__x86_64__", "");
137 cpp_define("__linux__", "");
138 return include_file(path
);
141 static void jumpws(void)
143 while (cur
< len
&& isspace(buf
[cur
]))
147 static void read_word(char *dst
)
150 while (cur
< len
&& (isalnum(buf
[cur
]) || buf
[cur
] == '_'))
155 static void jumpcomment(void)
157 while (++cur
< len
) {
158 if (buf
[cur
] == '*' && buf
[cur
+ 1] == '/') {
165 static void read_tilleol(char *dst
)
167 while (cur
< len
&& isspace(buf
[cur
]) && buf
[cur
] != '\n')
169 while (cur
< len
&& buf
[cur
] != '\n') {
170 if (buf
[cur
] == '\\')
172 else if (buf
[cur
] == '/' && buf
[cur
+ 1] == '*')
180 static char *putstr(char *d
, char *s
)
188 #define MAXLOCS (1 << 10)
190 static char *locs
[MAXLOCS
] = {"/usr/include"};
191 static int nlocs
= 1;
193 void cpp_addpath(char *s
)
198 static int include_find(char *name
, int std
)
201 for (i
= std
? nlocs
- 1 : nlocs
; i
>= 0; i
--) {
206 s
= putstr(s
, locs
[i
]);
210 if (!include_file(path
))
216 static void jumpstr(void)
218 if (buf
[cur
] == '\'') {
219 while (cur
< len
&& buf
[++cur
] != '\'')
220 if (buf
[cur
] == '\\')
225 if (buf
[cur
] == '"') {
226 while (cur
< len
&& buf
[++cur
] != '"')
227 if (buf
[cur
] == '\\')
234 static void readarg(char *s
)
238 while (cur
< len
&& (depth
|| buf
[cur
] != ',' && buf
[cur
] != ')')) {
257 if (buf
[cur
] == '/' && buf
[cur
+ 1] == '*')
264 memcpy(s
, buf
+ beg
, cur
- beg
);
269 static int macro_find(char *name
)
271 char *n
= tab_get(&mtab
, name
);
274 return container(n
, struct macro
, name
) - macros
;
277 static void macro_undef(char *name
)
279 int i
= macro_find(name
);
281 tab_del(&mtab
, macros
[i
].name
);
284 static int macro_new(char *name
)
286 int i
= macro_find(name
);
289 if (nmacros
>= MAXDEFS
)
290 die("nomem: MAXDEFS reached!\n");
292 strcpy(macros
[i
].name
, name
);
293 tab_add(&mtab
, macros
[i
].name
);
297 static void macro_define(void)
302 d
= ¯os
[macro_new(name
)];
305 if (buf
[cur
] == '(') {
308 while (cur
< len
&& buf
[cur
] != ')') {
309 readarg(d
->args
[d
->nargs
++]);
311 if (buf
[cur
++] != ',')
317 read_tilleol(d
->def
);
320 int cpp_read(char *buf
);
322 static char ebuf
[BUFSIZE
];
326 static long evalexpr(void);
328 static int cpp_eval(void)
332 char evalbuf
[BUFSIZE
];
333 read_tilleol(evalbuf
);
334 buf_new(BUF_EVAL
, evalbuf
, strlen(evalbuf
));
338 while (bufid
< nbufs
|| (bufid
== nbufs
&& cur
< len
))
339 elen
+= cpp_read(ebuf
+ elen
);
345 static void jumpifs(int jumpelse
)
349 if (buf
[cur
] == '#') {
353 if (!strcmp("else", cmd
))
354 if (!depth
&& !jumpelse
)
356 if (!strcmp("elif", cmd
))
357 if (!depth
&& !jumpelse
&& cpp_eval())
359 if (!strcmp("endif", cmd
)) {
365 if (!strcmp("ifdef", cmd
) || !strcmp("ifndef", cmd
) ||
370 if (buf
[cur
] == '/' && buf
[cur
+ 1] == '*') {
374 if (buf
[cur
] == '\'' || buf
[cur
] == '"') {
382 static void cpp_cmd(void)
387 if (!strcmp("define", cmd
)) {
391 if (!strcmp("undef", cmd
)) {
397 if (!strcmp("ifdef", cmd
) || !strcmp("ifndef", cmd
) ||
398 !strcmp("if", cmd
)) {
402 int not = cmd
[2] == 'n';
404 matched
= not ? macro_find(name
) < 0 :
405 macro_find(name
) >= 0;
407 matched
= cpp_eval();
413 if (!strcmp("else", cmd
) || !strcmp("elif", cmd
)) {
417 if (!strcmp("endif", cmd
))
419 if (!strcmp("include", cmd
)) {
424 e
= strchr(buf
+ cur
+ 1, buf
[cur
] == '"' ? '"' : '>');
425 memcpy(file
, s
, e
- s
);
428 if (include_find(file
, *e
== '>') == -1)
429 die("cannot include file\n");
434 static int macro_arg(struct macro
*m
, char *arg
)
437 for (i
= 0; i
< m
->nargs
; i
++)
438 if (!strcmp(arg
, m
->args
[i
]))
443 static int buf_arg_find(char *name
)
446 for (i
= nbufs
- 1; i
>= 0; i
--) {
447 struct buf
*mbuf
= &bufs
[i
];
448 struct macro
*m
= mbuf
->macro
;
449 if (mbuf
->type
== BUF_MACRO
&& macro_arg(m
, name
) >= 0)
451 if (mbuf
->type
== BUF_ARG
)
457 static void macro_expand(void)
463 if ((mbuf
= buf_arg_find(name
)) >= 0) {
464 int arg
= macro_arg(bufs
[mbuf
].macro
, name
);
465 char *dat
= bufs
[mbuf
].args
[arg
];
469 m
= ¯os
[macro_find(name
)];
475 if (buf
[cur
] == '(') {
477 struct buf
*mbuf
= &bufs
[nbufs
];
480 while (cur
< len
&& buf
[cur
] != ')') {
481 readarg(mbuf
->args
[i
++]);
489 mbuf
->args
[i
++][0] = '\0';
495 static int buf_expanding(char *macro
)
498 for (i
= nbufs
- 1; i
>= 0; i
--) {
499 if (bufs
[i
].type
== BUF_ARG
)
501 if (bufs
[i
].type
== BUF_MACRO
&&
502 !strcmp(macro
, bufs
[i
].macro
->name
))
508 static int expandable(char *word
)
510 if (buf_arg_find(word
) >= 0)
512 return !buf_expanding(word
) && macro_find(word
) != -1;
515 void cpp_define(char *name
, char *def
)
517 char tmp_buf
[MACROLEN
];
522 buf_new(BUF_TEMP
, tmp_buf
, s
- tmp_buf
);
527 static int seen_macro
;
532 int cpp_read(char *s
)
540 struct buf
*cbuf
= &bufs
[nbufs
- 1];
543 if (cbuf
->type
& BUF_FILE
)
548 if (buf
[cur
] == '#') {
555 if (buf
[cur
] == '/' && buf
[cur
+ 1] == '*') {
559 if (buf
[cur
] == '\'' || buf
[cur
] == '"') {
563 if (isalpha(buf
[cur
]) || buf
[cur
] == '_') {
566 if (expandable(word
)) {
571 if (buf_iseval() && !strcmp("defined", word
)) {
574 if (buf
[cur
] == '(') {
588 memcpy(s
, buf
+ old
, cur
- old
);
591 hunk_off
+= hunk_len
;
592 hunk_len
= cur
- old
;
597 /* preprocessor constant expression evaluation */
599 static char etok
[NAMELEN
];
602 static char *tok2
[] = {
603 "<<", ">>", "&&", "||", "==", "!=", "<=", ">="
606 static int eval_tok(void)
610 while (ecur
< elen
) {
611 while (ecur
< elen
&& isspace(ebuf
[ecur
]))
613 if (ebuf
[ecur
] == '/' && ebuf
[ecur
+ 1] == '*') {
614 while (ecur
< elen
&& (ebuf
[ecur
- 2] != '*' ||
615 ebuf
[ecur
- 1] != '/'))
623 if (isalpha(ebuf
[ecur
]) || ebuf
[ecur
] == '_') {
624 while (isalnum(ebuf
[ecur
]) || ebuf
[ecur
] == '_')
629 if (isdigit(ebuf
[ecur
])) {
630 while (isdigit(ebuf
[ecur
]))
632 while (tolower(ebuf
[ecur
]) == 'u' || tolower(ebuf
[ecur
]) == 'l')
636 for (i
= 0; i
< ARRAY_SIZE(tok2
); i
++)
637 if (TOK2(tok2
[i
]) == TOK2(ebuf
+ ecur
)) {
638 int ret
= TOK2(tok2
[i
]);
645 static int eval_see(void)
652 static int eval_get(void)
662 static long eval_num(void)
667 static int eval_jmp(int tok
)
669 if (eval_see() == tok
) {
676 static void eval_expect(int tok
)
681 static char *eval_id(void)
686 static long evalcexpr(void);
688 static long evalatom(void)
690 if (!eval_jmp(TOK_NUM
))
692 if (!eval_jmp(TOK_NAME
)) {
693 int parens
= !eval_jmp('(');
695 eval_expect(TOK_NAME
);
696 ret
= macro_find(eval_id()) >= 0;
701 if (!eval_jmp('(')) {
702 long ret
= evalcexpr();
709 static long evalpre(void)
720 static long evalmul(void)
722 long ret
= evalpre();
724 if (!eval_jmp('*')) {
728 if (!eval_jmp('/')) {
732 if (!eval_jmp('%')) {
741 static long evaladd(void)
743 long ret
= evalmul();
745 if (!eval_jmp('+')) {
749 if (!eval_jmp('-')) {
758 static long evalshift(void)
760 long ret
= evaladd();
762 if (!eval_jmp(TOK2("<<"))) {
766 if (!eval_jmp(TOK2(">>"))) {
775 static long evalcmp(void)
777 long ret
= evalshift();
779 if (!eval_jmp('<')) {
780 ret
= ret
< evalshift();
783 if (!eval_jmp('>')) {
784 ret
= ret
> evalshift();
787 if (!eval_jmp(TOK2("<="))) {
788 ret
= ret
<= evalshift();
791 if (!eval_jmp(TOK2(">="))) {
792 ret
= ret
>= evalshift();
800 static long evaleq(void)
802 long ret
= evalcmp();
804 if (!eval_jmp(TOK2("=="))) {
805 ret
= ret
== evalcmp();
808 if (!eval_jmp(TOK2("!="))) {
809 ret
= ret
!= evalcmp();
817 static long evalbitand(void)
820 while (!eval_jmp('&'))
825 static long evalxor(void)
827 long ret
= evalbitand();
828 while (!eval_jmp('^'))
833 static long evalbitor(void)
835 long ret
= evalxor();
836 while (!eval_jmp('|'))
841 static long evaland(void)
843 long ret
= evalbitor();
844 while (!eval_jmp(TOK2("&&")))
845 ret
= ret
&& evalbitor();
849 static long evalor(void)
851 long ret
= evaland();
852 while (!eval_jmp(TOK2("||")))
853 ret
= ret
|| evaland();
857 static long evalcexpr(void)
864 while (eval_get() != ':')
869 static long evalexpr(void)
875 static int buf_loc(char *s
, int off
)
879 while ((s
= strchr(s
, '\n')) && s
< e
) {
886 int cpp_loc(char *s
, long addr
)
890 for (i
= nbufs
- 1; i
> 0; i
--)
891 if (bufs
[i
].type
== BUF_FILE
)
893 if (addr
>= hunk_off
&& i
== nbufs
- 1)
894 line
= buf_loc(buf
, (cur
- hunk_len
) + (addr
- hunk_off
));
896 line
= buf_loc(bufs
[i
].buf
, bufs
[i
].cur
);
897 sprintf(s
, "%s:%d: ", bufs
[i
].path
, line
);