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