diff options
Diffstat (limited to 'libexec/tradcpp/directive.c')
-rw-r--r-- | libexec/tradcpp/directive.c | 204 |
1 files changed, 155 insertions, 49 deletions
diff --git a/libexec/tradcpp/directive.c b/libexec/tradcpp/directive.c index 5c81de24008..0d5c98916b5 100644 --- a/libexec/tradcpp/directive.c +++ b/libexec/tradcpp/directive.c @@ -28,10 +28,12 @@ */ #include <assert.h> -#include <stdbool.h> #include <stdlib.h> #include <string.h> +#include <limits.h> +#include <errno.h> +#include "bool.h" #include "utils.h" #include "mode.h" #include "place.h" @@ -175,13 +177,16 @@ ifstate_pop(void) static void -d_if(struct place *p, struct place *p2, char *line) +d_if(struct lineplace *lp, struct place *p2, char *line) { + bool doprint; char *expr; bool val; struct place p3 = *p2; size_t oldlen; + doprint = ifstate->curtrue; + expr = macroexpand(p2, line, strlen(line), true); oldlen = strlen(expr); @@ -194,41 +199,67 @@ d_if(struct place *p, struct place *p2, char *line) } else { val = 0; } - ifstate_push(p, val); + ifstate_push(&lp->current, val); dostrfree(expr); + + if (doprint) { + debuglog(&lp->current, "#if: %s", + ifstate->curtrue ? "taken" : "not taken"); + } } static void -d_ifdef(struct place *p, struct place *p2, char *line) +d_ifdef(struct lineplace *lp, struct place *p2, char *line) { + bool doprint; + + doprint = ifstate->curtrue; + uncomment(line); oneword("#ifdef", p2, line); - ifstate_push(p, macro_isdefined(line)); + ifstate_push(&lp->current, macro_isdefined(line)); + + if (doprint) { + debuglog(&lp->current, "#ifdef %s: %s", + line, ifstate->curtrue ? "taken" : "not taken"); + } } static void -d_ifndef(struct place *p, struct place *p2, char *line) +d_ifndef(struct lineplace *lp, struct place *p2, char *line) { + bool doprint; + + doprint = ifstate->curtrue; + uncomment(line); oneword("#ifndef", p2, line); - ifstate_push(p, !macro_isdefined(line)); + ifstate_push(&lp->current, !macro_isdefined(line)); + + if (doprint) { + debuglog(&lp->current, "#ifndef %s: %s", + line, ifstate->curtrue ? "taken" : "not taken"); + } } static void -d_elif(struct place *p, struct place *p2, char *line) +d_elif(struct lineplace *lp, struct place *p2, char *line) { + bool doprint; char *expr; struct place p3 = *p2; size_t oldlen; if (ifstate->seenelse) { - complain(p, "#elif after #else"); + complain(&lp->current, "#elif after #else"); complain_fail(); } + doprint = ifstate->curtrue; + if (ifstate->evertrue) { ifstate->curtrue = false; } else { @@ -243,36 +274,52 @@ d_elif(struct place *p, struct place *p2, char *line) ifstate->evertrue = ifstate->curtrue; dostrfree(expr); } + + if (doprint) { + debuglog2(&lp->current, &ifstate->startplace, "#elif: %s", + ifstate->curtrue ? "taken" : "not taken"); + } } static void -d_else(struct place *p, struct place *p2, char *line) +d_else(struct lineplace *lp, struct place *p2, char *line) { + bool doprint; + (void)p2; (void)line; if (ifstate->seenelse) { - complain(p, "Multiple #else directives in one conditional"); + complain(&lp->current, + "Multiple #else directives in one conditional"); complain_fail(); } + doprint = ifstate->curtrue; + ifstate->curtrue = !ifstate->evertrue; ifstate->evertrue = true; ifstate->seenelse = true; + + if (doprint) { + debuglog2(&lp->current, &ifstate->startplace, "#else: %s", + ifstate->curtrue ? "taken" : "not taken"); + } } static void -d_endif(struct place *p, struct place *p2, char *line) +d_endif(struct lineplace *lp, struct place *p2, char *line) { (void)p2; (void)line; if (ifstate->prev == NULL) { - complain(p, "Unmatched #endif"); + complain(&lp->current, "Unmatched #endif"); complain_fail(); } else { + debuglog2(&lp->current, &ifstate->startplace, "#endif"); ifstate_pop(); } } @@ -282,12 +329,12 @@ d_endif(struct place *p, struct place *p2, char *line) static void -d_define(struct place *p, struct place *p2, char *line) +d_define(struct lineplace *lp, struct place *p2, char *line) { size_t pos, argpos; struct place p3, p4; - (void)p; + (void)lp; /* * line may be: @@ -337,22 +384,25 @@ d_define(struct place *p, struct place *p2, char *line) p4.column += pos; if (argpos) { + debuglog(&lp->current, "Defining %s()", line); macro_define_params(p2, line, &p3, line + argpos, &p4, line + pos); } else { + debuglog(&lp->current, "Defining %s", line); macro_define_plain(p2, line, &p4, line + pos); } } static void -d_undef(struct place *p, struct place *p2, char *line) +d_undef(struct lineplace *lp, struct place *p2, char *line) { - (void)p; + (void)lp; uncomment(line); oneword("#undef", p2, line); + debuglog(&lp->current, "Undef %s", line); macro_undef(line); } @@ -368,13 +418,17 @@ tryinclude(struct place *p, char *line) len = strlen(line); if (len > 2 && line[0] == '"' && line[len-1] == '"') { line[len-1] = '\0'; + debuglog(p, "Entering include file \"%s\"", line+1); file_readquote(p, line+1); + debuglog(p, "Leaving include file \"%s\"", line+1); line[len-1] = '"'; return true; } if (len > 2 && line[0] == '<' && line[len-1] == '>') { line[len-1] = '\0'; + debuglog(p, "Entering include file <%s>", line+1); file_readbracket(p, line+1); + debuglog(p, "Leaving include file <%s>", line+1); line[len-1] = '>'; return true; } @@ -383,13 +437,13 @@ tryinclude(struct place *p, char *line) static void -d_include(struct place *p, struct place *p2, char *line) +d_include(struct lineplace *lp, struct place *p2, char *line) { char *text; size_t oldlen; uncomment(line); - if (tryinclude(p, line)) { + if (tryinclude(&lp->current, line)) { return; } text = macroexpand(p2, line, strlen(line), false); @@ -399,26 +453,78 @@ d_include(struct place *p, struct place *p2, char *line) /* trim to fit, so the malloc debugging won't complain */ text = dorealloc(text, oldlen + 1, strlen(text) + 1); - if (tryinclude(p, text)) { + if (tryinclude(&lp->current, text)) { dostrfree(text); return; } - complain(p, "Illegal #include directive"); - complain(p, "Before macro expansion: #include %s", line); - complain(p, "After macro expansion: #include %s", text); + complain(&lp->current, "Illegal #include directive"); + complain(&lp->current, "Before macro expansion: #include %s", line); + complain(&lp->current, "After macro expansion: #include %s", text); dostrfree(text); complain_fail(); } static void -d_line(struct place *p, struct place *p2, char *line) +d_line(struct lineplace *lp, struct place *p2, char *line) { - (void)p2; - (void)line; + char *text; + size_t oldlen; + unsigned long val; + char *moretext; + size_t moretextlen; + char *filename; + + text = macroexpand(p2, line, strlen(line), true); + + oldlen = strlen(text); + uncomment(text); + /* trim to fit, so the malloc debugging won't complain */ + text = dorealloc(text, oldlen + 1, strlen(text) + 1); + + /* + * What we should have here: either 1234 "file.c", + * or just 1234. + */ - /* XXX */ - complain(p, "Sorry, no #line yet"); + errno = 0; + val = strtoul(text, &moretext, 10); + if (errno) { + complain(&lp->current, "No line number in #line directive"); + goto fail; + } +#if UINT_MAX < ULONG_MAX + if (val > UINT_MAX) { + complain(&lp->current, + "Line number in #line directive too large"); + goto fail; + } +#endif + moretext += strspn(moretext, ws); + moretextlen = strlen(moretext); + lp->current.column += (moretext - text); + + if (moretextlen > 2 && + moretext[0] == '"' && moretext[moretextlen-1] == '"') { + filename = dostrndup(moretext+1, moretextlen-2); + place_changefile(&lp->nextline, filename); + dostrfree(filename); + } + else if (moretextlen > 0) { + complain(&lp->current, + "Invalid file name in #line directive"); + goto fail; + } + + lp->nextline.line = val; + dostrfree(text); + return; + +fail: + complain(&lp->current, "Before macro expansion: #line %s", line); + complain(&lp->current, "After macro expansion: #line %s", text); + complain_fail(); + dostrfree(text); } //////////////////////////////////////////////////////////// @@ -426,12 +532,12 @@ d_line(struct place *p, struct place *p2, char *line) static void -d_warning(struct place *p, struct place *p2, char *line) +d_warning(struct lineplace *lp, struct place *p2, char *line) { char *msg; msg = macroexpand(p2, line, strlen(line), false); - complain(p, "#warning: %s", msg); + complain(&lp->current, "#warning: %s", msg); if (mode.werror) { complain_fail(); } @@ -440,12 +546,12 @@ d_warning(struct place *p, struct place *p2, char *line) static void -d_error(struct place *p, struct place *p2, char *line) +d_error(struct lineplace *lp, struct place *p2, char *line) { char *msg; msg = macroexpand(p2, line, strlen(line), false); - complain(p, "#error: %s", msg); + complain(&lp->current, "#error: %s", msg); complain_fail(); dostrfree(msg); } @@ -455,11 +561,11 @@ d_error(struct place *p, struct place *p2, char *line) static void -d_pragma(struct place *p, struct place *p2, char *line) +d_pragma(struct lineplace *lp, struct place *p2, char *line) { (void)p2; - complain(p, "#pragma %s", line); + complain(&lp->current, "#pragma %s", line); complain_fail(); } @@ -469,7 +575,7 @@ d_pragma(struct place *p, struct place *p2, char *line) static const struct { const char *name; bool ifskip; - void (*func)(struct place *, struct place *, char *line); + void (*func)(struct lineplace *, struct place *, char *line); } directives[] = { { "define", true, d_define }, { "elif", false, d_elif }, @@ -489,13 +595,13 @@ static const unsigned numdirectives = HOWMANY(directives); static void -directive_gotdirective(struct place *p, char *line) +directive_gotdirective(struct lineplace *lp, char *line) { struct place p2; size_t len, skip; unsigned i; - p2 = *p; + p2 = lp->current; for (i=0; i<numdirectives; i++) { len = strlen(directives[i].name); if (!strncmp(line, directives[i].name, len) && @@ -512,7 +618,7 @@ directive_gotdirective(struct place *p, char *line) if (len < strlen(line)) { line[len] = '\0'; } - directives[i].func(p, &p2, line); + directives[i].func(lp, &p2, line); return; } } @@ -523,7 +629,7 @@ directive_gotdirective(struct place *p, char *line) } skip = strcspn(line, ws); - complain(p, "Unknown directive #%.*s", (int)skip, line); + complain(&lp->current, "Unknown directive #%.*s", (int)skip, line); complain_fail(); } @@ -532,13 +638,13 @@ directive_gotdirective(struct place *p, char *line) */ static size_t -directive_scancomments(const struct place *p, char *line, size_t len) +directive_scancomments(const struct lineplace *lp, char *line, size_t len) { size_t pos; bool incomment; struct place p2; - p2 = *p; + p2 = lp->current; incomment = 0; for (pos = 0; pos+1 < len; pos++) { if (line[pos] == '/' && line[pos+1] == '*') { @@ -574,25 +680,25 @@ directive_scancomments(const struct place *p, char *line, size_t len) } void -directive_gotline(struct place *p, char *line, size_t len) +directive_gotline(struct lineplace *lp, char *line, size_t len) { size_t skip; if (warns.nestcomment) { - directive_scancomments(p, line, len); + directive_scancomments(lp, line, len); } /* check if we have a directive line (# exactly in column 0) */ - if (line[0] == '#') { + if (len > 0 && line[0] == '#') { skip = 1 + strspn(line + 1, ws); assert(skip <= len); - p->column += skip; + lp->current.column += skip; assert(line[len] == '\0'); - directive_gotdirective(p, line+skip /*, length = len-skip */); - p->column += len-skip; + directive_gotdirective(lp, line+skip /*, length = len-skip */); + lp->current.column += len-skip; } else if (ifstate->curtrue) { - macro_sendline(p, line, len); - p->column += len; + macro_sendline(&lp->current, line, len); + lp->current.column += len; } } |