1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00

tradcpp: upgrade to 0.5.3

This commit is contained in:
Jon Trulson 2019-12-03 18:12:22 -07:00
parent 15dfdf231a
commit ec8f4b7464
28 changed files with 843 additions and 186 deletions

View 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) release 0.4 (20130713)
- Fix stupid build problem introduced in 0.3.1. - Fix stupid build problem introduced in 0.3.1.
- Accept and ignore -m32, which imake issues willy-nilly on a bunch - Accept and ignore -m32, which imake issues willy-nilly on a bunch

View file

@ -2,25 +2,9 @@ MAINTAINERCLEANFILES = Makefile.in
bin_PROGRAMS = tradcpp bin_PROGRAMS = tradcpp
tradcpp_SOURCES = array.c \ tradcpp_SOURCES = array.c directive.c files.c macro.h output.h \
array.h \ utils.c array.h directive.h files.h main.c place.c utils.h \
config.h \ bool.h eval.c inlinedefs.h mode.h place.h version.h config.h \
directive.c \ eval.h macro.c output.c union.h
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

View file

@ -8,7 +8,6 @@ not implemented:
- warns.endiflabels. (they cause errors) - warns.endiflabels. (they cause errors)
- warns.unused. - warns.unused.
- the -iremap option. - the -iremap option.
- #line directives.
- $CPP_RESTRICTED - $CPP_RESTRICTED
- other environment variables - other environment variables
@ -16,11 +15,12 @@ tidy up:
- get rid of inlinedefs.h - get rid of inlinedefs.h
- use of places in and below macro.c is pretty bogus. - use of places in and below macro.c is pretty bogus.
- macro code should be reworked. - 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: fix:
- "#if 0 && 1/0" should not crash; fix eval method. - "#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 - quote characters and comment delimiters that are emitted by
macros are not recognized. See: macros are not recognized. See:
t34 (should produce a quote and FOO Q) 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 twice, once when the macro is defined and again when it's
expanded. Note that gcc's cpp -traditional is getting t37 expanded. Note that gcc's cpp -traditional is getting t37
wrong, and it gets t36 wrong with -C. 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.)

