summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libexec/tradcpp/array.h2
-rw-r--r--libexec/tradcpp/bool.h41
-rw-r--r--libexec/tradcpp/directive.c204
-rw-r--r--libexec/tradcpp/directive.h14
-rw-r--r--libexec/tradcpp/eval.c2
-rw-r--r--libexec/tradcpp/eval.h2
-rw-r--r--libexec/tradcpp/files.c42
-rw-r--r--libexec/tradcpp/macro.c229
-rw-r--r--libexec/tradcpp/macro.h8
-rw-r--r--libexec/tradcpp/main.c33
-rw-r--r--libexec/tradcpp/mode.h3
-rw-r--r--libexec/tradcpp/output.c12
-rw-r--r--libexec/tradcpp/place.c130
-rw-r--r--libexec/tradcpp/place.h12
-rw-r--r--libexec/tradcpp/tradcpp.112
-rw-r--r--libexec/tradcpp/union.h36
-rw-r--r--libexec/tradcpp/utils.h10
-rw-r--r--libexec/tradcpp/version.h6
18 files changed, 650 insertions, 148 deletions
diff --git a/libexec/tradcpp/array.h b/libexec/tradcpp/array.h
index 8d1b98b3273..2fa474183e3 100644
--- a/libexec/tradcpp/array.h
+++ b/libexec/tradcpp/array.h
@@ -253,7 +253,7 @@ array_add(struct array *a, void *val, unsigned *index_ret)
#define DEFARRAY(T, INLINE) DEFARRAY_BYTYPE(T##array, struct T, INLINE)
#define DESTROYALL_ARRAY(T, INLINE) \
- void T##array_destroyall(struct T##array *arr); \
+ INLINE void T##array_destroyall(struct T##array *arr); \
\
INLINE void \
T##array_destroyall(struct T##array *arr) \
diff --git a/libexec/tradcpp/bool.h b/libexec/tradcpp/bool.h
new file mode 100644
index 00000000000..cf86ffb2cb9
--- /dev/null
+++ b/libexec/tradcpp/bool.h
@@ -0,0 +1,41 @@
+/*-
+ * Copyright (c) 2015 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by David A. Holland.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BOOL_H
+#define BOOL_H
+
+#if __STDC__ > 199901
+#include <stdbool.h>
+#else
+typedef int bool;
+#define true 1
+#define false 0
+#endif
+
+#endif /* BOOL_H */
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;
}
}
diff --git a/libexec/tradcpp/directive.h b/libexec/tradcpp/directive.h
index d4d5676e95f..7491a7a0fc5 100644
--- a/libexec/tradcpp/directive.h
+++ b/libexec/tradcpp/directive.h
@@ -29,11 +29,21 @@
#include <stddef.h>
-struct place;
+#include "place.h"
+
+/*
+ * Relevant places while we're processing a line:
+ * the place in the current line
+ * the beginning of the next line
+ */
+struct lineplace {
+ struct place current;
+ struct place nextline;
+};
void directive_init(void);
void directive_cleanup(void);
-void directive_gotline(struct place *p, char *line, size_t len);
+void directive_gotline(struct lineplace *lp, char *line, size_t len);
void directive_goteof(struct place *p);
diff --git a/libexec/tradcpp/eval.c b/libexec/tradcpp/eval.c
index cb5db991364..870ac6cf14d 100644
--- a/libexec/tradcpp/eval.c
+++ b/libexec/tradcpp/eval.c
@@ -642,6 +642,7 @@ wordval(struct place *p, char *word)
complain_fail();
}
}
+ debuglog(p, "Undefined symbol %s; substituting 0", word);
return 0;
}
@@ -744,6 +745,7 @@ eval(struct place *p, char *expr)
#ifdef DEBUG
fprintf(stderr, "eval: %s\n", expr);
#endif
+ debuglog(p, "eval: %s", expr);
tokenarray_init(&tokens);
tokenize(p, expr);
diff --git a/libexec/tradcpp/eval.h b/libexec/tradcpp/eval.h
index 0694fb4f9f7..d9193de0f06 100644
--- a/libexec/tradcpp/eval.h
+++ b/libexec/tradcpp/eval.h
@@ -27,6 +27,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <stdbool.h>
+#include "bool.h"
bool eval(struct place *p, char *expr);
diff --git a/libexec/tradcpp/files.c b/libexec/tradcpp/files.c
index e5e945581bb..e59388f0abb 100644
--- a/libexec/tradcpp/files.c
+++ b/libexec/tradcpp/files.c
@@ -27,7 +27,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -35,6 +34,7 @@
#include <fcntl.h>
#include <errno.h>
+#include "bool.h"
#include "array.h"
#include "mode.h"
#include "place.h"
@@ -172,14 +172,21 @@ static
void
file_read(const struct placefile *pf, int fd, const char *name, bool toplevel)
{
- struct place linestartplace, nextlinestartplace, ptmp;
+ struct lineplace places;
+ struct place ptmp;
size_t bufend, bufmax, linestart, lineend, nextlinestart, tmp;
ssize_t result;
bool ateof = false;
char *buf;
- place_setfilestart(&linestartplace, pf);
- nextlinestartplace = linestartplace;
+ place_setfilestart(&places.current, pf);
+ places.nextline = places.current;
+
+ if (name) {
+ debuglog(&places.current, "Reading file %s", name);
+ } else {
+ debuglog(&places.current, "Reading standard input");
+ }
bufmax = 128;
bufend = 0;
@@ -223,9 +230,15 @@ file_read(const struct placefile *pf, int fd, const char *name, bool toplevel)
} else if (result == 0) {
/* eof in middle of line */
ateof = true;
- ptmp = linestartplace;
+ ptmp = places.current;
ptmp.column += bufend - linestart;
- complain(&ptmp, "No newline at end of file");
+ if (buf[bufend - 1] == '\n') {
+ complain(&ptmp, "Unclosed comment");
+ complain_fail();
+ } else {
+ complain(&ptmp,
+ "No newline at end of file");
+ }
if (mode.werror) {
complain_fail();
}
@@ -244,7 +257,7 @@ file_read(const struct placefile *pf, int fd, const char *name, bool toplevel)
assert(buf[lineend] == '\n');
buf[lineend] = '\0';
nextlinestart = lineend+1;
- nextlinestartplace.line++;
+ places.nextline.line++;
/* check for CR/NL */
if (lineend > 0 && buf[lineend-1] == '\r') {
@@ -271,21 +284,18 @@ file_read(const struct placefile *pf, int fd, const char *name, bool toplevel)
assert(buf[lineend] == '\0');
/* count how many commented-out newlines we swallowed */
- nextlinestartplace.line += countnls(buf, linestart, lineend);
+ places.nextline.line += countnls(buf, linestart, lineend);
- /* if the line isn't empty, process it */
- if (lineend > linestart) {
- directive_gotline(&linestartplace,
- buf+linestart, lineend-linestart);
- }
+ /* process the line (even if it's empty) */
+ directive_gotline(&places, buf+linestart, lineend-linestart);
linestart = nextlinestart;
lineend = findeol(buf, linestart, bufend);
- linestartplace = nextlinestartplace;
+ places.current = places.nextline;
}
if (toplevel) {
- directive_goteof(&linestartplace);
+ directive_goteof(&places.current);
}
dofree(buf, bufmax);
}
@@ -396,7 +406,7 @@ file_readabsolute(struct place *place, const char *name)
assert(place != NULL);
- if ((name == NULL) || !strcmp(name, "-")) {
+ if (name == NULL) {
fd = STDIN_FILENO;
pf = place_addfile(place, "<standard-input>", false);
} else {
diff --git a/libexec/tradcpp/macro.c b/libexec/tradcpp/macro.c
index 8fe1e372aeb..147dfebb377 100644
--- a/libexec/tradcpp/macro.c
+++ b/libexec/tradcpp/macro.c
@@ -28,9 +28,11 @@
*/
#include <stdint.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include "union.h"
#include "array.h"
#include "mode.h"
#include "place.h"
@@ -38,15 +40,21 @@
#include "output.h"
struct expansionitem {
- bool isstring;
+ enum { EI_STRING, EI_PARAM, EI_FILE, EI_LINE } itemtype;
union {
- char *string;
- unsigned param;
- };
+ char *ei_string; /* for EI_STRING */
+ unsigned ei_param; /* for EI_PARAM */
+ } UN;
};
DECLARRAY(expansionitem, static UNUSED);
DEFARRAY(expansionitem, static);
+#ifdef NEED_UNION_ACCESSORS
+#define ei_string un.ei_string
+#define ei_param un.ei_param
+#endif
+
+
struct macro {
struct place defplace;
struct place expansionplace;
@@ -76,8 +84,8 @@ expansionitem_create_string(const char *string)
struct expansionitem *ei;
ei = domalloc(sizeof(*ei));
- ei->isstring = true;
- ei->string = dostrdup(string);
+ ei->itemtype = EI_STRING;
+ ei->ei_string = dostrdup(string);
return ei;
}
@@ -88,8 +96,8 @@ expansionitem_create_stringlen(const char *string, size_t len)
struct expansionitem *ei;
ei = domalloc(sizeof(*ei));
- ei->isstring = true;
- ei->string = dostrndup(string, len);
+ ei->itemtype = EI_STRING;
+ ei->ei_string = dostrndup(string, len);
return ei;
}
@@ -100,8 +108,30 @@ expansionitem_create_param(unsigned param)
struct expansionitem *ei;
ei = domalloc(sizeof(*ei));
- ei->isstring = false;
- ei->param = param;
+ ei->itemtype = EI_PARAM;
+ ei->ei_param = param;
+ return ei;
+}
+
+static
+struct expansionitem *
+expansionitem_create_file(void)
+{
+ struct expansionitem *ei;
+
+ ei = domalloc(sizeof(*ei));
+ ei->itemtype = EI_FILE;
+ return ei;
+}
+
+static
+struct expansionitem *
+expansionitem_create_line(void)
+{
+ struct expansionitem *ei;
+
+ ei = domalloc(sizeof(*ei));
+ ei->itemtype = EI_LINE;
return ei;
}
@@ -109,8 +139,14 @@ static
void
expansionitem_destroy(struct expansionitem *ei)
{
- if (ei->isstring) {
- dostrfree(ei->string);
+ switch (ei->itemtype) {
+ case EI_STRING:
+ dostrfree(ei->ei_string);
+ break;
+ case EI_PARAM:
+ case EI_FILE:
+ case EI_LINE:
+ break;
}
dofree(ei, sizeof(*ei));
}
@@ -120,17 +156,23 @@ bool
expansionitem_eq(const struct expansionitem *ei1,
const struct expansionitem *ei2)
{
- if (ei1->isstring != ei2->isstring) {
+ if (ei1->itemtype != ei2->itemtype) {
return false;
}
- if (ei1->isstring) {
- if (strcmp(ei1->string, ei2->string) != 0) {
+ switch (ei1->itemtype) {
+ case EI_STRING:
+ if (strcmp(ei1->ei_string, ei2->ei_string) != 0) {
return false;
}
- } else {
- if (ei1->param != ei2->param) {
+ break;
+ case EI_PARAM:
+ if (ei1->ei_param != ei2->ei_param) {
return false;
}
+ break;
+ case EI_FILE:
+ case EI_LINE:
+ break;
}
return true;
}
@@ -298,7 +340,7 @@ macrotable_cleanup(void)
static
struct macro *
-macrotable_findlen(const char *name, size_t len, bool remove)
+macrotable_findlen(const char *name, size_t len, bool remove_it)
{
unsigned hash;
struct macroarray *bucket;
@@ -319,7 +361,7 @@ macrotable_findlen(const char *name, size_t len, bool remove)
}
mlen = strlen(m->name);
if (len == mlen && !memcmp(name, m->name, len)) {
- if (remove) {
+ if (remove_it) {
if (i < num-1) {
m2 = macroarray_get(bucket, num-1);
macroarray_set(bucket, i, m2);
@@ -335,9 +377,9 @@ macrotable_findlen(const char *name, size_t len, bool remove)
static
struct macro *
-macrotable_find(const char *name, bool remove)
+macrotable_find(const char *name, bool remove_it)
{
- return macrotable_findlen(name, strlen(name), remove);
+ return macrotable_findlen(name, strlen(name), remove_it);
}
static
@@ -587,6 +629,24 @@ macro_define_params(struct place *p1, const char *macro,
}
void
+macro_define_magic(struct place *p, const char *macro)
+{
+ struct macro *m;
+ struct expansionitem *ei;
+
+ m = macro_define_common_start(p, macro, p);
+ if (!strcmp(macro, "__FILE__")) {
+ ei = expansionitem_create_file();
+ }
+ else {
+ assert(!strcmp(macro, "__LINE__"));
+ ei = expansionitem_create_line();
+ }
+ expansionitemarray_add(&m->expansion, ei, NULL);
+ macro_define_common_end(m);
+}
+
+void
macro_undef(const char *macro)
{
struct macro *m;
@@ -624,7 +684,7 @@ struct expstate {
static struct expstate mainstate;
static void doexpand(struct expstate *es, struct place *p,
- char *buf, size_t len);
+ const char *buf, size_t len);
static
void
@@ -705,7 +765,7 @@ expand_send_eof(struct expstate *es, struct place *p)
static
void
-expand_newarg(struct expstate *es, char *buf, size_t len)
+expand_newarg(struct expstate *es, const char *buf, size_t len)
{
char *text;
@@ -715,7 +775,7 @@ expand_newarg(struct expstate *es, char *buf, size_t len)
static
void
-expand_appendarg(struct expstate *es, char *buf, size_t len)
+expand_appendarg(struct expstate *es, const char *buf, size_t len)
{
unsigned num;
char *text;
@@ -742,6 +802,7 @@ expand_substitute(struct place *p, struct expstate *es)
char *arg;
char *ret;
unsigned numargs, numparams;
+ char numbuf[64];
numargs = stringarray_num(&es->args);
numparams = stringarray_num(&es->curmacro->params);
@@ -766,11 +827,20 @@ expand_substitute(struct place *p, struct expstate *es)
num = expansionitemarray_num(&es->curmacro->expansion);
for (i=0; i<num; i++) {
ei = expansionitemarray_get(&es->curmacro->expansion, i);
- if (ei->isstring) {
- len += strlen(ei->string);
- } else {
- arg = stringarray_get(&es->args, ei->param);
+ switch (ei->itemtype) {
+ case EI_STRING:
+ len += strlen(ei->ei_string);
+ break;
+ case EI_PARAM:
+ arg = stringarray_get(&es->args, ei->ei_param);
len += strlen(arg);
+ break;
+ case EI_FILE:
+ len += strlen(place_getname(p)) + 2;
+ break;
+ case EI_LINE:
+ len += snprintf(numbuf, sizeof(numbuf), "%u", p->line);
+ break;
}
}
@@ -778,11 +848,23 @@ expand_substitute(struct place *p, struct expstate *es)
*ret = '\0';
for (i=0; i<num; i++) {
ei = expansionitemarray_get(&es->curmacro->expansion, i);
- if (ei->isstring) {
- strlcat(ret, ei->string, len+1);
- } else {
- arg = stringarray_get(&es->args, ei->param);
- strlcat(ret, arg, len+1);
+ switch (ei->itemtype) {
+ case EI_STRING:
+ strlcat(ret, ei->ei_string, len + 1);
+ break;
+ case EI_PARAM:
+ arg = stringarray_get(&es->args, ei->ei_param);
+ strlcat(ret, arg, len + 1);
+ break;
+ case EI_FILE:
+ strlcat(ret, "\"", len + 1);
+ strlcat(ret, place_getname(p), len + 1);
+ strlcat(ret, "\"", len + 1);
+ break;
+ case EI_LINE:
+ snprintf(numbuf, sizeof(numbuf), "%u", p->line);
+ strlcat(ret, numbuf, len + 1);
+ break;
}
}
@@ -794,6 +876,7 @@ void
expand_domacro(struct expstate *es, struct place *p)
{
struct macro *m;
+ const char *name, *val;
char *newbuf, *newbuf2;
if (es->curmacro == NULL) {
@@ -804,23 +887,32 @@ expand_domacro(struct expstate *es, struct place *p)
expand_send(es, p, "0", 1);
return;
}
- m = macrotable_find(stringarray_get(&es->args, 0), false);
- expand_send(es, p, (m != NULL) ? "1" : "0", 1);
+ name = stringarray_get(&es->args, 0);
+ m = macrotable_find(name, false);
+ val = (m != NULL) ? "1" : "0";
+ debuglog(p, "defined(%s): %s", name, val);
+ expand_send(es, p, val, 1);
expstate_destroyargs(es);
return;
}
- assert(es->curmacro->inuse == false);
- es->curmacro->inuse = true;
+ m = es->curmacro;
+ assert(m->inuse == false);
+ m->inuse = true;
+ debuglog(p, "Expanding macro %s", m->name);
newbuf = expand_substitute(p, es);
+ debuglog(p, "Substituting for %s: %s", m->name, newbuf);
+
newbuf2 = macroexpand(p, newbuf, strlen(newbuf), false);
dostrfree(newbuf);
expstate_destroyargs(es);
+ debuglog(p, "Complete expansion for %s: %s", m->name, newbuf2);
+
doexpand(es, p, newbuf2, strlen(newbuf2));
dostrfree(newbuf2);
- es->curmacro->inuse = false;
+ m->inuse = false;
}
/*
@@ -846,13 +938,16 @@ expand_missingargs(struct expstate *es, struct place *p, bool needspace)
static
void
-expand_got_ws(struct expstate *es, struct place *p, char *buf, size_t len)
+expand_got_ws(struct expstate *es, struct place *p,
+ const char *buf, size_t len)
{
switch (es->state) {
case ES_NORMAL:
expand_send(es, p, buf, len);
break;
case ES_WANTLPAREN:
+ /* XXX notyet */
+ //expand_send(es, p, buf, len);
break;
case ES_NOARG:
expand_newarg(es, buf, len);
@@ -866,11 +961,10 @@ expand_got_ws(struct expstate *es, struct place *p, char *buf, size_t len)
static
void
-expand_got_word(struct expstate *es, struct place *p, char *buf, size_t len)
+expand_got_word(struct expstate *es, struct place *p,
+ const char *buf, size_t len)
{
struct macro *m;
- struct expansionitem *ei;
- char *newbuf;
switch (es->state) {
case ES_NORMAL:
@@ -884,15 +978,8 @@ expand_got_word(struct expstate *es, struct place *p, char *buf, size_t len)
if (m == NULL || m->inuse) {
expand_send(es, p, buf, len);
} else if (!m->hasparams) {
- m->inuse = true;
- assert(expansionitemarray_num(&m->expansion) == 1);
- ei = expansionitemarray_get(&m->expansion, 0);
- assert(ei->isstring);
- newbuf = macroexpand(p, ei->string,
- strlen(ei->string), false);
- doexpand(es, p, newbuf, strlen(newbuf));
- dostrfree(newbuf);
- m->inuse = false;
+ es->curmacro = m;
+ expand_domacro(es, p);
} else {
es->curmacro = m;
es->state = ES_WANTLPAREN;
@@ -923,7 +1010,8 @@ expand_got_word(struct expstate *es, struct place *p, char *buf, size_t len)
static
void
-expand_got_lparen(struct expstate *es, struct place *p, char *buf, size_t len)
+expand_got_lparen(struct expstate *es, struct place *p,
+ const char *buf, size_t len)
{
switch (es->state) {
case ES_NORMAL:
@@ -946,7 +1034,8 @@ expand_got_lparen(struct expstate *es, struct place *p, char *buf, size_t len)
static
void
-expand_got_rparen(struct expstate *es, struct place *p, char *buf, size_t len)
+expand_got_rparen(struct expstate *es, struct place *p,
+ const char *buf, size_t len)
{
switch (es->state) {
case ES_NORMAL:
@@ -981,7 +1070,8 @@ expand_got_rparen(struct expstate *es, struct place *p, char *buf, size_t len)
static
void
-expand_got_comma(struct expstate *es, struct place *p, char *buf, size_t len)
+expand_got_comma(struct expstate *es, struct place *p,
+ const char *buf, size_t len)
{
switch (es->state) {
case ES_NORMAL:
@@ -1009,7 +1099,8 @@ expand_got_comma(struct expstate *es, struct place *p, char *buf, size_t len)
static
void
-expand_got_other(struct expstate *es, struct place *p, char *buf, size_t len)
+expand_got_other(struct expstate *es, struct place *p,
+ const char *buf, size_t len)
{
switch (es->state) {
case ES_NORMAL:
@@ -1061,7 +1152,7 @@ expand_got_eof(struct expstate *es, struct place *p)
static
void
-doexpand(struct expstate *es, struct place *p, char *buf, size_t len)
+doexpand(struct expstate *es, struct place *p, const char *buf, size_t len)
{
char *s;
size_t x;
@@ -1150,7 +1241,7 @@ doexpand(struct expstate *es, struct place *p, char *buf, size_t len)
}
char *
-macroexpand(struct place *p, char *buf, size_t len, bool honordefined)
+macroexpand(struct place *p, const char *buf, size_t len, bool honordefined)
{
struct expstate es;
char *ret;
@@ -1172,10 +1263,30 @@ macroexpand(struct place *p, char *buf, size_t len, bool honordefined)
}
void
-macro_sendline(struct place *p, char *buf, size_t len)
+macro_sendline(struct place *p, const char *buf, size_t len)
{
doexpand(&mainstate, p, buf, len);
- output(p, "\n", 1);
+ switch (mainstate.state) {
+ case ES_NORMAL:
+ /*
+ * If we were sent a blank line, don't emit a newline
+ * for it. This matches the prior behavior of tradcpp.
+ */
+ if (len > 0) {
+ output(p, "\n", 1);
+ }
+ break;
+ case ES_WANTLPAREN:
+ case ES_NOARG:
+ case ES_HAVEARG:
+ /*
+ * Apparently to match gcc's -traditional behavior we
+ * need to emit a space for each newline that appears
+ * while processing macro args.
+ */
+ expand_got_ws(&mainstate, p, " ", 1);
+ break;
+ }
}
void
diff --git a/libexec/tradcpp/macro.h b/libexec/tradcpp/macro.h
index 98671e63bc9..76938a39548 100644
--- a/libexec/tradcpp/macro.h
+++ b/libexec/tradcpp/macro.h
@@ -27,8 +27,8 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <stdbool.h>
#include <stddef.h>
+#include "bool.h"
struct place;
@@ -40,10 +40,12 @@ void macro_define_plain(struct place *, const char *macro,
void macro_define_params(struct place *, const char *macro,
struct place *, const char *params,
struct place *, const char *expansion);
+void macro_define_magic(struct place *, const char *macro);
void macro_undef(const char *macro);
bool macro_isdefined(const char *macro);
-char *macroexpand(struct place *, char *buf, size_t len, bool honordefined);
+char *macroexpand(struct place *, const char *buf, size_t len,
+ bool honordefined);
-void macro_sendline(struct place *, char *buf, size_t len);
+void macro_sendline(struct place *, const char *buf, size_t len);
void macro_sendeof(struct place *);
diff --git a/libexec/tradcpp/main.c b/libexec/tradcpp/main.c
index 267c279be5e..9ce2ba1c76c 100644
--- a/libexec/tradcpp/main.c
+++ b/libexec/tradcpp/main.c
@@ -27,7 +27,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <stdbool.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
@@ -35,6 +34,7 @@
#include <string.h>
#include <errno.h>
+#include "bool.h"
#include "version.h"
#include "config.h"
#include "utils.h"
@@ -56,6 +56,7 @@ struct mode mode = {
.do_output = true,
.output_linenumbers = true,
+ .output_cheaplinenumbers = false,
.output_retain_comments = false,
.output_file = NULL,
@@ -167,7 +168,7 @@ void
commandline_undef(const struct place *p, char *str)
{
if (*str == '\0') {
- complain(NULL, "-D: macro name expected");
+ complain(NULL, "-U: macro name expected");
die();
}
commandline_macro_add(p, str, p, NULL);
@@ -196,6 +197,16 @@ apply_commandline_macros(void)
static
void
+apply_magic_macro(unsigned num, const char *name)
+{
+ struct place p;
+
+ place_setbuiltin(&p, num);
+ macro_define_magic(&p, name);
+}
+
+static
+void
apply_builtin_macro(unsigned num, const char *name, const char *val)
{
struct place p;
@@ -210,6 +221,9 @@ apply_builtin_macros(void)
{
unsigned n = 1;
+ apply_magic_macro(n++, "__FILE__");
+ apply_magic_macro(n++, "__LINE__");
+
#ifdef CONFIG_OS
apply_builtin_macro(n++, CONFIG_OS, "1");
#endif
@@ -782,6 +796,7 @@ static const struct flag_option flag_options[] = {
{ "fdollars-in-identifiers", &mode.input_allow_dollars, true },
{ "fno-dollars-in-identifiers", &mode.input_allow_dollars, false },
{ "nostdinc", &mode.do_stdinc, false },
+ { "p", &mode.output_cheaplinenumbers, true },
{ "undef", &mode.do_stddef, false },
};
static const unsigned num_flag_options = HOWMANY(flag_options);
@@ -815,6 +830,7 @@ static const struct arg_option arg_options[] = {
{ "MF", commandline_setdependoutput },
{ "MQ", commandline_setdependtarget_quoted },
{ "MT", commandline_setdependtarget },
+ { "debuglog", debuglog_open },
{ "idirafter", commandline_addincpath_late },
{ "imacros", commandline_addfile_nooutput },
{ "include", commandline_addfile_output },
@@ -935,7 +951,7 @@ check_arg_option(const char *opt, const struct place *argplace, char *arg)
return false;
}
-DEAD static
+DEAD PF(2, 3) static
void
usage(const char *progname, const char *fmt, ...)
{
@@ -947,7 +963,7 @@ usage(const char *progname, const char *fmt, ...)
va_end(ap);
fprintf(stderr, "\n");
- fprintf(stderr, "Usage: %s [options] [infile [outfile]]\n", progname);
+ fprintf(stderr, "usage: %s [options] [infile [outfile]]\n", progname);
fprintf(stderr, "Common options:\n");
fprintf(stderr, " -C Retain comments\n");
fprintf(stderr, " -Dmacro[=def] Predefine macro\n");
@@ -1000,6 +1016,7 @@ cleanup(void)
commandline_files_cleanup();
commandline_macros_cleanup();
incpath_cleanup();
+ debuglog_close();
num = stringarray_num(&freestrings);
for (i=0; i<num; i++) {
@@ -1046,7 +1063,7 @@ main(int argc, char *argv[])
init();
for (i=1; i<argc; i++) {
- if ((argv[i][0] != '-') || !strcmp(argv[i], "-")) {
+ if (argv[i][0] != '-' || argv[i][1] == 0) {
break;
}
place_setcommandline(&cmdplace, i, 1);
@@ -1071,9 +1088,15 @@ main(int argc, char *argv[])
}
if (i < argc) {
inputfile = argv[i++];
+ if (!strcmp(inputfile, "-")) {
+ inputfile = NULL;
+ }
}
if (i < argc) {
outputfile = argv[i++];
+ if (!strcmp(outputfile, "-")) {
+ outputfile = NULL;
+ }
}
if (i < argc) {
usage(progname, "Extra non-option argument %s", argv[i]);
diff --git a/libexec/tradcpp/mode.h b/libexec/tradcpp/mode.h
index 60f1636ff58..1b90e546f73 100644
--- a/libexec/tradcpp/mode.h
+++ b/libexec/tradcpp/mode.h
@@ -27,7 +27,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <stdbool.h>
+#include "bool.h"
struct mode {
bool werror;
@@ -37,6 +37,7 @@ struct mode {
bool do_stddef;
bool do_output;
bool output_linenumbers;
+ bool output_cheaplinenumbers;
bool output_retain_comments;
const char *output_file;
bool do_depend;
diff --git a/libexec/tradcpp/output.c b/libexec/tradcpp/output.c
index 5cc7165892c..d706a3180f6 100644
--- a/libexec/tradcpp/output.c
+++ b/libexec/tradcpp/output.c
@@ -27,6 +27,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
@@ -47,7 +48,7 @@ static
void
output_open(void)
{
- if ((mode.output_file == NULL) || !strcmp(mode.output_file, "-")) {
+ if (mode.output_file == NULL) {
outputfd = STDOUT_FILENO;
} else {
outputfd = open(mode.output_file, O_WRONLY|O_CREAT|O_TRUNC,
@@ -172,6 +173,15 @@ output(const struct place *p, const char *buf, size_t len)
linebuf = dorealloc(linebuf, oldmax, linebufmax);
}
if (linebufpos == 0) {
+ if (!place_samefile(&linebufplace, p)) {
+ if (mode.output_cheaplinenumbers) {
+ char str[256];
+
+ snprintf(str, sizeof(str), "# %u \"%s\"\n",
+ p->line, place_getname(p));
+ dowrite(str, strlen(str));
+ }
+ }
linebufplace = *p;
}
memcpy(linebuf + linebufpos, buf, len);
diff --git a/libexec/tradcpp/place.c b/libexec/tradcpp/place.c
index 267104875c5..72ab47ccb04 100644
--- a/libexec/tradcpp/place.c
+++ b/libexec/tradcpp/place.c
@@ -32,6 +32,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
#include "utils.h"
#include "array.h"
@@ -52,8 +53,10 @@ static bool overall_failure;
static const char *myprogname;
+static FILE *debuglogfile;
+
////////////////////////////////////////////////////////////
-// seenfiles
+// placefiles
static
struct placefile *
@@ -101,6 +104,42 @@ place_getparsedir(const struct place *place)
return place->file->dir;
}
+static
+struct placefile *
+placefile_find(const struct place *incfrom, const char *name)
+{
+ unsigned i, num;
+ struct placefile *pf;
+
+ num = placefilearray_num(&placefiles);
+ for (i=0; i<num; i++) {
+ pf = placefilearray_get(&placefiles, i);
+ if (place_eq(incfrom, &pf->includedfrom) &&
+ !strcmp(name, pf->name)) {
+ return pf;
+ }
+ }
+ return NULL;
+}
+
+void
+place_changefile(struct place *p, const char *name)
+{
+ struct placefile *pf;
+
+ assert(p->type == P_FILE);
+ if (!strcmp(name, p->file->name)) {
+ return;
+ }
+ pf = placefile_find(&p->file->includedfrom, name);
+ if (pf == NULL) {
+ pf = placefile_create(&p->file->includedfrom, name,
+ p->file->fromsystemdir);
+ placefilearray_add(&placefiles, pf, NULL);
+ }
+ p->file = pf;
+}
+
const struct placefile *
place_addfile(const struct place *place, const char *file, bool issystem)
{
@@ -154,7 +193,6 @@ place_setfilestart(struct place *p, const struct placefile *pf)
p->column = 1;
}
-static
const char *
place_getname(const struct place *p)
{
@@ -168,6 +206,30 @@ place_getname(const struct place *p)
return NULL;
}
+bool
+place_samefile(const struct place *a, const struct place *b)
+{
+ if (a->type != b->type) {
+ return false;
+ }
+ if (a->file != b->file) {
+ return false;
+ }
+ return true;
+}
+
+bool
+place_eq(const struct place *a, const struct place *b)
+{
+ if (!place_samefile(a, b)) {
+ return false;
+ }
+ if (a->line != b->line || a->column != b->column) {
+ return false;
+ }
+ return true;
+}
+
static
void
place_printfrom(const struct place *p)
@@ -225,6 +287,70 @@ complain_failed(void)
}
////////////////////////////////////////////////////////////
+// debug logging
+
+void
+debuglog_open(const struct place *p, /*const*/ char *file)
+{
+ assert(debuglogfile == NULL);
+ debuglogfile = fopen(file, "w");
+ if (debuglogfile == NULL) {
+ complain(p, "%s: %s", file, strerror(errno));
+ die();
+ }
+}
+
+void
+debuglog_close(void)
+{
+ if (debuglogfile != NULL) {
+ fclose(debuglogfile);
+ debuglogfile = NULL;
+ }
+}
+
+PF(2, 3) void
+debuglog(const struct place *p, const char *fmt, ...)
+{
+ va_list ap;
+
+ if (debuglogfile == NULL) {
+ return;
+ }
+
+ fprintf(debuglogfile, "%s:%u: ", place_getname(p), p->line);
+ va_start(ap, fmt);
+ vfprintf(debuglogfile, fmt, ap);
+ va_end(ap);
+ fprintf(debuglogfile, "\n");
+ fflush(debuglogfile);
+}
+
+PF(3, 4) void
+debuglog2(const struct place *p, const struct place *p2, const char *fmt, ...)
+{
+ va_list ap;
+
+ if (debuglogfile == NULL) {
+ return;
+ }
+
+ fprintf(debuglogfile, "%s:%u: ", place_getname(p), p->line);
+ if (place_samefile(p, p2)) {
+ fprintf(debuglogfile, "(block began at line %u) ",
+ p2->line);
+ } else {
+ fprintf(debuglogfile, "(block began at %s:%u)",
+ place_getname(p2), p2->line);
+ }
+ va_start(ap, fmt);
+ vfprintf(debuglogfile, fmt, ap);
+ va_end(ap);
+ fprintf(debuglogfile, "\n");
+ fflush(debuglogfile);
+}
+
+////////////////////////////////////////////////////////////
// module init and cleanup
void
diff --git a/libexec/tradcpp/place.h b/libexec/tradcpp/place.h
index 311645be145..d18dd82cbf2 100644
--- a/libexec/tradcpp/place.h
+++ b/libexec/tradcpp/place.h
@@ -27,7 +27,10 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <stdbool.h>
+#ifndef PLACE_H
+#define PLACE_H
+
+#include "bool.h"
enum places {
P_NOWHERE,
@@ -50,7 +53,14 @@ void place_setbuiltin(struct place *p, unsigned num);
void place_setcommandline(struct place *p, unsigned word, unsigned column);
void place_setfilestart(struct place *p, const struct placefile *pf);
+const char *place_getname(const struct place *);
const char *place_getparsedir(const struct place *incplace);
+bool place_eq(const struct place *, const struct place *);
+bool place_samefile(const struct place *, const struct place *);
+
+void place_changefile(struct place *p, const char *name);
const struct placefile *place_addfile(const struct place *incplace,
const char *name, bool fromsystemdir);
+
+#endif /* PLACE_H */
diff --git a/libexec/tradcpp/tradcpp.1 b/libexec/tradcpp/tradcpp.1
index c726dc44370..d4cf5355183 100644
--- a/libexec/tradcpp/tradcpp.1
+++ b/libexec/tradcpp/tradcpp.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: tradcpp.1,v 1.4 2016/12/28 22:47:11 schwarze Exp $
+.\" $OpenBSD: tradcpp.1,v 1.5 2018/09/02 08:28:05 jsg Exp $
.\"
.\" Copyright (c) 2013 The NetBSD Foundation, Inc.
.\" All rights reserved.
@@ -27,7 +27,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd $Mdocdate: December 28 2016 $
+.Dd $Mdocdate: September 2 2018 $
.Dt TRADCPP 1
.Os
.Sh NAME
@@ -261,6 +261,14 @@ but adds the result as if it were specified with
.El
.Ss Diagnostic Options
.Bl -tag -width bubblebabble
+.It Fl debuglog Ar file
+Write a trace of actions and operations to
+.Ar file
+as the input is processed.
+Meant for debugging problems in complex substitution schemes fed to
+.Nm ,
+such as those used by
+.Sy imake .
.It Fl dD
Dump all macro definitions, except for the predefined macros, after
the normal preprocessing output.
diff --git a/libexec/tradcpp/union.h b/libexec/tradcpp/union.h
new file mode 100644
index 00000000000..74113a5a8cb
--- /dev/null
+++ b/libexec/tradcpp/union.h
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2015 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by David A. Holland.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(__clang__) || defined(__GNUC__) || __STDC__ > 201101
+#define UN
+#undef NEED_UNION_ACCESSORS
+#else
+#define UN un
+#define NEED_UNION_ACCESSORS
+#endif
diff --git a/libexec/tradcpp/utils.h b/libexec/tradcpp/utils.h
index e6f1ae7286f..06d5f024d2c 100644
--- a/libexec/tradcpp/utils.h
+++ b/libexec/tradcpp/utils.h
@@ -27,8 +27,8 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <stdbool.h>
#include <stddef.h>
+#include "bool.h"
struct place;
@@ -63,10 +63,16 @@ bool is_identifier(const char *str);
/* in place.c */
void complain_init(const char *progname);
-void complain(const struct place *, const char *fmt, ...) PF(2, 3);
+PF(2, 3) void complain(const struct place *, const char *fmt, ...);
void complain_fail(void);
bool complain_failed(void);
+void debuglog_open(const struct place *p, /*const*/ char *file);
+void debuglog_close(void);
+PF(2, 3) void debuglog(const struct place *p, const char *fmt, ...);
+PF(3, 4) void debuglog2(const struct place *p, const struct place *p2,
+ const char *fmt, ...);
+
/* in main.c */
void freestringlater(char *s);
DEAD void die(void);
diff --git a/libexec/tradcpp/version.h b/libexec/tradcpp/version.h
index b278c662d11..3e0c5ca8531 100644
--- a/libexec/tradcpp/version.h
+++ b/libexec/tradcpp/version.h
@@ -28,6 +28,6 @@
*/
#define VERSION_MAJOR "0"
-#define VERSION_MINOR "4"
-#define VERSION_STRING "0.4"
-#define VERSION_LONG "NetBSD tradcpp 0.4"
+#define VERSION_MINOR "5"
+#define VERSION_STRING "0.5.2"
+#define VERSION_LONG "NetBSD tradcpp 0.5.2"