[Rpm-maint] [PATCH 16/19] Update %policy parsing to allow for more tags
Steve Lawrence
slawrence at tresys.com
Tue Feb 2 20:25:19 UTC 2010
The previous %policy section parsing assumed %module would be the only
tag in in the section. This is limiting as we may need to add more tags
in the future. This patch generalizes %policy section parsing and makes
it much easier to add new tags.
To add a tag, all that must be done is add a new POLDECTag entry, add an
entry in policyDeclarations, and add a function to parse the tag.
This also adds some error checking/cleanup.
---
build/policies.c | 217 ++++++++++++++++++++++++++++++++++++------------------
1 files changed, 145 insertions(+), 72 deletions(-)
diff --git a/build/policies.c b/build/policies.c
index 1076af0..a1ee679 100644
--- a/build/policies.c
+++ b/build/policies.c
@@ -15,8 +15,8 @@
#include "debug.h"
-#define SKIPSPACE(s) { while (*(s) && risspace(*(s))) (s)++; }
-#define SKIPNONSPACE(s) { while (*(s) && !risspace(*(s))) (s)++; }
+#define SKIPSPACE(s) { while ((s) && *(s) && risspace(*(s))) (s)++; }
+#define SKIPNONSPACE(s) { while ((s) && *(s) && !risspace(*(s))) (s)++; }
typedef struct ModuleRec_s {
char *path;
@@ -26,6 +26,19 @@ typedef struct ModuleRec_s {
uint32_t base;
} *ModuleRec;
+typedef enum POLDECTag_e {
+ POLDEC_UNKNOWN = 0,
+ POLDEC_MODULE = 1,
+} POLDECTag;
+
+typedef const struct POLDEC {
+ POLDECTag tag;
+ int deprecated;
+ size_t len;
+ const char *token;
+ rpmRC (*parse)(const struct POLDEC * dec, ARGV_t *lines, Package pkg);
+} POLDEC_t;
+
typedef enum MODATag_e {
MODOPT_UNKNOWN = 0,
MODOPT_NAME = 1,
@@ -41,8 +54,16 @@ typedef const struct MODA {
const char *token;
} MODA_t;
+static rpmRC parseModule(POLDEC_t *dec, ARGV_t *pol, Package pkg);
+
+
#define LEN_AND_STR(_tag) (sizeof(_tag)-1), _tag
+static POLDEC_t const policyDeclarations[] = {
+ {POLDEC_MODULE, 0, LEN_AND_STR("%module"), &parseModule},
+ {POLDEC_UNKNOWN, 0, 0, 0, 0} /* must be last */
+};
+
static MODA_t const moduleAttrs[] = {
{MODOPT_NAME, 0, LEN_AND_STR("name")},
{MODOPT_OBSOLETES, 0, LEN_AND_STR("obsoletes")},
@@ -89,6 +110,10 @@ static rpmRC writeModuleToHeader(ModuleRec mod, Package pkg)
rpmtdReset(&policytypes);
rpmtdReset(&policytypesidx);
+ if (!mod || !pkg) {
+ goto exit;
+ }
+
fullpath = rpmGenPath(buildDir, NULL, mod->path);
if ((rpmioSlurp(fullpath, &raw, &rawlen)) != 0 || raw == NULL) {
@@ -270,108 +295,81 @@ static ModuleRec newModule(char * path)
}
-static rpmRC parseModuleAttr(ModuleRec mod, char *line)
+static rpmRC parseModuleAttr(ModuleRec mod, MODATag key, char *val)
{
- MODA_t *moda;
- char *l;
char *s;
char *end;
int multitoken;
rpmRC rc = RPMRC_FAIL;
- if (!mod) {
- rpmlog(RPMLOG_ERR, _("Expected %%module directive: %s\n"), line);
- goto exit;
- }
-
- l = line;
- SKIPSPACE(l);
-
- for (moda = moduleAttrs; moda->token != MODOPT_UNKNOWN; moda++) {
- if (rstrncasecmp(l, moda->token, moda->len)) {
- continue;
- }
- if (moda->deprecated) {
- rpmlog(RPMLOG_WARNING, _("%s is deprecated: %s\n"), moda->token, line);
- }
- break;
- }
-
- if (moda->token == MODOPT_UNKNOWN) {
- rpmlog(RPMLOG_ERR, _("Unknown option: %s\n"), line);
+ SKIPSPACE(val);
+ if (val == '\0') {
+ rpmlog(RPMLOG_ERR, _("Empty value for module attribute %i\n"), key);
goto exit;
}
- l += moda->len;
- SKIPSPACE(l);
- if (*l++ != ':') {
- rpmlog(RPMLOG_ERR, _("Malformed option: %s\n"), line);
- goto exit;
- }
-
- SKIPSPACE(l);
- if (*l == '\0') {
- rpmlog(RPMLOG_ERR, _("Empty option: %s\n"), line);
+ if (!mod) {
+ rpmlog(RPMLOG_ERR, _("No %module directive given for attribute: %s\n"), val);
goto exit;
}
- s = end = l;
+ s = end = val;
SKIPNONSPACE(s); SKIPSPACE(s);
while (*end) end++;
multitoken = (s != end);
#define SINGLE_TOKEN_ONLY \
if (multitoken) { \
- rpmlog(RPMLOG_ERR, _("Option takes single token only: %s\n"), line); \
+ rpmlog(RPMLOG_ERR, _("Option takes single token only: %s\n"), val); \
goto exit; \
}
#define SINGLE_DEFINE_ONLY(ptr) \
if (ptr) { \
- rpmlog(RPMLOG_ERR, _("Option specified more than once: %s\n"), line); \
+ rpmlog(RPMLOG_ERR, _("Option specified more than once: %s\n"), val); \
goto exit; \
}
- switch (moda->tag) {
+ switch (key) {
case MODOPT_NAME:
SINGLE_DEFINE_ONLY(mod->name)
SINGLE_TOKEN_ONLY
- mod->name = strdup(l);
+ mod->name = strdup(val);
break;
case MODOPT_OBSOLETES:
SINGLE_DEFINE_ONLY(mod->obsoletes)
- s = l;
+ s = val;
do {
SKIPNONSPACE(s);
end = s;
SKIPSPACE(s);
*end = '\0';
- argvAdd(&mod->obsoletes, l);
- l = s;
- } while (*l != '\0');
+ argvAdd(&mod->obsoletes, val);
+ val = s;
+ } while (*val != '\0');
break;
case MODOPT_TYPES:
SINGLE_DEFINE_ONLY(mod->types)
- s = l;
+ s = val;
do {
SKIPNONSPACE(s);
end = s;
SKIPSPACE(s);
*end = '\0';
- argvAdd(&mod->types, l);
- l = s;
- } while (*l != '\0');
+ argvAdd(&mod->types, val);
+ val = s;
+ } while (*val != '\0');
break;
case MODOPT_BASE:
SINGLE_TOKEN_ONLY
- mod->base = parseYesNo(l);
+ mod->base = parseYesNo(val);
if (mod->base == -1) {
- rpmlog(RPMLOG_ERR, _("Unknown boolean value: %s\n"), line);
+ rpmlog(RPMLOG_ERR, _("Unknown boolean value: %s\n"), val);
goto exit;
}
break;
default:
- rpmlog(RPMLOG_ERR, _("Unhandled option: %s\n"), line);
+ rpmlog(RPMLOG_ERR, _("Unhandled option: %s\n"), val);
goto exit;
}
@@ -381,14 +379,96 @@ exit:
return rc;
}
+static rpmRC parseModule(POLDEC_t *dec, ARGV_t *pol, Package pkg)
+{
+ char *line;
+ char *s;
+ ModuleRec mod = NULL;
+ MODA_t *moda;
+ rpmRC rc = RPMRC_FAIL;
+
+ if (!dec || !pol || !pkg) {
+ goto exit;
+ }
+
+ line = **pol;
+ SKIPSPACE(line);
+ if (dec->tag != POLDEC_MODULE || rstrncasecmp(line, dec->token, dec->len)) {
+ rpmlog(RPMLOG_ERR, _("parseModule() cannot parse line: %s\n"), line);
+ goto exit;
+ }
+ line += dec->len;
+
+ mod = newModule(line);
+ if (!mod) {
+ goto exit;
+ }
+
+ /* parse attributes of the module */
+ while(*pol && *((*pol)+1)) {
+ s = line = *(*(pol)+1);
+ SKIPSPACE(s);
+
+ for (moda = moduleAttrs; moda->token != MODOPT_UNKNOWN; moda++) {
+ if (rstrncasecmp(s, moda->token, moda->len)) {
+ continue;
+ }
+ if (moda->deprecated) {
+ rpmlog(RPMLOG_WARNING, _("%s is deprecated: %s\n"), moda->token, line);
+ }
+ break;
+ }
+
+ if (moda->token == MODOPT_UNKNOWN) {
+ rc = RPMRC_OK;
+ goto exit;
+ }
+
+ s += moda->len;
+ SKIPSPACE(s);
+ if (*s++ != ':') {
+ rpmlog(RPMLOG_ERR, _("Malformed option: %s\n"), line);
+ goto exit;
+ }
+
+ SKIPSPACE(s);
+ if (*s == '\0') {
+ rpmlog(RPMLOG_ERR, _("Empty option: %s\n"), line);
+ goto exit;
+ }
+
+ rc = parseModuleAttr(mod, moda->tag, s);
+ if (rc != RPMRC_OK) {
+ goto exit;
+ }
+
+ (*pol)++;
+ }
+
+
+exit:
+ if (rc == RPMRC_OK) {
+ rc = writeModuleToHeader(mod, pkg);
+ }
+
+ freeModule(mod);
+
+ return rc;
+
+}
+
static rpmRC processPolicies(rpmSpec spec, Package pkg, int test)
{
ARGV_t policies = NULL;
ARGV_t pol;
- ModuleRec mod = NULL;
char *linep;
+ POLDEC_t *dec;
rpmRC rc = RPMRC_FAIL;
+ if (!spec || !pkg) {
+ goto exit;
+ }
+
argvSplit(&policies, getStringBuf(pkg->policyList), "\n");
for (pol = policies; *pol != NULL; pol++) {
linep = *pol;
@@ -397,29 +477,23 @@ static rpmRC processPolicies(rpmSpec spec, Package pkg, int test)
continue;
}
- if (!rstrncasecmp(linep, "%module", strlen("%module"))) {
- if (mod) {
- rc = writeModuleToHeader(mod, pkg);
- if (rc != RPMRC_OK) {
- goto exit;
- }
- mod = freeModule(mod);
- }
- mod = newModule(linep + strlen("%module"));
- if (!mod) {
- rc = RPMRC_FAIL;
- goto exit;
+ for (dec = policyDeclarations; dec->tag != POLDEC_UNKNOWN; dec++) {
+ if (rstrncasecmp(linep, dec->token, dec->len)) {
+ continue;
}
- } else {
- rc = parseModuleAttr(mod, linep);
- if (rc != RPMRC_OK) {
- goto exit;
+ if (dec->deprecated) {
+ rpmlog(RPMLOG_WARNING, _("%s is deprecated: %s\n"), dec->token, linep);
}
+ break;
}
- }
- if (mod) {
- rc = writeModuleToHeader(mod, pkg);
+ if (dec->tag == POLDEC_UNKNOWN) {
+ rpmlog(RPMLOG_ERR, _("Unknown option in %%policy section: %s\n"), linep);
+ rc = RPMRC_FAIL;
+ goto exit;
+ }
+
+ rc = dec->parse(dec, &pol, pkg);
if (rc != RPMRC_OK) {
goto exit;
}
@@ -428,7 +502,6 @@ static rpmRC processPolicies(rpmSpec spec, Package pkg, int test)
rc = RPMRC_OK;
exit:
- mod = freeModule(mod);
argvFree(policies);
return rc;
--
1.6.2.5
More information about the Rpm-maint
mailing list