script -e -c /usr/bin/true
script -e -c /usr/bin/false
exit with the proper exit code.
2. handle system return value correctly (nabijaczleweli)
3. factor out the conversion of wait status -> shell return code.
The previous variable names were misleading.
Paren_level is not the current level of parentheses but the one from the
beginning of the current output line. For better accuracy, rename it to
line_start_paren_level.
P_l_follow is not the level of parentheses that will be active at some
point in the future, as the previous name suggested. Instead, it is the
level of parentheses right now. For better accuracy, rename it to
nparen. This nicely matches its main usage, which is as index to the
parser_state.paren array.
No binary change.
The struct directly represents the properties of a pair of parentheses,
without forcing the human reader to decode any bitset. This makes it
easier to find the remaining bugs in the heuristic for determining the
kind of parentheses.
No functional change outside debug mode.
This fixes the Clang build, which failed with:
usr.bin/script/script.c:255:1: error:
function 'dooutput' could be declared with attribute 'noreturn'
[-Werror,-Wmissing-noreturn]
The solution is not elegant since it adds a small state machine inside
the parser state, but at least these states only depend on the sequence
of token types and not on any other part of the parser state.
Reported in PR#55453.
The member names in struct parser_state are not trustworthy, for example
in_decl does not correspond to the intuitive definition of "inside a
declaration". To cope with this uncertainty, output the full state of
the parser state to the debug log, not only the changes. This helps to
track the inner state for small differences in the input, such as
between 'typedef enum { TA, TB } TT' and 'enum { EA, EB } ET'.
This hopefully helps in fixing PR#55453.
No functional change outside debug mode.
Since job.c 1.83 from 2003-12-20, the command had been echoed even if
the target had the attribute '.SILENT'.
In sh-flags.exp, each removed 'echo' command is below a target name
matching the pattern 'opt-?j????-tgt-??s-cmd-?i?', which means that the
target was marked as silent, either through a global '.SILENT'
declaration or the command line option '-s' or the attribute '.SILENT'
on the target.
Reported by Alan Barrett in PR#45356.
At least on NetBSD, make cannot be fooled with an environment variable
having an empty name. When running '/usr/bin/env =undefined make', the
argument is parsed as a variable assignment, but putenv(3) refuses to
process an empty variable name. Calling execve(2) directly got a step
further, the kernel didn't filter '=undefined' from the environment
variables. But getenv(3) always returns NULL when querying the
environment variable with the empty name.
On other operating systems, things may be different. Trying to set an
environment variable with an empty name may cause errors in env(1),
putenv(3), execve(2), getenv(3) or other places, so don't add an
automatic test for now.
A line starting with '======' is parsed as a variable assignment, with
an empty variable name and a value starting with '=====', making that
condition unreachable.
No functional change.
Before main.c 1.231 from 2014-09-09, a variable assignment using the
operator '!=' generated a warning "Couldn't read shell's output" if the
output of the command was empty. The simplest way to suppress this
wrong warning was to add an empty 'echo' to the command. This hack is
no longer needed.
Since tools/README 1.5 from 2022-02-03, the tools no longer need to be
compatible with C90, they may now use C99 features. Lint had used
<stdbool.h> and snprintf already.
No functional change.
Fixed in parse.c 1.662 from today. To actually crash make, the end of
the expanded dependency line must be at the end of a mapped region.
There is no guaranteed crash, as this depends on the memory allocator.
NetBSD's jemalloc allocates large contiguous regions, making it less
likely for an allocation to end up at the end of a mapped region. The
memory allocators used by FreeBSD and OpenBSD are better at detecting
such bugs.
Do not use inline functions, remove trailing comma in enum declaration,
do not use 'long long' for printing a timestamp. This re-introduces the
Year 2038 Problem for pre-C99 compilers when printing the trace log, but
that is a seldom used feature.
Using a makefile for defining the test variants allows running several
test variants individually, instead of using a single filter expression.
The test variants can be configured more fine-grained. It is possible
to exclude a few test cases per variant, which is useful for no-regex, a
compile-time switch for excluding the variable modifier ':C'.
Fix the definitions for the C90 tests. Previously they didn't override
the compiler option '-Wsystem-headers', thereby complaining about usage
of 'long long'.
When the modifier ':On' was added on 2021-07-30, there were concerns
that pre-C99 environments would not have the type 'long long', therefore
the type was made configurable, but parsing such numbers was hard-coded
to using strtoll.
To improve compatibility with C90 environments, use 'long' and 'strtol'
in these environments. In C99 environments, use 'long long' and
'strtoll', to account for larger file sizes.
If the flexibility of choosing yet another type for these numbers should
ever arise, it can still be implemented. Until then, reduce the number
of possible build configurations.
Previously, some line numbers were stored as signed int while others
were stored as size_t. Since line numbers are never negative, use an
unsigned type. Since the maximum file size for makefiles is 1 GB (see
loadfile), unsigned int is large enough even on 64-bit platforms.
Using a single data types reduces the number of type conversions. Using
unsigned int improves compatibility with C90 (printf %u instead of %zu),
which is needed by bmake, which is derived from usr.bin/make.
No functional change.
All arguments to DEBUG0 are string literals, and none of them contains a
'%', which makes them safe to pass to printf directly. Any accidental
'%' would be caught by the compiler.
No functional change.
Since main.c 1.373 from 2020-10-18, make does not use iovec anymore, so
remove that test variant.
Document the details of why generating the test coverage took so long on
NetBSD < 10.
Add another test variant with optimization for binary size (-Os), since
with that option, GCC 10 does not perform the same data flow analysis as
with -O2, in particular it gets confused about whether local variables
are correctly initialized across function calls.
Print the approximate location based on the last command that has been
defined for the target. It would be possible to get more detailed
location information by counting the number of commands of the target,
but that would get messy due to .USEBEFORE, .USE and .DEFAULT, and
still, this is an edge case, so don't waste too much code for it now.
Having this hint about the location is more helpful than just a plain
"Variable X is recursive" without any further details.
The only fatal error that occurs while the makefiles are read in is the
one about recursive variables, which didn't give any hint about the
location before.
If a recursive variable is detected while evaluating the commands of a
target to be made, there is no location information, as before.
Reusing the target var-scope-local.o for several tests made the test
more difficult to understand than necessary. The test names '2' and '3'
didn't convey any meaning.
Instead, add more test targets that are named after what they test. Add
tests for each of the 5 variable assignment operators, to demonstrate an
inconsistency between '+=' and '?='.
Add tests for the built-in target-local variables as well and explain
the general concepts, in particular the exact point where target-local
expressions are expanded.
The lines in the expected output file are not generated in the same
order as they appear in the makefile, so allow the 'expect' lines in
non-linear order, in check-expect.lua.
Adding 1 + len bytes but only incrementing the pointer by len bytes
looked suspicious, so use the same expression in both places.
No functional change.
In HashEntry_KeyEquals, the line 'return false' was not covered by any
tests before. Since it is an edge case that two variable names (or
other keys) have the same 32-bit hash code and still differ, better test
for that edge case explicitly since a bug in this place would be rare
and hard to find.
The variable is set in the context of the target.
This syntax has been supported by gmake for ~ever.
If necessary a makefile can set .MAKE.TARGET_LOCAL_VARIABLES=false
to disable this.
Expose GetBooleanExpr so parse.c can use it.
At least on OpenBSD, "If the src and dst strings overlap, the behavior
is undefined" (since 2013-09-25), so rather use memmove instead.
Keep all other bugs for now, for example "/a/b//../" is reduced to
"/a/b/" instead of the correct "/a/", and for repeated "/././././" in
long paths, the performance is quadratic instead of linear.
Inline the two calls to eat_dots, turning the first into a two-liner.
At that point, emode can have only 2 values, none of which is
VARE_UNDEFERR.
No binary change since GCC had figured this out all the time, it just
didn't reveal this little secret.
It was wrong of Parse_File to output an unfinished line and hope for
some other code to finish it. As demonstrated in the test, PrintOnError
did not do that in the case of additional debug output.
To keep the overall behavior as close as possible to before, the other
callers of PrintOnError now have to pass the newline themselves. Passing
strings that start with newlines but don't end with them looked
suspicious anyway.
To trigger the faulty code path, the file where the targets gets its
first command must be included via its relative path. That was the case
when running 'cd usr.bin/make && make test' but not when running the
tests via ATF.
This warning flags the second semicolon of 'return;;' as being
unreachable. It does not warn about these superfluous semicolons in
general though.
Seen in usr.bin/make/bmake_malloc.c.
In meta mode, the affected variable patterns do not contain a '$'.
Outside of meta mode, Global_SetExpand was only called a single time, so
inline that call.
No functional change.