13 #define MAXDEFS (1 << 12)
14 #define MACROLEN (1 << 10)
15 #define MAXARGS (1 << 5)
16 #define NBUCKET (MAXDEFS << 1)
21 char args
[MAXARGS
][NAMELEN
];
26 /* macro hash table */
27 static struct tab mtab
;
29 #define MAXBUFS (1 << 5)
44 static void buf_new(int type
, char *name
)
47 bufs
[nbufs
- 1].cur
= cur
;
48 bufs
[nbufs
- 1].len
= len
;
51 die("nomem: MAXBUFS reached!\n");
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)
64 cur
= bufs
[nbufs
- 1].cur
;
65 len
= bufs
[nbufs
- 1].len
;
66 buf
= bufs
[nbufs
- 1].buf
;
70 static int buf_iseval(void)
73 for (i
= 0; i
< nbufs
; i
++)
74 if (bufs
[i
].type
== BUF_EVAL
)
79 static int buf_expanding(char *macro
)
82 for (i
= 0; i
< nbufs
; i
++)
83 if (bufs
[i
].type
== BUF_MACRO
&& !strcmp(macro
, bufs
[i
].name
))
88 static int include_file(char *path
)
90 int fd
= open(path
, O_RDONLY
);
94 buf_new(BUF_FILE
, path
);
95 while ((n
= read(fd
, buf
+ len
, BUFSIZE
- len
)) > 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
]))
115 static void read_word(char *dst
)
118 while (cur
< len
&& (isalnum(buf
[cur
]) || buf
[cur
] == '_'))
123 static void jumpcomment(void)
125 while (++cur
< len
) {
126 if (buf
[cur
] == '*' && buf
[cur
+ 1] == '/') {
133 static void read_tilleol(char *dst
)
135 while (cur
< len
&& isspace(buf
[cur
]) && buf
[cur
] != '\n')
137 while (cur
< len
&& buf
[cur
] != '\n') {
138 if (buf
[cur
] == '\\')
140 else if (buf
[cur
] == '/' && buf
[cur
+ 1] == '*')
148 static char *putstr(char *d
, char *s
)
156 #define MAXLOCS (1 << 10)
158 static char *locs
[MAXLOCS
] = {"/usr/include"};
159 static int nlocs
= 1;
161 void cpp_addpath(char *s
)
166 static int include_find(char *name
, int std
)
169 for (i
= std
? nlocs
- 1 : nlocs
; i
>= 0; i
--) {
174 s
= putstr(s
, locs
[i
]);
178 if (!include_file(path
))
184 static void 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
] == '\\')
202 static void readarg(char *s
)
206 while (cur
< len
&& (depth
|| buf
[cur
] != ',' && buf
[cur
] != ')')) {
225 if (buf
[cur
] == '/' && buf
[cur
+ 1] == '*')
231 memcpy(s
, buf
+ beg
, cur
- beg
);
235 static int macro_find(char *name
)
237 char *n
= tab_get(&mtab
, name
);
240 return container(n
, struct macro
, name
) - macros
;
243 static void macro_undef(char *name
)
245 int i
= macro_find(name
);
247 tab_del(&mtab
, macros
[i
].name
);
250 static int macro_new(char *name
)
252 int i
= macro_find(name
);
255 if (nmacros
>= MAXDEFS
)
256 die("nomem: MAXDEFS reached!\n");
258 strcpy(macros
[i
].name
, name
);
259 tab_add(&mtab
, macros
[i
].name
);
263 static void macro_define(void)
268 d
= ¯os
[macro_new(name
)];
271 if (buf
[cur
] == '(') {
274 while (cur
< len
&& buf
[cur
] != ')') {
275 readarg(d
->args
[d
->nargs
++]);
277 if (buf
[cur
++] != ',')
283 read_tilleol(d
->def
);
286 int cpp_read(char *buf
);
288 static char ebuf
[BUFSIZE
];
292 static long evalexpr(void);
294 static int cpp_eval(void)
298 char evalbuf
[BUFSIZE
];
299 read_tilleol(evalbuf
);
300 buf_new(BUF_EVAL
, NULL
);
301 strcpy(buf
, evalbuf
);
302 len
= strlen(evalbuf
);
306 while (bufid
< nbufs
|| cur
< len
)
307 elen
+= cpp_read(ebuf
+ elen
);
313 static void jumpifs(int jumpelse
)
317 if (buf
[cur
] == '#') {
321 if (!strcmp("else", cmd
))
322 if (!depth
&& !jumpelse
)
324 if (!strcmp("elif", cmd
))
325 if (!depth
&& !jumpelse
&& cpp_eval())
327 if (!strcmp("endif", cmd
)) {
333 if (!strcmp("ifdef", cmd
) || !strcmp("ifndef", cmd
) ||
338 if (buf
[cur
] == '/' && buf
[cur
+ 1] == '*') {
342 if (buf
[cur
] == '\'' || buf
[cur
] == '"') {
350 static void cpp_cmd(void)
355 if (!strcmp("define", cmd
)) {
359 if (!strcmp("undef", cmd
)) {
365 if (!strcmp("ifdef", cmd
) || !strcmp("ifndef", cmd
) ||
366 !strcmp("if", cmd
)) {
370 int not = cmd
[2] == 'n';
372 matched
= not ? macro_find(name
) < 0 :
373 macro_find(name
) >= 0;
375 matched
= cpp_eval();
381 if (!strcmp("else", cmd
) || !strcmp("elif", cmd
)) {
385 if (!strcmp("endif", cmd
))
387 if (!strcmp("include", cmd
)) {
392 e
= strchr(buf
+ cur
+ 1, buf
[cur
] == '"' ? '"' : '>');
393 memcpy(file
, s
, e
- s
);
396 if (include_find(file
, *e
== '>') == -1)
397 die("cannot include file\n");
402 static int macro_arg(struct macro
*m
, char *arg
)
405 for (i
= 0; i
< m
->nargs
; i
++)
406 if (!strcmp(arg
, m
->args
[i
]))
411 static void macro_expand(void)
414 char args
[MAXARGS
][MACROLEN
];
421 m
= ¯os
[macro_find(name
)];
423 buf_new(BUF_MACRO
, name
);
425 len
= strlen(m
->def
);
429 if (buf
[cur
] == '(') {
432 while (cur
< len
&& buf
[cur
] != ')') {
433 readarg(args
[nargs
++]);
443 buf_new(BUF_MACRO
, name
);
446 len
= strlen(m
->def
);
449 if (buf
[cur
] == '/' && buf
[cur
+ 1] == '*') {
453 if (strchr("'\"", buf
[cur
])) {
457 if (isalpha(buf
[cur
]) || buf
[cur
] == '_') {
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
);
467 memcpy(dst
+ dstlen
, argstr
, arglen
);
475 memcpy(dst
+ dstlen
, buf
+ beg
, len
- beg
);
483 void cpp_define(char *name
, char *def
)
486 buf_new(BUF_TEMP
, NULL
);
496 static int definedword
;
501 int cpp_read(char *s
)
514 if (buf
[cur
] == '#') {
521 if (buf
[cur
] == '/' && buf
[cur
+ 1] == '*') {
525 if (buf
[cur
] == '\'' || buf
[cur
] == '"') {
529 if (isalpha(buf
[cur
]) || buf
[cur
] == '_') {
532 if (!buf_expanding(word
) && macro_find(word
) != -1) {
537 if (buf_iseval() && !strcmp("defined", word
)) {
540 if (buf
[cur
] == '(') {
554 memcpy(s
, buf
+ old
, cur
- old
);
557 hunk_off
+= hunk_len
;
558 hunk_len
= cur
- old
;
563 /* preprocessor constant expression evaluation */
565 static char etok
[NAMELEN
];
568 static char *tok2
[] = {
569 "<<", ">>", "&&", "||", "==", "!=", "<=", ">="
572 static int eval_tok(void)
576 while (ecur
< elen
) {
577 while (ecur
< elen
&& isspace(ebuf
[ecur
]))
579 if (ebuf
[ecur
] == '/' && ebuf
[ecur
+ 1] == '*') {
580 while (ecur
< elen
&& (ebuf
[ecur
- 2] != '*' ||
581 ebuf
[ecur
- 1] != '/'))
589 if (isalpha(ebuf
[ecur
]) || ebuf
[ecur
] == '_') {
590 while (isalnum(ebuf
[ecur
]) || ebuf
[ecur
] == '_')
595 if (isdigit(ebuf
[ecur
])) {
596 while (isdigit(ebuf
[ecur
]))
598 while (tolower(ebuf
[ecur
]) == 'u' || tolower(ebuf
[ecur
]) == 'l')
602 for (i
= 0; i
< ARRAY_SIZE(tok2
); i
++)
603 if (TOK2(tok2
[i
]) == TOK2(ebuf
+ ecur
)) {
604 int ret
= TOK2(tok2
[i
]);
611 static int eval_see(void)
618 static int eval_get(void)
628 static long eval_num(void)
633 static int eval_jmp(int tok
)
635 if (eval_see() == tok
) {
642 static void eval_expect(int tok
)
647 static char *eval_id(void)
652 static long evalcexpr(void);
654 static long evalatom(void)
656 if (!eval_jmp(TOK_NUM
))
658 if (!eval_jmp(TOK_NAME
)) {
659 int parens
= !eval_jmp('(');
661 eval_expect(TOK_NAME
);
662 ret
= macro_find(eval_id()) >= 0;
667 if (!eval_jmp('(')) {
668 long ret
= evalcexpr();
675 static long evalpre(void)
686 static long evalmul(void)
688 long ret
= evalpre();
690 if (!eval_jmp('*')) {
694 if (!eval_jmp('/')) {
698 if (!eval_jmp('%')) {
707 static long evaladd(void)
709 long ret
= evalmul();
711 if (!eval_jmp('+')) {
715 if (!eval_jmp('-')) {
724 static long evalshift(void)
726 long ret
= evaladd();
728 if (!eval_jmp(TOK2("<<"))) {
732 if (!eval_jmp(TOK2(">>"))) {
741 static long evalcmp(void)
743 long ret
= evalshift();
745 if (!eval_jmp('<')) {
746 ret
= ret
< evalshift();
749 if (!eval_jmp('>')) {
750 ret
= ret
> evalshift();
753 if (!eval_jmp(TOK2("<="))) {
754 ret
= ret
<= evalshift();
757 if (!eval_jmp(TOK2(">="))) {
758 ret
= ret
>= evalshift();
766 static long evaleq(void)
768 long ret
= evalcmp();
770 if (!eval_jmp(TOK2("=="))) {
771 ret
= ret
== evalcmp();
774 if (!eval_jmp(TOK2("!="))) {
775 ret
= ret
!= evalcmp();
783 static long evalbitand(void)
786 while (!eval_jmp('&'))
791 static long evalxor(void)
793 long ret
= evalbitand();
794 while (!eval_jmp('^'))
799 static long evalbitor(void)
801 long ret
= evalxor();
802 while (!eval_jmp('|'))
807 static long evaland(void)
809 long ret
= evalbitor();
810 while (!eval_jmp(TOK2("&&")))
811 ret
= ret
&& evalbitor();
815 static long evalor(void)
817 long ret
= evaland();
818 while (!eval_jmp(TOK2("||")))
819 ret
= ret
|| evaland();
823 static long evalcexpr(void)
830 while (eval_get() != ':')
835 static long evalexpr(void)
841 static int numwidth(int n
)
851 static char *putnum(char *s
, int n
)
855 for (i
= 0; i
< w
; i
++) {
856 s
[w
- i
- 1] = !i
|| n
? '0' + n
% 10 : ' ';
862 static int buf_loc(char *s
, int off
)
866 while ((s
= strchr(s
, '\n')) && s
< e
) {
873 int cpp_loc(char *s
, long addr
)
878 for (i
= nbufs
- 1; i
> 0; i
--)
879 if (bufs
[i
].type
== BUF_FILE
)
881 if (addr
>= hunk_off
&& i
== nbufs
- 1)
882 line
= buf_loc(buf
, (cur
- hunk_len
) + (addr
- hunk_off
));
884 line
= buf_loc(bufs
[i
].buf
, bufs
[i
].cur
);
885 s
= putstr(s
, bufs
[i
].name
);