content2solv: a parser for the content file of Yast2 repos. Generates
authorMichael Matz <matz@suse.de>
Sat, 20 Oct 2007 16:32:08 +0000 (16:32 +0000)
committerMichael Matz <matz@suse.de>
Sat, 20 Oct 2007 16:32:08 +0000 (16:32 +0000)
a SOLV with only one solvable, the product.

tools/Makefile.am
tools/content2solv.c [new file with mode: 0644]
tools/source_content.c [new file with mode: 0644]
tools/source_content.h [new file with mode: 0644]

index 8caf7ba..b059245 100644 (file)
@@ -1,4 +1,4 @@
-noinst_PROGRAMS = rpmdb2solv rpmmd2solv helix2solv susetags2solv patchxml2solv dumpsolv mergesolv
+noinst_PROGRAMS = rpmdb2solv rpmmd2solv helix2solv susetags2solv patchxml2solv dumpsolv mergesolv content2solv
 
 INCLUDES =  \
        -I$(top_srcdir)/src
@@ -46,6 +46,12 @@ patchxml2solv_SOURCES = \
 
 patchxml2solv_LDADD = -lexpat $(LDADD)
 
+content2solv_SOURCES = \
+       content2solv.c          \
+       source_content.h        \
+       source_content.c        \
+       source_write.c
+
 dumpsolv_SOURCES = \
        dumpsolv.c
 
