Commit Graph

339 Commits

Author SHA1 Message Date
Michael Schroeder 7d3a87ca18 Remove duplicated code in macro expansion
The code for macro existence checking and flag processing
is exactly the same.
2020-02-10 15:41:33 +02:00
Panu Matilainen abcb0af241 Refactor %{verbose:...} handling out of doFoo()
%{verbose:...} is special due to conditional expansion so it makes
sense to have the logic separated. No functional changes.
2020-02-10 14:43:50 +02:00
Panu Matilainen 47dbb3e070 Don't double-expand arguments to built-in macros (#311)
Double-expanding the output makes it rather impossible to reliably
handle filenames (and other content) with % characters in them.

Fixes: #313
2020-02-10 14:43:50 +02:00
Panu Matilainen b551b256ea Refactor %{expand:...} handling to its own function
%{expand:...} is a rather special built-in as its *purpose* is to
double-expand its argument, so it makes sense to separate it from
the others.

No functional changes intended here.
2020-02-10 14:43:50 +02:00
Panu Matilainen 227cddca88 Fix %{uncompress:...} double-expanding arguments + other miscellania
%{uncompress:...} is fairly complicated as far as builtin macros go:
it needs to first expand its argument to discover the actual file
its supposed to look at, then determine whether the file exists and
what sort of compression to use, then determine the macro to use
for decompressing that kind of file, expand said macro and finally
catenate the expanded argument to the lot. That's a lot of goo to
do inline doFoo(), so refactor it into a separate function.

Up to now the last step was implemented by re-expanding the argument
too, which makes it impossible to reliably handle paths with percent
signs. Just expand the command, and catenate the argument as deity
intended.

Additionally make behavior with empty argument consistent with other
builtins: %{uncompress:} expands to nothing instead of printing out
an error message with an empty filename.
2020-02-10 14:43:50 +02:00
Panu Matilainen 94623389ba Fix buffer overflow in %{S:...} and %{P:...} macro primitives
We can't assume that a buffer allocated for one thing is sufficient
for another thing. The S and P macros share the same exact logic,
refactor to use common code to avoid having to fix twice, cleaning
up doFoo() a bit in the process.

Fixes: #1019
2020-02-10 14:43:50 +02:00
Michael Schroeder 8b1ea52de3 Double the '%' chars when splitting macro args
Before this commit, there was an "escape" flag that made the macro
expansion keep '%%' escapes. But this did not work for macros
that returned an '%' character by other means.

Remove the old escape mechanism and instead double the '%' characters
when the body is split into argument.

Fixes: #1055
2020-02-06 16:00:27 +02:00
Panu Matilainen da94ee8195 Drop useless %{F:..} built-in macro
I fail to see how this is useful functionality to anybody:

	$ rpm --eval "%{F:foo}"
	filefoo.file
2020-01-29 12:51:26 +01:00
Panu Matilainen 4cae7bc073 Drop bogus const from validName() return 2019-10-30 14:54:09 +01:00
Pavlina Moravcova Varekova ff4ce836e7 Add an error message when rpm fails to open a pipe for shell expansion 2019-09-26 11:37:24 +03:00
Panu Matilainen c5909bd869 Codify built-in macro argument acceptance
Built-in macros either take arguments via %{foo:...} or don't, raise
errors on unexpected and missing arguments.
2019-09-24 14:28:59 +03:00
Michael Schroeder cb4e5e755a Add support for primary expansion to the expression parser
And also wire it to %[ ... ] as new syntax to expand expressions.