View 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 DEFARRAY(T, INLINE) DEFARRAY_BYTYPE(T##array, struct T, INLINE)
#define DESTROYALL_ARRAY(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 \ INLINE void \
T##array_destroyall(struct T##array *arr) \ T##array_destroyall(struct T##array *arr) \

41
cde/util/tradcpp/bool.h Normal file
View file

@ -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 */

View file

@ -124,6 +124,22 @@
#define CONFIG_CPU "__ppc64__" #define CONFIG_CPU "__ppc64__"
#elif defined(__ARM__) #elif defined(__ARM__)
#define CONFIG_CPU "__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 #else
/* let it go */ /* let it go */
#endif #endif

View file

@ -28,10 +28,12 @@
*/ */
#include <assert.h> #include <assert.h>
#include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <limits.h>
#include <errno.h>
#include "bool.h"
#include "utils.h" #include "utils.h"
#include "mode.h" #include "mode.h"
#include "place.h" #include "place.h"
@ -112,7 +114,7 @@ oneword(const char *what, struct place *p2, char *line)
pos = strcspn(line, ws); pos = strcspn(line, ws);
if (line[pos] != '\0') { if (line[pos] != '\0') {
p2->column += pos; place_addcolumns(p2, pos);
complain(p2, "Garbage after %s argument", what); complain(p2, "Garbage after %s argument", what);
complain_fail(); complain_fail();
line[pos] = '\0'; line[pos] = '\0';
@ -175,13 +177,16 @@ ifstate_pop(void)
static static
void 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; char *expr;
bool val; bool val;
struct place p3 = *p2; struct place p3 = *p2;
size_t oldlen; size_t oldlen;
doprint = ifstate->curtrue;
expr = macroexpand(p2, line, strlen(line), true); expr = macroexpand(p2, line, strlen(line), true);
oldlen = strlen(expr); oldlen = strlen(expr);
@ -194,41 +199,67 @@ d_if(struct place *p, struct place *p2, char *line)
} else { } else {
val = 0; val = 0;
} }
ifstate_push(p, val); ifstate_push(&lp->current, val);
dostrfree(expr); dostrfree(expr);
if (doprint) {
debuglog(&lp->current, "#if: %s",
ifstate->curtrue ? "taken" : "not taken");
}
} }
static static
void 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); uncomment(line);
oneword("#ifdef", p2, 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 static
void 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); uncomment(line);
oneword("#ifndef", p2, 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 static
void 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; char *expr;
struct place p3 = *p2; struct place p3 = *p2;
size_t oldlen; size_t oldlen;
if (ifstate->seenelse) { if (ifstate->seenelse) {
complain(p, "#elif after #else"); complain(&lp->current, "#elif after #else");
complain_fail(); complain_fail();
} }
doprint = ifstate->curtrue;
if (ifstate->evertrue) { if (ifstate->evertrue) {
ifstate->curtrue = false; ifstate->curtrue = false;
} else { } else {
@ -243,36 +274,52 @@ d_elif(struct place *p, struct place *p2, char *line)
ifstate->evertrue = ifstate->curtrue; ifstate->evertrue = ifstate->curtrue;
dostrfree(expr); dostrfree(expr);
} }
if (doprint) {
debuglog2(&lp->current, &ifstate->startplace, "#elif: %s",
ifstate->curtrue ? "taken" : "not taken");
}
} }
static static
void 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)p2;
(void)line; (void)line;
if (ifstate->seenelse) { if (ifstate->seenelse) {
complain(p, "Multiple #else directives in one conditional"); complain(&lp->current,
"Multiple #else directives in one conditional");
complain_fail(); complain_fail();
} }
doprint = ifstate->curtrue;
ifstate->curtrue = !ifstate->evertrue; ifstate->curtrue = !ifstate->evertrue;
ifstate->evertrue = true; ifstate->evertrue = true;
ifstate->seenelse = true; ifstate->seenelse = true;
if (doprint) {
debuglog2(&lp->current, &ifstate->startplace, "#else: %s",
ifstate->curtrue ? "taken" : "not taken");
}
} }
static static
void void
d_endif(struct place *p, struct place *p2, char *line) d_endif(struct lineplace *lp, struct place *p2, char *line)
{ {
(void)p2; (void)p2;
(void)line; (void)line;
if (ifstate->prev == NULL) { if (ifstate->prev == NULL) {
complain(p, "Unmatched #endif"); complain(&lp->current, "Unmatched #endif");
complain_fail(); complain_fail();
} else { } else {
debuglog2(&lp->current, &ifstate->startplace, "#endif");
ifstate_pop(); ifstate_pop();
} }
} }
@ -282,12 +329,12 @@ d_endif(struct place *p, struct place *p2, char *line)
static static
void 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; size_t pos, argpos;
struct place p3, p4; struct place p3, p4;
(void)p; (void)lp;
/* /*
* line may be: * line may be:
@ -301,13 +348,13 @@ d_define(struct place *p, struct place *p2, char *line)
argpos = pos; argpos = pos;
pos = pos + strcspn(line+pos, "()"); pos = pos + strcspn(line+pos, "()");
if (line[pos] == '(') { if (line[pos] == '(') {
p2->column += pos; place_addcolumns(p2, pos);
complain(p2, "Left parenthesis in macro parameters"); complain(p2, "Left parenthesis in macro parameters");
complain_fail(); complain_fail();
return; return;
} }
if (line[pos] != ')') { if (line[pos] != ')') {
p2->column += pos; place_addcolumns(p2, pos);
complain(p2, "Unclosed macro parameter list"); complain(p2, "Unclosed macro parameter list");
complain_fail(); complain_fail();
return; return;
@ -331,28 +378,31 @@ d_define(struct place *p, struct place *p2, char *line)
pos += strspn(line+pos, ws); pos += strspn(line+pos, ws);
p3 = *p2; p3 = *p2;
p3.column += argpos; place_addcolumns(&p3, argpos);
p4 = *p2; p4 = *p2;
p4.column += pos; place_addcolumns(&p4, pos);
if (argpos) { if (argpos) {
debuglog(&lp->current, "Defining %s()", line);
macro_define_params(p2, line, &p3, macro_define_params(p2, line, &p3,
line + argpos, &p4, line + argpos, &p4,
line + pos); line + pos);
} else { } else {
debuglog(&lp->current, "Defining %s", line);
macro_define_plain(p2, line, &p4, line + pos); macro_define_plain(p2, line, &p4, line + pos);
} }
} }
static static
void 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); uncomment(line);
oneword("#undef", p2, line); oneword("#undef", p2, line);
debuglog(&lp->current, "Undef %s", line);
macro_undef(line); macro_undef(line);
} }
@ -368,13 +418,17 @@ tryinclude(struct place *p, char *line)
len = strlen(line); len = strlen(line);
if (len > 2 && line[0] == '"' && line[len-1] == '"') { if (len > 2 && line[0] == '"' && line[len-1] == '"') {
line[len-1] = '\0'; line[len-1] = '\0';
debuglog(p, "Entering include file \"%s\"", line+1);
file_readquote(p, line+1); file_readquote(p, line+1);
debuglog(p, "Leaving include file \"%s\"", line+1);
line[len-1] = '"'; line[len-1] = '"';
return true; return true;
} }
if (len > 2 && line[0] == '<' && line[len-1] == '>') { if (len > 2 && line[0] == '<' && line[len-1] == '>') {
line[len-1] = '\0'; line[len-1] = '\0';
debuglog(p, "Entering include file <%s>", line+1);
file_readbracket(p, line+1); file_readbracket(p, line+1);
debuglog(p, "Leaving include file <%s>", line+1);
line[len-1] = '>'; line[len-1] = '>';
return true; return true;
} }
@ -383,13 +437,13 @@ tryinclude(struct place *p, char *line)
static static
void void
d_include(struct place *p, struct place *p2, char *line) d_include(struct lineplace *lp, struct place *p2, char *line)
{ {
char *text; char *text;
size_t oldlen; size_t oldlen;
uncomment(line); uncomment(line);
if (tryinclude(p, line)) { if (tryinclude(&lp->current, line)) {
return; return;
} }
text = macroexpand(p2, line, strlen(line), false); 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 */ /* trim to fit, so the malloc debugging won't complain */
text = dorealloc(text, oldlen + 1, strlen(text) + 1); text = dorealloc(text, oldlen + 1, strlen(text) + 1);
if (tryinclude(p, text)) { if (tryinclude(&lp->current, text)) {
dostrfree(text); dostrfree(text);
return; return;
} }
complain(p, "Illegal #include directive"); complain(&lp->current, "Illegal #include directive");
complain(p, "Before macro expansion: #include %s", line); complain(&lp->current, "Before macro expansion: #include %s", line);
complain(p, "After macro expansion: #include %s", text); complain(&lp->current, "After macro expansion: #include %s", text);
dostrfree(text); dostrfree(text);
complain_fail(); complain_fail();
} }
static static
void void
d_line(struct place *p, struct place *p2, char *line) d_line(struct lineplace *lp, struct place *p2, char *line)
{ {
(void)p2; char *text;
(void)line; size_t oldlen;
unsigned long val;
char *moretext;
size_t moretextlen;
char *filename;
/* XXX */ text = macroexpand(p2, line, strlen(line), true);
complain(p, "Sorry, no #line yet");
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 static
void void
d_warning(struct place *p, struct place *p2, char *line) d_warning(struct lineplace *lp, struct place *p2, char *line)
{ {
char *msg; char *msg;
msg = macroexpand(p2, line, strlen(line), false); msg = macroexpand(p2, line, strlen(line), false);
complain(p, "#warning: %s", msg); complain(&lp->current, "#warning: %s", msg);
if (mode.werror) { if (mode.werror) {
complain_fail(); complain_fail();
} }
@ -440,12 +547,12 @@ d_warning(struct place *p, struct place *p2, char *line)
static static
void void
d_error(struct place *p, struct place *p2, char *line) d_error(struct lineplace *lp, struct place *p2, char *line)
{ {
char *msg; char *msg;
msg = macroexpand(p2, line, strlen(line), false); msg = macroexpand(p2, line, strlen(line), false);
complain(p, "#error: %s", msg); complain(&lp->current, "#error: %s", msg);
complain_fail(); complain_fail();
dostrfree(msg); dostrfree(msg);
} }
@ -455,11 +562,11 @@ d_error(struct place *p, struct place *p2, char *line)
static static
void void
d_pragma(struct place *p, struct place *p2, char *line) d_pragma(struct lineplace *lp, struct place *p2, char *line)
{ {
(void)p2; (void)p2;
complain(p, "#pragma %s", line); complain(&lp->current, "#pragma %s", line);
complain_fail(); complain_fail();
} }
@ -469,7 +576,7 @@ d_pragma(struct place *p, struct place *p2, char *line)
static const struct { static const struct {
const char *name; const char *name;
bool ifskip; bool ifskip;
void (*func)(struct place *, struct place *, char *line); void (*func)(struct lineplace *, struct place *, char *line);
} directives[] = { } directives[] = {
{ "define", true, d_define }, { "define", true, d_define },
{ "elif", false, d_elif }, { "elif", false, d_elif },
@ -489,13 +596,13 @@ static const unsigned numdirectives = HOWMANY(directives);
static static
void void
directive_gotdirective(struct place *p, char *line) directive_gotdirective(struct lineplace *lp, char *line)
{ {
struct place p2; struct place p2;
size_t len, skip; size_t len, skip;
unsigned i; unsigned i;
p2 = *p; p2 = lp->current;
for (i=0; i<numdirectives; i++) { for (i=0; i<numdirectives; i++) {
len = strlen(directives[i].name); len = strlen(directives[i].name);
if (!strncmp(line, directives[i].name, len) && if (!strncmp(line, directives[i].name, len) &&
@ -504,7 +611,7 @@ directive_gotdirective(struct place *p, char *line)
return; return;
} }
skip = len + strspn(line+len, ws); skip = len + strspn(line+len, ws);
p2.column += skip; place_addcolumns(&p2, skip);
line += skip; line += skip;
len = strlen(line); len = strlen(line);
@ -512,7 +619,7 @@ directive_gotdirective(struct place *p, char *line)
if (len < strlen(line)) { if (len < strlen(line)) {
line[len] = '\0'; line[len] = '\0';
} }
directives[i].func(p, &p2, line); directives[i].func(lp, &p2, line);
return; return;
} }
} }
@ -523,7 +630,7 @@ directive_gotdirective(struct place *p, char *line)
} }
skip = strcspn(line, ws); skip = strcspn(line, ws);
complain(p, "Unknown directive #%.*s", (int)skip, line); complain(&lp->current, "Unknown directive #%.*s", (int)skip, line);
complain_fail(); complain_fail();
} }
@ -532,13 +639,13 @@ directive_gotdirective(struct place *p, char *line)
*/ */
static static
size_t 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; size_t pos;
bool incomment; bool incomment;
struct place p2; struct place p2;
p2 = *p; p2 = lp->current;
incomment = 0; incomment = 0;
for (pos = 0; pos+1 < len; pos++) { for (pos = 0; pos+1 < len; pos++) {
if (line[pos] == '/' && line[pos+1] == '*') { if (line[pos] == '/' && line[pos+1] == '*') {
@ -561,10 +668,10 @@ directive_scancomments(const struct place *p, char *line, size_t len)
pos++; pos++;
} }
if (line[pos] == '\n') { if (line[pos] == '\n') {
p2.line++; place_addlines(&p2, 1);
p2.column = 0; p2.column = 0;
} else { } else {
p2.column++; place_addcolumns(&p2, 1);
} }
} }
@ -574,25 +681,25 @@ directive_scancomments(const struct place *p, char *line, size_t len)
} }
void void
directive_gotline(struct place *p, char *line, size_t len) directive_gotline(struct lineplace *lp, char *line, size_t len)
{ {
size_t skip; size_t skip;
if (warns.nestcomment) { if (warns.nestcomment) {
directive_scancomments(p, line, len); directive_scancomments(lp, line, len);
} }
/* check if we have a directive line (# exactly in column 0) */ /* 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); skip = 1 + strspn(line + 1, ws);
assert(skip <= len); assert(skip <= len);
p->column += skip; place_addcolumns(&lp->current, skip);
assert(line[len] == '\0'); assert(line[len] == '\0');
directive_gotdirective(p, line+skip /*, length = len-skip */); directive_gotdirective(lp, line+skip /*, length = len-skip */);
p->column += len-skip; place_addcolumns(&lp->current, len-skip);
} else if (ifstate->curtrue) { } else if (ifstate->curtrue) {
macro_sendline(p, line, len); macro_sendline(&lp->current, line, len);
p->column += len; place_addcolumns(&lp->current, len);
} }
} }

