Commit Graph

369 Commits

Author SHA1 Message Date
Panu Matilainen 561c59db1b Convert some obvious cases to use rstrndup() instead of manual work
The net win in terms of LoC is not that big but it does make things
that little more readable and obvious.
2020-11-09 09:28:54 +02:00
Panu Matilainen fc31fec661 Pass their own macro entry as an argument (ie self) to all builtins
No intended functional changes, but it's one argument less to pass
around, brings builtins one step closer to how user defined
macros are called and is a step towards supporting options to
builtins as well.
2020-11-04 10:19:40 +02:00
Panu Matilainen ded0282b05 Lose now unnecessary name length member in builtin macro table 2020-11-04 10:19:40 +02:00
Panu Matilainen 94e2c299e2 Handle builtin-macros as defined entries in the macro table
Add the necessary infra to pass and carry a function pointer in the macro
entry, define builtins as part of macro initialization and switch
the main expansion loop to use the macro entry info instead of special
builtin lookup.

This has various nice benefits, such as allowing simple testing whether
rpm supports a given primitive by testing whether said macro is defined
and a small performance boost as an extra lookup for the builtins is
eliminated from all macro expansion cycles.
It also paves way for later implementing various spec constructs as
actual macros instead of the confusing pseudo-macros they are now.

Apart from builtins showing up as defined and macro initialization now
being mandatory, this is not supposed to change any concrete behavior.
2020-11-04 10:19:40 +02:00
Panu Matilainen f691cab7a4 Always copy cli macros in rpmInitMacros()
Even if macrofiles is NULL we (may) have other initialization tasks
to do, always grab the context lock and mind segfaulting when loading
files if macrofiles is NULL.
2020-11-04 10:19:40 +02:00
Panu Matilainen f9a4c0a39a Move builtin type information to flags bitfield
Compacts things a bit and allows for more flexibility later on,
unfortunately at the price of losing type safety. No functinal changes,
just paving way for next steps.
2020-11-04 10:19:40 +02:00
Michael Schroeder 98b71f7a92 Remove common code from expandMacro() and expandThisMacro()
Add a mbInit() function that allocates the buffer, increases the
expansion depth and stashes some values into a MacroExpansionData area.
Add a mbFini() function that decreases the depth again,
restores the values and optionally prints the expansion result.
2020-10-30 12:11:41 +02:00
Michael Schroeder a2e60c0a50 Add new rpmExpandThisMacro() public method
This expands the maco with the specified name. Argument expandsion
for parametric macros can be turned on with the RPMEXPAND_EXPAND_ARGS
flag.
2020-10-30 12:11:41 +02:00
Michael Schroeder ef4241d727 Split mbCreate() function from doExpandMacros() 2020-10-30 12:11:41 +02:00
Michael Schroeder 05eb42be9a Split doExpandThisMacro() from expandMarco()
This eleminates duplicate code.
2020-10-30 12:11:41 +02:00
Michael Schroeder 339510b2bf No longer free the args ARGV in freeArgs
This gets rid of the weird and unneeded ownership transfer and
makes the args seetup more symmetric.
2020-10-30 12:11:41 +02:00
Michael Schroeder 374802f1ad Move setupArgs() function so that it is next to freeArgs()
No functional changes.
2020-10-30 12:11:41 +02:00
Michael Schroeder 9a3fb26ebd Make comments reflect new macro parsing reality 2020-10-30 12:11:41 +02:00
Panu Matilainen 0b75075a8d Shut up bogus Doxygen warnings about undocumented parameters
As of Doxygen >= 1.8.20 it started complaining about anything marked
as @retval being undocumented. As this is widely used in rpm...
Mass-replace all @retval uses with @param[out] to silence. Some of
these are actually in/out parameters but combing through all of them
is a bit too much...

Also escape <CR><LF> in rpmpgp.h to shut up yet another new warning.
2020-10-28 10:40:41 +02:00
Michael Schroeder fec16cc9b5 Fix access of already freed memory in macro expansion
A macro can undefine itself so we must not access the
entry data after we expanded the body.
2020-10-26 07:54:29 +02:00
Michael Schroeder 72ba3dc228 Simplify grabArgs() usage
Change grabArgs to just append the parsed arguments to the
passed args array and do the setupArgs call in expandMacro.
2020-10-26 07:54:29 +02:00
Michael Schroeder 0cd8268ed2 Split setupArgs() function from grabArgs()
We will reuse setupArgs() in the future.
2020-10-26 07:54:29 +02:00
Michael Schroeder 13df6fda91 Split off mbAllocBuf() from expandMacro()
No need to fiddle with the internals of the mb in expandMacro.
2020-10-26 07:54:29 +02:00
Michael Schroeder 6d7fa91949 Fix logic error in grabArgs()
If there was a \ at the end of the buffer, the code would
return a pointer after the trailing \0 leading to unallocated
memory access and weird results in some cases.

