d3e559ef6a825bae629ab85c3d1d768058f4cece
[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   { "else", 4, REL_ELSE },
24   { NULL, 0, 0},
25 };
26
27 static Id
28 parseRichDep(Pool *pool, const char **depp, Id chainfl)
29 {
30   const char *p = *depp;
31   const char *n;
32   Id id, evr;
33   int fl, bl;
34   struct RichOpComp *op;
35
36   if (!chainfl && *p++ != '(')
37     return 0;
38   while (*p == ' ')
39     p++;
40   if (*p == ')')
41     return 0;
42   if (*p == '(')
43     {
44       id = parseRichDep(pool, &p, 0);
45       if (!id)
46         return 0;
47     }
48   else
49     {
50       n = p;
51       bl = 0;
52       while (*p && !(*p == ' ' || *p == ',' || (*p == ')' && bl-- <= 0)))
53         if (*p++ == '(')
54           bl++;
55       if (n == p)
56         return 0;
57       id = pool_strn2id(pool, n, p - n, 1);
58       while (*p == ' ')
59         p++;
60       if (*p)
61         {
62           fl = 0;
63           for (;; p++)
64             {
65               if (*p == '<')
66                 fl |= REL_LT;
67               else if (*p == '=')
68                 fl |= REL_EQ;
69               else if (*p == '>')
70                 fl |= REL_GT;
71               else
72                 break;
73             }
74           if (fl)
75             {
76               while (*p == ' ')
77                 p++;
78               n = p;
79               bl = 0;
80               while (*p && !(*p == ' ' || *p == ',' || (*p == ')' && bl-- <= 0)))
81                 if (*p++ == '(')
82                   bl++;
83               if (p - n > 2 && n[0] == '0' && n[1] == ':')
84                 n += 2;         /* strip zero epoch */
85               if (n == p)
86                 return 0;
87               id = pool_rel2id(pool, id, pool_strn2id(pool, n, p - n, 1), fl, 1);
88             }
89         }
90     }
91   while (*p == ' ')
92     p++;
93   if (!*p)
94     return 0;
95   if (*p == ')')
96     {
97       *depp = p + 1;
98       return id;
99     }
100   n = p;
101   while (*p && *p != ' ')
102     p++;
103   for (op = RichOps; op->n; op++)
104     if (p - n == op->l && !strncmp(n, op->n, op->l))
105       break;
106   fl = op->fl;
107   if (!fl)
108     return 0;
109   if (chainfl == REL_COND && fl == REL_ELSE)
110     chainfl = 0;
111   if (chainfl && fl != chainfl)
112     return 0;
113   evr = parseRichDep(pool, &p, fl);
114   if (!evr)
115     return 0;
116   *depp = p;
117   return pool_rel2id(pool, id, evr, fl, 1);
118 }
119
120 Id
121 pool_parserpmrichdep(Pool *pool, const char *dep)
122 {
123   Id id = parseRichDep(pool, &dep, 0);
124   if (id && *dep)
125     id = 0;
126   return id;
127 }
128