View file

@ -29,11 +29,21 @@
#include <stddef.h> #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_init(void);
void directive_cleanup(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); void directive_goteof(struct place *p);

View file

@ -642,6 +642,7 @@ wordval(struct place *p, char *word)
complain_fail(); complain_fail();
} }
} }
debuglog(p, "Undefined symbol %s; substituting 0", word);
return 0; return 0;
} }
@ -707,29 +708,29 @@ tokenize(struct place *p, char *expr)
while (expr[pos] != '\0') { while (expr[pos] != '\0') {
len = strspn(expr+pos, ws); len = strspn(expr+pos, ws);
pos += len; pos += len;
p->column += len; place_addcolumns(p, len);
/* trailing whitespace is supposed to have been pruned */ /* trailing whitespace is supposed to have been pruned */
assert(expr[pos] != '\0'); assert(expr[pos] != '\0');
if (check_word(p, expr, pos, &len)) { if (check_word(p, expr, pos, &len)) {
pos += len; pos += len;
p->column += len; place_addcolumns(p, len);
continue; continue;
} }
if (check_tokens_2(p, expr, pos)) { if (check_tokens_2(p, expr, pos)) {
pos += 2; pos += 2;
p->column += 2; place_addcolumns(p, 2);
continue; continue;
} }
if (check_tokens_1(p, expr, pos)) { if (check_tokens_1(p, expr, pos)) {
pos++; pos++;
p->column++; place_addcolumns(p, 1);
continue; continue;
} }
complain(p, "Invalid character %u in #if-expression", complain(p, "Invalid character %u in #if-expression",
(unsigned char)expr[pos]); (unsigned char)expr[pos]);
complain_fail(); complain_fail();
pos++; pos++;
p->column++; place_addcolumns(p, 1);
} }
token(p, T_EOF, 0); token(p, T_EOF, 0);
} }
@ -744,6 +745,7 @@ eval(struct place *p, char *expr)
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "eval: %s\n", expr); fprintf(stderr, "eval: %s\n", expr);
#endif #endif
debuglog(p, "eval: %s", expr);
tokenarray_init(&tokens); tokenarray_init(&tokens);
tokenize(p, expr); tokenize(p, expr);

