742823a9d6915f7d4202551674f54387878505f7
[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 #define REL_THEN 0
16 #define REL_ELSE 0
17
18 static struct RichOpComp {
19   const char *n;
20   int l;
21   Id fl;
22 } RichOps[] = {
23   { "&&", 2, REL_AND },
24   { "&", 1, REL_AND },
25   { "AND", 3, REL_AND },
26   { "||", 2, REL_OR },
27   { "|", 1, REL_OR },
28   { "OR", 2, REL_OR },
29   { "IF", 2, REL_COND },
30   { "THEN", 4, REL_THEN },
31   { "?", 1, REL_THEN },
32   { "ELSE", 4, REL_ELSE },
33   { ":", 1, REL_ELSE },
34   { NULL, 0, 0},
35 };
36
37 static Id
38 parseRichDep(Pool *pool, const char **depp, Id chainfl)
39 {
40   const char *p = *depp;
41   const char *n;
42   Id id, evr;
43   int fl, bl;
44   struct RichOpComp *op;
45
46   if (!chainfl && *p++ != '(')
47     return 0;
48   while (*p == ' ')
49     p++;
50   if (*p == ')')
51     return 0;
52   if (*p == '(')
53     {
54       id = parseRichDep(pool, &p, 0);
55       if (!id)
56         return 0;
57     }
58   else
59     {
60       n = p;
61       bl = 0;
62       while (*p && !(*p == ' ' || *p == ',' || (*p == ')' && bl-- <= 0)))
63         if (*p++ == '(')
64           bl++;
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               bl = 0;
90               while (*p && !(*p == ' ' || *p == ',' || (*p == ')' && bl-- <= 0)))
91                 if (*p++ == '(')
92                   bl++;
93               if (p - n > 2 && n[0] == '0' && n[1] == ':')
94                 n += 2;         /* strip zero epoch */
95               if (n == p)
96                 return 0;
97               id = pool_rel2id(pool, id, pool_strn2id(pool, n, p - n, 1), fl, 1);
98             }
99         }
100     }
101   while (*p == ' ')
102     p++;
103   if (!*p)
104     return 0;
105   if (*p == ')')
106     {
107       *depp = p + 1;
108       return id;
109     }
110   n = p;
111   while (*p && *p != ' ')
112     p++;
113   for (op = RichOps; op->n; op++)
114     if (p - n == op->l && !strncmp(n, op->n, op->l))
115       break;
116   fl = op->fl;
117   if (!fl)
118     return 0;
119   if (chainfl == REL_THEN && fl == REL_ELSE)
120     chainfl = 0;
121   if (chainfl && fl != chainfl)
122     return 0;
123   evr = parseRichDep(pool, &p, fl);
124   if (!evr)
125     return 0;
126   *depp = p;
127   return pool_rel2id(pool, id, evr, fl, 1);
128 }
129
130 Id
131 pool_parserpmrichdep(Pool *pool, const char *dep)
132 {
133   Id id = parseRichDep(pool, &dep, 0);
134   if (id && *dep)
135     id = 0;
136   return id;
137 }
138