diff --git a/tools/content2solv.c b/tools/content2solv.c
new file mode 100644 (file)
index 0000000..26d7140
--- /dev/null
@@ -0,0 +1,20 @@
+#include <sys/types.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pool.h"
+#include "source_content.h"
+#include "source_write.h"
+
+int
+main(int argc, char **argv)
+{
+  Pool *pool = pool_create();
+  Source *source = pool_addsource_content(pool, stdin);
+  pool_writesource(pool, source, stdout);
+  pool_free(pool);
+  return 0;
+}
diff --git a/tools/source_content.c b/tools/source_content.c
new file mode 100644 (file)
index 0000000..c939ca8
--- /dev/null
@@ -0,0 +1,312 @@
+#include <sys/types.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "pool.h"
+#include "source_content.h"
+
+#define PACK_BLOCK 16
+
+static int
+split(char *l, char **sp, int m)
+{
+  int i;
+  for (i = 0; i < m;)
+    {
+      while (*l == ' ' || *l == '\t')
+       l++;
+      if (!*l)
+       break;
+      sp[i++] = l;
+      if (i == m)
+        break;
+      while (*l && !(*l == ' ' || *l == '\t'))
+       l++;
+      if (!*l)
+       break;
+      *l++ = 0;
+    }
+  return i;
+}
+
+struct deps {
+  unsigned int provides;
+  unsigned int requires;
+  unsigned int obsoletes;
+  unsigned int conflicts;
+  unsigned int recommends;
+  unsigned int supplements;
+  unsigned int enhances;
+  unsigned int suggests;
+  unsigned int freshens;
+};
+
+struct parsedata {
+  char *kind;
+  Source *source;
+  char *tmp;
+  int tmpl;
+};
+
+static Id
+makeevr(Pool *pool, char *s)
+{
+  if (!strncmp(s, "0:", 2) && s[2])
+    s += 2;
+  return str2id(pool, s, 1);
+}
+
+static char *flagtab[] = {
+  ">",
+  "=",
+  ">=",
+  "<",
+  "!=",
+  "<="
+};
+
+static char *
+join(struct parsedata *pd, char *s1, char *s2, char *s3)
+{
+  int l = 1;
+  char *p;
+
+  if (s1)
+    l += strlen(s1);
+  if (s2)
+    l += strlen(s2);
+  if (s3)
+    l += strlen(s3);
+  if (l > pd->tmpl)
+    {
+      pd->tmpl = l + 256;
+      if (!pd->tmp)
+       pd->tmp = malloc(pd->tmpl);
+      else
+       pd->tmp = realloc(pd->tmp, pd->tmpl);
+    }
+  p = pd->tmp;
+  if (s1)
+    {
+      strcpy(p, s1);
+      p += strlen(s1);
+    }
+  if (s2)
+    {
+      strcpy(p, s2);
+      p += strlen(s2);
+    }
+  if (s3)
+    {
+      strcpy(p, s3);
+      p += strlen(s3);
+    }
+  return pd->tmp;
+}
+
+static unsigned int
+adddep(Pool *pool, struct parsedata *pd, unsigned int olddeps, char *line, int isreq)
+{
+  int flags, words;
+  Id id, evrid;
+  char *sp[4];
+
+  words = 0;
+  while (1)
+    {
+      /* Name [relop evr [rest]] --> 1, 3 or 4 fields.  */
+      words += split(line, sp + words, 4 - words);
+      if (words == 2)
+       {
+         fprintf(stderr, "Bad dependency line: %s\n", line);
+         exit(1);
+       }
+      line = 0;
+      /* Hack, as the content file adds 'package:' for package
+         dependencies sometimes.  */
+      if (!strncmp (sp[0], "package:", 8))
+        sp[0] += 8;
+      id = str2id(pool, sp[0], 1);
+      if (words >= 3 && strpbrk (sp[1], "<>="))
+       {
+         evrid = makeevr(pool, sp[2]);
+         for (flags = 0; flags < 6; flags++)
+           if (!strcmp(sp[1], flagtab[flags]))
+             break;
+         if (flags == 6)
+           {
+             fprintf(stderr, "Unknown relation '%s'\n", sp[1]);
+             exit(1);
+           }
+         id = rel2id(pool, id, evrid, flags + 1, 1);
+         /* Consume three words, there's nothing to move to front.  */
+         if (words == 4)
+           line = sp[3], words = 0;
+       }
+      else
+        {
+         int j;
+         /* Consume one word.  If we had more move them to front.  */
+         words--;
+         for (j = 0; j < words; j++)
+           sp[j] = sp[j+1];
+         if (words == 3)
+           line = sp[2], words = 2;
+       }
+      olddeps = source_addid_dep(pd->source, olddeps, id, isreq);
+      if (!line)
+        break;
+    }
+  return olddeps;
+}
+
+Source *
+pool_addsource_content(Pool *pool, FILE *fp)
+{
+  char *line, *linep;
+  int aline;
+  Source *source;
+  Solvable *s;
+  struct deps *deps = 0, *dp = 0;
+  int pack, i;
+  struct parsedata pd;
+
+  source = pool_addsource_empty(pool);
+  memset(&pd, 0, sizeof(pd));
+  line = malloc(1024);
+  aline = 1024;
+
+  pd.source = source;
+  linep = line;
+  pack = 0;
+  s = 0;
+
+  for (;;)
+    {
+      char *fields[2];
+      if (linep - line + 16 > aline)
+       {
+         aline = linep - line;
+         line = realloc(line, aline + 512);
+         linep = line + aline;
+         aline += 512;
+       }
+      if (!fgets(linep, aline - (linep - line), fp))
+       break;
+      linep += strlen(linep);
+      if (linep == line || linep[-1] != '\n')
+        continue;
+      *--linep = 0;
+      linep = line;
+      if (split (line, fields, 2) == 2)
+        {
+         char *key = fields[0];
+         char *value = fields[1];
+         char *modifier = strchr (key, '.');
+         if (modifier)
+           *modifier++ = 0;
+#if 0
+         if (modifier)
+           fprintf (stderr, "key %s, mod %s, value %s\n", key, modifier, fields[1]);
+         else
+           fprintf (stderr, "key %s, value %s\n", key, fields[1]);
+#endif
+
+#define istag(x) !strcmp (key, x)
+         if (istag ("PRODUCT"))
+           {
+             /* Only support one product.  */
+             assert (!dp);
+             pd.kind = "product";
+             if ((pack & PACK_BLOCK) == 0)
+               {
+                 pool->solvables = realloc(pool->solvables, (pool->nsolvables + pack + PACK_BLOCK + 1) * sizeof(Solvable));
+                 memset(pool->solvables + source->start + pack, 0, (PACK_BLOCK + 1) * sizeof(Solvable));
+                 if (!deps)
+                   deps = malloc((pack + PACK_BLOCK + 1) * sizeof(struct deps));
+                 else
+                   deps = realloc(deps, (pack + PACK_BLOCK + 1) * sizeof(struct deps));
+                 memset(deps + pack, 0, (PACK_BLOCK + 1) * sizeof(struct deps));
+               }
+             s = pool->solvables + source->start + pack;
+             dp = deps + pack;
+             pack++;
+           }
+         else if (istag ("VERSION"))
+           ;
+         else if (istag ("DISTPRODUCT"))
+           s->name = str2id(pool, join(&pd, pd.kind, ":", value), 1);
+         else if (istag ("DISTVERSION"))
+           s->evr = makeevr(pool, value);
+         else if (istag ("ARCH"))
+           /* Theoretically we want to have the best arch of the given
+              modifiers which still is compatible with the system
+              arch.  We don't know the latter here, though.  */
+           s->arch = str2id (pool, "noarch" , 1);
+         else if (istag ("PREREQUIRES"))
+           dp->requires = adddep(pool, &pd, dp->requires, value, 2);
+         else if (istag ("REQUIRES"))
+           dp->requires = adddep(pool, &pd, dp->requires, value, 1);
+         else if (istag ("PROVIDES"))
+           dp->provides = adddep(pool, &pd, dp->provides, value, 0);
+         else if (istag ("CONFLICTS"))
+           dp->conflicts = adddep(pool, &pd, dp->conflicts, value, 0);
+         else if (istag ("OBSOLETES"))
+           dp->obsoletes = adddep(pool, &pd, dp->obsoletes, value, 0);
+         else if (istag ("RECOMMENDS"))
+           dp->recommends = adddep(pool, &pd, dp->recommends, value, 0);
+         else if (istag ("SUGGESTS"))
+           dp->suggests = adddep(pool, &pd, dp->suggests, value, 0);
+         else if (istag ("SUPPLEMENTS"))
+           dp->supplements = adddep(pool, &pd, dp->supplements, value, 0);
+         else if (istag ("ENHANCES"))
+           dp->enhances = adddep(pool, &pd, dp->enhances, value, 0);
+         /* There doesn't seem to exist FRESHENS.  */
+         /* XXX do something about LINGUAS and ARCH? */
+#undef istag
+       }
+      else
+       fprintf (stderr, "malformed line: %s\n", line);
+    }
+
+  if (dp && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
+    dp->provides = source_addid_dep(source, dp->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
+  if (dp)
+    dp->supplements = source_fix_legacy(source, dp->provides, dp->supplements);
+    
+  pool->nsolvables += pack;
+  source->nsolvables = pack;
+  s = pool->solvables + source->start;
+  for (i = 0; i < pack; i++, s++)
+    {
+      if (deps[i].provides)
+        s->provides = source->idarraydata + deps[i].provides;
+      if (deps[i].requires)
+        s->requires = source->idarraydata + deps[i].requires;
+      if (deps[i].conflicts)
+        s->conflicts = source->idarraydata + deps[i].conflicts;
+      if (deps[i].obsoletes)
+        s->obsoletes = source->idarraydata + deps[i].obsoletes;
+      if (deps[i].recommends)
+        s->recommends = source->idarraydata + deps[i].recommends;
+      if (deps[i].supplements)
+        s->supplements = source->idarraydata + deps[i].supplements;
+      if (deps[i].suggests)
+        s->suggests = source->idarraydata + deps[i].suggests;
+      if (deps[i].enhances)
+        s->enhances = source->idarraydata + deps[i].enhances;
+      if (deps[i].freshens)
+        s->freshens = source->idarraydata + deps[i].freshens;
+    }
+
+  free(deps);
+  if (pd.tmp)
+    free(pd.tmp);
+  free(line);
+
+  return source;
+}
diff --git a/tools/source_content.h b/tools/source_content.h
new file mode 100644 (file)
index 0000000..ca7f0ad
--- /dev/null
@@ -0,0 +1 @@
+Source * pool_addsource_content(Pool *pool, FILE *fp);