1
0
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:
Dag-Erling Smørgrav 2023-08-21 19:33:42 +02:00
parent 9b3517a49d
commit 2b7d40ea0c
22 changed files with 198 additions and 63 deletions

View File

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

View File

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

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

View File

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

View File

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

0
tests/000-init.expout Normal file
View File

1
tests/000-init.exprc Normal file
View File

@ -0,0 +1 @@
0

1
tests/000-init.sh Normal file
View File

@ -0,0 +1 @@
unifdef </dev/null >/dev/null 2>&1 || true

6
tests/dangle.c Normal file
View File

@ -0,0 +1,6 @@
#ifdef FIRST
wombats
#endif /* com
mmm
mmmm
ment */

0
tests/dangle.experr Normal file
View File

6
tests/dangle.expout Normal file
View File

@ -0,0 +1,6 @@
#ifdef FIRST
wombats
#endif /* com
mmm
mmmm
ment */

1
tests/dangle.exprc Normal file
View File

@ -0,0 +1 @@
0

1
tests/dangle.sh Normal file
View File

@ -0,0 +1 @@
unifdef dangle.c

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 *, ...);

View File

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