tradcpp: upgrade to 0.5.3
authorJon Trulson <jon@radscan.com>
Wed, 4 Dec 2019 01:12:22 +0000 (18:12 -0700)
committerJon Trulson <jon@radscan.com>
Wed, 4 Dec 2019 01:13:27 +0000 (18:13 -0700)
28 files changed:
cde/util/tradcpp/CHANGES
cde/util/tradcpp/Makefile.am
cde/util/tradcpp/TODO
cde/util/tradcpp/array.h
cde/util/tradcpp/bool.h [new file with mode: 0644]
cde/util/tradcpp/config.h
cde/util/tradcpp/directive.c
cde/util/tradcpp/directive.h
cde/util/tradcpp/eval.c
cde/util/tradcpp/eval.h
cde/util/tradcpp/files.c
cde/util/tradcpp/macro.c
cde/util/tradcpp/macro.h
cde/util/tradcpp/main.c
cde/util/tradcpp/mode.h
cde/util/tradcpp/output.c
cde/util/tradcpp/place.c
cde/util/tradcpp/place.h
cde/util/tradcpp/tests/t38.c [new file with mode: 0644]
cde/util/tradcpp/tests/t38.good [new file with mode: 0644]
cde/util/tradcpp/tests/t39.c [new file with mode: 0644]
cde/util/tradcpp/tests/t39.good [new file with mode: 0644]
cde/util/tradcpp/tests/t40.c [new file with mode: 0644]
cde/util/tradcpp/tests/t40.good [new file with mode: 0644]
cde/util/tradcpp/tradcpp.1
cde/util/tradcpp/union.h [new file with mode: 0644]
cde/util/tradcpp/utils.h
cde/util/tradcpp/version.h

index 1eaaf5f315757b40158e497924dd0aaa9fd075a5..3c92d446aee0f878f407fc7acbf63632523e90ca 100644 (file)
@@ -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 <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
index 9b1f4cf99b4e67b8b80a67d81b946f2046d68377..1a1c86dca835ebc05a3421a9c33ca59749b051b2 100644 (file)
@@ -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
+
 
index cb306a14f9b0296da9038620cdd14784e4c71e1c..85395857fff4cf672bbb549943aef13b0a67fda9 100644 (file)
@@ -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.)
index 8d1b98b3273f6ceab6f13d9c46e5f39b5d36db28..2fa474183e3661c3a1cfeff9096a1b92866c7a40 100644 (file)
@@ -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 (file)
index 0000000..cf86ffb
--- /dev/null
@@ -0,0 +1,41 @@
+/*-
+ * Copyright (c) 2015 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by David A. Holland.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BOOL_H
+#define BOOL_H
+
+#if __STDC__ > 199901
+#include <stdbool.h>
+#else
+typedef int bool;
+#define true 1
+#define false 0
+#endif
+
+#endif /* BOOL_H */
index c8ad5f1fa80cc4e33b6c4c113accb3029e995d6b..c42dcc5ac5d0b5b6709d3c2182c0cdac35acc1b4 100644 (file)
 #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
index 5c81de24008b0c997c04fc1fa4a592481fe1372f..308b5ace6e8f828ca6735f27617479762cd2d280 100644 (file)
  */
 
 #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"
@@ -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;
+
+       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);
 }
 
 ////////////////////////////////////////////////////////////
@@ -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; i<numdirectives; i++) {
                len = strlen(directives[i].name);
                if (!strncmp(line, directives[i].name, len) &&
@@ -504,7 +611,7 @@ directive_gotdirective(struct place *p, char *line)
                                return;
                        }
                        skip = len + strspn(line+len, ws);
-                       p2.column += skip;
+                       place_addcolumns(&p2, skip);
                        line += skip;
 
                        len = strlen(line);
@@ -512,7 +619,7 @@ directive_gotdirective(struct place *p, char *line)
                        if (len < strlen(line)) {
                                line[len] = '\0';
                        }
-                       directives[i].func(p, &p2, line);
+                       directives[i].func(lp, &p2, line);
                        return;
                }
        }
@@ -523,7 +630,7 @@ directive_gotdirective(struct place *p, char *line)
        }
 
        skip = strcspn(line, ws);
-       complain(p, "Unknown directive #%.*s", (int)skip, line);
+       complain(&lp->current, "Unknown directive #%.*s", (int)skip, line);
        complain_fail();
 }
 
@@ -532,13 +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);
        }
 }
 
index d4d5676e95f5b8d58a706ca02ee19fa91b54abbc..7491a7a0fc5f0c862320feeb4e05798f9eea41c4 100644 (file)
 
 #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);
 
