summaryrefslogtreecommitdiff
path: root/ext/pool_parserpmrichdep.c
blob: d3e559ef6a825bae629ab85c3d1d768058f4cece (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*
 * 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"

static struct RichOpComp {
  const char *n;
  int l;
  Id fl;
} RichOps[] = {
  { "and",  3, REL_AND },
  { "or",   2, REL_OR },
  { "if",   2, REL_COND },
  { "else", 4, 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_COND && 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;
}