See commit 817959609b.
2020-10-23 15:41:24 +03:00
Mark Wielaard b2659f9ec9 Fix warnings from set but unused, variables in macro.c and rpmlua.c
macro.c: In function ‘mbopt’:
macro.c:895:19: warning: unused variable ‘me’ [-Wunused-variable]
  895 |     rpmMacroEntry me = mb->me;
      |                   ^~

rpmlua.c: In function ‘fd_seek’:
rpmlua.c:985:22: warning: unused variable ‘mode’ [-Wunused-variable]
  985 |     static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
      |                      ^~~~

The former is actually unused, the latter should be used.
2020-10-23 15:07:36 +03:00
Panu Matilainen ce79e166fe Wrap getopt() usage into internal helper
Avoids code duplication (glibc quirks and whatnot) between macro and lua
option parsing, isolate the global opt* variable accesses to one spot.
Makes it easier to ensure identical behavior between the users if/when
something changes.

No behavior changes intended.
2020-10-19 11:27:35 +03:00
Michael Schroeder 6de7374bb8 Treat unparsable macros like undefined macros
This seems to be the intention of the code but it did
not work because macro parsing was resumed at the wrong
point of the input string. Without this commit, "%{}"
expanded to "%" instead of "%{}".
2020-10-14 13:27:09 +03:00
Panu Matilainen 67abf72ef5 Pass parametric macro options and arguments to Lua natively (#1092)
We already have the macro arguments in an ARGV that's suitable for
passing to Lua, just store it in the macro buffer for passing around.
As macros can nest arbitrarily, we need to store and restore the mb
args which is a bit hacky, but much less trouble than changing all the
related functions to pass argound an argv which only one function
ever uses. Ditto with the macro entry itself, which is needed to pass
around the options (and name, and maybe something else too later).

Besides all the normal rpm defined macros for arguments and options,
parametric Lua macros now get pre-processed options and arguments
in native local tables "opt" and "arg" for much more pleasant access.
"opt" and "arg" tables are always there even if no options or arguments
were passed, this avoids having to deal with multiple cases and test
for nil's all over the place.

Fixes: #1092
2020-10-09 12:52:47 +03:00
Panu Matilainen 192cbafcb2 Add API support for passing options and arguments to natively to Lua
Add support for passing getopt options and arguments to natively to Lua
scriptlets via the internal API. The processed opts and args are stored
in two chunk local two tables, options keyed by the letter and arguments
by their numeric index.

Update call sites accordingly, but no actual functionality changes here,
just pre-requisites for next steps.
2020-10-09 12:52:47 +03:00
Panu Matilainen d690ed7e48 Restore flagless variants of rpmExprBool() and rpmExprStr() for ABI compat
Commit cb4e5e755a added flags arguments
to rpmExprBool() and rpmExprStr(), but unfortunately rpm 4.15 sailed
with flagless versions them. It's extremely unlikely that anything out
there is actually using these, but then you never really know.
Rpm soname bumps are so inconvenient that we really do not want to do
that just for these two, so preserve binary compatibility and restore
flagless variants of both, adjust internal code to use flagged versions
always. If only we had symbol versioning, sigh.
2020-03-23 13:44:12 +02:00
Panu Matilainen 1d624239c4 Implement %{macrobody:...} built-in for retrieving the literal macro body
Fixes: #582
2020-02-19 13:09:21 +01:00
Panu Matilainen 9b37c4b349 Add APIs for testing whether a macro is defined and whether its parametric
Whether a macro is defined can be tested with eg rpmExpandNumeric()
but this is somewhat cumbersome and expensive for such a simple thing.
Prior to this, there was no way to find out whether a macro is
parametric (aka parameterized) or not.
2020-02-11 11:18:57 +01:00
Michael Schroeder 490c70d43c Use RPMMACRO_LITERAL/ME_LITERAL when defining some macros
It is used for setting __file_name, __file_lineno, buildsubdir.
We also use it for unmasking %license in the %files section.
2020-02-10 15:41:33 +02:00
Michael Schroeder cc66df4fa1 Add rpmPushMacroFlags function to allow the definition of literal macros
Literal macros are macros that do not expand their body when they
get expanded.
2020-02-10 15:41:33 +02:00
Michael Schroeder 07cc75f4d4 Add a ME_LITERAL macro flag that turns off body expansion
This is a much saner than to double the '%' characters after
macro argument expansion.
2020-02-10 15:41:33 +02:00
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