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:
parent
15dfdf231a
commit
ec8f4b7464
28 changed files with 843 additions and 186 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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.)
|
||||
|
|
|
@ -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) \
|
||||
|
|
41
cde/util/tradcpp/bool.h
Normal file
41
cde/util/tradcpp/bool.h
Normal 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 */
|
|
@ -124,6 +124,22 @@
|
|||
#define CONFIG_CPU "__ppc64__"
|
||||
#elif defined(__ARM__)
|
||||
#define CONFIG_CPU "__ARM__"
|
||||
#elif defined(__AARCH64__)
|
||||
#define CONFIG_CPU "__AARCH64__"
|
||||
#elif defined(__aarch64__)
|
||||
#define CONFIG_CPU "__aarch64__"
|
||||
#elif defined(__RISCV__)
|
||||
#define CONFIG_CPU "__RISCV__"
|
||||
#elif defined(__riscv__)
|
||||
#define CONFIG_CPU "__riscv__"
|
||||
#elif defined(__RISCV64__)
|
||||
#define CONFIG_CPU "__RISCV64__"
|
||||
#elif defined(__riscv64__)
|
||||
#define CONFIG_CPU "__riscv64__"
|
||||
#elif defined(__riscv64)
|
||||
#define CONFIG_CPU "__riscv64"
|
||||
#elif defined(__ia64__)
|
||||
#define CONFIG_CPU "__ia64__"
|
||||
#else
|
||||
/* let it go */
|
||||
#endif
|
||||
|
|
|
@ -28,10 +28,12 @@
|
|||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "bool.h"
|
||||
#include "utils.h"
|
||||
#include "mode.h"
|
||||
#include "place.h"
|
||||
|
@ -112,7 +114,7 @@ oneword(const char *what, struct place *p2, char *line)
|
|||
|
||||
pos = strcspn(line, ws);
|
||||
if (line[pos] != '\0') {
|
||||
p2->column += pos;
|
||||
place_addcolumns(p2, pos);
|
||||
complain(p2, "Garbage after %s argument", what);
|
||||
complain_fail();
|
||||
line[pos] = '\0';
|
||||
|
@ -175,13 +177,16 @@ ifstate_pop(void)
|
|||
|
||||
static
|
||||
void
|
||||
d_if(struct place *p, struct place *p2, char *line)
|
||||
d_if(struct lineplace *lp, struct place *p2, char *line)
|
||||
{
|
||||
bool doprint;
|
||||
char *expr;
|
||||
bool val;
|
||||
struct place p3 = *p2;
|
||||
size_t oldlen;
|
||||
|
||||
doprint = ifstate->curtrue;
|
||||
|
||||
expr = macroexpand(p2, line, strlen(line), true);
|
||||
|
||||
oldlen = strlen(expr);
|
||||
|
@ -194,41 +199,67 @@ d_if(struct place *p, struct place *p2, char *line)
|
|||
} else {
|
||||
val = 0;
|
||||
}
|
||||
ifstate_push(p, val);
|
||||
ifstate_push(&lp->current, val);
|
||||
dostrfree(expr);
|
||||
|
||||
if (doprint) {
|
||||
debuglog(&lp->current, "#if: %s",
|
||||
ifstate->curtrue ? "taken" : "not taken");
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
d_ifdef(struct place *p, struct place *p2, char *line)
|
||||
d_ifdef(struct lineplace *lp, struct place *p2, char *line)
|
||||
{
|
||||
bool doprint;
|
||||
|
||||
doprint = ifstate->curtrue;
|
||||
|
||||
uncomment(line);
|
||||
oneword("#ifdef", p2, line);
|
||||
ifstate_push(p, macro_isdefined(line));
|
||||
ifstate_push(&lp->current, macro_isdefined(line));
|
||||
|
||||
if (doprint) {
|
||||
debuglog(&lp->current, "#ifdef %s: %s",
|
||||
line, ifstate->curtrue ? "taken" : "not taken");
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
d_ifndef(struct place *p, struct place *p2, char *line)
|
||||
d_ifndef(struct lineplace *lp, struct place *p2, char *line)
|
||||
{
|
||||
bool doprint;
|
||||
|
||||
doprint = ifstate->curtrue;
|
||||
|
||||
uncomment(line);
|
||||
oneword("#ifndef", p2, line);
|
||||
ifstate_push(p, !macro_isdefined(line));
|
||||
ifstate_push(&lp->current, !macro_isdefined(line));
|
||||
|
||||
if (doprint) {
|
||||
debuglog(&lp->current, "#ifndef %s: %s",
|
||||
line, ifstate->curtrue ? "taken" : "not taken");
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
d_elif(struct place *p, struct place *p2, char *line)
|
||||
d_elif(struct lineplace *lp, struct place *p2, char *line)
|
||||
{
|
||||
bool doprint;
|
||||
char *expr;
|
||||
struct place p3 = *p2;
|
||||
size_t oldlen;
|
||||
|
||||
if (ifstate->seenelse) {
|
||||
complain(p, "#elif after #else");
|
||||
complain(&lp->current, "#elif after #else");
|
||||
complain_fail();
|
||||
}
|
||||
|
||||
doprint = ifstate->curtrue;
|
||||
|
||||
if (ifstate->evertrue) {
|
||||
ifstate->curtrue = false;
|
||||
} else {
|
||||
|
@ -243,36 +274,52 @@ d_elif(struct place *p, struct place *p2, char *line)
|
|||
ifstate->evertrue = ifstate->curtrue;
|
||||
dostrfree(expr);
|
||||
}
|
||||
|
||||
if (doprint) {
|
||||
debuglog2(&lp->current, &ifstate->startplace, "#elif: %s",
|
||||
ifstate->curtrue ? "taken" : "not taken");
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
d_else(struct place *p, struct place *p2, char *line)
|
||||
d_else(struct lineplace *lp, struct place *p2, char *line)
|
||||
{
|
||||
bool doprint;
|
||||
|
||||
(void)p2;
|
||||
(void)line;
|
||||
|
||||
if (ifstate->seenelse) {
|
||||
complain(p, "Multiple #else directives in one conditional");
|
||||
complain(&lp->current,
|
||||
"Multiple #else directives in one conditional");
|
||||
complain_fail();
|
||||
}
|
||||
|
||||
doprint = ifstate->curtrue;
|
||||
|
||||
ifstate->curtrue = !ifstate->evertrue;
|
||||
ifstate->evertrue = true;
|
||||
ifstate->seenelse = true;
|
||||
|
||||
if (doprint) {
|
||||
debuglog2(&lp->current, &ifstate->startplace, "#else: %s",
|
||||
ifstate->curtrue ? "taken" : "not taken");
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
d_endif(struct place *p, struct place *p2, char *line)
|
||||
d_endif(struct lineplace *lp, struct place *p2, char *line)
|
||||
{
|
||||
(void)p2;
|
||||
(void)line;
|
||||
|
||||
if (ifstate->prev == NULL) {
|
||||
complain(p, "Unmatched #endif");
|
||||
complain(&lp->current, "Unmatched #endif");
|
||||
complain_fail();
|
||||
} else {
|
||||
debuglog2(&lp->current, &ifstate->startplace, "#endif");
|
||||
ifstate_pop();
|
||||
}
|
||||
}
|
||||
|
@ -282,12 +329,12 @@ d_endif(struct place *p, struct place *p2, char *line)
|
|||
|
||||
static
|
||||
void
|
||||
d_define(struct place *p, struct place *p2, char *line)
|
||||
d_define(struct lineplace *lp, struct place *p2, char *line)
|
||||
{
|
||||
size_t pos, argpos;
|
||||
struct place p3, p4;
|
||||
|
||||
(void)p;
|
||||
(void)lp;
|
||||
|
||||
/*
|
||||
* line may be:
|
||||
|
@ -301,13 +348,13 @@ d_define(struct place *p, struct place *p2, char *line)
|
|||
argpos = pos;
|
||||
pos = pos + strcspn(line+pos, "()");
|
||||
if (line[pos] == '(') {
|
||||
p2->column += pos;
|
||||
place_addcolumns(p2, pos);
|
||||
complain(p2, "Left parenthesis in macro parameters");
|
||||
complain_fail();
|
||||
return;
|
||||
}
|
||||
if (line[pos] != ')') {
|
||||
p2->column += pos;
|
||||
place_addcolumns(p2, pos);
|
||||
complain(p2, "Unclosed macro parameter list");
|
||||
complain_fail();
|
||||
return;
|
||||
|
@ -331,28 +378,31 @@ d_define(struct place *p, struct place *p2, char *line)
|
|||
pos += strspn(line+pos, ws);
|
||||
|
||||
p3 = *p2;
|
||||
p3.column += argpos;
|
||||
place_addcolumns(&p3, argpos);
|
||||
|
||||
p4 = *p2;
|
||||
p4.column += pos;
|
||||
place_addcolumns(&p4, pos);
|
||||
|
||||
if (argpos) {
|
||||
debuglog(&lp->current, "Defining %s()", line);
|
||||
macro_define_params(p2, line, &p3,
|
||||
line + argpos, &p4,
|
||||
line + pos);
|
||||
} else {
|
||||
debuglog(&lp->current, "Defining %s", line);
|
||||
macro_define_plain(p2, line, &p4, line + pos);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
d_undef(struct place *p, struct place *p2, char *line)
|
||||
d_undef(struct lineplace *lp, struct place *p2, char *line)
|
||||
{
|
||||
(void)p;
|
||||
(void)lp;
|
||||
|
||||
uncomment(line);
|
||||
oneword("#undef", p2, line);
|
||||
debuglog(&lp->current, "Undef %s", line);
|
||||
macro_undef(line);
|
||||
}
|
||||
|
||||
|
@ -368,13 +418,17 @@ tryinclude(struct place *p, char *line)
|
|||
len = strlen(line);
|
||||
if (len > 2 && line[0] == '"' && line[len-1] == '"') {
|
||||
line[len-1] = '\0';
|
||||
debuglog(p, "Entering include file \"%s\"", line+1);
|
||||
file_readquote(p, line+1);
|
||||
debuglog(p, "Leaving include file \"%s\"", line+1);
|
||||
line[len-1] = '"';
|
||||
return true;
|
||||
}
|
||||
if (len > 2 && line[0] == '<' && line[len-1] == '>') {
|
||||
line[len-1] = '\0';
|
||||
debuglog(p, "Entering include file <%s>", line+1);
|
||||
file_readbracket(p, line+1);
|
||||
debuglog(p, "Leaving include file <%s>", line+1);
|
||||
line[len-1] = '>';
|
||||
return true;
|
||||
}
|
||||
|
@ -383,13 +437,13 @@ tryinclude(struct place *p, char *line)
|
|||
|
||||
static
|
||||
void
|
||||
d_include(struct place *p, struct place *p2, char *line)
|
||||
d_include(struct lineplace *lp, struct place *p2, char *line)
|
||||
{
|
||||
char *text;
|
||||
size_t oldlen;
|
||||
|
||||
uncomment(line);
|
||||
if (tryinclude(p, line)) {
|
||||
if (tryinclude(&lp->current, line)) {
|
||||
return;
|
||||
}
|
||||
text = macroexpand(p2, line, strlen(line), false);
|
||||
|
@ -399,26 +453,79 @@ d_include(struct place *p, struct place *p2, char *line)
|
|||
/* trim to fit, so the malloc debugging won't complain */
|
||||
text = dorealloc(text, oldlen + 1, strlen(text) + 1);
|
||||
|
||||
if (tryinclude(p, text)) {
|
||||
if (tryinclude(&lp->current, text)) {
|
||||
dostrfree(text);
|
||||
return;
|
||||
}
|
||||
complain(p, "Illegal #include directive");
|
||||
complain(p, "Before macro expansion: #include %s", line);
|
||||
complain(p, "After macro expansion: #include %s", text);
|
||||
complain(&lp->current, "Illegal #include directive");
|
||||
complain(&lp->current, "Before macro expansion: #include %s", line);
|
||||
complain(&lp->current, "After macro expansion: #include %s", text);
|
||||
dostrfree(text);
|
||||
complain_fail();
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
d_line(struct place *p, struct place *p2, char *line)
|
||||
d_line(struct lineplace *lp, struct place *p2, char *line)
|
||||
{
|
||||
(void)p2;
|
||||
(void)line;
|
||||
char *text;
|
||||
size_t oldlen;
|
||||
unsigned long val;
|
||||
char *moretext;
|
||||
size_t moretextlen;
|
||||
char *filename;
|
||||
|
||||
/* XXX */
|
||||
complain(p, "Sorry, no #line yet");
|
||||
text = macroexpand(p2, line, strlen(line), true);
|
||||
|
||||
oldlen = strlen(text);
|
||||
uncomment(text);
|
||||
/* trim to fit, so the malloc debugging won't complain */
|
||||
text = dorealloc(text, oldlen + 1, strlen(text) + 1);
|
||||
|
||||
/*
|
||||
* What we should have here: either 1234 "file.c",
|
||||
* or just 1234.
|
||||
*/
|
||||
|
||||
errno = 0;
|
||||
val = strtoul(text, &moretext, 10);
|
||||
if (errno) {
|
||||
complain(&lp->current,
|
||||
"Invalid line number in #line directive");
|
||||
goto fail;
|
||||
}
|
||||
#if UINT_MAX < ULONG_MAX
|
||||
if (val > UINT_MAX) {
|
||||
complain(&lp->current,
|
||||
"Line number in #line directive too large");
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
moretext += strspn(moretext, ws);
|
||||
moretextlen = strlen(moretext);
|
||||
place_addcolumns(&lp->current, moretext - text);
|
||||
|
||||
if (moretextlen > 2 &&
|
||||
moretext[0] == '"' && moretext[moretextlen-1] == '"') {
|
||||
filename = dostrndup(moretext+1, moretextlen-2);
|
||||
place_changefile(&lp->nextline, filename);
|
||||
dostrfree(filename);
|
||||
}
|
||||
else if (moretextlen > 0) {
|
||||
complain(&lp->current,
|
||||
"Invalid file name in #line directive");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
lp->nextline.line = val;
|
||||
dostrfree(text);
|
||||
return;
|
||||
|
||||
fail:
|
||||
complain(&lp->current, "Before macro expansion: #line %s", line);
|
||||
complain(&lp->current, "After macro expansion: #line %s", text);
|
||||
complain_fail();
|
||||
dostrfree(text);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
@ -426,12 +533,12 @@ d_line(struct place *p, struct place *p2, char *line)
|
|||
|
||||
static
|
||||
void
|
||||
d_warning(struct place *p, struct place *p2, char *line)
|
||||
d_warning(struct lineplace *lp, struct place *p2, char *line)
|
||||
{
|
||||
char *msg;
|
||||
|
||||
msg = macroexpand(p2, line, strlen(line), false);
|
||||
complain(p, "#warning: %s", msg);
|
||||
complain(&lp->current, "#warning: %s", msg);
|
||||
if (mode.werror) {
|
||||
complain_fail();
|
||||
}
|
||||
|
@ -440,12 +547,12 @@ d_warning(struct place *p, struct place *p2, char *line)
|
|||
|
||||
static
|
||||
void
|
||||
d_error(struct place *p, struct place *p2, char *line)
|
||||
d_error(struct lineplace *lp, struct place *p2, char *line)
|
||||
{
|
||||
char *msg;
|
||||
|
||||
msg = macroexpand(p2, line, strlen(line), false);
|
||||
complain(p, "#error: %s", msg);
|
||||
complain(&lp->current, "#error: %s", msg);
|
||||
complain_fail();
|
||||
dostrfree(msg);
|
||||
}
|
||||
|
@ -455,11 +562,11 @@ d_error(struct place *p, struct place *p2, char *line)
|
|||
|
||||
static
|
||||
void
|
||||
d_pragma(struct place *p, struct place *p2, char *line)
|
||||
d_pragma(struct lineplace *lp, struct place *p2, char *line)
|
||||
{
|
||||
(void)p2;
|
||||
|
||||
complain(p, "#pragma %s", line);
|
||||
complain(&lp->current, "#pragma %s", line);
|
||||
complain_fail();
|
||||
}
|
||||
|
||||
|
@ -469,7 +576,7 @@ d_pragma(struct place *p, struct place *p2, char *line)
|
|||
static const struct {
|
||||
const char *name;
|
||||
bool ifskip;
|
||||
void (*func)(struct place *, struct place *, char *line);
|
||||
void (*func)(struct lineplace *, struct place *, char *line);
|
||||
} directives[] = {
|
||||
{ "define", true, d_define },
|
||||
{ "elif", false, d_elif },
|
||||
|
@ -489,13 +596,13 @@ static const unsigned numdirectives = HOWMANY(directives);
|
|||
|
||||
static
|
||||
void
|
||||
directive_gotdirective(struct place *p, char *line)
|
||||
directive_gotdirective(struct lineplace *lp, char *line)
|
||||
{
|
||||
struct place p2;
|
||||
size_t len, skip;
|
||||
unsigned i;
|
||||
|
||||
p2 = *p;
|
||||
p2 = lp->current;
|
||||
for (i=0; 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,11 +29,21 @@
|
|||
|
||||
#include <stddef.h>
|
||||
|
||||
struct place;
|
||||
#include "place.h"
|
||||
|
||||
/*
|
||||
* Relevant places while we're processing a line:
|
||||
* the place in the current line
|
||||
* the beginning of the next line
|
||||
*/
|
||||
struct lineplace {
|
||||
struct place current;
|
||||
struct place nextline;
|
||||
};
|
||||
|
||||
void directive_init(void);
|
||||
void directive_cleanup(void);
|
||||
|
||||
void directive_gotline(struct place *p, char *line, size_t len);
|
||||
void directive_gotline(struct lineplace *lp, char *line, size_t len);
|
||||
void directive_goteof(struct place *p);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -27,6 +27,6 @@
|
|||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "bool.h"
|
||||
|
||||
bool eval(struct place *p, char *expr);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -28,9 +28,11 @@
|
|||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "union.h"
|
||||
#include "array.h"
|
||||
#include "mode.h"
|
||||
#include "place.h"
|
||||
|
@ -38,15 +40,21 @@
|
|||
#include "output.h"
|
||||
|
||||
struct expansionitem {
|
||||
bool isstring;
|
||||
enum { EI_STRING, EI_PARAM, EI_FILE, EI_LINE } itemtype;
|
||||
union {
|
||||
char *string;
|
||||
unsigned param;
|
||||
};
|
||||
char *ei_string; /* for EI_STRING */
|
||||
unsigned ei_param; /* for EI_PARAM */
|
||||
} UN;
|
||||
};
|
||||
DECLARRAY(expansionitem, static UNUSED);
|
||||
DEFARRAY(expansionitem, static);
|
||||
|
||||
#ifdef NEED_UNION_ACCESSORS
|
||||
#define ei_string un.ei_string
|
||||
#define ei_param un.ei_param
|
||||
#endif
|
||||
|
||||
|
||||
struct macro {
|
||||
struct place defplace;
|
||||
struct place expansionplace;
|
||||
|
@ -76,8 +84,8 @@ expansionitem_create_string(const char *string)
|
|||
struct expansionitem *ei;
|
||||
|
||||
ei = domalloc(sizeof(*ei));
|
||||
ei->isstring = true;
|
||||
ei->string = dostrdup(string);
|
||||
ei->itemtype = EI_STRING;
|
||||
ei->ei_string = dostrdup(string);
|
||||
return ei;
|
||||
}
|
||||
|
||||
|
@ -88,8 +96,8 @@ expansionitem_create_stringlen(const char *string, size_t len)
|
|||
struct expansionitem *ei;
|
||||
|
||||
ei = domalloc(sizeof(*ei));
|
||||
ei->isstring = true;
|
||||
ei->string = dostrndup(string, len);
|
||||
ei->itemtype = EI_STRING;
|
||||
ei->ei_string = dostrndup(string, len);
|
||||
return ei;
|
||||
}
|
||||
|
||||
|
@ -100,8 +108,30 @@ expansionitem_create_param(unsigned param)
|
|||
struct expansionitem *ei;
|
||||
|
||||
ei = domalloc(sizeof(*ei));
|
||||
ei->isstring = false;
|
||||
ei->param = param;
|
||||
ei->itemtype = EI_PARAM;
|
||||
ei->ei_param = param;
|
||||
return ei;
|
||||
}
|
||||
|
||||
static
|
||||
struct expansionitem *
|
||||
expansionitem_create_file(void)
|
||||
{
|
||||
struct expansionitem *ei;
|
||||
|
||||
ei = domalloc(sizeof(*ei));
|
||||
ei->itemtype = EI_FILE;
|
||||
return ei;
|
||||
}
|
||||
|
||||
static
|
||||
struct expansionitem *
|
||||
expansionitem_create_line(void)
|
||||
{
|
||||
struct expansionitem *ei;
|
||||
|
||||
ei = domalloc(sizeof(*ei));
|
||||
ei->itemtype = EI_LINE;
|
||||
return ei;
|
||||
}
|
||||
|
||||
|
@ -109,8 +139,14 @@ static
|
|||
void
|
||||
expansionitem_destroy(struct expansionitem *ei)
|
||||
{
|
||||
if (ei->isstring) {
|
||||
dostrfree(ei->string);
|
||||
switch (ei->itemtype) {
|
||||
case EI_STRING:
|
||||
dostrfree(ei->ei_string);
|
||||
break;
|
||||
case EI_PARAM:
|
||||
case EI_FILE:
|
||||
case EI_LINE:
|
||||
break;
|
||||
}
|
||||
dofree(ei, sizeof(*ei));
|
||||
}
|
||||
|
@ -120,17 +156,23 @@ bool
|
|||
expansionitem_eq(const struct expansionitem *ei1,
|
||||
const struct expansionitem *ei2)
|
||||
{
|
||||
if (ei1->isstring != ei2->isstring) {
|
||||
if (ei1->itemtype != ei2->itemtype) {
|
||||
return false;
|
||||
}
|
||||
if (ei1->isstring) {
|
||||
if (strcmp(ei1->string, ei2->string) != 0) {
|
||||
switch (ei1->itemtype) {
|
||||
case EI_STRING:
|
||||
if (strcmp(ei1->ei_string, ei2->ei_string) != 0) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (ei1->param != ei2->param) {
|
||||
break;
|
||||
case EI_PARAM:
|
||||
if (ei1->ei_param != ei2->ei_param) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case EI_FILE:
|
||||
case EI_LINE:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -298,7 +340,7 @@ macrotable_cleanup(void)
|
|||
|
||||
static
|
||||
struct macro *
|
||||
macrotable_findlen(const char *name, size_t len, bool remove)
|
||||
macrotable_findlen(const char *name, size_t len, bool remove_it)
|
||||
{
|
||||
unsigned hash;
|
||||
struct macroarray *bucket;
|
||||
|
@ -319,7 +361,7 @@ macrotable_findlen(const char *name, size_t len, bool remove)
|
|||
}
|
||||
mlen = strlen(m->name);
|
||||
if (len == mlen && !memcmp(name, m->name, len)) {
|
||||
if (remove) {
|
||||
if (remove_it) {
|
||||
if (i < num-1) {
|
||||
m2 = macroarray_get(bucket, num-1);
|
||||
macroarray_set(bucket, i, m2);
|
||||
|
@ -335,9 +377,9 @@ macrotable_findlen(const char *name, size_t len, bool remove)
|
|||
|
||||
static
|
||||
struct macro *
|
||||
macrotable_find(const char *name, bool remove)
|
||||
macrotable_find(const char *name, bool remove_it)
|
||||
{
|
||||
return macrotable_findlen(name, strlen(name), remove);
|
||||
return macrotable_findlen(name, strlen(name), remove_it);
|
||||
}
|
||||
|
||||
static
|
||||
|
@ -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);
|
||||
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
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -27,13 +27,13 @@
|
|||
* 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]);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -27,7 +27,10 @@
|
|||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#ifndef PLACE_H
|
||||
#define PLACE_H
|
||||
|
||||
#include "bool.h"
|
||||
|
||||
enum places {
|
||||
P_NOWHERE,
|
||||
|
@ -50,7 +53,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 */
|
||||
|
|
11
cde/util/tradcpp/tests/t38.c
Normal file
11
cde/util/tradcpp/tests/t38.c
Normal 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()
|
8
cde/util/tradcpp/tests/t38.good
Normal file
8
cde/util/tradcpp/tests/t38.good
Normal file
|
@ -0,0 +1,8 @@
|
|||
2
|
||||
"t38.c"
|
||||
4
|
||||
"t38.c":5
|
||||
"t38.c":500
|
||||
"foo.c":600
|
||||
hello
|
||||
"foo.c":602
|
21
cde/util/tradcpp/tests/t39.c
Normal file
21
cde/util/tradcpp/tests/t39.c
Normal 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)
|
11
cde/util/tradcpp/tests/t39.good
Normal file
11
cde/util/tradcpp/tests/t39.good
Normal file
|
@ -0,0 +1,11 @@
|
|||
=123:: 456
|
||||
------
|
||||
=123:: 456
|
||||
------
|
||||
= 123:: 456
|
||||
------
|
||||
= 123:: 456
|
||||
------
|
||||
=123:: 456
|
||||
------
|
||||
=123:: 456
|
6
cde/util/tradcpp/tests/t40.c
Normal file
6
cde/util/tradcpp/tests/t40.c
Normal file
|
@ -0,0 +1,6 @@
|
|||
#define foo bar
|
||||
|
||||
#define bar(x) do x do
|
||||
|
||||
foo(de)
|
||||
|
1
cde/util/tradcpp/tests/t40.good
Normal file
1
cde/util/tradcpp/tests/t40.good
Normal file
|
@ -0,0 +1 @@
|
|||
do de do
|
|
@ -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.
|
||||
|
|
36
cde/util/tradcpp/union.h
Normal file
36
cde/util/tradcpp/union.h
Normal 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
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue