From e9c997f637af1ae022af988db2c3773feceaf814 Mon Sep 17 00:00:00 2001 From: Panu Matilainen Date: Fri, 20 Oct 2023 15:32:40 +0300 Subject: [PATCH] Add support for defining auxiliary macro functions Add rpmPushMacroAux() function which allows registering auxiliary macros implemented in C and some required helper facilities: export the types, rpmMacroBufAppend*() and rpmMacroBufErr() functions, and finally add rpmMacroEntryPriv() to let macro retrieve their private data. And that's all folks. --- include/rpm/rpmmacro.h | 50 ++++++++++++++++++++++++++++++++++++++++++ rpmio/macro.c | 36 +++++++++++++++++++++--------- 2 files changed, 76 insertions(+), 10 deletions(-) diff --git a/include/rpm/rpmmacro.h b/include/rpm/rpmmacro.h index e7bee11ef..6664b6752 100644 --- a/include/rpm/rpmmacro.h +++ b/include/rpm/rpmmacro.h @@ -21,6 +21,10 @@ typedef struct rpmMacroEntry_s * rpmMacroEntry; typedef struct rpmMacroContext_s * rpmMacroContext; +typedef struct rpmMacroBuf_s *rpmMacroBuf; + +typedef void (*macroFunc)(rpmMacroBuf mb, rpmMacroEntry me, ARGV_t argv, size_t *parsed); + extern rpmMacroContext rpmGlobalMacroContext; extern rpmMacroContext rpmCLIMacroContext; @@ -121,6 +125,52 @@ int rpmPushMacroFlags (rpmMacroContext mc, const char * n, const char * b, int level, rpmMacroFlags flags); +/** \ingroup rpmmacro + * Push an auxiliary macro to context. + * @param mc macro context (NULL uses global context). + * @param n macro name + * @param o macro parameters (or NULL) + * @param f macro function + * @param priv private user data (or NULL) + * @param level macro recursion level (0 is entry API) + * @param flags macro flags + * @return 0 on success + */ +int rpmPushMacroAux(rpmMacroContext mc, + const char * n, const char * o, + macroFunc f, void *priv, int nargs, + int level, rpmMacroFlags flags); + +/** \ingroup rpmmacro + * Return macro entry user data (in aux macro) + * @param me macro entry + * @return pointer to private data passed on define or NULL + */ +void *rpmMacroEntryPriv(rpmMacroEntry me); + +/** \ingroup rpmmacro + * Append a character to macro buffer (in aux macro) + * @param mb macro buffer + * @param c character to append + */ +void rpmMacroBufAppend(rpmMacroBuf mb, char c); + +/** \ingroup rpmmacro + * Append a string to macro buffer (in aux macro) + * @param mb macro buffer + * @param str string to append + */ +void rpmMacroBufAppendStr(rpmMacroBuf mb, const char *str); + +/** \ingroup rpmmacro + * Raise an error or warning in macro buffer (in aux macro) + * @param mb macro buffer + * @param error 1 if error, 0 if warning + * @param fmt j + */ +RPM_GNUC_PRINTF(3, 4) +void rpmMacroBufErr(rpmMacroBuf mb, int error, const char *fmt, ...); + /** \ingroup rpmmacro * Pop macro from context. * @param mc macro context (NULL uses global context). diff --git a/rpmio/macro.c b/rpmio/macro.c index 1780227e3..046abdef8 100644 --- a/rpmio/macro.c +++ b/rpmio/macro.c @@ -41,9 +41,6 @@ enum macroFlags_e { ME_FUNC = (1 << 4), }; -typedef struct rpmMacroBuf_s *rpmMacroBuf; -typedef void (*macroFunc)(rpmMacroBuf mb, rpmMacroEntry me, ARGV_t argv, size_t *parsed); - /*! The structure used to store a macro. */ struct rpmMacroEntry_s { struct rpmMacroEntry_s *prev;/*!< Macro entry stack. */ @@ -51,6 +48,7 @@ struct rpmMacroEntry_s { const char *opts; /*!< Macro parameters (a la getopt) */ const char *body; /*!< Macro body. */ macroFunc func; /*!< Macro function (builtin macros) */ + void *priv; /*!< Private user data (aux macros) */ int nargs; /*!< Number of required args */ int flags; /*!< Macro state bits. */ int level; /*!< Scoping level. */ @@ -318,7 +316,7 @@ matchchar(const char * p, char pl, char pr) return (const char *)NULL; } -static void rpmMacroBufErr(rpmMacroBuf mb, int error, const char *fmt, ...) +void rpmMacroBufErr(rpmMacroBuf mb, int error, const char *fmt, ...) { char *emsg = NULL; int n; @@ -506,7 +504,7 @@ static void mbFini(rpmMacroBuf mb, rpmMacroEntry me, MacroExpansionData *med) mb->expand_trace = med->expand_trace; } -static void rpmMacroBufAppend(rpmMacroBuf mb, char c) +void rpmMacroBufAppend(rpmMacroBuf mb, char c) { if (mb->nb < 1) { mb->buf = xrealloc(mb->buf, mb->tpos + MACROBUFSIZ + 1); @@ -517,7 +515,7 @@ static void rpmMacroBufAppend(rpmMacroBuf mb, char c) mb->nb--; } -static void rpmMacroBufAppendStr(rpmMacroBuf mb, const char *str) +void rpmMacroBufAppendStr(rpmMacroBuf mb, const char *str) { size_t len = strlen(str); if (len > mb->nb) { @@ -1740,7 +1738,7 @@ static int doExpandMacros(rpmMacroContext mc, const char *src, int flags, static void pushMacroAny(rpmMacroContext mc, const char * n, const char * o, const char * b, - macroFunc f, int nargs, int level, int flags) + macroFunc f, void *priv, int nargs, int level, int flags) { /* new entry */ rpmMacroEntry me; @@ -1785,6 +1783,7 @@ static void pushMacroAny(rpmMacroContext mc, me->opts = o ? "" : NULL; /* initialize */ me->func = f; + me->priv = priv; me->nargs = nargs; me->flags = flags; me->flags &= ~(ME_USED); @@ -1797,7 +1796,7 @@ static void pushMacroAny(rpmMacroContext mc, static void pushMacro(rpmMacroContext mc, const char * n, const char * o, const char * b, int level, int flags) { - return pushMacroAny(mc, n, o, b, NULL, 0, level, flags); + return pushMacroAny(mc, n, o, b, NULL, NULL, 0, level, flags); } static void popMacro(rpmMacroContext mc, const char * n) @@ -1975,6 +1974,18 @@ int rpmPushMacro(rpmMacroContext mc, return rpmPushMacroFlags(mc, n, o, b, level, RPMMACRO_DEFAULT); } +int rpmPushMacroAux(rpmMacroContext mc, + const char * n, const char * o, + macroFunc f, void *priv, int nargs, + int level, rpmMacroFlags flags) +{ + mc = rpmmctxAcquire(mc); + pushMacroAny(mc, n, nargs ? "" : NULL, "", f, priv, nargs, + level, flags|ME_FUNC); + rpmmctxRelease(mc); + return 0; +} + int rpmPopMacro(rpmMacroContext mc, const char * n) { mc = rpmmctxAcquire(mc); @@ -2016,6 +2027,11 @@ int rpmMacroIsParametric(rpmMacroContext mc, const char *n) return parametric; } +void *rpmMacroEntryPriv(rpmMacroEntry me) +{ + return (me != NULL) ? me->priv : NULL; +} + void rpmLoadMacros(rpmMacroContext mc, int level) { @@ -2053,8 +2069,8 @@ rpmInitMacros(rpmMacroContext mc, const char * macrofiles) /* Define built-in macros */ for (const struct builtins_s *b = builtinmacros; b->name; b++) { - pushMacroAny(mc, b->name, b->nargs ? "" : NULL, "", b->func, b->nargs, - RMIL_BUILTIN, b->flags | ME_FUNC); + pushMacroAny(mc, b->name, b->nargs ? "" : NULL, "", + b->func, NULL, b->nargs, RMIL_BUILTIN, b->flags | ME_FUNC); } argvSplit(&globs, macrofiles, ":");