Imported Upstream version 0.7.12
[platform/upstream/libsolv.git] / ext / pool_parserpmrichdep.c
1 /*
2  * Copyright (c) 2015, SUSE Inc.
3  *
4  * This program is licensed under the BSD license, read LICENSE.BSD
5  * for further information
6  */
7
8 /* this is used by repo_rpmmd, repo_rpmdb, and repo_susetags */
9
10 #include <stdio.h>
11
12 #include "pool.h"
13 #include "pool_parserpmrichdep.h"
14
15 static struct RichOpComp {
16   const char *n;
17   int l;
18   Id fl;
19 } RichOps[] = {
20   { "and",     3, REL_AND },
21   { "or",      2, REL_OR },
22   { "if",      2, REL_COND },
23   { "unless",  6, REL_UNLESS },
24   { "else",    4, REL_ELSE },
25   { "with",    4, REL_WITH },
26   { "without", 7, REL_WITHOUT },
27   { NULL, 0, 0},
28 };
29
30 static inline const char *
31 skipnonwhite(const char *p)
32 {
33   int bl = 0;
34   while (*p && !(*p == ' ' || *p == ',' || (*p == ')' && bl-- <= 0)))
35     if (*p++ == '(')
36       bl++;
37   return p;
38 }
39
40 static Id
41 parseRichDep(Pool *pool, const char **depp, Id chainfl)
42 {
43   const char *p = *depp;
44   const char *n;
45   Id id, evr;
46   int fl;
47   struct RichOpComp *op;
48
49   if (!chainfl && *p++ != '(')
50     return 0;
51   while (*p == ' ')
52     p++;
53   if (*p == ')')
54     return 0;
55   if (*p == '(')
56     {
57       id = parseRichDep(pool, &p, 0);
58       if (!id)
59         return 0;
60     }
61   else
62     {
63       n = p;
64       p = skipnonwhite(p);
65       if (n == p)
66         return 0;
67       id = pool_strn2id(pool, n, p - n, 1);
68       while (*p == ' ')
69         p++;
70       if (*p)
71         {
72           fl = 0;
73           for (;; p++)
74             {
75               if (*p == '<')
76                 fl |= REL_LT;
77               else if (*p == '=')
78                 fl |= REL_EQ;
79               else if (*p == '>')
80                 fl |= REL_GT;
81               else
82                 break;
83             }
84           if (fl)
85             {
86               while (*p == ' ')
87                 p++;
88               n = p;
89               p = skipnonwhite(p);
90               if (p - n > 2 && n[0] == '0' && n[1] == ':')
91                 n += 2;         /* strip zero epoch */
92               if (n == p)
93                 return 0;
94               id = pool_rel2id(pool, id, pool_strn2id(pool, n, p - n, 1), fl, 1);
95             }
96         }
97     }
98   while (*p == ' ')
99     p++;
100   if (!*p)
101     return 0;
102   if (*p == ')')
103     {
104       *depp = p + 1;
105       return id;
106     }
107   n = p;
108   while (*p && *p != ' ')
109     p++;
110   for (op = RichOps; op->n; op++)
111     if (p - n == op->l && !strncmp(n, op->n, op->l))
112       break;
113   fl = op->fl;
114   if (!fl)
115     return 0;
116   if ((chainfl == REL_COND || chainfl == REL_UNLESS) && fl == REL_ELSE)
117     chainfl = 0;
118   if (chainfl && fl != chainfl)
119     return 0;
120   evr = parseRichDep(pool, &p, fl);
121   if (!evr)
122     return 0;
123   *depp = p;
124   return pool_rel2id(pool, id, evr, fl, 1);
125 }
126
127 Id
128 pool_parserpmrichdep(Pool *pool, const char *dep)
129 {
130   Id id = parseRichDep(pool, &dep, 0);
131   if (id && *dep)
132     id = 0;
133   return id;
134 }
135