+release 0.5.3 (20190121)
+ - Fix markup typo in the man page.
+ - Abort on line numbering or column numbering overflow. Line
+ numbers are limited to values that fit in "unsigned int". Also
+ reject input lines longer than 2^32-1 characters. It seems
+ reasonable to presume that any input that violates these
+ constraints is someone screwing around and not a serious attempt
+ to compile or preprocess anything useful. Done in response to
+ n2129, but without getting into any of the silliness found there.
+ - Recognize __ia64__ for IA64 builds.
+ - Recognize __aarch64__ for 64-bit ARM builds, as sent in by
+ various people.
+ - Recognize __riscv__ and __riscv64__ for risc-v builds.
+
+release 0.5.2 (20160904)
+ - Fix typo in -U usage message, noticed by Joerg.
+ - Add a -debuglog option to send an execution trace to a file.
+ Intended to be used when debugging imake templates and other
+ complex input, not for debugging tradcpp itself.
+
+release 0.5.1 (20150612)
+ - Fix a stupid regression in 0.5 that causes it to not recognize a
+ pile of options.
+ - Fix output corruption caused by mishandling which macros are
+ currently in use. In particular, "curmacro" is only valid while
+ we're parsing a macro name and arguments, and can change once we
+ start expanding, so don't use it to clear the in-use flag. This
+ problem has been around all along but was only just exposed.
+ - Also don't set curmacro to null after calling expand_domacro as
+ that can cause us to think a macro name we just read is defined().
+ This one was introduced in 0.5.
+ - Don't use "remove" as a local variable as gcc 4.1 gets upset
+ about it vs. remove(3) in stdio.h.
+
+release 0.5 (20150612)
+ - Don't report unclosed comments as "No newline at end of file".
+ - Don't rely on <stdbool.h> existing, as (predictably) it doesn't
+ work on Solaris.
+ - Similarly, don't rely on C11 anonymous unions as the Solaris
+ compiler vomits on them.
+ - Typo fix in man page from Jason McIntyre; and change "Usage" to
+ "usage" in usage for pedantic reasons, from Igor Sobrado.
+ - Accept "-" as either input or output file name to mean stdin or
+ stdout respectively. Suggested by Jonathan Gray.
+ - Fix output spacing behavior to match gcc when newlines appear in or
+ while looking for macro arguments. Partly from Joerg Sonnenberger.
+ - Implement __FILE__ and __LINE__ macros. Mostly from Joerg Sonnenberger.
+ - Implement #line. Partly from Joerg Sonnenberger.
+ - Declare usage() with PF(). From wiz.
+
release 0.4 (20130713)
- Fix stupid build problem introduced in 0.3.1.
- Accept and ignore -m32, which imake issues willy-nilly on a bunch
bin_PROGRAMS = tradcpp
-tradcpp_SOURCES = array.c \
- array.h \
- config.h \
- directive.c \
- directive.h \
- eval.c \
- eval.h \
- files.c \
- files.h \
- inlinedefs.h \
- macro.c \
- macro.h \
- main.c \
- mode.h \
- output.c \
- output.h \
- place.c \
- place.h \
- utils.c \
- utils.h \
- version.h
+tradcpp_SOURCES = array.c directive.c files.c macro.h output.h \
+ utils.c array.h directive.h files.h main.c place.c utils.h \
+ bool.h eval.c inlinedefs.h mode.h place.h version.h config.h \
+ eval.h macro.c output.c union.h
+
- warns.endiflabels. (they cause errors)
- warns.unused.
- the -iremap option.
- - #line directives.
- $CPP_RESTRICTED
- other environment variables
- get rid of inlinedefs.h
- use of places in and below macro.c is pretty bogus.
- macro code should be reworked.
+ - place_changefile is manky and wastes memory. Also, in an ideal
+ world we'd remember the place #line changed the name and refer
+ to it when printing errors.
fix:
- "#if 0 && 1/0" should not crash; fix eval method.
- - an unterminated comment is reported as "no newline at end of file"
- (which isn't fatal by default)
- quote characters and comment delimiters that are emitted by
macros are not recognized. See:
t34 (should produce a quote and FOO Q)
twice, once when the macro is defined and again when it's
expanded. Note that gcc's cpp -traditional is getting t37
wrong, and it gets t36 wrong with -C.
+ - remove the intentionally undocumented -p option and generate
+ proper linenumber output. (also, in this code what happens if
+ a comment spans files? I bet currently it will emit the line
+ number into the comment.)
#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) \
--- /dev/null
+/*-
+ * 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 */
#define CONFIG_CPU "__ppc64__"
#elif defined(__ARM__)
#define CONFIG_CPU "__ARM__"
+#elif defined(__AARCH64__)
+#define CONFIG_CPU "__AARCH64__"
+#elif defined(__aarch64__)
+#define CONFIG_CPU "__aarch64__"
+#elif defined(__RISCV__)
+#define CONFIG_CPU "__RISCV__"
+#elif defined(__riscv__)
+#define CONFIG_CPU "__riscv__"
+#elif defined(__RISCV64__)
+#define CONFIG_CPU "__RISCV64__"
+#elif defined(__riscv64__)
+#define CONFIG_CPU "__riscv64__"
+#elif defined(__riscv64)
+#define CONFIG_CPU "__riscv64"
+#elif defined(__ia64__)
+#define CONFIG_CPU "__ia64__"
#else
/* let it go */
#endif
*/
#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"
pos = strcspn(line, ws);
if (line[pos] != '\0') {
- p2->column += pos;
+ place_addcolumns(p2, pos);
complain(p2, "Garbage after %s argument", what);
complain_fail();
line[pos] = '\0';
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);
} 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 {
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();
}
}
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:
argpos = pos;
pos = pos + strcspn(line+pos, "()");
if (line[pos] == '(') {
- p2->column += pos;
+ place_addcolumns(p2, pos);
complain(p2, "Left parenthesis in macro parameters");
complain_fail();
return;
}
if (line[pos] != ')') {
- p2->column += pos;
+ place_addcolumns(p2, pos);
complain(p2, "Unclosed macro parameter list");
complain_fail();
return;
pos += strspn(line+pos, ws);
p3 = *p2;
- p3.column += argpos;
+ place_addcolumns(&p3, argpos);
p4 = *p2;
- p4.column += pos;
+ place_addcolumns(&p4, 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);
}
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;
}
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);
/* 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,
+ "Invalid 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);
+ place_addcolumns(&lp->current, 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);
}
////////////////////////////////////////////////////////////
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();
}
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);
}
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();
}
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 },
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) &&
return;
}
skip = len + strspn(line+len, ws);
- p2.column += skip;
+ place_addcolumns(&p2, skip);
line += skip;
len = strlen(line);
if (len < strlen(line)) {
line[len] = '\0';
}
- directives[i].func(p, &p2, line);
+ directives[i].func(lp, &p2, line);
return;
}
}
}
skip = strcspn(line, ws);
- complain(p, "Unknown directive #%.*s", (int)skip, line);
+ complain(&lp->current, "Unknown directive #%.*s", (int)skip, line);
complain_fail();
}
*/
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] == '*') {
pos++;
}
if (line[pos] == '\n') {
- p2.line++;
+ place_addlines(&p2, 1);
p2.column = 0;
} else {
- p2.column++;
+ place_addcolumns(&p2, 1);
}
}
}
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;
+ place_addcolumns(&lp->current, 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 */);
+ place_addcolumns(&lp->current, len-skip);
} else if (ifstate->curtrue) {
- macro_sendline(p, line, len);
- p->column += len;
+ macro_sendline(&lp->current, line, len);
+ place_addcolumns(&lp->current, len);
}
}
#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);
complain_fail();
}
}
+ debuglog(p, "Undefined symbol %s; substituting 0", word);
return 0;
}
while (expr[pos] != '\0') {
len = strspn(expr+pos, ws);
pos += len;
- p->column += len;
+ place_addcolumns(p, len);
/* trailing whitespace is supposed to have been pruned */
assert(expr[pos] != '\0');
if (check_word(p, expr, pos, &len)) {
pos += len;
- p->column += len;
+ place_addcolumns(p, len);
continue;
}
if (check_tokens_2(p, expr, pos)) {
pos += 2;
- p->column += 2;
+ place_addcolumns(p, 2);
continue;
}
if (check_tokens_1(p, expr, pos)) {
pos++;
- p->column++;
+ place_addcolumns(p, 1);
continue;
}
complain(p, "Invalid character %u in #if-expression",
(unsigned char)expr[pos]);
complain_fail();
pos++;
- p->column++;
+ place_addcolumns(p, 1);
}
token(p, T_EOF, 0);
}
#ifdef DEBUG
fprintf(stderr, "eval: %s\n", expr);
#endif
+ debuglog(p, "eval: %s", expr);
tokenarray_init(&tokens);
tokenize(p, expr);
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <stdbool.h>
+#include "bool.h"
bool eval(struct place *p, char *expr);
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
+#include "bool.h"
#include "array.h"
#include "mode.h"
#include "place.h"
for (i=start; i<limit; i++) {
if (buf[i] == '\n') {
count++;
+ if (count == 0) {
+ /* just return the max and error downstream */
+ return count - 1;
+ }
}
}
return count;
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;
/* need bigger buffer */
buf = dorealloc(buf, bufmax, bufmax*2);
bufmax = bufmax*2;
+ /* just in case someone's screwing around */
+ if (bufmax > 0xffffffff) {
+ complain(&places.current,
+ "Input line too long");
+ die();
+ }
}
if (ateof) {
} else if (result == 0) {
/* eof in middle of line */
ateof = true;
- ptmp = linestartplace;
- ptmp.column += bufend - linestart;
- complain(&ptmp, "No newline at end of file");
+ ptmp = places.current;
+ place_addcolumns(&ptmp, bufend - linestart);
+ 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();
}
assert(buf[lineend] == '\n');
buf[lineend] = '\0';
nextlinestart = lineend+1;
- nextlinestartplace.line++;
+ place_addlines(&places.nextline, 1);
/* check for CR/NL */
if (lineend > 0 && buf[lineend-1] == '\r') {
assert(buf[lineend] == '\0');
/* count how many commented-out newlines we swallowed */
- nextlinestartplace.line += countnls(buf, linestart, lineend);
+ place_addlines(&places.nextline,
+ 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);
}
*/
#include <stdint.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include "union.h"
#include "array.h"
#include "mode.h"
#include "place.h"
#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;
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;
}
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;
}
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;
}
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));
}
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;
}
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;
}
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);
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
while (params != NULL) {
len = strspn(params, ws);
params += len;
- p->column += len;
+ place_addcolumns(p, len);
s = strchr(params, ',');
if (s) {
len = s-params;
stringarray_add(&m->params, param, NULL);
}
params = s;
- p->column += len;
+ place_addcolumns(p, len);
}
}
macro_define_common_end(m);
}
+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)
{
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
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;
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;
char *arg;
char *ret;
unsigned numargs, numparams;
+ char numbuf[64];
numargs = stringarray_num(&es->args);
numparams = stringarray_num(&es->curmacro->params);
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;
}
}
*ret = '\0';
for (i=0; i<num; i++) {
ei = expansionitemarray_get(&es->curmacro->expansion, i);
- if (ei->isstring) {
- strcat(ret, ei->string);
- } else {
- arg = stringarray_get(&es->args, ei->param);
+ switch (ei->itemtype) {
+ case EI_STRING:
+ strcat(ret, ei->ei_string);
+ break;
+ case EI_PARAM:
+ arg = stringarray_get(&es->args, ei->ei_param);
strcat(ret, arg);
+ break;
+ case EI_FILE:
+ strcat(ret, "\"");
+ strcat(ret, place_getname(p));
+ strcat(ret, "\"");
+ break;
+ case EI_LINE:
+ snprintf(numbuf, sizeof(numbuf), "%u", p->line);
+ strcat(ret, numbuf);
+ break;
}
}
expand_domacro(struct expstate *es, struct place *p)
{
struct macro *m;
+ const char *name, *val;
char *newbuf, *newbuf2;
if (es->curmacro == NULL) {
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;
}
/*
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);
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:
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;
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:
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:
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:
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:
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;
}
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;
}
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
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <stdbool.h>
#include <stddef.h>
+#include "bool.h"
struct place;
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 *);
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <stdbool.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
+#include "bool.h"
#include "version.h"
#include "config.h"
#include "utils.h"
.do_output = true,
.output_linenumbers = true,
+ .output_cheaplinenumbers = false,
.output_retain_comments = false,
.output_file = NULL,
if (val) {
p2 = *p;
- p2.column += strlen(str);
+ place_addcolumns(&p2, strlen(str));
} else {
place_setbuiltin(&p2, 1);
}
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);
array_setsize(&commandline_macros, 0);
}
+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)
{
unsigned n = 1;
+ apply_magic_macro(n++, "__FILE__");
+ apply_magic_macro(n++, "__LINE__");
+
#ifdef CONFIG_OS
apply_builtin_macro(n++, CONFIG_OS, "1");
#endif
{ "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);
{ "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 },
return false;
}
-DEAD static
+DEAD PF(2, 3) static
void
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");
commandline_files_cleanup();
commandline_macros_cleanup();
incpath_cleanup();
+ debuglog_close();
num = stringarray_num(&freestrings);
for (i=0; i<num; i++) {
init();
for (i=1; i<argc; i++) {
- if (argv[i][0] != '-') {
+ if (argv[i][0] != '-' || argv[i][1] == 0) {
break;
}
place_setcommandline(&cmdplace, i, 1);
}
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]);
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <stdbool.h>
+#include "bool.h"
struct mode {
bool werror;
bool do_stddef;
bool do_output;
bool output_linenumbers;
+ bool output_cheaplinenumbers;
bool output_retain_comments;
const char *output_file;
bool do_depend;
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
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);
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
#include "utils.h"
#include "array.h"
static const char *myprogname;
+static FILE *debuglogfile;
+
////////////////////////////////////////////////////////////
-// seenfiles
+// placefiles
static
struct placefile *
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)
{
p->column = 1;
}
-static
+void
+place_addcolumns(struct place *p, unsigned cols)
+{
+ unsigned newcol;
+
+ newcol = p->column + cols;
+ if (newcol < p->column) {
+ /* overflow (use the old place to complain) */
+ complain(p, "Column numbering overflow");
+ die();
+ }
+ p->column = newcol;
+}
+
+void
+place_addlines(struct place *p, unsigned lines)
+{
+ unsigned nextline;
+
+ nextline = p->line + lines;
+ if (nextline < p->line) {
+ /* overflow (use the old place to complain) */
+ complain(p, "Line numbering overflow");
+ die();
+ }
+ p->line = nextline;
+}
+
const char *
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)
return overall_failure;
}
+////////////////////////////////////////////////////////////
+// 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
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <stdbool.h>
+#ifndef PLACE_H
+#define PLACE_H
+
+#include "bool.h"
enum places {
P_NOWHERE,
void place_setcommandline(struct place *p, unsigned word, unsigned column);
void place_setfilestart(struct place *p, const struct placefile *pf);
+void place_addcolumns(struct place *, unsigned cols);
+void place_addlines(struct place *, unsigned lines);
+
+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 */
--- /dev/null
+#define m() __FILE__:__LINE__
+__LINE__
+__FILE__
+__LINE__
+m()
+#line 500
+m()
+#line 600 "foo.c"
+m()
+#include "subdir/test.h"
+m()
--- /dev/null
+2
+"t38.c"
+4
+"t38.c":5
+"t38.c":500
+"foo.c":600
+hello
+"foo.c":602
--- /dev/null
+#define m(a,b) a::b
+=m(123,
+456)
+ ------
+=m
+(123, 456)
+ ------
+=m(
+123, 456)
+ ------
+=m(
+123,
+456
+)
+ ------
+=m(123,
+
+456)
+ ------
+=m(123,
+ 456)
--- /dev/null
+=123:: 456
+ ------
+=123:: 456
+ ------
+= 123:: 456
+ ------
+= 123:: 456
+ ------
+=123:: 456
+ ------
+=123:: 456
--- /dev/null
+#define foo bar
+
+#define bar(x) do x do
+
+foo(de)
+
Currently line number information is not generated at all and this
option has no effect.
.It Fl Umacro
-Remove any existing defintion for the named macro.
+Remove any existing definition for the named macro.
Note that like many Unix compilers,
.Nm
does not accept a space between the
.Fl idirafter .
.It Fl iwithprefixbefore
Like
--Fl iwithprefix
+.Fl iwithprefix
but adds the result as if it were specified with
.Fl I .
.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
+.Xr imake 1 .
.It Fl dD
Dump all macro definitions, except for the predefined macros, after
the normal preprocessing output.
--- /dev/null
+/*-
+ * 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
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <stdbool.h>
#include <stddef.h>
+#include "bool.h"
struct place;
/* 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);
*/
#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.3"
+#define VERSION_LONG "NetBSD tradcpp 0.5.3"