Blame ext/pool_parserpmrichdep.c

Packit Service ff689b
/*
Packit Service ff689b
 * Copyright (c) 2015, SUSE Inc.
Packit Service ff689b
 *
Packit Service ff689b
 * This program is licensed under the BSD license, read LICENSE.BSD
Packit Service ff689b
 * for further information
Packit Service ff689b
 */
Packit Service ff689b
Packit Service ff689b
/* this is used by repo_rpmmd, repo_rpmdb, and repo_susetags */
Packit Service ff689b
Packit Service ff689b
#include <stdio.h>
Packit Service ff689b
Packit Service ff689b
#include "pool.h"
Packit Service ff689b
#include "pool_parserpmrichdep.h"
Packit Service ff689b
Packit Service ff689b
static struct RichOpComp {
Packit Service ff689b
  const char *n;
Packit Service ff689b
  int l;
Packit Service ff689b
  Id fl;
Packit Service ff689b
} RichOps[] = {
Packit Service ff689b
  { "and",     3, REL_AND },
Packit Service ff689b
  { "or",      2, REL_OR },
Packit Service ff689b
  { "if",      2, REL_COND },
Packit Service ff689b
  { "unless",  6, REL_UNLESS },
Packit Service ff689b
  { "else",    4, REL_ELSE },
Packit Service ff689b
  { "with",    4, REL_WITH },
Packit Service ff689b
  { "without", 7, REL_WITHOUT },
Packit Service ff689b
  { NULL, 0, 0},
Packit Service ff689b
};
Packit Service ff689b
Packit Service ff689b
static inline const char *
Packit Service ff689b
skipnonwhite(const char *p)
Packit Service ff689b
{
Packit Service ff689b
  int bl = 0;
Packit Service ff689b
  while (*p && !(*p == ' ' || *p == ',' || (*p == ')' && bl-- <= 0)))
Packit Service ff689b
    if (*p++ == '(')
Packit Service ff689b
      bl++;
Packit Service ff689b
  return p;
Packit Service ff689b
}
Packit Service ff689b
Packit Service ff689b
static Id
Packit Service ff689b
parseRichDep(Pool *pool, const char **depp, Id chainfl)
Packit Service ff689b
{
Packit Service ff689b
  const char *p = *depp;
Packit Service ff689b
  const char *n;
Packit Service ff689b
  Id id, evr;
Packit Service ff689b
  int fl;
Packit Service ff689b
  struct RichOpComp *op;
Packit Service ff689b
Packit Service ff689b
  if (!chainfl && *p++ != '(')
Packit Service ff689b
    return 0;
Packit Service ff689b
  while (*p == ' ')
Packit Service ff689b
    p++;
Packit Service ff689b
  if (*p == ')')
Packit Service ff689b
    return 0;
Packit Service ff689b
  if (*p == '(')
Packit Service ff689b
    {
Packit Service ff689b
      id = parseRichDep(pool, &p, 0);
Packit Service ff689b
      if (!id)
Packit Service ff689b
	return 0;
Packit Service ff689b
    }
Packit Service ff689b
  else
Packit Service ff689b
    {
Packit Service ff689b
      n = p;
Packit Service ff689b
      p = skipnonwhite(p);
Packit Service ff689b
      if (n == p)
Packit Service ff689b
	return 0;
Packit Service ff689b
      id = pool_strn2id(pool, n, p - n, 1);
Packit Service ff689b
      while (*p == ' ')
Packit Service ff689b
	p++;
Packit Service ff689b
      if (*p)
Packit Service ff689b
	{
Packit Service ff689b
	  fl = 0;
Packit Service ff689b
	  for (;; p++)
Packit Service ff689b
	    {
Packit Service ff689b
	      if (*p == '<')
Packit Service ff689b
		fl |= REL_LT;
Packit Service ff689b
	      else if (*p == '=')
Packit Service ff689b
		fl |= REL_EQ;
Packit Service ff689b
	      else if (*p == '>')
Packit Service ff689b
		fl |= REL_GT;
Packit Service ff689b
	      else
Packit Service ff689b
		break;
Packit Service ff689b
	    }
Packit Service ff689b
	  if (fl)
Packit Service ff689b
	    {
Packit Service ff689b
	      while (*p == ' ')
Packit Service ff689b
		p++;
Packit Service ff689b
	      n = p;
Packit Service ff689b
	      p = skipnonwhite(p);
Packit Service ff689b
	      if (p - n > 2 && n[0] == '0' && n[1] == ':')
Packit Service ff689b
		n += 2;		/* strip zero epoch */
Packit Service ff689b
	      if (n == p)
Packit Service ff689b
		return 0;
Packit Service ff689b
	      id = pool_rel2id(pool, id, pool_strn2id(pool, n, p - n, 1), fl, 1);
Packit Service ff689b
	    }
Packit Service ff689b
	}
Packit Service ff689b
    }
Packit Service ff689b
  while (*p == ' ')
Packit Service ff689b
    p++;
Packit Service ff689b
  if (!*p)
Packit Service ff689b
    return 0;
Packit Service ff689b
  if (*p == ')')
Packit Service ff689b
    {
Packit Service ff689b
      *depp = p + 1;
Packit Service ff689b
      return id;
Packit Service ff689b
    }
Packit Service ff689b
  n = p;
Packit Service ff689b
  while (*p && *p != ' ')
Packit Service ff689b
    p++;
Packit Service ff689b
  for (op = RichOps; op->n; op++)
Packit Service ff689b
    if (p - n == op->l && !strncmp(n, op->n, op->l))
Packit Service ff689b
      break;
Packit Service ff689b
  fl = op->fl;
Packit Service ff689b
  if (!fl)
Packit Service ff689b
    return 0;
Packit Service ff689b
  if ((chainfl == REL_COND || chainfl == REL_UNLESS) && fl == REL_ELSE)
Packit Service ff689b
    chainfl = 0;
Packit Service ff689b
  if (chainfl && fl != chainfl)
Packit Service ff689b
    return 0;
Packit Service ff689b
  evr = parseRichDep(pool, &p, fl);
Packit Service ff689b
  if (!evr)
Packit Service ff689b
    return 0;
Packit Service ff689b
  *depp = p;
Packit Service ff689b
  return pool_rel2id(pool, id, evr, fl, 1);
Packit Service ff689b
}
Packit Service ff689b
Packit Service ff689b
Id
Packit Service ff689b
pool_parserpmrichdep(Pool *pool, const char *dep)
Packit Service ff689b
{
Packit Service ff689b
  Id id = parseRichDep(pool, &dep, 0);
Packit Service ff689b
  if (id && *dep)
Packit Service ff689b
    id = 0;
Packit Service ff689b
  return id;
Packit Service ff689b
}
Packit Service ff689b