22 char args
[NARGS
][NAMELEN
];
27 /* macro hash table */
28 static struct tab mtab
;
45 char args
[NARGS
][MACROLEN
]; /* arguments passed to a macro */
47 int arg_buf
; /* the bufs index of the owning macro */
50 static int bufs_limit
= 1; /* cpp_read() limit; useful in cpp_eval() */
52 void die(char *fmt
, ...)
57 vsprintf(msg
, fmt
, ap
);
59 write(2, msg
, strlen(msg
));
63 static void buf_new(int type
, char *dat
, int dlen
)
66 bufs
[nbufs
- 1].buf
= buf
;
67 bufs
[nbufs
- 1].cur
= cur
;
68 bufs
[nbufs
- 1].len
= len
;
71 die("nomem: NBUFS reached!\n");
76 bufs
[nbufs
- 1].type
= type
;
79 static void buf_file(char *path
, char *dat
, int dlen
)
81 buf_new(BUF_FILE
, dat
, dlen
);
82 strcpy(bufs
[nbufs
- 1].path
, path
? path
: "");
85 static void buf_macro(struct macro
*m
)
87 buf_new(BUF_MACRO
, m
->def
, strlen(m
->def
));
88 bufs
[nbufs
- 1].macro
= m
;
91 static void buf_arg(char *arg
, int mbuf
)
93 buf_new(BUF_ARG
, arg
, strlen(arg
));
94 bufs
[nbufs
- 1].arg_buf
= mbuf
;
97 static void buf_pop(void)
101 cur
= bufs
[nbufs
- 1].cur
;
102 len
= bufs
[nbufs
- 1].len
;
103 buf
= bufs
[nbufs
- 1].buf
;
107 static int buf_iseval(void)
110 for (i
= nbufs
- 1; i
>= 0; i
--)
111 if (bufs
[i
].type
== BUF_EVAL
)
116 static size_t file_size(int fd
)
124 static int include_file(char *path
)
126 int fd
= open(path
, O_RDONLY
);
132 size
= file_size(fd
) + 1;
134 while ((n
= read(fd
, dat
+ nr
, size
- nr
)) > 0)
138 buf_file(path
, dat
, nr
);
142 int cpp_init(char *path
)
144 return include_file(path
);
147 static int jumpws(void)
150 while (cur
< len
&& isspace(buf
[cur
]))
155 static void read_word(char *dst
)
158 while (cur
< len
&& (isalnum(buf
[cur
]) || buf
[cur
] == '_'))
163 static int jumpcomment(void)
165 if (buf
[cur
] == '/' && buf
[cur
+ 1] == '*') {
166 while (++cur
< len
) {
167 if (buf
[cur
] == '*' && buf
[cur
+ 1] == '/') {
173 if (buf
[cur
] == '/' && buf
[cur
+ 1] == '/') {
175 if (buf
[cur
] == '\n')
182 static int jumpstr(void)
184 if (buf
[cur
] == '\'') {
185 while (cur
< len
&& buf
[++cur
] != '\'')
186 if (buf
[cur
] == '\\')
191 if (buf
[cur
] == '"') {
192 while (cur
< len
&& buf
[++cur
] != '"')
193 if (buf
[cur
] == '\\')
201 static void read_tilleol(char *dst
)
203 while (cur
< len
&& isspace(buf
[cur
]) && buf
[cur
] != '\n')
205 while (cur
< len
&& buf
[cur
] != '\n') {
207 if (buf
[cur
] == '\\' && buf
[cur
+ 1] == '\n') {
212 memcpy(dst
, buf
+ last
, cur
- last
);
223 static char *putstr(char *d
, char *s
)
231 static char *locs
[NLOCS
] = {};
232 static int nlocs
= 0;
234 void cpp_addpath(char *s
)
239 static int include_find(char *name
, int std
)
242 for (i
= std
? nlocs
- 1 : nlocs
; i
>= 0; i
--) {
247 s
= putstr(s
, locs
[i
]);
251 if (!include_file(path
))
257 static void readarg(char *s
)
261 while (cur
< len
&& (depth
|| (buf
[cur
] != ',' && buf
[cur
] != ')'))) {
262 if (!jumpstr() || !jumpcomment())
264 switch (buf
[cur
++]) {
278 memcpy(s
, buf
+ beg
, cur
- beg
);
283 static int macro_find(char *name
)
285 char *n
= tab_get(&mtab
, name
);
288 return container(n
, struct macro
, name
) - macros
;
291 static void macro_undef(char *name
)
293 int i
= macro_find(name
);
295 tab_del(&mtab
, macros
[i
].name
);
298 static int macro_new(char *name
)
300 int i
= macro_find(name
);
303 if (nmacros
>= NDEFS
)
304 die("nomem: NDEFS reached!\n");
306 strcpy(macros
[i
].name
, name
);
307 tab_add(&mtab
, macros
[i
].name
);
311 static void macro_define(void)
316 d
= ¯os
[macro_new(name
)];
319 if (buf
[cur
] == '(') {
322 while (cur
< len
&& buf
[cur
] != ')') {
323 readarg(d
->args
[d
->nargs
++]);
333 read_tilleol(d
->def
);
336 int cpp_read(char *buf
);
338 static char ebuf
[BUFLEN
];
342 static long evalexpr(void);
344 static int cpp_eval(void)
346 char evalbuf
[BUFLEN
];
349 read_tilleol(evalbuf
);
350 buf_new(BUF_EVAL
, evalbuf
, strlen(evalbuf
));
353 old_limit
= bufs_limit
;
355 while ((nr
= cpp_read(ebuf
+ elen
)) >= 0)
357 bufs_limit
= old_limit
;
363 static void jumpifs(int jumpelse
)
367 if (buf
[cur
] == '#') {
371 if (!strcmp("else", cmd
))
372 if (!depth
&& !jumpelse
)
374 if (!strcmp("elif", cmd
))
375 if (!depth
&& !jumpelse
&& cpp_eval())
377 if (!strcmp("endif", cmd
)) {
383 if (!strcmp("ifdef", cmd
) || !strcmp("ifndef", cmd
) ||
396 static int cpp_cmd(void)
401 if (!strcmp("define", cmd
)) {
405 if (!strcmp("undef", cmd
)) {
411 if (!strcmp("ifdef", cmd
) || !strcmp("ifndef", cmd
) ||
412 !strcmp("if", cmd
)) {
416 int not = cmd
[2] == 'n';
418 matched
= not ? macro_find(name
) < 0 :
419 macro_find(name
) >= 0;
421 matched
= cpp_eval();
427 if (!strcmp("else", cmd
) || !strcmp("elif", cmd
)) {
431 if (!strcmp("endif", cmd
))
433 if (!strcmp("include", cmd
)) {
438 e
= strchr(buf
+ cur
+ 1, buf
[cur
] == '"' ? '"' : '>');
439 memcpy(file
, s
, e
- s
);
442 if (include_find(file
, *e
== '>') == -1)
443 err("cannot include <%s>\n", file
);
449 static int macro_arg(struct macro
*m
, char *arg
)
452 for (i
= 0; i
< m
->nargs
; i
++)
453 if (!strcmp(arg
, m
->args
[i
]))
458 static int buf_arg_find(char *name
)
461 for (i
= nbufs
- 1; i
>= 0; i
--) {
462 struct buf
*mbuf
= &bufs
[i
];
463 struct macro
*m
= mbuf
->macro
;
464 if (mbuf
->type
== BUF_MACRO
&& macro_arg(m
, name
) >= 0)
466 if (mbuf
->type
== BUF_ARG
)
472 static void macro_expand(char *name
)
476 if ((mbuf
= buf_arg_find(name
)) >= 0) {
477 int arg
= macro_arg(bufs
[mbuf
].macro
, name
);
478 char *dat
= bufs
[mbuf
].args
[arg
];
482 m
= ¯os
[macro_find(name
)];
488 if (buf
[cur
] == '(') {
490 struct buf
*mbuf
= &bufs
[nbufs
];
493 while (cur
< len
&& buf
[cur
] != ')') {
494 readarg(mbuf
->args
[i
++]);
502 mbuf
->args
[i
++][0] = '\0';
508 static int buf_expanding(char *macro
)
511 for (i
= nbufs
- 1; i
>= 0; i
--) {
512 if (bufs
[i
].type
== BUF_ARG
)
514 if (bufs
[i
].type
== BUF_MACRO
&&
515 !strcmp(macro
, bufs
[i
].macro
->name
))
521 /* return 1 for plain macros and arguments and 2 for function macros */
522 static int expandable(char *word
)
525 if (buf_arg_find(word
) >= 0)
527 if (buf_expanding(word
))
529 i
= macro_find(word
);
530 return i
>= 0 ? macros
[i
].isfunc
+ 1 : 0;
533 void cpp_define(char *name
, char *def
)
535 char tmp_buf
[MACROLEN
];
540 buf_new(BUF_TEMP
, tmp_buf
, s
- tmp_buf
);
545 static int seen_macro
; /* seen a macro; 2 if a function macro */
546 static char seen_name
[NAMELEN
]; /* the name of the last macro */
551 int cpp_read(char *s
)
555 if (seen_macro
== 1) {
556 macro_expand(seen_name
);
560 struct buf
*cbuf
= &bufs
[nbufs
- 1];
561 if (nbufs
< bufs_limit
+ 1)
563 if (cbuf
->type
== BUF_FILE
)
578 if (seen_macro
== 2) {
580 macro_expand(seen_name
);
587 if (isalnum(buf
[cur
]) || buf
[cur
] == '_') {
590 seen_macro
= expandable(word
);
592 strcpy(seen_name
, word
);
596 if (buf_iseval() && !strcmp("defined", word
)) {
599 if (buf
[cur
] == '(') {
613 /* macros are expanded later; ignore its name */
614 end
= jump_name
? cur
- strlen(seen_name
) : cur
;
615 memcpy(s
, buf
+ old
, end
- old
);
618 hunk_off
+= hunk_len
;
619 hunk_len
= end
- old
;
624 /* preprocessor constant expression evaluation */
626 static char etok
[NAMELEN
];
629 static char *tok2
[] = {
630 "<<", ">>", "&&", "||", "==", "!=", "<=", ">="
633 static int eval_tok(void)
637 while (ecur
< elen
) {
638 while (ecur
< elen
&& isspace(ebuf
[ecur
]))
640 if (ebuf
[ecur
] == '/' && ebuf
[ecur
+ 1] == '*') {
641 while (ecur
< elen
&& (ebuf
[ecur
- 2] != '*' ||
642 ebuf
[ecur
- 1] != '/'))
650 if (isalpha(ebuf
[ecur
]) || ebuf
[ecur
] == '_') {
651 while (isalnum(ebuf
[ecur
]) || ebuf
[ecur
] == '_')
656 if (isdigit(ebuf
[ecur
])) {
657 while (isdigit(ebuf
[ecur
]))
659 while (tolower(ebuf
[ecur
]) == 'u' || tolower(ebuf
[ecur
]) == 'l')
664 for (i
= 0; i
< LEN(tok2
); i
++)
665 if (TOK2(tok2
[i
]) == TOK2(ebuf
+ ecur
)) {
666 int ret
= TOK2(tok2
[i
]);
673 static int eval_see(void)
680 static int eval_get(void)
690 static long eval_num(void)
695 static int eval_jmp(int tok
)
697 if (eval_see() == tok
) {
704 static void eval_expect(int tok
)
709 static char *eval_id(void)
714 static long evalcexpr(void);
716 static long evalatom(void)
718 if (!eval_jmp(TOK_NUM
))
720 if (!eval_jmp(TOK_NAME
)) {
721 int parens
= !eval_jmp('(');
723 eval_expect(TOK_NAME
);
724 ret
= macro_find(eval_id()) >= 0;
729 if (!eval_jmp('(')) {
730 long ret
= evalcexpr();
737 static long evalpre(void)
748 static long evalmul(void)
750 long ret
= evalpre();
752 if (!eval_jmp('*')) {
756 if (!eval_jmp('/')) {
760 if (!eval_jmp('%')) {
769 static long evaladd(void)
771 long ret
= evalmul();
773 if (!eval_jmp('+')) {
777 if (!eval_jmp('-')) {
786 static long evalshift(void)
788 long ret
= evaladd();
790 if (!eval_jmp(TOK2("<<"))) {
794 if (!eval_jmp(TOK2(">>"))) {
803 static long evalcmp(void)
805 long ret
= evalshift();
807 if (!eval_jmp('<')) {
808 ret
= ret
< evalshift();
811 if (!eval_jmp('>')) {
812 ret
= ret
> evalshift();
815 if (!eval_jmp(TOK2("<="))) {
816 ret
= ret
<= evalshift();
819 if (!eval_jmp(TOK2(">="))) {
820 ret
= ret
>= evalshift();
828 static long evaleq(void)
830 long ret
= evalcmp();
832 if (!eval_jmp(TOK2("=="))) {
833 ret
= ret
== evalcmp();
836 if (!eval_jmp(TOK2("!="))) {
837 ret
= ret
!= evalcmp();
845 static long evalbitand(void)
848 while (!eval_jmp('&'))
853 static long evalxor(void)
855 long ret
= evalbitand();
856 while (!eval_jmp('^'))
861 static long evalbitor(void)
863 long ret
= evalxor();
864 while (!eval_jmp('|'))
869 static long evaland(void)
871 long ret
= evalbitor();
872 while (!eval_jmp(TOK2("&&")))
873 ret
= ret
&& evalbitor();
877 static long evalor(void)
879 long ret
= evaland();
880 while (!eval_jmp(TOK2("||")))
881 ret
= ret
|| evaland();
885 static long evalcexpr(void)
892 while (eval_get() != ':')
897 static long evalexpr(void)
903 static int buf_loc(char *s
, int off
)
907 while ((s
= strchr(s
, '\n')) && s
< e
) {
914 char *cpp_loc(long addr
)
916 static char loc
[256];
919 for (i
= nbufs
- 1; i
> 0; i
--)
920 if (bufs
[i
].type
== BUF_FILE
)
922 if (addr
>= hunk_off
&& i
== nbufs
- 1)
923 line
= buf_loc(buf
, (cur
- hunk_len
) + (addr
- hunk_off
));
925 line
= buf_loc(bufs
[i
].buf
, bufs
[i
].cur
);
926 sprintf(loc
, "%s:%d", bufs
[i
].path
, line
);