In most cases the Lst functions are only called when the arguments are
indeed valid. It's not guaranteed though, therefore each function call
needs to be analyzed and converted individually.
While here, remove a few statements that were only useful when the Lst
functions handled circular lists.
Lst_Duplicate would have passed through any null pointer, which was not
needed for make. It was the last function that used Lst_AtEnd, which in
turn was the last function that used LstInsertAfter. As a result, these
two functions have been removed.
Since the lists don't contain null pointers, it doesn't make sense to
search for a null pointer. All calls but one already had obviously
non-null arguments. The one remaining call using targ->suff has been
guarded for now.
The code for Lst_Member became much simpler than before. Partly because
the old code had an extra condition for circular lists, which are not
used by make.
Except for once instance in parse.c, the usage pattern for Lst_Dequeue
was to first test whether the list is empty. This pattern allowed the
implementation of Lst_Dequeue to become simpler since the null check is
not needed anymore.
The calls to Lst_Enqueue never pass an invalid list or a null pointer,
therefore making them strict was trivial.
This change ensures that there is actually something added to the list.
Lst_AtEnd had silently skipped the addition if the list was invalid
(null pointer), which was not intended in these cases. The "(void)" is
assumed to mean "I know that this cannot fail", while it could also mean
"I don't care whether something actually happened".
Running "./build.sh -j6 tools" still succeeds after this change,
therefore chances are very low that this change breaks anything. If
there is any change, it's an obvious assertion failure. There is no
silent change in behavior though.
The previous variant of using a special case of Lst_InsertAfter was
unnecessarily complicated. Linked lists are a very basic data
structure, and there is no need to overcomplicate things by introducing
unnecessary conditions and branches.
In several places, it just doesn't make sense to have a null pointer
when a list is expected.
In the existing unit tests, the list passed to Lst_Open is always valid,
but that's not a guarantee for real-world usage. Therefore, Lst_Open
has been left for now, and Lst_OpenS is only the preferred alternative
to it.
Up to now, the list library didn't distinguish between programming
mistakes (violations of invariants, illegal parameter values) and
actually interesting situations like "element not found in list".
The current code contains many branches for conditions that are neither
exercised by the unit tests nor by real-world usage. There is no point
in keeping this unnecessary code.
The list functions will be migrated from their lenient variants to the
stricter variants in small parts, each function getting the S suffix
when it is made strict, to avoid any confusion about how strict a
particular function is. When all functions have been migrated, they
will be renamed back to their original names.
While here, the comments of the functions are cleaned up since they
mention irrelevant implementation details in the API comments, as well
as "side effects" that are really main effects.
The list library had probably been imported from a general-purpose
library that also supported circular lists. These are not used by make
though.
After replacing Lst_Init(FALSE) with Lst_Init(), only a single call to
Lst_Init remained with a non-constant argument, and that was in
Lst_Concat, which was to be expected.
This avoids unnecessary string allocations, especially for long lists.
There is no unit test to cover this code. Since this is an obscure,
undocumented part of make, I wasn't able to come up with a unit test.
Therefore I resorted to write a separate testing program to verify the
expected results.
$ cat <<'EOF' >dir_test.c
#include <stdio.h>
#include "make.h"
#include "dir.h"
int main(int argc, char **argv)
{
int i;
Lst lst;
char *flags;
lst = Lst_Init(FALSE);
for (i = 1; i < argc; i++)
Dir_AddDir(lst, argv[i]);
flags = Dir_MakeFlags("-I", lst);
printf("%s\n", flags);
free(flags);
return 0;
}
EOF
# Needs some trivial patches to Makefile and main.c
$ make PROG=dir_test EXTRA_SRCS=dir_test.c EXTRA_CPPFLAGS=-DNO_MAIN \
COPTS.main.c=-Wno-unused-function NOMAN=1
$ ./dir_test a b c
$ mkdir a b c
$ ./dir_test a b c
-Ia -Ib -Ic
$ rmdir a b c
The new functions have a simpler interface, and str_concat3 is even more
general-purpose, since the middle string is no longer required to be
exactly of length 1.
The previous documentation mentioned Str_Concat, but str_concat has been
written in lowercase for years. The "flags" are not flags since they
cannot be combined, not even when they are written in hex.
Some files use 4 spaces per indentation level, others use 8. At least
for the few files from this commit, they use a consistent style
throughout each file now.
In Cond_Eval, the #define has changed into an enum since the identifiers
need not be visible to the C preprocessor.
NetBSD make is intended to be maximally portable, therefore it uses only
C89. This was not declared in the Makefile before.
There are still a few places in parse.c and metachar.c that use
end-of-line comments. These will be fixed in a follow-up commit.
The UNCONST macro is really terrible.
This segmentation fault can be forced by setting _PATH_DEFSYSMK in
pathnames.h to "./sys*.mk" or any other string that has a slash and a
wildcard to the right of the slash.
Separating the low-level parts into small functions reduces the need for
summarizing comments between the code lines.
Using a consistent naming scheme for the variables and expressive names
makes the code easier to understand. The number of variables has
increased from 7 to 11, their clearer names compensate for that, plus
the fact that they come in triples (x, x_end, x_len). Placing the
variables into appropriate registers and eliminating memory access is
left as an exercise to the compiler.
Before, make could not parse {{thi,fou}r,fif}teen properly. It did
correctly split up the outer brace into "" + "{thi,fou}r,fif" + "teen",
but then, when expanding the inner braces, it interpreted the first
comma already as a separator, even though this comma was enclosed in
another set of braces.
This resulted in the wrong expansion "{thiteen", which produced the
error message. The next word "fouteen" was produced since the parser
stopped at the next closing brace. After this, parsing continued after
the closing brace, producing "rteen". Finally, the last expansion was
the correct "fifteen".
with versions prefixed by MAKE_ATTR_* to avoid modifying the
implementation namespace. Make sure they are available in all places
using nonints.h to fix bootstrap on Linux.