We'll add short-circuit support in the next commit.
2019-09-23 12:49:21 +03:00
Michael Schroeder bebd15081a Add findMacroEnd() function to find the end of a macro call
Refactor expandMacro to use this function. We'll also make use
of it in the expression parser in a future commit.
2019-09-23 12:49:21 +03:00
Michael Schroeder 7659f40cfe Do not expand %{expr:} again after evaluating the expression 2019-09-18 15:06:23 +03:00
Michael Schroeder c9e34b257e Drop slen from builtin macro parser function
The calculation of the slen parameter was not correct, as it didn't
account for already processed characters. The parameter itself was
also not used to limit the passed string, as the code assumed zero
termination. Thus we can as well simplify the code by using strlen()
on the passed string.
2019-09-18 11:11:31 +03:00
Panu Matilainen 3a6a7cf691 Add %{expr:...} macro for parsing expressions
Supports the same expressions as spec %if conditions because, well,
it's the same expression parser. Only this returns the result as
a string instead of a boolean.
2019-08-21 15:39:40 +03:00
Pavlina Moravcova Varekova 7131d84ecf Print newline after "failed to load macro file" error is emitted 2019-07-08 11:45:09 +02:00
Panu Matilainen 44180fc740 Implement %dnl (discard to next line) macro primitive for comment use
There has been no way to add comments to multiline macros, and while
spec files technically support #-commenting at beginning of lines, it
does not apply to all sections and causes generation after generation
of packagers to stumble on the same items over and over: macros
are expanded within spec comment lines, which makes commenting multiline
macros such as %configure annoying, comments inteded for scriptlets
end up being in the previous scriptlets body, and numerous other quirks.

This implements the M4-inspired %dnl macro primitive which literally
discards everything until the next newline (or end of string), without
expanding the contents. This allows comments to be used inside multiline
macros and everywhere in spec.

Caveat: in some places such as %description the newline doesn't actually
get discarded but this is a a spec parser issue, not on the macro side.

Closes: #158
2019-06-19 14:22:11 +02:00
Panu Matilainen 20797ad209 Report file name and line number on all macro file errors and warnings
Report file name and/or line number on macro errors if %__file_name
and/or %__file_lineno macros are defined, arrange them to be
appropriately defined when loading macro files. Drop the former per-file
failure counting as its no longer useful. Add a testcase.
2019-05-21 13:54:51 +02:00
Panu Matilainen 3a87f969d3 Return number of read lines from rdcl() macro helper
rdcl() reads line continuations so its useful to know how many
physical lines it read. The returned buffer was never used by anything
so no actual behavior changes here, but we'll need this shortly.
2019-05-21 13:54:51 +02:00
Panu Matilainen 05366596a6 Consider macro file load fail on any errors
The previous "only fail if everything fails" behavior from commit
f7aff1193e is just too arbitrary to live.
If there was a failure, it failed. Period.
2019-05-21 13:54:51 +02:00
Panu Matilainen d86c0c28ab Consolidate macro error reporting to a helper function
No changes to messages or other behavior here.
2019-05-21 13:54:51 +02:00
Pavlina Moravcova Varekova f0ae94b397 Remove nonexistent macro "Q" from the table of builtin macros
The macro was accidentally added in commit 9343ecd.
2019-05-14 09:52:10 +02:00
Pavlina Moravcova Varekova 03909fc4d3 Fix a buffer over-read of an unfinished macro "%{!" expansion
Problem was in a buffer over-read of the memory right after
the end of the allocated area when expanding of an unfinished macro
starting "%{" that can contain only exclamation marks and question
marks. Like "%{", or "%{!", or "%{??!".

Similar problem as in commit 54f24ec548
with the difference that this problem was not found by a memory
sanitizer.

This is a good opportunity to refactor the corresponding code
(setting variables according to the number of exclamation marks and
question mark after % an before the macro).
2019-05-09 14:31:49 +03:00
Panu Matilainen b1db055984 Raise an actual macro error if %{uncompress:...} fails 2019-02-25 16:29:06 +02:00
Panu Matilainen 4fa27e084e Convert %define, %global, %undefine and %dump to work via lookup table too
These are very different from the other built-ins as these do their
own parsing and return a continue address, so we need a separate
prototype for them. Having two pointers for each macro makes the table
a bit ugly but the alternative of tracking type by some other means
would lose type-safety. Other than all the boilerplate needed, this is
remarkably straightforward. No functional changes.

