Commit 3f47016b authored by Koen Martens's avatar Koen Martens

Add empty lines to #else if replacing #elif to avoid deleting lines.

parent 2f0c9d4c
Symbian v0.1. Mike Kinghan.
* Added getopt.c and getopt.h for Standard C compatibility.
* Added implementations for err(), errx(), warnx(), vwarnx() for
Standard C compatibility.
* New: Added options -v, -h
* New: Made usage() much more explanatory.
* New: Accept `defined x' as well as `defined (x)' as per C Standard.
* New:
Handle #defines and #undefs:
We will drop a `#define sym' that reiterates a -Dsym.
(But we can't drop `#define sym val' even if it
reiterates -Dsym=val, because macro substitution may
depend on it.)
We will drop an `#undef sym' that reiterates a -Usym
We will replace `#define sym....' with an #error
when it contradicts -Usym or when it is a differing
redefinition of -Dsym[=val].
We will replace `#undef sym' with an #error when it
contradicts -Dsym[=val]
* New:
Simplify truth-functional #ifs where possible even when
they cannot be eliminated on the basis of the -D or -U assumptions,
* Opt:
Introduce fast comparison op_cmp() in place of frequent calls
to strncmp() and strlen() on 1 or 2 byte strings.
* Opt:
The debug() function tested the debugging flag in every call
and did nothing in case false. Replace it with function ptr
debug that is initialised -> debug_live() when debugging == true
and empty function debug_dummy() when debugging == false.
* Opt:
Eliminated numerous strlcmp() calls re-testing initial
substrings of the same string.
* Fix:
Line continuations were recognised by skipcomment()
but on reading a line continuation it did not extend
the line buffer to get the rest of the continued line.
So e.g.
#define \
was construed as an insoluble #if followed by a plain
* Fix: eval_table() had two early returns with LT_IF in which it failed
to update the output argument char **cpp. This could lead
to a line being classified LS_DIRTY - not a possible
preprocessor line - when it was a valid preprocessor line.
Symbian v0.1.1 Mike Kinghan.
* Fix:
Shortcircuit evaluation of binary truth functors did not
respect operator precedence.
Symbian v0.1.2 Mike Kinghan.
* Fix:
Shortcircuit evaluation of binary truth functors was
broken in attempting to respect operator precedence.
* Fix:
Shortcircuit evaluation of binary truth functors
sometimes failed to propagate the value of shortcircuited
* Fix:
Invalid fall-through in getline() from symbol-not-found case
to ignore-symbol case.
Symbian v0.2 Mike Kinghan
* New:
Substantial new logic to achieve a consistent handling of
constants (in the absence of -k), both in cases like #if 1,
#if 0, and in cases where constants are truth-functionally
combined with non-constant expressions.
* Fix:
Previous optimisation had broken keywordedit()
Symbian v0.2.1 Mike Kinghan
* Fix:
#ifs of the form p && q or p || q with q constant and p
and p an insoluble expression where not handled correctly.
This version also contains inactive code preparatory to
resolving truth-functional tautologies and contradictions
in #ifs even where the operands are insoluable expressions.
Symbian v1.0.0 Mike Kinghan
* New:
Errors diagnosing conflicts between the -U or -D assumptions
and #defines or #undefs encountered on input are now reported
on stderr, as well as reflected by #error directives on stdout.
* Fix:
A missing newline at the end of a preprocessor directive at EOF
is now reported as a non-fatal error, rather than provoking abort().
Symbian v1.0.0a Mike Kinghan
* Temporary hack version to enable system testing pending better handling
for case of:
#undef FOO
#define FOO
Emitted #error directives are made comments for now.
Symbian v1.0.1 Mike Kinghan
* Fix:
When -DFOO[=STRING] is passed we're now smart enough to treat the
input sequence:
#undef FOO
#define FOO[=STRING]
as innocuously redundant. It is deleted, rather than diagnosing
a contradiction at #undef FOO.
Symbian v1.0.2 Mike Kinghan
* Fix:
When deleting a superfluous bracket, now replace it with a space
instead of a '\v' ('\v'es being erased on output). This fixes the
bug whereby e.g.
# if(FOO == 0)
becomes # ifFOO == 0
Symbian v1.0.3 Mike Kinghan
* Fix:
v1.0.1 introduces a bug: it is possible for a deferred #error
diagnostic if and when it is output to overwrite the next "real"
line of pending output, so that the #error is output twice and the
real output line not at all. Now fixed.
The fix in 1.0.1 was hastily tied off in respect of stderr output.
The innocuous input sequence:
#undef FOO
#define FOO[=STRING]
was deleted on stdout, but on stderr the #undef still provoked
an error diagnostic, and the following #define produced another
diagnostic to "excuse" the previous one. stderr is aligned with
stdout out and made silent for this input sequence
The fix in v1.0.2 is the undesirable side-effect of leaving
superfluous whitespace instead of superfluous brackets. The fix is
now refined so that a superfluous bracket is deleted when it is
safe to do so and otherwise replaced with a space. "Safe" means
the superfluous bracket is flanked by whitespace or another bracket.
Symbian v1.0.4 Mike Kinghan
* New:
Simplification will no longer remove redundant parentheses from
a directive if it is otherwise unchanged. In the interest of
minimising insignificant diffs v. original code lines which are
not __materially__ simplified will be left alone.
Symbian v1.0.5 Mike Kinghan
* Fix:
find_sym() was erroneously reporting a match of name1 with name2 if
name1 was an initial substring of name2. Overlooked side-effect of
replacing strlcmp() with strncmp().
#define and #undef directives were being processed without prior
decision as to whether the current if-state required them to be
dropped. Thus e.g. with unifdef -UUNDEFINED -DDEFINED the sequence
#undef DEFINED
was provoking a "contradictory #undef" diagnostic.
Symbian v1.0.6
* New:
If an EOF-in-comment error is given, the diagnostic now includes the
line number at which the unclosed comment begins.
* Fix:
Debug output fpr #defines and #undefs was garbled.
Symbian v1.1.0 Mike Kinghan.
* New:
Handling of quoted strings ("<string>" or '<string>') is
implemented. This eliminates broken behaviour when
comment-delimiters occur within quoted strings. The implementation
is within the function formerly known as "skipcomment()",
which is now more suitably called "chew_on()";
chew_on() treats paired double-quotes and paired single-quotes as
equivalent delimiters of text within which it will not parse
quotations of the other kind. It leaves the detection of
single-quote strings that are illegal character constants
to your compiler.
chew_on() parses '\' as the escape character. A quote character that
is preceded by an unescaped escape is parsed as escaped, i.e. it
does not open or close a quotation.
chew_on() will not parse the start of a comment within quotation, but
it will parse quotation within a comment, and will parse the end of
a comment within quotation within a comment. If an open quotation
is left dangling when a containing comment closes, the quotation
is deemed to be closed. chew_on() gives an error if an unescaped
newline occurs within quotation that is not within a comment.
Thus chew_on() will never enter a an in-comment state within
quotation, but it tolerates all the following as comments.
(As I cannot nest C-comments, '{{' denotes a C-comment opening
and '}}' denotes a C-comment closure.)
// This comment has contains an unclosed "-character.
// This comment doesn't but it contains an unclosed single quote.
{{ The following comment terminator isn't quoted by the
previous apostrophe or by this "-character }}
Unifdef now gives error if EOF is read within quotation or within
a comment. The diagnostic refers to the line number at which the
dangling comment or quotation begins.
* New:
A new commandline option -x is introduced to control the policy for
handling #defines or #undefs that contradict the -D or
-U assumptions. 3 policies are provided:
-xd A contradictory #define or #undef is just deleted
-xc A diagnostic comment is inserted in place of the
contradictory directive
-xe A diagnostic #error directive is inserted in place
of the contradictory directive
A diagnostic is written to stderr whatever the policy
* New:
Experimental code is removed because I have decided it has no future.
Symbian v1.1.1 Mike Kinghan.
* New:
The program now provides discriminating return codes. If the return
code is negative then unifdef ended abnormally and the input was
not completely processed. The abend codes are:
-1 = Commandline line usage error.
-2 = Some resource was exhausted, probably memory.
-3 = A system error stopped execution.
-4 = Unifdef bailed out in confusion, due to a logic bug
If the return code is non-negative then it is a bitmask.
If all bits are clear then the input was valid and has been copied
to output unchanged.
If return code & 1 is clear then the input was valid.
If return code & 1 is set then the input was found to be in error.
If return code & 2 is set then some input lines were deleted on
If return code & 4 is set then #defines or #undefs in contradiction
of the -Ds and -Uswere deleted on output.
If return code & 8 is set then contradictory #defines or #undefs
were replaced with diagnostic comments.
If return code & 16 is set then contradictory #defines or #undefs
were replaced with diagnostic #errors.
The flagging of contradictions does not entail that the input was
in error (return code & 1 may be clear).
If return code & 32 is set then a parsing error was found
(and return code & 1 is set).
Thus unproblematic return codes are 0 and 2. Return codes that are
odd or negative mean the output is not valid for the CPP.
* Fix:
The policy flags that were supposed to be -xd, -xc and -xe were in
fact implemented as -x0, -x1 and -x2 respectively.
They are now as intended.
Symbian v1.1.2 Mike Kinghan
* Fix:
The tool distinguishes the #-line statuses LT_CONSISTENT_DEFINE_KEEP
and LT_CONSISTENT_DEFINE_DROP, depending on whether a #define was
non-contradictory and non-redundant vis-a-vis -Ds and -Us, or
non-contradictory but redundant. But it neglected to make the same
necessary distinction for #undefs. They were just distinguished as
either contradictory or non-contradictory any non-contradictory
was #undef was dropped.
* New:
The warning "output may be truncated" that was issued for any
terminal error was unsatisfactorily vague. A new terminal error
message gives the return code and states whether end-of-input was
in fact reached.
* New:
The non-portable unix APIs err(), errx(), warnx() etc. do not well
answer our diagnostic needs since we have started to compose
provisional diagnostics for deferred use, so a second family of
diagnostic functions was introduced based on vcomplain(). This
became messy. All diagnostic functions are now based on vcomplain()
and the unix APIs are dispensed with.
Symbian v1.1.3 Mike Kinghan
* Fix:
The debug() optimisation of v0.1 introduced a bug that bites if
debug() is called before all the commandline arguments were parsed,
because the symbol would still be an uninitialised function pointer
(NULL). This would occur e.g. if a -D or -U symbol was found to be
a duplicate. The function pointer is now initialised to &debug_live.
* Fix:
A repercussion of parsing quotation is that we now also need to
recognise the #error directive as initiating a sort of comment-state
within which quotations need not be well-formed. Otherwise an #error
directive like:
#error You can't define FOO and BAR at the same time!
is faulted for newline within '...
A new chew_on()-state called ERROR_COMMENT is introduced for this
purpose. The ERROR_COMMENT state is like the CXX_COMMENT state
except that it is terminated by the start of a C comment as well
as by a newline.
* Fix:
Innocuous logic error in chew_on() could cause an unescaped newline
within quotation within a comment to be processed twice.
* New:
Shared use of static scratch buffer for assembling formatted output
was too fragile, and needed a static MAXLINE. Safe dynamic solution
Symbian v1.1.4 Mike Kinghan
* Fix.
Trashed the line-count in 1.1.3 :(
Symbian v1.1.5 Mike Kinghan
* Fix:
It was possible for chew_on() to return leaving itself
falsely in the escape state.
Recognised that text following
#define NAME[(arg,...)]
until an unescaped newline must be parsed in the same way as the
text of an #error directive, i.e. as a sort of pseudo-comment that
is indefeasibly closed by unescaped newline or by the opening of a
true comment. Therefore have renamed the ERROR_COMMENT state
introduced in 1.1.3 as PSEUDO_COMMENT and forced the PSEUDO_COMMENT
state on the definiens of a #define.
PSEUDO_COMMENT requires the diagnostic for EOF-within-comment to be
generalised and that an opening line number for this disgnostic
shall be recorded just after every #error and every
#define NAME[(arg,...)]. The diagnostic is now:
"EOF within comment, #error ... or #define ... context \
commencing at line <line>"
A line-continuation sequenence that is inadvertently not escaped
can trigger this diagnostic for C++ comments, #errors or #defines.
The strip_newline() function that I used to remove the terminal
newline from the end of a line preparatory to quoting it in a
diagnostic was the source of a bug when I called it before I had
finished parsing the line. strip_newline() is now dispensed with
in favour of more recherche but safer sprintf() formatting.
* New:
Now check for duplicated or contradictory -Ds and -Us while parsing
commandline. Complain on duplicate. Bail on contradiction.
* New:
Complain when we output an #error directive not in #if-scope. This
indicates either that our -D and -U assumptions conflict with
conditions that the authors of the code wished to assert or else
that the code was already going to #error.
If #error was unconditional on input, say:
"An unconditional #error directive was input".
If #error has been made unconditional by our assumptions, say:
"An unconditional #error directive was output".
* New:
Now complain of garbage following conditional directives. The
common error "#else if..." instead of #elif" gets this diagnostic
and is parsed as #else. The legacy behavior for garbage on
#-lines silently discarded the current truth-state and instated
an unresolved state.
The new diagnostics for unconditional #error directives and
garbage after preprocessor directive are not classified as parse
errors - they are warning - but would be indistinguishably reported
on stderr by the existing diagnostic machinery and not reflected
in the return code.
The return codes and diagnostics are now rationalised on a
severity/reason-code model. Every diagnostic has a distinct reason
code that also encodes a severity. 4 severities are now assigned..
The severity of a reason code R is R & 0x1ff.
A small number of reason codes are __summary__ reason codes,
i.e. they belong to summary diagnostics that are written to
stderr at termination. 4 summary reason codes are now assigned.
All return codes are now non-negative and the return code is always
a bitmask of severities and summary reason codes.
The return code encodes each distinct severity and each distinct
summary reason code that has accrued in the course of execution.
A return code RC can be interpreted as follows:
Execution ended with 0 diagnostics.
Good end of input reached.
Execution ended with at worst informational
Good EOF reached.
Execution ended with at worst warnings.
Good EOF reached.
Execution ended with at worst errors.
Good EOF not reached.
(Errors may be diagnosed in the commandline
arguments or in parsing input).
Execution was aborted by an environment or internal
error, including unavailability of resource.
Good EOF not reached..
(Inability to open an input file is classified as an
abend, though it may in fact result from user error).
Input lines were dropped on output
Input lines were changed on output
Input lines were changed to #errors on output,
because they contradicted the -Ds or -Us.
An unconditional #error was output.
Every diagnostic written on stderr includes its reason code.
The severity of the reason code is expressed in the diagnostic
with the appropriate format chosen from:
"info <reason>:"
"warning <reason>:"
"error <reason>:"
"abend <reason>:"
Reason codes are in ascending order by severity,
i.e info < warning < error < abend.
Symbian v1.1.6 Mike Kinghan
* Fix:
Typo in severities enum caused contention for 1 bit flag
in the return code. Caused exit summary to claim errors when
there had only been info diagnostics
* Fix:
Corrected some errors and ommissions in usage help.
* New:
New commandline option -m controls verbosity. (Has no
effect on the information in the return code.)
suppresses all diagnostics no worse than the specified
suppresses summary diagnostics at exit.
suppresses all diagnostics with codes matching all bits
in 0xXXXX
Output all diagnostics.
If no -m specified default is -minfo -msummary (outputs
warnings and worse, no exit summary).
For readability, diagnostics now prefixed just with
unqualified filename of executable rather than full path.
* New:
Exit message shorter and clearer: Either:
"Completed [{at|before} EOF with \
{remarks|warnings|errors}], exit code 0xXXXX"
"Aborted, exit code 0xXXX"
* New:
Diagnostics now refer to "foo.cpp: line nnnn:"
rather than "foo.cpp: nnnn:"
Symbian v1.1.7 Mike Kinghan
* Fix:
The "Abort..." exit diagnostic lacked an argument, would
use random memory.
* Fix:
The structure of the return code causes information to
be lost on environments that truncate process return codes
to unsigned char. (Doh!) The structure is therefore revised.
The severity bits are shifted into the low-order four bits
and the summary reason codes are shifted into bits immediately
higher. The 5th-9th bits were idle in the old rc.
Isomorphism is lost between the reason codes as given in
diagnostics and the return code, but this is trivial.
With this arrangement all the severity bits will be returned in
an unsigned char to the environment, and so will all 4 summary
bits that are currently assigned.
Thus a return code is now interpreted:
Symbian v1.1.8 Mike Kinghan
* Fix:
Serious bug caused evaluation of ...op...op... expressions or
for op = && or op = || to stop at the first occurrence.
* Fix:
Shy bug would make it possible for only one of a pair of
parentheses to be deleted in simplifying a directive,
when the other had no flanking whitespace.
* Fix:
Clarified usage help for -k option.
* Fix:
v1.1.7 displayed its version as v1.1.6 for unifdef -v
* Fix:
vbail() failed to record severity in the exit code if no
message was passed.
* Fix:
Superfluous occurrence of word "with" in exit message.
* Fix:
Reason were codes displayed with excess width.
* New:
The previously non-supressable exit message "Completed..."
is now classified as an informational diagnostic, so is
suppressed by -minfo or stronger (and so is suppressed by
* New:
New option -fFILE allows options to be read from FILE.
Symbian v1.2.0 Mike Kinghan
(1.1.8 was supposed to be 1.2.0 but I forgot).
* Fix:
Windows build gave spurious read error on an -f file
if the file contained newlines. The check that fread()
returned bytes = size of file is invalid on Windows
because the read converts CRLFs to LFs. Have relaxed
check so that fread returns > 0.
* Fix:
The sequence
#undef FOO
#define FOO
has been spared a "contradiction" diagnostic in the
presence of -DFOO since 1.0.1. The diagnostic is stored
when #undef FOO is seen but discarded if #define FOO
turns up next. It was a bug however that the warning bit
set in the program return code when the contradiction was
provisionally noted was not returned to its prior set/clear
status when the diagnostic was discarded. Thus the rc could
indicate falsely that warnings had been issued. (Ideally
would not set the warning bit until the diagnostic is actually
issued but in the implementation that is more complicated
than resetting the status quo ante).
* New:
-fFILE option made more flexible - is no longer exclusive
of other commandline args:
Can now occur anywhere in a commandline and the options
read from FILE will be parsed as if they occurred in the
commandline at the position of the -f.
This feature supports drivers that wish to input a constant
-f file for each of variable input files. Previously was
necessary for such a driver to assemble a fresh -f for
each input file so that the input file would be specified
in it. The alternative of redirecting stdin from the
input file would cause all diagnostics to refer to "[stdin]".
The -f option may only occur once (so it may not occur
in the options read from an -f file).
Symbian v.1.2.1 Mike Kinghan
* Fix:
Blanks lines output in lieu of deleted lines when -l used
were wrongly counted as dropped lines rather than changed lines.
* Fix:
Debugging literal for the PSEUDO_COMMENT state had been
left as "#error COMMENT". Changed to "PSEUDO COMMENT"
* Fix:
If an input #undef was found in conflict with the
-Ds and -Us and replaced with a diagnostic comment or #error,
the return code would indicate lines dropped and also lines
changed. Should only indicate lines changed. The monitoring
of lines changed/lines dropped now simplified by just counting
these events at the point of occurrence and then working out
the final status bits at exit.
sunifdef v0.1.0 Mike Kinghan
* New:
Tool renamed sunifdef to escape unifdef compatibility.
Root & branch modularisation of program.
* New:
Long options implemented. Library versions of getopt(),
getopt_long() were non-retentrant, hampering the implementation
of -fFILE. Using our own rentrant getopt_long(). Short
option flags are changed to harmonise with the long option
* New:
Increased tolerance for sequences like:
#undef FOO
#define FOO
when we have -DFOO. We now refrain from complaint if the #undef and
the #define are separated, provided there is only whitespace and
comments in between. We also tolerate e.g.
#undef FOO
#undef FOO
#define FOO
* New:
Hard-coded limit on line length removed.
* New:
Hard-coded limit on number of symbols removed.
* New:
New options:
-r | --replace
-B | --backup [SUFFIX]
support processing of multiple input files.
--replace replaces each input file with the corresponding
output file.
--backup SUFFIX backs up each input file
by appending SUFFIX to input filename.
--replace changes the function of stdin when no input
files are specified. Without --replace stdin will supply the
sole input file, as before. With --replace, stdin will supply
names of input files.
* Fix:
Parentheses that ought to be deleted failed to be deleted when
they closed at end of line.
* Fix:
Modularisation compels back off the debug() optimisation
of v0.1 because extern function ptr
void (*debug)(const char *,...) does not honour variable
sunifdef v0.1.1 Mike Kinghan
* New:
Doxygen comments.
* Fix:
ptr_vector_insert() failed to extend heap block sufficiently on demand;