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.
These variables all belong to a string variable. Connect them using
FStr, which reduces the number of variables to keep track of.
No functional change.
Require caller to pass a buffer and size if they
want the tempfile not unlinked.
Add Job_TempFile to handle blocking signals around
call to mkTempFile, so that meta_open_filemon can use it
in jobs mode.
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.
The word "context" does not fit perfectly to the variables that are
associate with a GNode, as the context is usually something from the
outside and the variables are more like properties inherent to the
GNode.
The term "global context" fits even less. Since the thing where
variables are looked up is commonly named a scope, use that term
instead.
This commit only renames the global variables VAR_GLOBAL, VAR_INTERNAL
and VAR_CMDLINE, plus a few very closely related comments. These are:
GNode.vars (because of line breaks)
GNode_Free (dito)
varname-make_print_var_on_error.mk
varname-make_print_var_on_error-jobs.mk
The debug message in Var_Stats is left as-is since there is no unit test
for it yet.
The other renamings (variable names "context", "ctxt", as well as
further comments) will be done in a follow-up commit.
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.
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.
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.
Most of the make code already followed the style of explicitly writing
(ptr != NULL) instead of the shorter (ptr) in conditions.
The remaining 50 instances have been found by an experimental,
unpublished check in lint(1) that treats bool expressions as
incompatible to any other scalar type, just as in Java, C#, Pascal and
several other languages.
The only unsafe operation on Boolean that is left over is (flags &
FLAG), for an enum implementing a bit set. If Boolean is an ordinary
integer type (the default), some high bits may get lost. But if Boolean
is the same as _Bool (by compiling with -DUSE_C99_BOOLEAN), C99 6.3.1.2
defines that a conversion from any scalar to the type _Bool acts as a
comparison to 0, which cannot lose any bits.
This macro was supposed to return a boolean expression all the time, it
just hadn't been implemented this way. This resulted in wrong output
for the test sh-flags, in compilation modes -DUSE_UCHAR_BOOLEAN and
-DUSE_CHAR_BOOLEAN, since in ParseCommandFlags, the expression
DEBUG(LOUD) didn't fit into a boolean.
Do not increment a null pointer.
Do not assign to a variable twice in the same statement. To be fair,
this may be safe because of the sequence point when the function is
called, but anyway, it looks too close to undefined behavior.
This is needed to compile bmake with GCC 2.8.1 on SunOS 5.9.
To support ancient systems like this, the whole code of usr.bin/make is
supposed to use only ISO C90 features, except for filemon, which is not
used on these systems.
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.
Having all these flags in a single bitmask makes it harder to see where
exactly they can possibly be used since their state could also be
modified using the unsuspicious job->flags = 0. Using individual names
just leaves the single memset, and that is only used during
initialization.
This means no more unnecessary void pointers in function signatures and
no more abstraction level at checking a single element of a list. In
most cases it is more appropriate to define a function that operates on
the list as a whole, thereby hiding implementation details like the
ListNode from the caller.
The main changes are in the comments, which have been shortened and
corrected.
Some local variables changed their names.
In ParseErrorInternal, the scope of va_start is now narrower.
In ParseDoDependency, the type of tOp has been fixed.
ParseGetLine doesn't take flags anymore but instead a parsing mode.
Previously, the flags had not been combined anyway.
At the beginning of Parse_File, fatals is already guaranteed to be 0, and
even if not, it would be wrong to just discard the fatal errors.
In the cache for stat(2) and lstat(2), only one of the two timestamps
was ever used. To prevent a result from stat(2) leaking into the cache
for lstat(2), there have been two completely separate caches all the
time. Using different fields in the struct was therefore unnecessary.
By removing the redundant field, the internal struct in the cache is the
same as the external struct. This makes one of them redundant, thus
struct make_stat has been renamed to cached_stat, which better describes
its purpose, and the internal struct cache_st has been removed.
Just as before, the cache prevents any direct access to its internal
data. When passing it to the caller, it is copied.
Just as before, the field names of struct cached_stat cannot correspond
to those from struct stat, since the latter are often defined as macros.
Therefore they are prefixed with cst instead of st.
The redundancy had been added on 2020-06-05.
* Replace character literal 0 with '\0'.
* Replace pointer literal 0 with NULL.
* Remove redundant parentheses.
* Parentheses in multi-line conditions are not redundant at the
beginning of a line.
* Replace a few !ptr with ptr == NULL.
* Replace a few ptr with ptr != NULL.
* Replace (expr & mask) == 0 with !(expr & mask).
* Remove redundant braces for blocks in cases where the generated code
stays the same. (Assertions further down in the code would get
different line numbers.)
* Rename parameters in CondParser_String to reflect the data flow.
* Replace #ifdef notdef with #if 0.
The generated code stays exactly the same, at least with GCC 5.5.0 on
NetBSD 8.0 amd64 using the default configuration.
Robust programs don't have extern variable declarations in .c files, as
that risks incomatible definitions that are not detected by the compiler
and invoke undefined behavior. Make make a little more robust.
Since there is only a single variable left that needs to be freed at the
end (and probably never actually needs to be freed since nobody defines
an environment variable named .OBJDIR), there is no need to loop over
these variables.
Nobody defines a global variable named .TARGET since that would have
many unpredictable effects, applying to all targets at once.
Nobody defines an environment variable named .TARGET since that's
against the naming conventions for environment variables and would have
the same effect.
Because of this, there is no point looking up the variables that are
local to a GNode anywhere else. This means they cannot come from the
environment and thus their value doesn't need to be freed after use,
which makes the code simpler.
The newly added accessor functions in make.h refer to external
functions, but since that header is not used anywhere outside of
usr.bin/make, it doesn't matter. Between 2020-08-25 and 2020-10-30,
that header had been referenced by usr.bin/xinstall.
The only purpose of the parameter freeIt is to free the memory
associated with the return value. To do this, no pointer arithmetic is
needed. Therefore, change to a void pointer, to catch accidental use of
that pointer.