View file

@ -27,6 +27,6 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <stdbool.h> #include "bool.h"
bool eval(struct place *p, char *expr); bool eval(struct place *p, char *expr);

View file

@ -27,7 +27,6 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -35,6 +34,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
#include "bool.h"
#include "array.h" #include "array.h"
#include "mode.h" #include "mode.h"
#include "place.h" #include "place.h"
@ -163,6 +163,10 @@ countnls(const char *buf, size_t start, size_t limit)
for (i=start; i<limit; i++) { for (i=start; i<limit; i++) {
if (buf[i] == '\n') { if (buf[i] == '\n') {
count++; count++;
if (count == 0) {
/* just return the max and error downstream */
return count - 1;
}
} }
} }
return count; return count;
@ -172,14 +176,21 @@ static
void void
file_read(const struct placefile *pf, int fd, const char *name, bool toplevel) 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; size_t bufend, bufmax, linestart, lineend, nextlinestart, tmp;
ssize_t result; ssize_t result;
bool ateof = false; bool ateof = false;
char *buf; char *buf;
place_setfilestart(&linestartplace, pf); place_setfilestart(&places.current, pf);
nextlinestartplace = linestartplace; places.nextline = places.current;
if (name) {
debuglog(&places.current, "Reading file %s", name);
} else {
debuglog(&places.current, "Reading standard input");
}
bufmax = 128; bufmax = 128;
bufend = 0; bufend = 0;
@ -202,6 +213,12 @@ file_read(const struct placefile *pf, int fd, const char *name, bool toplevel)
/* need bigger buffer */ /* need bigger buffer */
buf = dorealloc(buf, bufmax, bufmax*2); buf = dorealloc(buf, bufmax, bufmax*2);
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) { if (ateof) {
@ -223,9 +240,15 @@ file_read(const struct placefile *pf, int fd, const char *name, bool toplevel)
} else if (result == 0) { } else if (result == 0) {
/* eof in middle of line */ /* eof in middle of line */
ateof = true; ateof = true;
ptmp = linestartplace; ptmp = places.current;
ptmp.column += bufend - linestart; place_addcolumns(&ptmp, bufend - linestart);
complain(&ptmp, "No newline at end of file"); if (buf[bufend - 1] == '\n') {
complain(&ptmp, "Unclosed comment");
complain_fail();
} else {
complain(&ptmp,
"No newline at end of file");
}
if (mode.werror) { if (mode.werror) {
complain_fail(); complain_fail();
} }
@ -244,7 +267,7 @@ file_read(const struct placefile *pf, int fd, const char *name, bool toplevel)
assert(buf[lineend] == '\n'); assert(buf[lineend] == '\n');
buf[lineend] = '\0'; buf[lineend] = '\0';
nextlinestart = lineend+1; nextlinestart = lineend+1;
nextlinestartplace.line++; place_addlines(&places.nextline, 1);
/* check for CR/NL */ /* check for CR/NL */
if (lineend > 0 && buf[lineend-1] == '\r') { 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'); assert(buf[lineend] == '\0');
/* count how many commented-out newlines we swallowed */ /* 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 */ /* process the line (even if it's empty) */
if (lineend > linestart) { directive_gotline(&places, buf+linestart, lineend-linestart);
directive_gotline(&linestartplace,
buf+linestart, lineend-linestart);
}
linestart = nextlinestart; linestart = nextlinestart;
lineend = findeol(buf, linestart, bufend); lineend = findeol(buf, linestart, bufend);
linestartplace = nextlinestartplace; places.current = places.nextline;
} }
if (toplevel) { if (toplevel) {
directive_goteof(&linestartplace); directive_goteof(&places.current);
} }
dofree(buf, bufmax); dofree(buf, bufmax);
} }

