These will be used for making the string handling more efficient,
avoiding allocations, especially when evaluating variable expressions.
Since the string handling has grown quite a bit in the last months,
extract it into its own header file.
No functional change.
As was apparent in VarEvalFlags_ToString, a bit-set was not the best
data type since most of the flags were not freely combinable. The two
flags that could be combined were keepDollar and keepUndef, but even
these have distinguished names in the debug log.
The downside of struct bit-fields is that they need extra helper
functions in C90 (see nonints.h). Exchange these for a few helper
functions in var.c, to keep the code outside var.c simple.
No functional change.
In the past few months I had accidentally used C99 features in the make
code. According to tools/README, tools that are used in the build
system should restrict themselves to C90.
This allows make to build with GCC's options "-pedantic
-Wno-system-headers -Dinline= -Wno-error=cast-qual".
I didn't notice anyone actively complaining though, I just wanted to see
how much work this backporting would be. The identifier __func__ is
still used, as in other tools.
No functional change.
This makes the code easier to read, especially in var.c. It also makes
debugging sessions easier since some debuggers don't show enum
bit-fields symbolically as soon as more than one bit is set.
The code outside var.c is basically unchanged, except that instead of
passing the individual flags, there are 4 predefined evaluation modes.
These suffice for all practical use cases. Only in the implementation
deep inside var.c, the value of the flags keepDollar and keepUndef
differs.
There is no way of passing the struct to EnumFlags_ToString, which means
the ToString function has to be spelled out explicitly. This allows for
fine-tuning the representation in the debug log, to reduce the amount of
uppercae letters.
No functional change.
The name 'NONE' described the bit pattern, which was not useful to
understand its meaning. Omitting VARE_WANTRES only parses the
expression, without evaluating any part of it.
No functional change, not even in debug mode since Enum_FlagsToString
always returns "none" for all-bits-unset.
This change provides for a more natural reading order in the code.
Placing the scope first makes it immediately clear in which context the
remaining parameters are interpreted.
No functional change.
Add back Var_SetWithFlags for the one call that doesn't need to expand
the name.
Now one of the flags is encoded in the function name while the others
are encoded in VarSetFlags. This is inconsistent. Maybe there is a
better way to model the different variants of setting a variable.
After doing the textual renaming across all files, I added a new
function Var_Set that does not expand the variable name. I then undid
the renaming for all calls where the variable name cannot ever contain a
dollar sign. I omitted the word "Expand" from the textual references in
the unit tests and in the debug logging messages since the focus is
usually on the "Set" part, not on the "Expand".
No functional change.
The function names now follow the naming scheme from the other functions
that handle variables.
There are several calls that remain syntactically unchanged but that
omit the call to strchr('$') now. Since all these calls use constant
variable names, there is no functional change.
Most previous calls to Var_Exists use constant variable names. Only the
two calls in parse.c need to expand the variable name.
It may be a good idea to expand the variable name once in VarAssign_Eval
instead of repeating the expansion in each of its special cases.
No functional change.
All callers with a variable name that is guaranteed to not contain a
dollar sign have been converted to call Global_Append instead of the
previous Global_AppendExpand. After that, Global_AppendExpand was
unused, therefore it was effectively just renamed.
The plain Var_Append now does not expand the variable name anymore. It
is used in situations where the variable name is known to not contain a
dollar sign.
This is a preparation for adding Global_Append, corresponding to
Global_AppendExpand.
There are many places where global variables are set or appended to. To
reduce clutter and code size, encode the VAR_GLOBAL in the function
name.
The word Expand in the function names says that the variable name is
expanded. In most of the cases, this is not necessary, but there are no
corresponding functions Global_Set or Global_Append yet.
Encoding the information whether the name is expanded or not in the
function name will make inconsistencies obvious in future manual code
reviews. Letting the compiler check this by using different types for
unexpanded and expanded variable names is probably not worth the effort.
There are still a few bugs to be fixed, such as in SetVar, which expands
the variable name twice in a row.
For printing the status of a GNode, there was already made_name (now
renamed to GNodeMade_Name), which prints user-friendly text instead of
the bare enum constant names.
To do this change confidently, I first had to demonstrate that the
output really affects something other than just the word "UNMADE". There
had not been a test for that case before, and the test immediately
discovered a bug in the -dg2 and -dg3 options. This bug is one of the
oldest in make, dating back to at least 1993.
These markers had been used inconsistently. Furthermore the source code
had not been formatted automatically before 2020 at all, otherwise there
wouldn't have been any trailing whitespace left.
Controlling the expansion of variable expressions using a global
variable and a VARE flag was inconsistent.
Converting the global variable into a flag had to prerequisites:
1. The unintended duplicate variable assignment had to be fixed, as
done in parse.c 1.520 from 2020-12-27. Without this fix, it would have
been necessary to add more flags to Var_Exists and Var_SetWithFlags, and
this would have become too complex.
2. There had to be a unit test demonstrating that VARE_KEEP_DOLLAR only
applies to the top-level expression and is not passed to the
subexpressions, while VARE_KEEP_UNDEF applies to all subexpressions as
well. This test is in var-op-expand.mk 1.10 from 2020-12-28, at least
for the ':@word@' modifier. In ParseModifierPartSubst, VARE_KEEP_UNDEF
is not passed down either, in the same way.
The many constants were invented because at that time I didn't quite
understand the actual outcomes of Var_Parse that need to be
distinguished. There are only a few:
(1) Errors, whether they are parse errors, or evaluation errors or
undefined variables. The old constants VPR_PARSE_MSG and
VPR_UNDEF_MSG are merged into VPR_ERR.
(2) Undefined expressions in a situation in which they are allowed.
Previously the documentation for VPR_UNDEF_SILENT talked about
undefined expressions in situations where they were not allowed.
That case is fully covered by VPR_ERR instead.
(3) Errors that are silently ignored. These are probably bugs.
(4) Everything went fine, the expression has a defined value.
Since make doesn't support variable names containing spaces, this edge
case is not enough reason to stop this feature. Having multiple
variable names as arguments nicely aligns with other directives such as
.for and .export.
The function basename from POSIX has a few unfortunate properties, it is
allowed to return a pointer to static memory. This is too unreliable,
therefore this trivial own implementation.
Now that the parsing of the directives is unified and strict, there is
no need anymore for the dispatched functions to check for unknown
directives. These functions don't even get the information to decide
that since this decision is already done.