mirror of
https://git.FreeBSD.org/src.git
synced 2024-11-22 07:20:00 +00:00
Import unifdef 2.12
This commit is contained in:
parent
9b3517a49d
commit
2b7d40ea0c
42
.travis.yml
42
.travis.yml
@ -1,19 +1,42 @@
|
||||
language: c
|
||||
|
||||
sudo: false
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- compiler: i586-mingw32msvc-gcc
|
||||
env: BUILD_MINGW="yes"
|
||||
|
||||
before_install:
|
||||
- sudo apt-get -qq update
|
||||
include:
|
||||
## Ubuntu 14.04 Trusty (beta), sudo required!
|
||||
- os: linux
|
||||
dist: trusty
|
||||
sudo: required
|
||||
compiler: gcc
|
||||
env: TRUSTY="yes"
|
||||
- os: linux
|
||||
dist: trusty
|
||||
sudo: required
|
||||
compiler: clang
|
||||
env: TRUSTY="yes"
|
||||
## MinGW / wine
|
||||
- os: linux
|
||||
sudo: required
|
||||
compiler: i586-mingw32msvc-gcc
|
||||
env: BUILD_MINGW="yes"
|
||||
allow_failures:
|
||||
- compiler: i586-mingw32msvc-gcc
|
||||
|
||||
install:
|
||||
- if test "${BUILD_MINGW}" = "yes"; then sudo apt-get -qq install wine; fi
|
||||
- env | grep -v "encrypted" | LC_ALL=C sort
|
||||
- if test "${BUILD_MINGW}" = "yes"; then
|
||||
sudo apt-get -qq update &&
|
||||
sudo apt-get -qq install wine;
|
||||
fi
|
||||
|
||||
script:
|
||||
- if test "${BUILD_MINGW}" != "yes"; then
|
||||
@ -28,8 +51,9 @@ script:
|
||||
make -f win32/Makefile.mingw test;
|
||||
fi
|
||||
|
||||
## whitelist
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- tmp
|
||||
- next
|
||||
- /^travis.*/
|
||||
- /^tmp.*/
|
||||
|
2
COPYING
2
COPYING
@ -14,7 +14,7 @@ remain) so it now carries the more liberal two-clause licence.
|
||||
|
||||
Unless otherwise stated, the files in this package are:
|
||||
|
||||
Copyright (c) 2002 - 2015 Tony Finch <dot@dotat.at>
|
||||
Copyright (c) 2002 - 2020 Tony Finch <dot@dotat.at>
|
||||
|
||||
unifdefall.sh is:
|
||||
|
||||
|
13
README
13
README
@ -11,9 +11,6 @@ Please see the INSTALL file for installation instructions.
|
||||
|
||||
Pre-formatted documentation can be found in unifdef.txt
|
||||
|
||||
You can subscribe to release announcements at:
|
||||
http://freecode.com/projects/unifdef
|
||||
|
||||
You can download the latest release tar and zip files from:
|
||||
http://dotat.at/prog/unifdef
|
||||
|
||||
@ -23,9 +20,10 @@ You can clone the development repository using:
|
||||
I also maintain a copy at http://github.com/fanf2/unifdef
|
||||
(Warning: GitHub's zip download is incomplete and unusable.)
|
||||
|
||||
Please send bug reports and patches to me. Unless you state otherwise,
|
||||
I will assume that any contributions are under the two-clause BSD
|
||||
licence. See the COPYING file for details.
|
||||
Please send bug reports and patches to me via email to the
|
||||
address above. Unless you state otherwise, I will assume that
|
||||
any contributions are under the two-clause BSD licence. See
|
||||
the COPYING file for details.
|
||||
|
||||
Thanks to the following people for their contributions:
|
||||
|
||||
@ -38,6 +36,9 @@ Jonathan Nieder <jrnieder@gmail.com>
|
||||
Anders H Kaseorg <andersk@mit.edu>
|
||||
- bug fixes and other improvements
|
||||
|
||||
Ruediger Meier <ruediger.meier@ga-group.nl>
|
||||
- build and portability cleanups
|
||||
|
||||
Ben Hutchings at Solarflare Communications
|
||||
- lenient evaluation of && and ||
|
||||
|
||||
|
42
ifdef-how.pl
Executable file
42
ifdef-how.pl
Executable file
@ -0,0 +1,42 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
if (@ARGV != 2) {
|
||||
die <<END;
|
||||
usage: ifdef-how <file> <line>
|
||||
|
||||
Print the sequence of preprocessor conditionals which lead to the
|
||||
given line being retained after preprocessing. There is no output
|
||||
if the line is always retained. Conditionals that must be true are
|
||||
printed verbatim; conditionals that musy be false have their
|
||||
preprocessor keyword prefixed with NOT.
|
||||
|
||||
Warning: this program does not parse comments or strings, so it will
|
||||
not handle tricky code correctly.
|
||||
END
|
||||
}
|
||||
|
||||
my $file = shift;
|
||||
my $line = shift;
|
||||
|
||||
open my $fh, '<', $file
|
||||
or die "ifdef-how: open $file: $!\n";
|
||||
|
||||
my @stack;
|
||||
while (<$fh>) {
|
||||
last if $. == $line;
|
||||
if (m{^\s*#\s*(if|ifdef|ifndef)\b}) {
|
||||
push @stack, $_;
|
||||
}
|
||||
if (m{^\s*#\s*(elif|else)\b}) {
|
||||
$stack[-1] =~ s{^(\s*#\s*)(?!NOT)\b}{${1}NOT}gm;
|
||||
$stack[-1] .= $_;
|
||||
}
|
||||
if (m{^\s*#\s*endif\b}) {
|
||||
pop @stack;
|
||||
}
|
||||
}
|
||||
|
||||
print @stack;
|
@ -2,7 +2,8 @@
|
||||
|
||||
line="---------------------------------------------------"
|
||||
|
||||
git log --no-merges --decorate -M --stat --pretty=format:"$line%n%ai %an <%ae>%d%n%n%s%n%n%b" |
|
||||
git log --no-merges -M --stat \
|
||||
--pretty=format:"$line%n%ai %an <%ae>%n%n%s%n%n%b" |
|
||||
uniq | fold -s
|
||||
echo
|
||||
echo $line
|
||||
|
@ -10,6 +10,11 @@ do
|
||||
sh ./${cmd} >${t}.out 2>${t}.err
|
||||
echo $? >${t}.rc
|
||||
|
||||
# strip carriage returns from error output
|
||||
# in case we are trying to run on MinGW
|
||||
tr -d '
' >${t}.xerr <${t}.err
|
||||
mv ${t}.xerr ${t}.err
|
||||
|
||||
ok=true
|
||||
for e in out err rc
|
||||
do
|
||||
|
0
tests/000-init.experr
Normal file
0
tests/000-init.experr
Normal file
0
tests/000-init.expout
Normal file
0
tests/000-init.expout
Normal file
1
tests/000-init.exprc
Normal file
1
tests/000-init.exprc
Normal file
@ -0,0 +1 @@
|
||||
0
|
1
tests/000-init.sh
Normal file
1
tests/000-init.sh
Normal file
@ -0,0 +1 @@
|
||||
unifdef </dev/null >/dev/null 2>&1 || true
|
6
tests/dangle.c
Normal file
6
tests/dangle.c
Normal file
@ -0,0 +1,6 @@
|
||||
#ifdef FIRST
|
||||
wombats
|
||||
#endif /* com
|
||||
mmm
|
||||
mmmm
|
||||
ment */
|
0
tests/dangle.experr
Normal file
0
tests/dangle.experr
Normal file
6
tests/dangle.expout
Normal file
6
tests/dangle.expout
Normal file
@ -0,0 +1,6 @@
|
||||
#ifdef FIRST
|
||||
wombats
|
||||
#endif /* com
|
||||
mmm
|
||||
mmmm
|
||||
ment */
|
1
tests/dangle.exprc
Normal file
1
tests/dangle.exprc
Normal file
@ -0,0 +1 @@
|
||||
0
|
1
tests/dangle.sh
Normal file
1
tests/dangle.sh
Normal file
@ -0,0 +1 @@
|
||||
unifdef dangle.c
|
@ -1,7 +1,10 @@
|
||||
umask 027
|
||||
unifdef -DFOO=1 -DFOOB=42 -UBAR -ooutfile.c if1.c
|
||||
e=$?
|
||||
ls -l outfile.c | cut -d' ' -f1 1>&2
|
||||
case ${BUILD_MINGW} in
|
||||
(yes) printf '%s\n' '-rw-r-----' 1>&2 ;;
|
||||
(*) ls -l outfile.c | cut -d' ' -f1 1>&2 ;;
|
||||
esac
|
||||
cat outfile.c
|
||||
rm outfile.c
|
||||
exit $e
|
||||
|
@ -3,7 +3,10 @@ chmod 640 outfile.c
|
||||
ls -l outfile.c | cut -d' ' -f1 1>&2
|
||||
unifdef -DFOO=1 -DFOOB=42 -UBAR -m outfile.c
|
||||
e=$?
|
||||
ls -l outfile.c | cut -d' ' -f1 1>&2
|
||||
case ${BUILD_MINGW} in
|
||||
(yes) printf '%s\n' '-rw-r-----' 1>&2 ;;
|
||||
(*) ls -l outfile.c | cut -d' ' -f1 1>&2 ;;
|
||||
esac
|
||||
cat outfile.c
|
||||
rm outfile.c
|
||||
exit $e
|
||||
|
@ -1,2 +1,2 @@
|
||||
unifdef: whitespace.c: 3: Obfuscated preprocessor control line (#if line 1 depth 1)
|
||||
unifdef: whitespace.c: 4: Obfuscated preprocessor control line (#if line 1 depth 1)
|
||||
unifdef: Output may be truncated
|
||||
|
38
unifdef.1
38
unifdef.1
@ -182,9 +182,12 @@ utility understands just enough about C
|
||||
to know when one of the directives is inactive
|
||||
because it is inside
|
||||
a comment,
|
||||
or affected by a backslash-continued line.
|
||||
or cannot be evaluated because it is split by a backslash-continued line.
|
||||
It spots unusually-formatted preprocessor directives
|
||||
and knows when the layout is too odd for it to handle.
|
||||
and passes them through unchanged when the layout is too odd for it to handle.
|
||||
(See the
|
||||
.Sx BUGS
|
||||
section below.)
|
||||
.Pp
|
||||
A script called
|
||||
.Nm unifdefall
|
||||
@ -485,30 +488,43 @@ command appeared in
|
||||
support was added in
|
||||
.Fx 4.7 .
|
||||
.Sh AUTHORS
|
||||
.An -nosplit
|
||||
The original implementation was written by
|
||||
.An Dave Yost Aq Dave@Yost.com .
|
||||
.An Tony Finch Aq dot@dotat.at
|
||||
.An Dave Yost Aq Mt Dave@Yost.com .
|
||||
.An Tony Finch Aq Mt dot@dotat.at
|
||||
rewrote it to support
|
||||
.Tn ANSI\~C .
|
||||
.Sh BUGS
|
||||
.Bl -bullet
|
||||
.It
|
||||
Expression evaluation is very limited.
|
||||
.Pp
|
||||
.It
|
||||
Character constants are not evaluated.
|
||||
String literals and character constants in
|
||||
.Fl f
|
||||
definition files are ignored rather than parsed as
|
||||
part of a macro's replacement tokens.
|
||||
.Pp
|
||||
Handling one line at a time means
|
||||
preprocessor directives split across more than one physical line
|
||||
.It
|
||||
Only the basic form of C++ raw string literals is recognized,
|
||||
like
|
||||
.Li R"(string)"
|
||||
without delimiters as in
|
||||
.Li R"delimiter(string)delimiter" .
|
||||
.It
|
||||
Source files are processed one line at a time,
|
||||
so preprocessor directives split across more than one physical line
|
||||
(because of comments or backslash-newline)
|
||||
cannot be handled in every situation.
|
||||
.Pp
|
||||
.It
|
||||
Trigraphs are not recognized.
|
||||
.Pp
|
||||
.It
|
||||
There is no support for macros with different definitions at
|
||||
different points in the source file.
|
||||
.Pp
|
||||
.It
|
||||
The text-mode and ignore functionality does not correspond to modern
|
||||
.Xr cpp 1
|
||||
behaviour.
|
||||
.El
|
||||
.Pp
|
||||
Please send bug reports by email to
|
||||
.Aq Mt dot@dotat.at .
|
||||
|
60
unifdef.c
60
unifdef.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002 - 2015 Tony Finch <dot@dotat.at>
|
||||
* Copyright (c) 2002 - 2020 Tony Finch <dot@dotat.at>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -114,7 +114,8 @@ typedef enum {
|
||||
STARTING_COMMENT, /* just after slash-backslash-newline */
|
||||
FINISHING_COMMENT, /* star-backslash-newline in a C comment */
|
||||
CHAR_LITERAL, /* inside '' */
|
||||
STRING_LITERAL /* inside "" */
|
||||
STRING_LITERAL, /* inside "" */
|
||||
RAW_STRING_LITERAL /* inside R"()" */
|
||||
} Comment_state;
|
||||
|
||||
static char const * const comment_name[] = {
|
||||
@ -848,12 +849,14 @@ parseline(void)
|
||||
if (fgets(tline + len, MAXLINE - len, input) == NULL) {
|
||||
if (ferror(input))
|
||||
err(2, "can't read %s", filename);
|
||||
/* append the missing newline at eof */
|
||||
debug("parser insert newline at EOF", linenum);
|
||||
strcpy(tline + len, newline);
|
||||
cp += strlen(newline);
|
||||
linestate = LS_START;
|
||||
} else {
|
||||
linestate = LS_DIRTY;
|
||||
debug("parser concatenate dangling whitespace");
|
||||
++linenum;
|
||||
cp = skipcomment(cp);
|
||||
}
|
||||
}
|
||||
if (retval != LT_PLAIN && (wascomment || linestate != LS_START)) {
|
||||
@ -974,24 +977,24 @@ struct ops {
|
||||
struct op op[5];
|
||||
};
|
||||
static const struct ops eval_ops[] = {
|
||||
{ eval_table, { { "||", op_or } } },
|
||||
{ eval_table, { { "&&", op_and } } },
|
||||
{ eval_table, { { "|", op_bor, "|" } } },
|
||||
{ eval_table, { { "^", op_bxor } } },
|
||||
{ eval_table, { { "&", op_band, "&" } } },
|
||||
{ eval_table, { { "==", op_eq },
|
||||
{ "!=", op_ne } } },
|
||||
{ eval_table, { { "<=", op_le },
|
||||
{ ">=", op_ge },
|
||||
{ "<", op_lt, "<=" },
|
||||
{ ">", op_gt, ">=" } } },
|
||||
{ eval_table, { { "<<", op_blsh },
|
||||
{ ">>", op_brsh } } },
|
||||
{ eval_table, { { "+", op_add },
|
||||
{ "-", op_sub } } },
|
||||
{ eval_unary, { { "*", op_mul },
|
||||
{ "/", op_div },
|
||||
{ "%", op_mod } } },
|
||||
{ eval_table, { { "||", op_or, NULL } } },
|
||||
{ eval_table, { { "&&", op_and, NULL } } },
|
||||
{ eval_table, { { "|", op_bor, "|" } } },
|
||||
{ eval_table, { { "^", op_bxor, NULL } } },
|
||||
{ eval_table, { { "&", op_band, "&" } } },
|
||||
{ eval_table, { { "==", op_eq, NULL },
|
||||
{ "!=", op_ne, NULL } } },
|
||||
{ eval_table, { { "<=", op_le, NULL },
|
||||
{ ">=", op_ge, NULL },
|
||||
{ "<", op_lt, "<=" },
|
||||
{ ">", op_gt, ">=" } } },
|
||||
{ eval_table, { { "<<", op_blsh, NULL },
|
||||
{ ">>", op_brsh, NULL } } },
|
||||
{ eval_table, { { "+", op_add, NULL },
|
||||
{ "-", op_sub, NULL } } },
|
||||
{ eval_unary, { { "*", op_mul, NULL },
|
||||
{ "/", op_div, NULL },
|
||||
{ "%", op_mod, NULL } } },
|
||||
};
|
||||
|
||||
/* Current operator precedence level */
|
||||
@ -1264,6 +1267,10 @@ skipcomment(const char *cp)
|
||||
incomment = STRING_LITERAL;
|
||||
linestate = LS_DIRTY;
|
||||
cp += 1;
|
||||
} else if (strncmp(cp, "R\"(", 3) == 0) {
|
||||
incomment = RAW_STRING_LITERAL;
|
||||
linestate = LS_DIRTY;
|
||||
cp += 3;
|
||||
} else if (strncmp(cp, "\n", 1) == 0) {
|
||||
linestate = LS_START;
|
||||
cp += 1;
|
||||
@ -1298,6 +1305,13 @@ skipcomment(const char *cp)
|
||||
} else
|
||||
cp += 1;
|
||||
continue;
|
||||
case RAW_STRING_LITERAL:
|
||||
if (strncmp(cp, ")\"", 2) == 0) {
|
||||
incomment = NO_COMMENT;
|
||||
cp += 2;
|
||||
} else
|
||||
cp += 1;
|
||||
continue;
|
||||
case C_COMMENT:
|
||||
if (strncmp(cp, "*\\\r\n", 4) == 0) {
|
||||
incomment = FINISHING_COMMENT;
|
||||
@ -1626,7 +1640,7 @@ xstrdup(const char *start, const char *end)
|
||||
|
||||
if (end < start) abort(); /* bug */
|
||||
n = (size_t)(end - start) + 1;
|
||||
s = malloc(n);
|
||||
s = (char *)malloc(n);
|
||||
if (s == NULL)
|
||||
err(2, "malloc");
|
||||
snprintf(s, n, "%s", start);
|
||||
|
@ -52,11 +52,17 @@
|
||||
/* used by err.c and getopt.c */
|
||||
#define _getprogname() "unifdef"
|
||||
|
||||
/*
|
||||
* The snprintf() workaround is unnecessary in Visual Studio 2015 or later
|
||||
* but dogma dictates that #if directives are not allowed inside unifdef.
|
||||
*/
|
||||
#define snprintf c99_snprintf
|
||||
|
||||
/* win32.c */
|
||||
int replace(const char *old, const char *new);
|
||||
int replace(const char *oldname, const char *newname);
|
||||
FILE *mktempmode(char *tmp, int mode);
|
||||
FILE *fbinmode(FILE *fp);
|
||||
int snprintf(char *buf, size_t buflen, const char *format, ...);
|
||||
int c99_snprintf(char *buf, size_t buflen, const char *format, ...);
|
||||
|
||||
/* err.c */
|
||||
void err(int, const char *, ...);
|
||||
|
@ -31,11 +31,11 @@
|
||||
* remove anything that might be in the way before renaming.
|
||||
*/
|
||||
int
|
||||
replace(const char *old, const char *new)
|
||||
replace(const char *oldname, const char *newname)
|
||||
{
|
||||
if (remove(new) < 0)
|
||||
warn("can't remove \"%s\"", new);
|
||||
return (rename(old, new));
|
||||
if (remove(newname) < 0 && errno != ENOENT)
|
||||
warn("can't remove \"%s\"", newname);
|
||||
return (rename(oldname, newname));
|
||||
}
|
||||
|
||||
FILE *
|
||||
@ -53,9 +53,13 @@ fbinmode(FILE *fp)
|
||||
}
|
||||
|
||||
/*
|
||||
* Windows has _snprintf() but it does not work like real snprintf().
|
||||
* This is more long-winded than seems necessary because MinGW
|
||||
* doesn't have a proper implementation of _vsnprintf_s().
|
||||
*
|
||||
* This link has some useful info about snprintf() on Windows:
|
||||
* http://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
|
||||
*/
|
||||
int snprintf(char *buf, size_t buflen, const char *format, ...)
|
||||
int c99_snprintf(char *buf, size_t buflen, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int outlen, cpylen, tmplen;
|
||||
@ -73,7 +77,7 @@ int snprintf(char *buf, size_t buflen, const char *format, ...)
|
||||
/* Paranoia about off-by-one errors in _snprintf() */
|
||||
tmplen = outlen + 2;
|
||||
|
||||
tmp = malloc(tmplen);
|
||||
tmp = (char *)malloc(tmplen);
|
||||
if (tmp == NULL)
|
||||
err(2, "malloc");
|
||||
va_start(ap, format);
|
||||
|
Loading…
Reference in New Issue
Block a user