summaryrefslogtreecommitdiff
path: root/ext/pool_parserpmrichdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/pool_parserpmrichdep.c')
-rw-r--r--ext/pool_parserpmrichdep.c138
1 files changed, 138 insertions, 0 deletions
diff --git a/ext/pool_parserpmrichdep.c b/ext/pool_parserpmrichdep.c
new file mode 100644
index 0000000..742823a
--- /dev/null
+++ b/ext/pool_parserpmrichdep.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2015, SUSE Inc.
+ *
+ * This program is licensed under the BSD license, read LICENSE.BSD
+ * for further information
+ */
+
+/* this is used by repo_rpmmd, repo_rpmdb, and repo_susetags */
+
+#include <stdio.h>
+
+#include "pool.h"
+#include "pool_parserpmrichdep.h"
+
+#define REL_THEN 0
+#define REL_ELSE 0
+
+static struct RichOpComp {
+ const char *n;
+ int l;
+ Id fl;
+} RichOps[] = {
+ { "&&", 2, REL_AND },
+ { "&", 1, REL_AND },
+ { "AND", 3, REL_AND },
+ { "||", 2, REL_OR },
+ { "|", 1, REL_OR },
+ { "OR", 2, REL_OR },
+ { "IF", 2, REL_COND },
+ { "THEN", 4, REL_THEN },
+ { "?", 1, REL_THEN },
+ { "ELSE", 4, REL_ELSE },
+ { ":", 1, REL_ELSE },
+ { NULL, 0, 0},
+};
+
+static Id
+parseRichDep(Pool *pool, const char **depp, Id chainfl)
+{
+ const char *p = *depp;
+ const char *n;
+ Id id, evr;
+ int fl, bl;
+ struct RichOpComp *op;
+
+ if (!chainfl && *p++ != '(')
+ return 0;
+ while (*p == ' ')
+ p++;
+ if (*p == ')')
+ return 0;
+ if (*p == '(')
+ {
+ id = parseRichDep(pool, &p, 0);
+ if (!id)
+ return 0;
+ }
+ else
+ {
+ n = p;
+ bl = 0;
+ while (*p && !(*p == ' ' || *p == ',' || (*p == ')' && bl-- <= 0)))
+ if (*p++ == '(')
+ bl++;
+ if (n == p)
+ return 0;
+ id = pool_strn2id(pool, n, p - n, 1);
+ while (*p == ' ')
+ p++;
+ if (*p)
+ {
+ fl = 0;
+ for (;; p++)
+ {
+ if (*p == '<')
+ fl |= REL_LT;
+ else if (*p == '=')
+ fl |= REL_EQ;
+ else if (*p == '>')
+ fl |= REL_GT;
+ else
+ break;
+ }
+ if (fl)
+ {
+ while (*p == ' ')
+ p++;
+ n = p;
+ bl = 0;
+ while (*p && !(*p == ' ' || *p == ',' || (*p == ')' && bl-- <= 0)))
+ if (*p++ == '(')
+ bl++;
+ if (p - n > 2 && n[0] == '0' && n[1] == ':')
+ n += 2; /* strip zero epoch */
+ if (n == p)
+ return 0;
+ id = pool_rel2id(pool, id, pool_strn2id(pool, n, p - n, 1), fl, 1);
+ }
+ }
+ }
+ while (*p == ' ')
+ p++;
+ if (!*p)
+ return 0;
+ if (*p == ')')
+ {
+ *depp = p + 1;
+ return id;
+ }
+ n = p;
+ while (*p && *p != ' ')
+ p++;
+ for (op = RichOps; op->n; op++)
+ if (p - n == op->l && !strncmp(n, op->n, op->l))
+ break;
+ fl = op->fl;
+ if (!fl)
+ return 0;
+ if (chainfl == REL_THEN && fl == REL_ELSE)
+ chainfl = 0;
+ if (chainfl && fl != chainfl)
+ return 0;
+ evr = parseRichDep(pool, &p, fl);
+ if (!evr)
+ return 0;
+ *depp = p;
+ return pool_rel2id(pool, id, evr, fl, 1);
+}
+
+Id
+pool_parserpmrichdep(Pool *pool, const char *dep)
+{
+ Id id = parseRichDep(pool, &dep, 0);
+ if (id && *dep)
+ id = 0;
+ return id;
+}
+