diff --git a/cde/util/tradcpp/CHANGES b/cde/util/tradcpp/CHANGES index 1eaaf5f31..3c92d446a 100644 --- a/cde/util/tradcpp/CHANGES +++ b/cde/util/tradcpp/CHANGES @@ -1,3 +1,53 @@ +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 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 diff --git a/cde/util/tradcpp/Makefile.am b/cde/util/tradcpp/Makefile.am index 9b1f4cf99..1a1c86dca 100644 --- a/cde/util/tradcpp/Makefile.am +++ b/cde/util/tradcpp/Makefile.am @@ -2,25 +2,9 @@ MAINTAINERCLEANFILES = Makefile.in 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 + diff --git a/cde/util/tradcpp/TODO b/cde/util/tradcpp/TODO index cb306a14f..85395857f 100644 --- a/cde/util/tradcpp/TODO +++ b/cde/util/tradcpp/TODO @@ -8,7 +8,6 @@ not implemented: - warns.endiflabels. (they cause errors) - warns.unused. - the -iremap option. - - #line directives. - $CPP_RESTRICTED - other environment variables @@ -16,11 +15,12 @@ tidy up: - 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) @@ -31,3 +31,7 @@ fix: 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.) diff --git a/cde/util/tradcpp/array.h b/cde/util/tradcpp/array.h index 8d1b98b32..2fa474183 100644 --- a/cde/util/tradcpp/array.h +++ b/cde/util/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/cde/util/tradcpp/bool.h b/cde/util/tradcpp/bool.h new file mode 100644 index 000000000..cf86ffb2c --- /dev/null +++ b/cde/util/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 +#else +typedef int bool; +#define true 1 +#define false 0 +#endif + +#endif /* BOOL_H */ diff --git a/cde/util/tradcpp/config.h b/cde/util/tradcpp/config.h index c8ad5f1fa..c42dcc5ac 100644 --- a/cde/util/tradcpp/config.h +++ b/cde/util/tradcpp/config.h @@ -124,6 +124,22 @@ #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 diff --git a/cde/util/tradcpp/directive.c b/cde/util/tradcpp/directive.c index 5c81de240..308b5ace6 100644 --- a/cde/util/tradcpp/directive.c +++ b/cde/util/tradcpp/directive.c @@ -28,10 +28,12 @@ */ #include -#include #include #include +#include +#include +#include "bool.h" #include "utils.h" #include "mode.h" #include "place.h" @@ -112,7 +114,7 @@ oneword(const char *what, struct place *p2, char *line) 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'; @@ -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: @@ -301,13 +348,13 @@ d_define(struct place *p, struct place *p2, char *line) 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; @@ -331,28 +378,31 @@ d_define(struct place *p, struct place *p2, char *line) 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); } @@ -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,79 @@ 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; - /* XXX */ - complain(p, "Sorry, no #line yet"); + 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. + */ + + 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); } //////////////////////////////////////////////////////////// @@ -426,12 +533,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 +547,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 +562,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 +576,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 +596,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; icurrent, "Unknown directive #%.*s", (int)skip, line); complain_fail(); } @@ -532,13 +639,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] == '*') { @@ -561,10 +668,10 @@ directive_scancomments(const struct place *p, char *line, size_t len) pos++; } if (line[pos] == '\n') { - p2.line++; + place_addlines(&p2, 1); p2.column = 0; } else { - p2.column++; + place_addcolumns(&p2, 1); } } @@ -574,25 +681,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; + 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); } } diff --git a/cde/util/tradcpp/directive.h b/cde/util/tradcpp/directive.h index d4d5676e9..7491a7a0f 100644 --- a/cde/util/tradcpp/directive.h +++ b/cde/util/tradcpp/directive.h @@ -29,11 +29,21 @@ #include -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/cde/util/tradcpp/eval.c b/cde/util/tradcpp/eval.c index cb5db9913..6a6bcad81 100644 --- a/cde/util/tradcpp/eval.c +++ b/cde/util/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; } @@ -707,29 +708,29 @@ tokenize(struct place *p, char *expr) 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); } @@ -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/cde/util/tradcpp/eval.h b/cde/util/tradcpp/eval.h index 0694fb4f9..d9193de0f 100644 --- a/cde/util/tradcpp/eval.h +++ b/cde/util/tradcpp/eval.h @@ -27,6 +27,6 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include +#include "bool.h" bool eval(struct place *p, char *expr); diff --git a/cde/util/tradcpp/files.c b/cde/util/tradcpp/files.c index f0ee45eee..52e2866bc 100644 --- a/cde/util/tradcpp/files.c +++ b/cde/util/tradcpp/files.c @@ -27,7 +27,6 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include #include #include #include @@ -35,6 +34,7 @@ #include #include +#include "bool.h" #include "array.h" #include "mode.h" #include "place.h" @@ -163,6 +163,10 @@ countnls(const char *buf, size_t start, size_t limit) for (i=start; i 0xffffffff) { + complain(&places.current, + "Input line too long"); + die(); + } } if (ateof) { @@ -223,9 +240,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.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(); } @@ -244,7 +267,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++; + place_addlines(&places.nextline, 1); /* check for CR/NL */ if (lineend > 0 && buf[lineend-1] == '\r') { @@ -271,21 +294,19 @@ 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); + 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); } diff --git a/cde/util/tradcpp/macro.c b/cde/util/tradcpp/macro.c index 210598013..e1bdce3d7 100644 --- a/cde/util/tradcpp/macro.c +++ b/cde/util/tradcpp/macro.c @@ -28,9 +28,11 @@ */ #include +#include #include #include +#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 @@ -481,7 +523,7 @@ macro_parse_parameters(struct macro *m, struct place *p, const char *params) while (params != NULL) { len = strspn(params, ws); params += len; - p->column += len; + place_addcolumns(p, len); s = strchr(params, ','); if (s) { len = s-params; @@ -499,7 +541,7 @@ macro_parse_parameters(struct macro *m, struct place *p, const char *params) stringarray_add(&m->params, param, NULL); } params = s; - p->column += len; + place_addcolumns(p, len); } } @@ -586,6 +628,24 @@ macro_define_params(struct place *p1, const char *macro, 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) { @@ -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; icurmacro->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; icurmacro->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; } } @@ -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/cde/util/tradcpp/macro.h b/cde/util/tradcpp/macro.h index 98671e63b..76938a395 100644 --- a/cde/util/tradcpp/macro.h +++ b/cde/util/tradcpp/macro.h @@ -27,8 +27,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include #include +#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/cde/util/tradcpp/main.c b/cde/util/tradcpp/main.c index 35f9bca13..7c8f26566 100644 --- a/cde/util/tradcpp/main.c +++ b/cde/util/tradcpp/main.c @@ -27,13 +27,13 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include #include #include #include #include #include +#include "bool.h" #include "version.h" #include "config.h" #include "utils.h" @@ -55,6 +55,7 @@ struct mode mode = { .do_output = true, .output_linenumbers = true, + .output_cheaplinenumbers = false, .output_retain_comments = false, .output_file = NULL, @@ -154,7 +155,7 @@ commandline_def(const struct place *p, char *str) if (val) { p2 = *p; - p2.column += strlen(str); + place_addcolumns(&p2, strlen(str)); } else { place_setbuiltin(&p2, 1); } @@ -166,7 +167,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); @@ -193,6 +194,16 @@ apply_commandline_macros(void) 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) @@ -209,6 +220,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 @@ -781,6 +795,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); @@ -814,6 +829,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 }, @@ -934,7 +950,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, ...) { @@ -946,7 +962,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"); @@ -999,6 +1015,7 @@ cleanup(void) commandline_files_cleanup(); commandline_macros_cleanup(); incpath_cleanup(); + debuglog_close(); num = stringarray_num(&freestrings); for (i=0; i +#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/cde/util/tradcpp/output.c b/cde/util/tradcpp/output.c index d1d1f2d4d..d706a3180 100644 --- a/cde/util/tradcpp/output.c +++ b/cde/util/tradcpp/output.c @@ -27,6 +27,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include #include @@ -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/cde/util/tradcpp/place.c b/cde/util/tradcpp/place.c index 267104875..a2e1e0263 100644 --- a/cde/util/tradcpp/place.c +++ b/cde/util/tradcpp/place.c @@ -32,6 +32,7 @@ #include #include #include +#include #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; iincludedfrom) && + !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,34 @@ place_setfilestart(struct place *p, const struct placefile *pf) 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) { @@ -168,6 +234,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) @@ -224,6 +314,70 @@ complain_failed(void) 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 diff --git a/cde/util/tradcpp/place.h b/cde/util/tradcpp/place.h index 311645be1..7dab03755 100644 --- a/cde/util/tradcpp/place.h +++ b/cde/util/tradcpp/place.h @@ -27,7 +27,10 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include +#ifndef PLACE_H +#define PLACE_H + +#include "bool.h" enum places { P_NOWHERE, @@ -50,7 +53,17 @@ 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); +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 */ diff --git a/cde/util/tradcpp/tests/t38.c b/cde/util/tradcpp/tests/t38.c new file mode 100644 index 000000000..ef4503835 --- /dev/null +++ b/cde/util/tradcpp/tests/t38.c @@ -0,0 +1,11 @@ +#define m() __FILE__:__LINE__ +__LINE__ +__FILE__ +__LINE__ +m() +#line 500 +m() +#line 600 "foo.c" +m() +#include "subdir/test.h" +m() diff --git a/cde/util/tradcpp/tests/t38.good b/cde/util/tradcpp/tests/t38.good new file mode 100644 index 000000000..1783caab6 --- /dev/null +++ b/cde/util/tradcpp/tests/t38.good @@ -0,0 +1,8 @@ +2 +"t38.c" +4 +"t38.c":5 +"t38.c":500 +"foo.c":600 +hello +"foo.c":602 diff --git a/cde/util/tradcpp/tests/t39.c b/cde/util/tradcpp/tests/t39.c new file mode 100644 index 000000000..a8dd204af --- /dev/null +++ b/cde/util/tradcpp/tests/t39.c @@ -0,0 +1,21 @@ +#define m(a,b) a::b +=m(123, +456) + ------ +=m +(123, 456) + ------ +=m( +123, 456) + ------ +=m( +123, +456 +) + ------ +=m(123, + +456) + ------ +=m(123, + 456) diff --git a/cde/util/tradcpp/tests/t39.good b/cde/util/tradcpp/tests/t39.good new file mode 100644 index 000000000..a4561fcf5 --- /dev/null +++ b/cde/util/tradcpp/tests/t39.good @@ -0,0 +1,11 @@ +=123:: 456 + ------ +=123:: 456 + ------ += 123:: 456 + ------ += 123:: 456 + ------ +=123:: 456 + ------ +=123:: 456 diff --git a/cde/util/tradcpp/tests/t40.c b/cde/util/tradcpp/tests/t40.c new file mode 100644 index 000000000..9e485bcb3 --- /dev/null +++ b/cde/util/tradcpp/tests/t40.c @@ -0,0 +1,6 @@ +#define foo bar + +#define bar(x) do x do + +foo(de) + diff --git a/cde/util/tradcpp/tests/t40.good b/cde/util/tradcpp/tests/t40.good new file mode 100644 index 000000000..e98d592e5 --- /dev/null +++ b/cde/util/tradcpp/tests/t40.good @@ -0,0 +1 @@ +do de do diff --git a/cde/util/tradcpp/tradcpp.1 b/cde/util/tradcpp/tradcpp.1 index 952d8b723..97e4eddfa 100644 --- a/cde/util/tradcpp/tradcpp.1 +++ b/cde/util/tradcpp/tradcpp.1 @@ -96,7 +96,7 @@ Suppress line number information in the output. 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 @@ -254,12 +254,20 @@ and add this directory as if it were specified with .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. diff --git a/cde/util/tradcpp/union.h b/cde/util/tradcpp/union.h new file mode 100644 index 000000000..74113a5a8 --- /dev/null +++ b/cde/util/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/cde/util/tradcpp/utils.h b/cde/util/tradcpp/utils.h index e6f1ae728..06d5f024d 100644 --- a/cde/util/tradcpp/utils.h +++ b/cde/util/tradcpp/utils.h @@ -27,8 +27,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include #include +#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/cde/util/tradcpp/version.h b/cde/util/tradcpp/version.h index b278c662d..bb77fd56e 100644 --- a/cde/util/tradcpp/version.h +++ b/cde/util/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.3" +#define VERSION_LONG "NetBSD tradcpp 0.5.3"