All built-in macros are now invoked via the lookup-table, which means
that adding new built-ins just got more straightforward and less ad hocey
pokey.
2019-01-15 17:03:47 +02:00
Panu Matilainen 93cda82b22 Convert %{trace} to work via the macro lookup table
%trace differs from the others as it doesn't take any arguments,
it just silently eats any passed. Not that it really matters here.
No functional changes.
2019-01-15 15:40:43 +02:00
Panu Matilainen 672c9e378b Convert %{load:...} to work via the macro lookup table
Annoyingly the amount of other boilerplate makes this slightly more code
than the original, but then saner code isn't always smaller, and it does
make expandMacros() smaller, which can only be a good thing.
No functional changes.
2019-01-15 15:31:19 +02:00
Panu Matilainen 311c5fdb0b Convert %{echo:...}, %{warn:...} and %{error:...} to work via lookup table
Handle log level determination inside doOutput() to make the interface
match with the others and as a bonus, make expandMacros() that little
bit smaller again. Empty argument needs to be handled differently
but shouldn't affect functionality.
2019-01-15 15:30:44 +02:00
Panu Matilainen 60327e1865 Convert %{lua:...} to work via builtin lookup table
No functional changes. chkexist and negate arguments are unused for
now, but they could perhaps be used for error condition handling later
(similar to %load)
2019-01-15 15:17:24 +02:00
Panu Matilainen ad0cf2cfa9 Start using the builtin macro table for looking up macro primitives, step 1
Replace the "necessary but clunky" string comparisons in expandMacro()
with a lookup on the builtins. For starters, only the primitives
handled in doFoo() are converted, others will require varying amount
of further changes. chkexist argument is unused by doFoo() but will be
needed later for others, add now to avoid having to change more later.

