summaryrefslogtreecommitdiff
path: root/libexec/tradcpp/directive.c
diff options
context:
space:
mode:
Diffstat (limited to 'libexec/tradcpp/directive.c')
-rw-r--r--libexec/tradcpp/directive.c204
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;
}
}