index cb5db9913646753aee5f92b3c3a1ba300b550ea9..6a6bcad81935320667813ce0dbf0bb2cda7ca766 100644 (file)
@@ -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);
index 0694fb4f9f77adb0f64f8fb45ff5f92aef3becc6..d9193de0f06fe266aee9f97499c05f7b165a7292 100644 (file)
@@ -27,6 +27,6 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <stdbool.h>
+#include "bool.h"
 
 bool eval(struct place *p, char *expr);
index f0ee45eee55651a590919aaf4c7ca94c4b957bda..52e2866bc9bb142e84c114435778d25fc798d1f5 100644 (file)
@@ -27,7 +27,6 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -35,6 +34,7 @@
 #include <fcntl.h>
 #include <errno.h>
 
+#include "bool.h"
 #include "array.h"
 #include "mode.h"
 #include "place.h"
@@ -163,6 +163,10 @@ countnls(const char *buf, size_t start, size_t limit)
        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;
@@ -172,14 +176,21 @@ static
 void
 file_read(const struct placefile *pf, int fd, const char *name, bool toplevel)
 {
-       struct place linestartplace, nextlinestartplace, ptmp;
+       struct lineplace places;
+       struct place ptmp;
        size_t bufend, bufmax, linestart, lineend, nextlinestart, tmp;
        ssize_t result;
        bool ateof = false;
        char *buf;
 
-       place_setfilestart(&linestartplace, pf);
-       nextlinestartplace = linestartplace;
+       place_setfilestart(&places.current, pf);
+       places.nextline = places.current;
+
+       if (name) {
+               debuglog(&places.current, "Reading file %s", name);
+       } else {
+               debuglog(&places.current, "Reading standard input");
+       }
 
        bufmax = 128;
        bufend = 0;
@@ -202,6 +213,12 @@ file_read(const struct placefile *pf, int fd, const char *name, bool toplevel)
                                /* 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) {
@@ -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);
 }
index 210598013338edcb5e0fbd9e4774c5a38a17d95d..e1bdce3d771827439f067a0cd6993101c471317c 100644 (file)
  */
 
 #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;
@@ -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; i<num; i++) {
                ei = expansionitemarray_get(&es->curmacro->expansion, i);
-               if (ei->isstring) {
-                       len += strlen(ei->string);
-               } else {
-                       arg = stringarray_get(&es->args, ei->param);
+               switch (ei->itemtype) {
+                   case EI_STRING:
+                       len += strlen(ei->ei_string);
+                       break;
+                   case EI_PARAM:
+                       arg = stringarray_get(&es->args, ei->ei_param);
                        len += strlen(arg);
+                       break;
+                   case EI_FILE:
+                       len += strlen(place_getname(p)) + 2;
+                       break;
+                   case EI_LINE:
+                       len += snprintf(numbuf, sizeof(numbuf), "%u", p->line);
+                       break;
                }
        }
 
@@ -778,11 +848,23 @@ expand_substitute(struct place *p, struct expstate *es)
        *ret = '\0';
        for (i=0; i<num; i++) {
                ei = expansionitemarray_get(&es->curmacro->expansion, i);
-               if (ei->isstring) {
-                       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
index 98671e63bc90316f9128fb8a403e60e4352d2e65..76938a395486bd76a9bfbbdbc8ecf99aae88ae0a 100644 (file)
@@ -27,8 +27,8 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <stdbool.h>
 #include <stddef.h>
+#include "bool.h"
 
 struct place;
 
@@ -40,10 +40,12 @@ void macro_define_plain(struct place *, const char *macro,
 void macro_define_params(struct place *, const char *macro,
                         struct place *, const char *params,
                         struct place *, const char *expansion);
+void macro_define_magic(struct place *, const char *macro);
 void macro_undef(const char *macro);
 bool macro_isdefined(const char *macro);
 
-char *macroexpand(struct place *, char *buf, size_t len, bool honordefined);
+char *macroexpand(struct place *, const char *buf, size_t len,
+                 bool honordefined);
 
-void macro_sendline(struct place *, char *buf, size_t len);
+void macro_sendline(struct place *, const char *buf, size_t len);
 void macro_sendeof(struct place *);
index 35f9bca1326e0524fd2bc0773c8f77df53cf0754..7c8f26566657989477df759dfc3a60256f17d074 100644 (file)
  * 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"
@@ -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<num; i++) {
@@ -1040,7 +1057,7 @@ main(int argc, char *argv[])
        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);
@@ -1065,9 +1082,15 @@ main(int argc, char *argv[])
        }
        if (i < argc) {
                inputfile = argv[i++];
+               if (!strcmp(inputfile, "-")) {
+                       inputfile = NULL;
+               }
        }
        if (i < argc) {
                outputfile = argv[i++];
+               if (!strcmp(outputfile, "-")) {
+                       outputfile = NULL;
+               }
        }
        if (i < argc) {
                usage(progname, "Extra non-option argument %s", argv[i]);
index 60f1636ff5840cfdf4b55d34b5ce7d938da14eb0..1b90e546f7327298fdb16f4fc9afd05aafab2394 100644 (file)
@@ -27,7 +27,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <stdbool.h>
+#include "bool.h"
 
 struct mode {
        bool werror;
@@ -37,6 +37,7 @@ struct mode {
        bool do_stddef;
        bool do_output;
        bool output_linenumbers;
+       bool output_cheaplinenumbers;
        bool output_retain_comments;
        const char *output_file;
        bool do_depend;
index d1d1f2d4d9468248a65436206ba398279eccaeae..d706a3180f6d38631aa2f0407b86a039ac6bc0f8 100644 (file)
@@ -27,6 +27,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <stdio.h>
 #include <string.h>
 #include <unistd.h>
 #include <fcntl.h>
@@ -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);
index 267104875c5434559f16cbe9f80265699876c1e3..a2e1e02637b391b03edd6025b644738e2f864ae4 100644 (file)
@@ -32,6 +32,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <errno.h>
 
 #include "utils.h"
 #include "array.h"
@@ -52,8 +53,10 @@ static bool overall_failure;
 
 static const char *myprogname;
 
+static FILE *debuglogfile;
+
 ////////////////////////////////////////////////////////////
-// seenfiles
+// placefiles
 
 static
 struct placefile *
@@ -101,6 +104,42 @@ place_getparsedir(const struct place *place)
        return place->file->dir;
 }
 
+static
+struct placefile *
+placefile_find(const struct place *incfrom, const char *name)
+{
+       unsigned i, num;
+       struct placefile *pf;
+
+       num = placefilearray_num(&placefiles);
+       for (i=0; i<num; i++) {
+               pf = placefilearray_get(&placefiles, i);
+               if (place_eq(incfrom, &pf->includedfrom) &&
+                   !strcmp(name, pf->name)) {
+                       return pf;
+               }
+       }
+       return NULL;
+}
+
+void
+place_changefile(struct place *p, const char *name)
+{
+       struct placefile *pf;
+
+       assert(p->type == P_FILE);
+       if (!strcmp(name, p->file->name)) {
+               return;
+       }
+       pf = placefile_find(&p->file->includedfrom, name);
+       if (pf == NULL) {
+               pf = placefile_create(&p->file->includedfrom, name,
+                                     p->file->fromsystemdir);
+               placefilearray_add(&placefiles, pf, NULL);
+       }
+       p->file = pf;
+}
+
 const struct placefile *
 place_addfile(const struct place *place, const char *file, bool issystem)
 {
@@ -154,7 +193,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
 
index 311645be145e15d1ba68f56a3679433741cabba9..7dab03755832796bbc5d560ce89a08fd42ae6b95 100644 (file)
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <stdbool.h>
+#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 (file)
index 0000000..ef45038
--- /dev/null
@@ -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 (file)
index 0000000..1783caa
--- /dev/null
@@ -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 (file)
index 0000000..a8dd204
--- /dev/null
@@ -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 (file)
index 0000000..a4561fc
--- /dev/null
@@ -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 (file)
index 0000000..9e485bc
--- /dev/null
@@ -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 (file)
index 0000000..e98d592
--- /dev/null
@@ -0,0 +1 @@
+do de do
index 952d8b7232caa67ddfcb99f0e0d9e28481eda2f3..97e4eddfa2033b7e73d1e4cbe399873bd4fd2c5d 100644 (file)
@@ -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 (file)
index 0000000..74113a5
--- /dev/null
@@ -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
index e6f1ae7286fbc3542fac3844f0d6caaf5d246bbd..06d5f024d2c61cbf54a641b36d7c4f72a80a0836 100644 (file)
@@ -27,8 +27,8 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <stdbool.h>
 #include <stddef.h>
+#include "bool.h"
 
 struct place;
 
@@ -63,10 +63,16 @@ bool is_identifier(const char *str);
 
 /* in place.c */
 void complain_init(const char *progname);
-void complain(const struct place *, const char *fmt, ...) PF(2, 3);
+PF(2, 3) void complain(const struct place *, const char *fmt, ...);
 void complain_fail(void);
 bool complain_failed(void);
 
+void debuglog_open(const struct place *p, /*const*/ char *file);
+void debuglog_close(void);
+PF(2, 3) void debuglog(const struct place *p, const char *fmt, ...);
+PF(3, 4) void debuglog2(const struct place *p, const struct place *p2,
+                       const char *fmt, ...);
+
 /* in main.c */
 void freestringlater(char *s);
 DEAD void die(void);
index b278c662d118f109c528e6664727afdc68536d54..bb77fd56eb6ebba60ce5e3228a1bd0d7ba23b29e 100644 (file)
@@ -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"