No functional changes intended, anything like that would simply be a bug.
2019-01-15 15:16:17 +02:00
Panu Matilainen 1c069fe246 Add two missing builtin macros (u2p and F) to the builtins table 2019-01-15 14:21:08 +02:00
Panu Matilainen 858e8c58f6 Make macro lookupBuiltin() work with non-terminated strings
For current uses this shouldn't make any difference, but much of the
macro engine works with string lengths so to avoid having to create
\0-terminated versions of all strings we might look at...
2019-01-15 13:36:46 +02:00
Panu Matilainen 69e8b91dcc Add a built-in macro for fetching number of CPUs, affinity aware and all
There's an increasing number of placing wanting to know the number of
CPU's for parallel processing, and increasingly these things are running
in containers and such where the total host CPU count is not meaningful.
2019-01-15 11:16:04 +02:00
Pavlina Moravcova Varekova 2456c12894 Fix a macro end detection if the first char of a macro line is '}' (#401)
The algorithm that detects the end of a macro counts for all macro chars their level of nested. It iteratively moves from the first char of the macro further.
Before the patch the rpm function does not implement this algorithm correctly. After finishing with the last char of a macro line, it additionally skips one char of the next line. The first char in the line was omitted.

Probably affects every rpm version from this millenium.
2018-03-27 12:29:56 +02:00
Panu Matilainen f7aff1193e Track and log failures when loading macro files
It's much easier for rpm to point out the location of invalid macro
definitions than it is for humans to grep all the places a given rpm
version might look at. Log the macro file path once per file in case
of failures, and additionally return and error if all definitions fail.

Based on patch by Pavlina Moravcova Varekova.
2018-01-08 13:08:45 +02:00
Pavlina Moravcova Varekova 9343ecd94c Disable redefinition or undefinition of a built-in macro
Prior to this patch if a name of a newly created macro was the same as a built-in macro name, the macro looked correctly defined. But the newly defined macro could not be used.

It is obvious that a built-in macro can not be undefined.
2018-01-08 12:53:43 +02:00
Pavlina Moravcova Varekova 25653e5db6 Consolidate macro name verification to helper function 2018-01-08 12:53:31 +02:00
Pavlina Moravcova Varekova 0032ee8c23 Don't expand %{verbose:...} argument on false condition
Prior to this patch %{verbose:...} argument was always expanded, eg:

	rpm -v --eval '%{verbose:%{echo:is verbose}}' \
	       --eval '%{!verbose:%{echo:is not verbose}}'

	is verbose

	is not verbose

Obviously both cannot be true.
2017-10-18 11:27:54 +03:00
Mark Wielaard 62bde9545a Avoid warning about mbAppendStr if lui support isn't enabled.
Guard the whole mbAppendStr function with ifdef WITH_LUA to avoid a
warning when lua support isn't enabled because it is only used inside
the doLua function (which is empty unles WITH_LUA is defined).

Signed-off-by: Mark Wielaard <mark@klomp.org>
2017-10-10 07:39:54 +03:00
Pavlina Moravcova Varekova e9d1ec565d Remove an outdated todo for %trace
I cannot find any reason for the TODO in these days.
2017-09-26 13:14:48 +03:00
Panu Matilainen 44570e253d Remove leftover parentheses, no functional change.
Should've been in commit 206c12acc2.
2017-09-01 11:17:48 +03:00
Panu Matilainen 206c12acc2 Don't assume %{quote:...} is surrounded by whitespace
As implemented in commit cdbc7e1d8b,
%{quote:...} only works when its used to quote the entire argument
and produces garbage when used in middle of other text, such as
"x%{quote:y}z". Not sure there's actual need to do that, but producing
garbage is never good.

Only unquoted separators can split an argument, copy argument manually
to strip any quote characters and adjust the math to match. Oh and
add testcases too.

Thanks to Pavlina Moravcova Varekova for pointing this out.
2017-09-01 10:59:21 +03:00
Panu Matilainen cdbc7e1d8b Support parametric macro argument quoting, take three (#222)
All the nice quote-characters are already spoken for, we need to
do something more special here. Add a special-purpose built-in %{quote:...}
macro which quotes its argument using ASCII unit separator character 0x1f
(so it really shouldn't get into anybodys way) and teach macro argument
splitting to support that.

So with %{quote:...} it's now possible to pass strings containing
whitespace and empty strings as arguments. It might not be pretty, but
it's at least POSSIBLE, and no existing user is bothered by this.
2017-08-31 12:36:32 +03:00
Pavlina Moravcova Varekova d78813fa94 When printMacro() is used, print newline after "(empty)" macro 2017-08-30 10:37:01 +03:00
Pavlina Moravcova Varekova fa39cb730d %trace mb states at the beginning/end of expandMacro must be equal
Macro %trace switched on in a nested stage level writes the trace
until the level is leaved to a lower stage level. This did not
work e.g. for macros containing several condition macros.

For example:
%prep
%define Branch1() {%trace %global Leaf1 "1"}
%define Branch2() {%global Leaf2 "2"}
%define Main() {%{?test1: %Branch1} %{?test1: %Branch2}}
%Main

with the result:
  4>         %global^Leaf1 "1"
  2>     %{?test1: %Branch2}^
  3>       %Branch2^
  4>         %global^Leaf2 "2"

It was because macro expansion is context free. This patch fixes it.
2017-08-30 10:33:14 +03:00
Panu Matilainen 4e647cd979 Eliminate unnecessary "delete" argument to freeArgs()
This became unused and useless with the big scoping change in
commit 237f35f16f. No functional
changes here.
2017-08-22 10:25:56 +03:00
Panu Matilainen 609adaa758 Bump macro max recursion limit up
Fedora java packages are running into the old limit of sixteen nesting
levels (commit b3179e6de3), bump it up
to 64. The old limit lasted almost twenty years, lets see how far this
gets us.
2017-08-21 16:36:32 +03:00
Panu Matilainen 2986e7659d Remove redundant max_macro_depth initialization
Oldies but goodies: the max depth is already initialized in declaration
to _MAX_MACRO_DEPTH which has been the same 16 since late nineties. This
wasn't always the case of course...
2017-08-18 17:12:47 +03:00
Pavlina Moravcova Varekova 94e8cd6058 Make macro %{error:...} cause an actual failure 2017-08-17 16:16:23 +03:00