18 #define MAXDEFS (1 << 12)
19 #define MACROLEN (1 << 10)
20 #define MAXARGS (1 << 5)
21 #define NBUCKET (MAXDEFS << 1)
26 char args
[MAXARGS
][NAMELEN
];
31 /* macro hash table */
32 static struct tab mtab
;
34 #define MAXBUFS (1 << 5)
50 char args
[MAXARGS
][MACROLEN
]; /* arguments passed to a macro */
52 int arg_buf
; /* the bufs index of the owning macro */
56 void die(char *fmt
, ...)
61 vsprintf(msg
, fmt
, ap
);
63 write(2, msg
, strlen(msg
));
67 static void buf_new(int type
, char *dat
, int dlen
)
70 bufs
[nbufs
- 1].buf
= buf
;
71 bufs
[nbufs
- 1].cur
= cur
;
72 bufs
[nbufs
- 1].len
= len
;
75 die("nomem: MAXBUFS reached!\n");
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)
105 cur
= bufs
[nbufs
- 1].cur
;
106 len
= bufs
[nbufs
- 1].len
;
107 buf
= bufs
[nbufs
- 1].buf
;
111 static int buf_iseval(void)
114 for (i
= nbufs
- 1; i
>= 0; i
--)
115 if (bufs
[i
].type
== BUF_EVAL
)
120 static size_t file_size(int fd
)
128 static int include_file(char *path
)
130 int fd
= open(path
, O_RDONLY
);
136 size
= file_size(fd
) + 1;
138 while ((n
= read(fd
, dat
+ nr
, size
- nr
)) > 0)
142 buf_file(path
, dat
, nr
);
146 int cpp_init(char *path
)
148 return include_file(path
);
151 static void jumpws(void)
153 while (cur
< len
&& isspace(buf
[cur
]))
157 static void read_word(char *dst
)
160 while (cur
< len
&& (isalnum(buf
[cur
]) || buf
[cur
] == '_'))
165 static int jumpcomment(void)
167 if (buf
[cur
] == '/' && buf
[cur
+ 1] == '*') {
168 while (++cur
< len
) {
169 if (buf
[cur
] == '*' && buf
[cur
+ 1] == '/') {
175 if (buf
[cur
] == '/' && buf
[cur
+ 1] == '/') {
177 if (buf
[cur
] == '\n')
184 static int jumpstr(void)
186 if (buf
[cur
] == '\'') {
187 while (cur
< len
&& buf
[++cur
] != '\'')
188 if (buf
[cur
] == '\\')
193 if (buf
[cur
] == '"') {
194 while (cur
< len
&& buf
[++cur
] != '"')
195 if (buf
[cur
] == '\\')
203 static void read_tilleol(char *dst
)
205 while (cur
< len
&& isspace(buf
[cur
]) && buf
[cur
] != '\n')
207 while (cur
< len
&& buf
[cur
] != '\n') {
209 if (buf
[cur
] == '\\' && buf
[cur
+ 1] == '\n') {
214 memcpy(dst
, buf
+ last
, cur
- last
);
225 static char *putstr(char *d
, char *s
)
233 #define MAXLOCS (1 << 10)
235 static char *locs
[MAXLOCS
] = {};
236 static int nlocs
= 0;
238 void cpp_addpath(char *s
)
243 static int include_find(char *name
, int std
)
246 for (i
= std
? nlocs
- 1 : nlocs
; i
>= 0; i
--) {
251 s
= putstr(s
, locs
[i
]);
255 if (!include_file(path
))
261 static void readarg(char *s
)
265 while (cur
< len
&& (depth
|| buf
[cur
] != ',' && buf
[cur
] != ')')) {
266 if (!jumpstr() || !jumpcomment())
268 switch (buf
[cur
++]) {
282 memcpy(s
, buf
+ beg
, cur
- beg
);
287 static int macro_find(char *name
)
289 char *n
= tab_get(&mtab
, name
);
292 return container(n
, struct macro
, name
) - macros
;
295 static void macro_undef(char *name
)
297 int i
= macro_find(name
);
299 tab_del(&mtab
, macros
[i
].name
);
302 static int macro_new(char *name
)
304 int i
= macro_find(name
);
307 if (nmacros
>= MAXDEFS
)
308 die("nomem: MAXDEFS reached!\n");
310 strcpy(macros
[i
].name
, name
);
311 tab_add(&mtab
, macros
[i
].name
);
315 static void macro_define(void)
320 d
= ¯os
[macro_new(name
)];
323 if (buf
[cur
] == '(') {
326 while (cur
< len
&& buf
[cur
] != ')') {
327 readarg(d
->args
[d
->nargs
++]);
337 read_tilleol(d
->def
);
340 int cpp_read(char *buf
);
342 static char ebuf
[BUFSIZE
];
346 static long evalexpr(void);
348 static int cpp_eval(void)
352 char evalbuf
[BUFSIZE
];
353 read_tilleol(evalbuf
);
354 buf_new(BUF_EVAL
, evalbuf
, strlen(evalbuf
));
358 while (bufid
< nbufs
|| (bufid
== nbufs
&& cur
< len
))
359 elen
+= cpp_read(ebuf
+ elen
);
365 static void jumpifs(int jumpelse
)
369 if (buf
[cur
] == '#') {
373 if (!strcmp("else", cmd
))
374 if (!depth
&& !jumpelse
)
376 if (!strcmp("elif", cmd
))
377 if (!depth
&& !jumpelse
&& cpp_eval())
379 if (!strcmp("endif", cmd
)) {
385 if (!strcmp("ifdef", cmd
) || !strcmp("ifndef", cmd
) ||
398 static int cpp_cmd(void)
403 if (!strcmp("define", cmd
)) {
407 if (!strcmp("undef", cmd
)) {
413 if (!strcmp("ifdef", cmd
) || !strcmp("ifndef", cmd
) ||
414 !strcmp("if", cmd
)) {
418 int not = cmd
[2] == 'n';
420 matched
= not ? macro_find(name
) < 0 :
421 macro_find(name
) >= 0;
423 matched
= cpp_eval();
429 if (!strcmp("else", cmd
) || !strcmp("elif", cmd
)) {
433 if (!strcmp("endif", cmd
))
435 if (!strcmp("include", cmd
)) {
440 e
= strchr(buf
+ cur
+ 1, buf
[cur
] == '"' ? '"' : '>');
441 memcpy(file
, s
, e
- s
);
444 if (include_find(file
, *e
== '>') == -1)
445 die("cannot include <%s>\n", file
);
451 static int macro_arg(struct macro
*m
, char *arg
)
454 for (i
= 0; i
< m
->nargs
; i
++)
455 if (!strcmp(arg
, m
->args
[i
]))
460 static int buf_arg_find(char *name
)
463 for (i
= nbufs
- 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)
468 if (mbuf
->type
== BUF_ARG
)
474 static void macro_expand(void)
480 if ((mbuf
= buf_arg_find(name
)) >= 0) {
481 int arg
= macro_arg(bufs
[mbuf
].macro
, name
);
482 char *dat
= bufs
[mbuf
].args
[arg
];
486 m
= ¯os
[macro_find(name
)];
492 if (buf
[cur
] == '(') {
494 struct buf
*mbuf
= &bufs
[nbufs
];
497 while (cur
< len
&& buf
[cur
] != ')') {
498 readarg(mbuf
->args
[i
++]);
506 mbuf
->args
[i
++][0] = '\0';
512 static int buf_expanding(char *macro
)
515 for (i
= nbufs
- 1; i
>= 0; i
--) {
516 if (bufs
[i
].type
== BUF_ARG
)
518 if (bufs
[i
].type
== BUF_MACRO
&&
519 !strcmp(macro
, bufs
[i
].macro
->name
))
525 static int expandable(char *word
)
527 if (buf_arg_find(word
) >= 0)
529 return !buf_expanding(word
) && macro_find(word
) != -1;
532 void cpp_define(char *name
, char *def
)
534 char tmp_buf
[MACROLEN
];
539 buf_new(BUF_TEMP
, tmp_buf
, s
- tmp_buf
);
544 static int seen_macro
;
549 int cpp_read(char *s
)
557 struct buf
*cbuf
= &bufs
[nbufs
- 1];
560 if (cbuf
->type
== BUF_FILE
)
575 if (isalpha(buf
[cur
]) || buf
[cur
] == '_') {
578 if (expandable(word
)) {
583 if (buf_iseval() && !strcmp("defined", word
)) {
586 if (buf
[cur
] == '(') {
600 memcpy(s
, buf
+ old
, cur
- old
);
603 hunk_off
+= hunk_len
;
604 hunk_len
= cur
- old
;
609 /* preprocessor constant expression evaluation */
611 static char etok
[NAMELEN
];
614 static char *tok2
[] = {
615 "<<", ">>", "&&", "||", "==", "!=", "<=", ">="
618 static int eval_tok(void)
622 while (ecur
< elen
) {
623 while (ecur
< elen
&& isspace(ebuf
[ecur
]))
625 if (ebuf
[ecur
] == '/' && ebuf
[ecur
+ 1] == '*') {
626 while (ecur
< elen
&& (ebuf
[ecur
- 2] != '*' ||
627 ebuf
[ecur
- 1] != '/'))
635 if (isalpha(ebuf
[ecur
]) || ebuf
[ecur
] == '_') {
636 while (isalnum(ebuf
[ecur
]) || ebuf
[ecur
] == '_')
641 if (isdigit(ebuf
[ecur
])) {
642 while (isdigit(ebuf
[ecur
]))
644 while (tolower(ebuf
[ecur
]) == 'u' || tolower(ebuf
[ecur
]) == 'l')
649 for (i
= 0; i
< ARRAY_SIZE(tok2
); i
++)
650 if (TOK2(tok2
[i
]) == TOK2(ebuf
+ ecur
)) {
651 int ret
= TOK2(tok2
[i
]);
658 static int eval_see(void)
665 static int eval_get(void)
675 static long eval_num(void)
680 static int eval_jmp(int tok
)
682 if (eval_see() == tok
) {
689 static void eval_expect(int tok
)
694 static char *eval_id(void)
699 static long evalcexpr(void);
701 static long evalatom(void)
703 if (!eval_jmp(TOK_NUM
))
705 if (!eval_jmp(TOK_NAME
)) {
706 int parens
= !eval_jmp('(');
708 eval_expect(TOK_NAME
);
709 ret
= macro_find(eval_id()) >= 0;
714 if (!eval_jmp('(')) {
715 long ret
= evalcexpr();
722 static long evalpre(void)
733 static long evalmul(void)
735 long ret
= evalpre();
737 if (!eval_jmp('*')) {
741 if (!eval_jmp('/')) {
745 if (!eval_jmp('%')) {
754 static long evaladd(void)
756 long ret
= evalmul();
758 if (!eval_jmp('+')) {
762 if (!eval_jmp('-')) {
771 static long evalshift(void)
773 long ret
= evaladd();
775 if (!eval_jmp(TOK2("<<"))) {
779 if (!eval_jmp(TOK2(">>"))) {
788 static long evalcmp(void)
790 long ret
= evalshift();
792 if (!eval_jmp('<')) {
793 ret
= ret
< evalshift();
796 if (!eval_jmp('>')) {
797 ret
= ret
> evalshift();
800 if (!eval_jmp(TOK2("<="))) {
801 ret
= ret
<= evalshift();
804 if (!eval_jmp(TOK2(">="))) {
805 ret
= ret
>= evalshift();
813 static long evaleq(void)
815 long ret
= evalcmp();
817 if (!eval_jmp(TOK2("=="))) {
818 ret
= ret
== evalcmp();
821 if (!eval_jmp(TOK2("!="))) {
822 ret
= ret
!= evalcmp();
830 static long evalbitand(void)
833 while (!eval_jmp('&'))
838 static long evalxor(void)
840 long ret
= evalbitand();
841 while (!eval_jmp('^'))
846 static long evalbitor(void)
848 long ret
= evalxor();
849 while (!eval_jmp('|'))
854 static long evaland(void)
856 long ret
= evalbitor();
857 while (!eval_jmp(TOK2("&&")))
858 ret
= ret
&& evalbitor();
862 static long evalor(void)
864 long ret
= evaland();
865 while (!eval_jmp(TOK2("||")))
866 ret
= ret
|| evaland();
870 static long evalcexpr(void)
877 while (eval_get() != ':')
882 static long evalexpr(void)
888 static int buf_loc(char *s
, int off
)
892 while ((s
= strchr(s
, '\n')) && s
< e
) {
899 char *cpp_loc(long addr
)
901 static char loc
[256];
904 for (i
= nbufs
- 1; i
> 0; i
--)
905 if (bufs
[i
].type
== BUF_FILE
)
907 if (addr
>= hunk_off
&& i
== nbufs
- 1)
908 line
= buf_loc(buf
, (cur
- hunk_len
) + (addr
- hunk_off
));
910 line
= buf_loc(bufs
[i
].buf
, bufs
[i
].cur
);
911 sprintf(loc
, "%s:%d", bufs
[i
].path
, line
);