View file

@ -28,9 +28,11 @@
*/ */
#include <stdint.h> #include <stdint.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "union.h"
#include "array.h" #include "array.h"
#include "mode.h" #include "mode.h"
#include "place.h" #include "place.h"
@ -38,15 +40,21 @@
#include "output.h" #include "output.h"
struct expansionitem { struct expansionitem {
bool isstring; enum { EI_STRING, EI_PARAM, EI_FILE, EI_LINE } itemtype;
union { union {
char *string; char *ei_string; /* for EI_STRING */
unsigned param; unsigned ei_param; /* for EI_PARAM */
}; } UN;
}; };
DECLARRAY(expansionitem, static UNUSED); DECLARRAY(expansionitem, static UNUSED);
DEFARRAY(expansionitem, static); DEFARRAY(expansionitem, static);
#ifdef NEED_UNION_ACCESSORS
#define ei_string un.ei_string
#define ei_param un.ei_param
#endif
struct macro { struct macro {
struct place defplace; struct place defplace;
struct place expansionplace; struct place expansionplace;
@ -76,8 +84,8 @@ expansionitem_create_string(const char *string)
struct expansionitem *ei; struct expansionitem *ei;
ei = domalloc(sizeof(*ei)); ei = domalloc(sizeof(*ei));
ei->isstring = true; ei->itemtype = EI_STRING;
ei->string = dostrdup(string); ei->ei_string = dostrdup(string);
return ei; return ei;
} }
@ -88,8 +96,8 @@ expansionitem_create_stringlen(const char *string, size_t len)
struct expansionitem *ei; struct expansionitem *ei;
ei = domalloc(sizeof(*ei)); ei = domalloc(sizeof(*ei));
ei->isstring = true; ei->itemtype = EI_STRING;
ei->string = dostrndup(string, len); ei->ei_string = dostrndup(string, len);
return ei; return ei;
} }
@ -100,8 +108,30 @@ expansionitem_create_param(unsigned param)
struct expansionitem *ei; struct expansionitem *ei;
ei = domalloc(sizeof(*ei)); ei = domalloc(sizeof(*ei));
ei->isstring = false; ei->itemtype = EI_PARAM;
ei->param = 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; return ei;
} }
@ -109,8 +139,14 @@ static
void void
expansionitem_destroy(struct expansionitem *ei) expansionitem_destroy(struct expansionitem *ei)
{ {
if (ei->isstring) { switch (ei->itemtype) {
dostrfree(ei->string); case EI_STRING:
dostrfree(ei->ei_string);
break;
case EI_PARAM:
case EI_FILE:
case EI_LINE:
break;
} }
dofree(ei, sizeof(*ei)); dofree(ei, sizeof(*ei));
} }
@ -120,17 +156,23 @@ bool
expansionitem_eq(const struct expansionitem *ei1, expansionitem_eq(const struct expansionitem *ei1,
const struct expansionitem *ei2) const struct expansionitem *ei2)
{ {
if (ei1->isstring != ei2->isstring) { if (ei1->itemtype != ei2->itemtype) {
return false; return false;
} }
if (ei1->isstring) { switch (ei1->itemtype) {
if (strcmp(ei1->string, ei2->string) != 0) { case EI_STRING:
if (strcmp(ei1->ei_string, ei2->ei_string) != 0) {
return false; return false;
} }
} else { break;
if (ei1->param != ei2->param) { case EI_PARAM:
if (ei1->ei_param != ei2->ei_param) {
return false; return false;
} }
break;
case EI_FILE:
case EI_LINE:
break;
} }
return true; return true;
} }
@ -298,7 +340,7 @@ macrotable_cleanup(void)
static static
struct macro * 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; unsigned hash;
struct macroarray *bucket; struct macroarray *bucket;
@ -319,7 +361,7 @@ macrotable_findlen(const char *name, size_t len, bool remove)
} }
mlen = strlen(m->name); mlen = strlen(m->name);
if (len == mlen && !memcmp(name, m->name, len)) { if (len == mlen && !memcmp(name, m->name, len)) {
if (remove) { if (remove_it) {
if (i < num-1) { if (i < num-1) {
m2 = macroarray_get(bucket, num-1); m2 = macroarray_get(bucket, num-1);
macroarray_set(bucket, i, m2); macroarray_set(bucket, i, m2);
@ -335,9 +377,9 @@ macrotable_findlen(const char *name, size_t len, bool remove)
static static
struct macro * 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 static
@ -481,7 +523,7 @@ macro_parse_parameters(struct macro *m, struct place *p, const char *params)
while (params != NULL) { while (params != NULL) {
len = strspn(params, ws); len = strspn(params, ws);
params += len; params += len;
p->column += len; place_addcolumns(p, len);
s = strchr(params, ','); s = strchr(params, ',');
if (s) { if (s) {
len = s-params; 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); stringarray_add(&m->params, param, NULL);
} }
params = s; 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); 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 void
macro_undef(const char *macro) macro_undef(const char *macro)
{ {
@ -624,7 +684,7 @@ struct expstate {
static struct expstate mainstate; static struct expstate mainstate;
static void doexpand(struct expstate *es, struct place *p, static void doexpand(struct expstate *es, struct place *p,
char *buf, size_t len); const char *buf, size_t len);
static static
void void
@ -705,7 +765,7 @@ expand_send_eof(struct expstate *es, struct place *p)
static static
void void
expand_newarg(struct expstate *es, char *buf, size_t len) expand_newarg(struct expstate *es, const char *buf, size_t len)
{ {
char *text; char *text;
@ -715,7 +775,7 @@ expand_newarg(struct expstate *es, char *buf, size_t len)
static static
void void
expand_appendarg(struct expstate *es, char *buf, size_t len) expand_appendarg(struct expstate *es, const char *buf, size_t len)
{ {
unsigned num; unsigned num;
char *text; char *text;
@ -742,6 +802,7 @@ expand_substitute(struct place *p, struct expstate *es)
char *arg; char *arg;
char *ret; char *ret;
unsigned numargs, numparams; unsigned numargs, numparams;
char numbuf[64];
numargs = stringarray_num(&es->args); numargs = stringarray_num(&es->args);
numparams = stringarray_num(&es->curmacro->params); numparams = stringarray_num(&es->curmacro->params);
@ -766,11 +827,20 @@ expand_substitute(struct place *p, struct expstate *es)
num = expansionitemarray_num(&es->curmacro->expansion); num = expansionitemarray_num(&es->curmacro->expansion);
for (i=0; i<num; i++) { for (i=0; i<num; i++) {
ei = expansionitemarray_get(&es->curmacro->expansion, i); ei = expansionitemarray_get(&es->curmacro->expansion, i);
if (ei->isstring) { switch (ei->itemtype) {
len += strlen(ei->string); case EI_STRING:
} else { len += strlen(ei->ei_string);
arg = stringarray_get(&es->args, ei->param); break;
case EI_PARAM:
arg = stringarray_get(&es->args, ei->ei_param);
len += strlen(arg); 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'; *ret = '\0';
for (i=0; i<num; i++) { for (i=0; i<num; i++) {
ei = expansionitemarray_get(&es->curmacro->expansion, i); ei = expansionitemarray_get(&es->curmacro->expansion, i);
if (ei->isstring) { switch (ei->itemtype) {
strcat(ret, ei->string); case EI_STRING:
} else { strcat(ret, ei->ei_string);
arg = stringarray_get(&es->args, ei->param); break;
case EI_PARAM:
arg = stringarray_get(&es->args, ei->ei_param);
strcat(ret, arg); 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) expand_domacro(struct expstate *es, struct place *p)
{ {
struct macro *m; struct macro *m;
const char *name, *val;
char *newbuf, *newbuf2; char *newbuf, *newbuf2;
if (es->curmacro == NULL) { if (es->curmacro == NULL) {
@ -804,23 +887,32 @@ expand_domacro(struct expstate *es, struct place *p)
expand_send(es, p, "0", 1); expand_send(es, p, "0", 1);
return; return;
} }
m = macrotable_find(stringarray_get(&es->args, 0), false); name = stringarray_get(&es->args, 0);
expand_send(es, p, (m != NULL) ? "1" : "0", 1); 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); expstate_destroyargs(es);
return; return;
} }
assert(es->curmacro->inuse == false); m = es->curmacro;
es->curmacro->inuse = true; assert(m->inuse == false);
m->inuse = true;
debuglog(p, "Expanding macro %s", m->name);
newbuf = expand_substitute(p, es); newbuf = expand_substitute(p, es);
debuglog(p, "Substituting for %s: %s", m->name, newbuf);
newbuf2 = macroexpand(p, newbuf, strlen(newbuf), false); newbuf2 = macroexpand(p, newbuf, strlen(newbuf), false);
dostrfree(newbuf); dostrfree(newbuf);
expstate_destroyargs(es); expstate_destroyargs(es);
debuglog(p, "Complete expansion for %s: %s", m->name, newbuf2);
doexpand(es, p, newbuf2, strlen(newbuf2)); doexpand(es, p, newbuf2, strlen(newbuf2));
dostrfree(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 static
void 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) { switch (es->state) {
case ES_NORMAL: case ES_NORMAL:
expand_send(es, p, buf, len); expand_send(es, p, buf, len);
break; break;
case ES_WANTLPAREN: case ES_WANTLPAREN:
/* XXX notyet */
//expand_send(es, p, buf, len);
break; break;
case ES_NOARG: case ES_NOARG:
expand_newarg(es, buf, len); expand_newarg(es, buf, len);
@ -866,11 +961,10 @@ expand_got_ws(struct expstate *es, struct place *p, char *buf, size_t len)
static static
void 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 macro *m;
struct expansionitem *ei;
char *newbuf;
switch (es->state) { switch (es->state) {
case ES_NORMAL: 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) { if (m == NULL || m->inuse) {
expand_send(es, p, buf, len); expand_send(es, p, buf, len);
} else if (!m->hasparams) { } else if (!m->hasparams) {
m->inuse = true; es->curmacro = m;
assert(expansionitemarray_num(&m->expansion) == 1); expand_domacro(es, p);
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;
} else { } else {
es->curmacro = m; es->curmacro = m;
es->state = ES_WANTLPAREN; es->state = ES_WANTLPAREN;
@ -923,7 +1010,8 @@ expand_got_word(struct expstate *es, struct place *p, char *buf, size_t len)
static static
void 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) { switch (es->state) {
case ES_NORMAL: case ES_NORMAL:
@ -946,7 +1034,8 @@ expand_got_lparen(struct expstate *es, struct place *p, char *buf, size_t len)
static static
void 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) { switch (es->state) {
case ES_NORMAL: case ES_NORMAL:
@ -981,7 +1070,8 @@ expand_got_rparen(struct expstate *es, struct place *p, char *buf, size_t len)
static static
void 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) { switch (es->state) {
case ES_NORMAL: case ES_NORMAL:
@ -1009,7 +1099,8 @@ expand_got_comma(struct expstate *es, struct place *p, char *buf, size_t len)
static static
void 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) { switch (es->state) {
case ES_NORMAL: case ES_NORMAL:
@ -1061,7 +1152,7 @@ expand_got_eof(struct expstate *es, struct place *p)
static static
void 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; char *s;
size_t x; size_t x;
@ -1150,7 +1241,7 @@ doexpand(struct expstate *es, struct place *p, char *buf, size_t len)
} }
char * 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; struct expstate es;
char *ret; char *ret;
@ -1172,10 +1263,30 @@ macroexpand(struct place *p, char *buf, size_t len, bool honordefined)
} }
void 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); doexpand(&mainstate, p, buf, len);
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); 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 void

View file

@ -27,8 +27,8 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include "bool.h"
struct place; struct place;
@ -40,10 +40,12 @@ void macro_define_plain(struct place *, const char *macro,
void macro_define_params(struct place *, const char *macro, void macro_define_params(struct place *, const char *macro,
struct place *, const char *params, struct place *, const char *params,
struct place *, const char *expansion); struct place *, const char *expansion);
void macro_define_magic(struct place *, const char *macro);
void macro_undef(const char *macro); void macro_undef(const char *macro);
bool macro_isdefined(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 *); void macro_sendeof(struct place *);

View file

@ -27,13 +27,13 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include "bool.h"
#include "version.h" #include "version.h"
#include "config.h" #include "config.h"
#include "utils.h" #include "utils.h"
@ -55,6 +55,7 @@ struct mode mode = {
.do_output = true, .do_output = true,
.output_linenumbers = true, .output_linenumbers = true,
.output_cheaplinenumbers = false,
.output_retain_comments = false, .output_retain_comments = false,
.output_file = NULL, .output_file = NULL,
@ -154,7 +155,7 @@ commandline_def(const struct place *p, char *str)
if (val) { if (val) {
p2 = *p; p2 = *p;
p2.column += strlen(str); place_addcolumns(&p2, strlen(str));
} else { } else {
place_setbuiltin(&p2, 1); place_setbuiltin(&p2, 1);
} }
@ -166,7 +167,7 @@ void
commandline_undef(const struct place *p, char *str) commandline_undef(const struct place *p, char *str)
{ {
if (*str == '\0') { if (*str == '\0') {
complain(NULL, "-D: macro name expected"); complain(NULL, "-U: macro name expected");
die(); die();
} }
commandline_macro_add(p, str, p, NULL); commandline_macro_add(p, str, p, NULL);
@ -193,6 +194,16 @@ apply_commandline_macros(void)
array_setsize(&commandline_macros, 0); 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 static
void void
apply_builtin_macro(unsigned num, const char *name, const char *val) apply_builtin_macro(unsigned num, const char *name, const char *val)
@ -209,6 +220,9 @@ apply_builtin_macros(void)
{ {
unsigned n = 1; unsigned n = 1;
apply_magic_macro(n++, "__FILE__");
apply_magic_macro(n++, "__LINE__");
#ifdef CONFIG_OS #ifdef CONFIG_OS
apply_builtin_macro(n++, CONFIG_OS, "1"); apply_builtin_macro(n++, CONFIG_OS, "1");
#endif #endif
@ -781,6 +795,7 @@ static const struct flag_option flag_options[] = {
{ "fdollars-in-identifiers", &mode.input_allow_dollars, true }, { "fdollars-in-identifiers", &mode.input_allow_dollars, true },
{ "fno-dollars-in-identifiers", &mode.input_allow_dollars, false }, { "fno-dollars-in-identifiers", &mode.input_allow_dollars, false },
{ "nostdinc", &mode.do_stdinc, false }, { "nostdinc", &mode.do_stdinc, false },
{ "p", &mode.output_cheaplinenumbers, true },
{ "undef", &mode.do_stddef, false }, { "undef", &mode.do_stddef, false },
}; };
static const unsigned num_flag_options = HOWMANY(flag_options); static const unsigned num_flag_options = HOWMANY(flag_options);
@ -814,6 +829,7 @@ static const struct arg_option arg_options[] = {
{ "MF", commandline_setdependoutput }, { "MF", commandline_setdependoutput },
{ "MQ", commandline_setdependtarget_quoted }, { "MQ", commandline_setdependtarget_quoted },
{ "MT", commandline_setdependtarget }, { "MT", commandline_setdependtarget },
{ "debuglog", debuglog_open },
{ "idirafter", commandline_addincpath_late }, { "idirafter", commandline_addincpath_late },
{ "imacros", commandline_addfile_nooutput }, { "imacros", commandline_addfile_nooutput },
{ "include", commandline_addfile_output }, { "include", commandline_addfile_output },
@ -934,7 +950,7 @@ check_arg_option(const char *opt, const struct place *argplace, char *arg)
return false; return false;
} }
DEAD static DEAD PF(2, 3) static
void void
usage(const char *progname, const char *fmt, ...) usage(const char *progname, const char *fmt, ...)
{ {
@ -946,7 +962,7 @@ usage(const char *progname, const char *fmt, ...)
va_end(ap); va_end(ap);
fprintf(stderr, "\n"); 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, "Common options:\n");
fprintf(stderr, " -C Retain comments\n"); fprintf(stderr, " -C Retain comments\n");
fprintf(stderr, " -Dmacro[=def] Predefine macro\n"); fprintf(stderr, " -Dmacro[=def] Predefine macro\n");
@ -999,6 +1015,7 @@ cleanup(void)
commandline_files_cleanup(); commandline_files_cleanup();
commandline_macros_cleanup(); commandline_macros_cleanup();
incpath_cleanup(); incpath_cleanup();
debuglog_close();
num = stringarray_num(&freestrings); num = stringarray_num(&freestrings);
for (i=0; i<num; i++) { for (i=0; i<num; i++) {
@ -1040,7 +1057,7 @@ main(int argc, char *argv[])
init(); init();
for (i=1; i<argc; i++) { for (i=1; i<argc; i++) {
if (argv[i][0] != '-') { if (argv[i][0] != '-' || argv[i][1] == 0) {
break; break;
} }
place_setcommandline(&cmdplace, i, 1); place_setcommandline(&cmdplace, i, 1);
@ -1065,9 +1082,15 @@ main(int argc, char *argv[])
} }
if (i < argc) { if (i < argc) {
inputfile = argv[i++]; inputfile = argv[i++];
if (!strcmp(inputfile, "-")) {
inputfile = NULL;
}
} }
if (i < argc) { if (i < argc) {
outputfile = argv[i++]; outputfile = argv[i++];
if (!strcmp(outputfile, "-")) {
outputfile = NULL;
}
} }
if (i < argc) { if (i < argc) {
usage(progname, "Extra non-option argument %s", argv[i]); usage(progname, "Extra non-option argument %s", argv[i]);

View file

@ -27,7 +27,7 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <stdbool.h> #include "bool.h"
struct mode { struct mode {
bool werror; bool werror;
@ -37,6 +37,7 @@ struct mode {
bool do_stddef; bool do_stddef;
bool do_output; bool do_output;
bool output_linenumbers; bool output_linenumbers;
bool output_cheaplinenumbers;
bool output_retain_comments; bool output_retain_comments;
const char *output_file; const char *output_file;
bool do_depend; bool do_depend;

View file

@ -27,6 +27,7 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <stdio.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
@ -172,6 +173,15 @@ output(const struct place *p, const char *buf, size_t len)
linebuf = dorealloc(linebuf, oldmax, linebufmax); linebuf = dorealloc(linebuf, oldmax, linebufmax);
} }
if (linebufpos == 0) { 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; linebufplace = *p;
} }
memcpy(linebuf + linebufpos, buf, len); memcpy(linebuf + linebufpos, buf, len);

View file

@ -32,6 +32,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <errno.h>
#include "utils.h" #include "utils.h"
#include "array.h" #include "array.h"
@ -52,8 +53,10 @@ static bool overall_failure;
static const char *myprogname; static const char *myprogname;
static FILE *debuglogfile;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// seenfiles // placefiles
static static
struct placefile * struct placefile *
@ -101,6 +104,42 @@ place_getparsedir(const struct place *place)
return place->file->dir; 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 * const struct placefile *
place_addfile(const struct place *place, const char *file, bool issystem) 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; 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 * const char *
place_getname(const struct place *p) place_getname(const struct place *p)
{ {
@ -168,6 +234,30 @@ place_getname(const struct place *p)
return NULL; 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 static
void void
place_printfrom(const struct place *p) place_printfrom(const struct place *p)
@ -224,6 +314,70 @@ complain_failed(void)
return overall_failure; 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 // module init and cleanup

View file

@ -27,7 +27,10 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <stdbool.h> #ifndef PLACE_H
#define PLACE_H
#include "bool.h"
enum places { enum places {
P_NOWHERE, 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_setcommandline(struct place *p, unsigned word, unsigned column);
void place_setfilestart(struct place *p, const struct placefile *pf); 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); 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 struct placefile *place_addfile(const struct place *incplace,
const char *name, bool fromsystemdir); const char *name, bool fromsystemdir);
#endif /* PLACE_H */

View file

@ -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()

View file

@ -0,0 +1,8 @@
2
"t38.c"
4
"t38.c":5
"t38.c":500
"foo.c":600
hello
"foo.c":602

View file

@ -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)

View file

@ -0,0 +1,11 @@
=123:: 456
------
=123:: 456
------
= 123:: 456
------
= 123:: 456
------
=123:: 456
------
=123:: 456

View file

@ -0,0 +1,6 @@
#define foo bar
#define bar(x) do x do
foo(de)

View file

@ -0,0 +1 @@
do de do

View file

@ -96,7 +96,7 @@ Suppress line number information in the output.
Currently line number information is not generated at all and this Currently line number information is not generated at all and this
option has no effect. option has no effect.
.It Fl Umacro .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, Note that like many Unix compilers,
.Nm .Nm
does not accept a space between the does not accept a space between the
@ -254,12 +254,20 @@ and add this directory as if it were specified with
.Fl idirafter . .Fl idirafter .
.It Fl iwithprefixbefore .It Fl iwithprefixbefore
Like Like
-Fl iwithprefix .Fl iwithprefix
but adds the result as if it were specified with but adds the result as if it were specified with
.Fl I . .Fl I .
.El .El
.Ss Diagnostic Options .Ss Diagnostic Options
.Bl -tag -width bubblebabble .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 .It Fl dD
Dump all macro definitions, except for the predefined macros, after Dump all macro definitions, except for the predefined macros, after
the normal preprocessing output. the normal preprocessing output.

36
cde/util/tradcpp/union.h Normal file
View file

@ -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

View file

@ -27,8 +27,8 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include "bool.h"
struct place; struct place;
@ -63,10 +63,16 @@ bool is_identifier(const char *str);
/* in place.c */ /* in place.c */
void complain_init(const char *progname); 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); void complain_fail(void);
bool complain_failed(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 */ /* in main.c */
void freestringlater(char *s); void freestringlater(char *s);
DEAD void die(void); DEAD void die(void);

View file

@ -28,6 +28,6 @@
*/ */
#define VERSION_MAJOR "0" #define VERSION_MAJOR "0"
#define VERSION_MINOR "4" #define VERSION_MINOR "5"
#define VERSION_STRING "0.4" #define VERSION_STRING "0.5.3"
#define VERSION_LONG "NetBSD tradcpp 0.4" #define VERSION_LONG "NetBSD tradcpp 0.5.3"