- no longer needed
authorMichael Schroeder <mls@suse.de>
Wed, 20 Feb 2008 10:51:48 +0000 (10:51 +0000)
committerMichael Schroeder <mls@suse.de>
Wed, 20 Feb 2008 10:51:48 +0000 (10:51 +0000)
src/attr_store.c [deleted file]
src/attr_store.h [deleted file]
src/attr_store_p.h [deleted file]

diff --git a/src/attr_store.c b/src/attr_store.c
deleted file mode 100644 (file)
index 3deb7ca..0000000
+++ /dev/null
@@ -1,1872 +0,0 @@
-/*
- * Copyright (c) 2007, Novell Inc.
- *
- * This program is licensed under the BSD license, read LICENSE.BSD
- * for further information
- */
-
-/* We need FNM_CASEFOLD and strcasestr.  */
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <fnmatch.h>
-#include <regex.h>
-
-#include "attr_store.h"
-#include "pool.h"
-#include "repo.h"
-#include "util.h"
-
-#include "attr_store_p.h"
-
-#include "fastlz.c"
-
-/* #define DEBUG_PAGING */
-
-#define BLOB_BLOCK 65535
-
-#define STRINGSPACE_BLOCK 1023
-#define STRING_BLOCK 127
-#define LOCALID_NULL  0
-#define LOCALID_EMPTY 1
-
-static Id add_key (Attrstore *s, Id name, unsigned type, unsigned size);
-
-Attrstore *
-new_store (Pool *pool)
-{
-  static const char *predef_strings[] = {
-    "<NULL>",
-    "",
-    0
-  };
-  Attrstore *s = sat_calloc (1, sizeof (Attrstore));
-  s->pool = pool;
-  stringpool_init (&s->ss, predef_strings);
-  add_key (s, 0, 0, 0);
-
-  return s;
-}
-
-LocalId
-str2localid (Attrstore *s, const char *str, int create)
-{
-  return stringpool_str2id (&s->ss, str, create);
-}
-
-const char *
-localid2str(Attrstore *s, LocalId id)
-{
-  return s->ss.stringspace + s->ss.strings[id];
-}
-
-static void
-setup_dirs (Attrstore *s)
-{
-  static const char *ss_init_strs[] =
-  {
-    "<NULL>",
-    "",
-    0
-  };
-
-  s->dirtree.dirs = sat_calloc (1024, sizeof (s->dirtree.dirs[0]));
-  s->dirtree.ndirs = 2;
-  s->dirtree.dirs[0].child = 0;
-  s->dirtree.dirs[0].sibling = 0;
-  s->dirtree.dirs[0].name = 0;
-  s->dirtree.dirs[1].child = 0;
-  s->dirtree.dirs[1].sibling = 0;
-  s->dirtree.dirs[1].name = STRID_EMPTY;
-
-  s->dirtree.dirstack_size = 16;
-  s->dirtree.dirstack = sat_malloc (s->dirtree.dirstack_size * sizeof (s->dirtree.dirstack[0]));
-  s->dirtree.ndirstack = 0;
-  s->dirtree.dirstack[s->dirtree.ndirstack++] = 1; //dir-id of /
-
-  stringpool_init (&s->dirtree.ss, ss_init_strs);
-}
-
-#if 0
-static void
-dir_setup_flatsons (Dirtree *d)
-{
-  if (d->flatsons)
-    return;
-  if (!d->nflatdirs)
-    return;
-  d->flatsons = sat_calloc (d->nflatdirs, sizeof (d->flatsons[0]));
-  unsigned firstson = -1;
-  unsigned i;
-  for (i = 0; i < d->nflatdirs; i++)
-    if (d->flatdirs[i] & 1)
-      /* A node, i.e. potential son.  */
-      {
-        if (firstson == -1)
-         firstson = i;
-      }
-    else if (d->flatdirs[i] & 2)
-      /* An intermediate parent pointer.  */
-      ;
-    else
-      /* The final parent pointer.  Remember the first son.  */
-      {
-        assert (firstson != -1);
-       d->flatsons[d->flatdirs[i] >> 2] = firstson;
-       firstson = -1;
-      }
-}
-#endif
-
-static unsigned
-dir_lookup_1 (Attrstore *s, unsigned dir, const char *name, unsigned insert)
-{
-  Id nameid;
-  while (*name == '/')
-    name++;
-  if (!*name)
-    return dir;
-  const char *end = strchrnul (name, '/');
-  nameid = stringpool_strn2id (&s->dirtree.ss, name, end - name, 1);
-  unsigned c, num = 0;
-  Dir *dirs = s->dirtree.dirs;
-  for (c = dirs[dir].child; c; c = dirs[c].sibling, num++)
-    if (nameid == dirs[c].name)
-      break;
-  if (!c && !insert)
-    return 0;
-  if (!c)
-    {
-      c = s->dirtree.ndirs++;
-      if (!(c & 1023))
-       dirs = sat_realloc (dirs, (c + 1024) * sizeof (dirs[0]));
-      dirs[c].child = 0;
-      dirs[c].sibling = dirs[dir].child;
-      dirs[c].name = nameid;
-      dirs[c].parent = dir;
-      dirs[dir].child = c;
-      s->dirtree.dirs = dirs;
-    }
-  if (!(s->dirtree.ndirstack & 15))
-    {
-      s->dirtree.dirstack_size += 16;
-      s->dirtree.dirstack = sat_realloc (s->dirtree.dirstack, s->dirtree.dirstack_size * sizeof (s->dirtree.dirstack[0]));
-    }
-  s->dirtree.dirstack[s->dirtree.ndirstack++] = c;
-  if (!*end)
-    return c;
-  unsigned ret = dir_lookup_1 (s, c, end + 1, insert);
-  return ret;
-}
-
-unsigned
-dir_lookup (Attrstore *s, const char *name, unsigned insert)
-{
-  if (!s->dirtree.ndirs)
-    setup_dirs (s);
-
-  /* Detect number of common path components.  Accept multiple // .  */
-  const char *new_start;
-  unsigned components;
-  for (components = 1, new_start = name; components < s->dirtree.ndirstack; )
-    {
-      int ofs;
-      const char *dirname;
-      while (*new_start == '/')
-       new_start++;
-      dirname = stringpool_id2str (&s->dirtree.ss, s->dirtree.dirs[s->dirtree.dirstack[components]].name);
-      for (ofs = 0;; ofs++)
-       {
-         char n = new_start[ofs];
-         char d = dirname[ofs];
-         if (d == 0 && (n == 0 || n == '/'))
-           {
-             new_start += ofs;
-             components++;
-             if (n == 0)
-               goto endmatch2;
-             break;
-           }
-         if (n != d)
-           goto endmatch;
-       }
-    }
-endmatch:
-  while (*new_start == '/')
-    new_start++;
-endmatch2:
-
-  /* We have always / on the stack.  */
-  //assert (ndirstack);
-  //assert (ndirstack >= components);
-  s->dirtree.ndirstack = components;
-  unsigned ret = s->dirtree.dirstack[s->dirtree.ndirstack - 1];
-  if (*new_start)
-    ret = dir_lookup_1 (s, ret, new_start, insert);
-  //assert (ret == dirstack[ndirstack - 1]);
-  return ret;
-}
-
-unsigned
-dir_parent (Attrstore *s, unsigned dir)
-{
-  if (s->dirtree.dirs)
-    return s->dirtree.dirs[dir].parent;
-  /* We have the packed representation.  */
-  unsigned p;
-  while ((p = s->dirtree.flatdirs[dir]) & 1)
-    dir++;
-  return p >> 2;
-}
-
-void
-dir2str (Attrstore *s, unsigned dir, char **str, unsigned *len)
-{
-  unsigned l = 0;
-  Id ids[256];
-  unsigned i, ii;
-  if (s->dirtree.dirs)
-    for (i = 0; i < 256 && dir > 1; dir = dir_parent (s, dir), i++)
-      ids[i] = s->dirtree.dirs[dir].name;
-  else
-    for (i = 0; i < 256 && dir > 1; dir = dir_parent (s, dir), i++)
-      {
-        assert (s->dirtree.flatdirs[dir] & 1);
-        ids[i] = s->dirtree.flatdirs[dir] >> 1;
-      }
-  ii = i;
-  l = 1;
-  for (i = 0; i < ii; i++)
-    l += 1 + strlen (stringpool_id2str (&s->dirtree.ss, ids[i]));
-  l++;
-  if (l > *len)
-    {
-      *str = sat_malloc (l);
-      *len = l;
-    }
-  char *dest = *str;
-  *dest++ = '/';
-  for (i = ii; i--;)
-    {
-      const char *name = stringpool_id2str (&s->dirtree.ss, ids[i]);
-      dest = mempcpy (dest, name, strlen (name));
-      *dest++ = '/';
-    }
-  *dest = 0;
-}
-
-void
-ensure_entry (Attrstore *s, unsigned int entry)
-{
-  unsigned int old_num = s->entries;
-  if (entry < s->entries)
-    return;
-  s->entries = entry + 1;
-  if (((old_num + 127) & ~127) != ((s->entries + 127) & ~127))
-    {
-      if (s->attrs)
-        s->attrs = sat_realloc (s->attrs, (((s->entries+127) & ~127) * sizeof (s->attrs[0])));
-      else
-        s->attrs = sat_malloc (((s->entries+127) & ~127) * sizeof (s->attrs[0]));
-    }
-  memset (s->attrs + old_num, 0, (s->entries - old_num) * sizeof (s->attrs[0]));
-}
-
-unsigned int
-new_entry (Attrstore *s)
-{
-  if ((s->entries & 127) == 0)
-    {
-      if (s->attrs)
-        s->attrs = sat_realloc (s->attrs, ((s->entries+128) * sizeof (s->attrs[0])));
-      else
-        s->attrs = sat_malloc ((s->entries+128) * sizeof (s->attrs[0]));
-    }
-  s->attrs[s->entries++] = 0;
-  return s->entries - 1;
-}
-
-static LongNV *
-find_attr (Attrstore *s, unsigned int entry, Id name)
-{
-  LongNV *nv;
-  if (entry >= s->entries)
-    return 0;
-  nv = s->attrs[entry];
-  if (nv)
-    {
-      while (nv->key && s->keys[nv->key].name != name)
-       nv++;
-      if (nv->key)
-        return nv;
-    }
-  return 0;
-}
-
-static void
-add_attr (Attrstore *s, unsigned int entry, LongNV attr)
-{
-  LongNV *nv;
-  unsigned int len;
-  ensure_entry (s, entry);
-  if (attr.key >= s->nkeys)
-    return;
-  nv = s->attrs[entry];
-  len = 0;
-  if (nv)
-    {
-      while (nv->key && nv->key != attr.key)
-       nv++;
-      if (nv->key)
-        return;
-      len = nv - s->attrs[entry];
-    }
-  len += 2;
-  if (s->attrs[entry])
-    s->attrs[entry] = sat_realloc (s->attrs[entry], len * sizeof (LongNV));
-  else
-    s->attrs[entry] = sat_malloc (len * sizeof (LongNV));
-  nv = s->attrs[entry] + len - 2;
-  *nv++ = attr;
-  nv->key = 0;
-}
-
-void
-add_attr_int (Attrstore *s, unsigned int entry, Id name, unsigned int val)
-{
-  LongNV nv;
-  nv.key = add_key (s, name, TYPE_ATTR_INT, 0);
-  nv.v.i[0] = val;
-  add_attr (s, entry, nv);
-}
-
-void
-add_attr_special_int (Attrstore *s, unsigned int entry, Id name, unsigned int val)
-{
-  LongNV nv;
-  nv.key = add_key (s, name, TYPE_VOID, val);
-  add_attr (s, entry, nv);
-}
-
-static void
-add_attr_chunk (Attrstore *s, unsigned int entry, Id name, unsigned int ofs, unsigned int len)
-{
-  LongNV nv;
-  nv.key = add_key (s, name, TYPE_ATTR_CHUNK, 0);
-  nv.v.i[0] = ofs;
-  nv.v.i[1] = len;
-  add_attr (s, entry, nv);
-}
-
-void
-add_attr_blob (Attrstore *s, unsigned int entry, Id name, const void *ptr, unsigned int len)
-{
-  if (((s->blob_next_free + BLOB_BLOCK) & ~BLOB_BLOCK)
-      != ((s->blob_next_free + len + BLOB_BLOCK) & ~BLOB_BLOCK))
-    {
-      unsigned int blobsz = (s->blob_next_free + len + BLOB_BLOCK) &~BLOB_BLOCK;
-      s->blob_store = sat_realloc (s->blob_store, blobsz);
-    }
-  memcpy (s->blob_store + s->blob_next_free, ptr, len);
-  add_attr_chunk (s, entry, name, s->blob_next_free, len);
-  s->blob_next_free += len;
-
-  unsigned int npages = (s->blob_next_free + BLOB_PAGESIZE - 1) / BLOB_PAGESIZE;
-  if (npages != s->num_pages)
-    {
-      Attrblobpage *p;
-      s->pages = sat_realloc (s->pages, npages * sizeof (s->pages[0]));
-      for (p = s->pages + s->num_pages; s->num_pages < npages;
-          p++, s->num_pages++)
-       {
-         p->mapped_at = s->num_pages * BLOB_PAGESIZE;
-         p->file_offset = 0;
-         p->file_size = 0;
-       }
-    }
-}
-
-void
-add_attr_string (Attrstore *s, unsigned int entry, Id name, const char *val)
-{
-  LongNV nv;
-  nv.key = add_key (s, name, TYPE_ATTR_STRING, 0);
-  nv.v.str = strdup (val);
-  add_attr (s, entry, nv);
-}
-
-void
-add_attr_intlist_int (Attrstore *s, unsigned int entry, Id name, int val)
-{
-  LongNV *nv = find_attr (s, entry, name);
-  if (nv)
-    {
-      unsigned len = nv->v.intlist[0]++;
-      nv->v.intlist = sat_realloc (nv->v.intlist, (len + 2) * sizeof (nv->v.intlist[0]));
-      nv->v.intlist[len+1] = val;
-    }
-  else
-    {
-      LongNV mynv;
-      mynv.key = add_key (s, name, TYPE_ATTR_INTLIST, 0);
-      mynv.v.intlist = sat_malloc (2 * sizeof (mynv.v.intlist[0]));
-      mynv.v.intlist[0] = 1;
-      mynv.v.intlist[1] = val;
-      add_attr (s, entry, mynv);
-    }
-}
-
-void
-add_attr_localids_id (Attrstore *s, unsigned int entry, Id name, LocalId id)
-{
-  LongNV *nv = find_attr (s, entry, name);
-  if (nv)
-    {
-      unsigned len = 0;
-      while (nv->v.localids[len])
-        len++;
-      nv->v.localids = sat_realloc (nv->v.localids, (len + 2) * sizeof (nv->v.localids[0]));
-      nv->v.localids[len] = id;
-      nv->v.localids[len+1] = 0;
-    }
-  else
-    {
-      LongNV mynv;
-      mynv.key = add_key (s, name, TYPE_ATTR_LOCALIDS, 0);
-      mynv.v.localids = sat_malloc (2 * sizeof (mynv.v.localids[0]));
-      mynv.v.localids[0] = id;
-      mynv.v.localids[1] = 0;
-      add_attr (s, entry, mynv);
-    }
-}
-
-void
-add_attr_void (Attrstore *s, unsigned int entry, Id name)
-{
-  LongNV nv;
-  nv.key = add_key (s, name, TYPE_VOID, 0);
-  add_attr (s, entry, nv);
-}
-
-void
-merge_attrs (Attrstore *s, unsigned dest, unsigned src)
-{
-  LongNV *nv;
-  ensure_entry (s, dest);
-  nv = s->attrs[src];
-  if (nv)
-    {
-      for (; nv->key; nv++)
-        if (!find_attr (s, dest, s->keys[nv->key].name))
-         switch (s->keys[nv->key].type)
-           {
-             case TYPE_ATTR_INTLIST:
-               {
-                 unsigned i, len = nv->v.intlist[0];
-                 for (i = 0; i < len; i++)
-                   add_attr_intlist_int (s, dest, s->keys[nv->key].name, nv->v.intlist[i + 1]);
-               }
-               break;
-             case TYPE_ATTR_LOCALIDS:
-               {
-                 unsigned len = 0;
-                 while (nv->v.localids[len])
-                   add_attr_localids_id (s, dest, s->keys[nv->key].name, nv->v.localids[len++]);
-               }
-               break;
-             case TYPE_ATTR_STRING:
-               add_attr_string (s, dest, s->keys[nv->key].name, nv->v.str);
-               break;
-             default:
-               add_attr (s, dest, *nv);
-               break;
-           }
-    }
-}
-
-#define pool_debug(a,b,...) fprintf (stderr, __VA_ARGS__)
-
-static Id read_id (FILE *fp, Id max);
-
-/* This routine is used only when attributes are embedded into the
-   normal repo SOLV file.  */
-void
-add_attr_from_file (Attrstore *s, unsigned entry, Id name, int type, Id *idmap, unsigned maxid, FILE *fp, unsigned size)
-{
-  Pool *pool = s->pool;
-  //fprintf (stderr, "%s: attribute in a repo SOLV?\n", id2str (pool, name));
-  switch (type)
-    {
-      case TYPE_VOID:
-       if (size)
-         add_attr_special_int (s, entry, name, size);
-       else
-          add_attr_void (s, entry, name);
-       break;
-      case TYPE_ATTR_CHUNK:
-       {
-         unsigned ofs = read_id (fp, 0);
-         unsigned len = read_id (fp, 0);
-         add_attr_chunk (s, entry, name, ofs, len);
-       }
-       break;
-      case TYPE_ATTR_INT:
-       {
-         unsigned i = read_id(fp, 0);
-         add_attr_int (s, entry, name, i);
-       }
-       break;
-      case TYPE_ATTR_STRING:
-        {
-         unsigned char localbuf[1024];
-         int c;
-         unsigned char *buf = localbuf;
-         unsigned len = sizeof (localbuf);
-         unsigned ofs = 0;
-         while((c = getc (fp)) != 0)
-           {
-             if (c == EOF)
-               {
-                 pool_debug (mypool, SAT_FATAL, "unexpected EOF\n");
-                 exit (1);
-               }
-             /* Plus 1 as we also want to add the 0.  */
-             if (ofs + 1 >= len)
-               {
-                 len += 256;
-                 if (buf == localbuf)
-                   {
-                     buf = sat_malloc (len);
-                     memcpy (buf, localbuf, len - 256);
-                   }
-                 else
-                   buf = sat_realloc (buf, len);
-               }
-             buf[ofs++] = c;
-           }
-         buf[ofs++] = 0;
-         add_attr_string (s, entry, name, (char*) buf);
-         if (buf != localbuf)
-           sat_free (buf);
-       }
-       break;
-      case TYPE_ATTR_INTLIST:
-       {
-         int i;
-         while ((i = read_id(fp, 0)) & 64)
-           add_attr_intlist_int (s, entry, name, (i & 63) | ((i >> 1) & ~63));
-         add_attr_intlist_int (s, entry, name, (i & 63) | ((i >> 1) & ~63));
-       }
-       break;
-      case TYPE_ATTR_LOCALIDS:
-        {
-         Id i;
-         /* The read ID will be pool-based.  */
-         while ((i = read_id(fp, maxid)) != 0)
-           {
-             if (idmap)
-               i = idmap[i];
-             add_attr_localids_id (s, entry, name, str2localid (s, id2str (pool, i), 1));
-           }
-       }
-       break;
-      default:
-       pool_debug(pool, SAT_FATAL, "unknown type %d\n", type);
-       exit(0);
-    }
-}
-
-/* Make sure all pages from PSTART to PEND (inclusive) are loaded,
-   and are consecutive.  Return a pointer to the mapping of PSTART.  */
-static const void *
-load_page_range (Attrstore *s, unsigned int pstart, unsigned int pend)
-{
-  unsigned char buf[BLOB_PAGESIZE];
-  unsigned int i;
-
-  /* Quick check in case all pages are there already and consecutive.  */
-  for (i = pstart; i <= pend; i++)
-    if (s->pages[i].mapped_at == -1
-        || (i > pstart
-           && s->pages[i].mapped_at
-              != s->pages[i-1].mapped_at + BLOB_PAGESIZE))
-      break;
-  if (i > pend)
-    return s->blob_store + s->pages[pstart].mapped_at;
-
-  /* Ensure that we can map the numbers of pages we need at all.  */
-  if (pend - pstart + 1 > s->ncanmap)
-    {
-      unsigned int oldcan = s->ncanmap;
-      s->ncanmap = pend - pstart + 1;
-      if (s->ncanmap < 4)
-        s->ncanmap = 4;
-      s->mapped = sat_realloc (s->mapped, s->ncanmap * sizeof (s->mapped[0]));
-      memset (s->mapped + oldcan, 0, (s->ncanmap - oldcan) * sizeof (s->mapped[0]));
-      s->blob_store = sat_realloc (s->blob_store, s->ncanmap * BLOB_PAGESIZE);
-#ifdef DEBUG_PAGING
-      fprintf (stderr, "PAGE: can map %d pages\n", s->ncanmap);
-#endif
-    }
-
-  /* Now search for "cheap" space in our store.  Space is cheap if it's either
-     free (very cheap) or contains pages we search for anyway.  */
-
-  /* Setup cost array.  */
-  unsigned int cost[s->ncanmap];
-  for (i = 0; i < s->ncanmap; i++)
-    {
-      unsigned int pnum = s->mapped[i];
-      if (pnum == 0)
-        cost[i] = 0;
-      else
-        {
-         pnum--;
-         Attrblobpage *p = s->pages + pnum;
-         assert (p->mapped_at != -1);
-         if (pnum >= pstart && pnum <= pend)
-           cost[i] = 1;
-         else
-           cost[i] = 3;
-       }
-    }
-
-  /* And search for cheapest space.  */
-  unsigned int best_cost = -1;
-  unsigned int best = 0;
-  unsigned int same_cost = 0;
-  for (i = 0; i + pend - pstart < s->ncanmap; i++)
-    {
-      unsigned int c = cost[i];
-      unsigned int j;
-      for (j = 0; j < pend - pstart + 1; j++)
-        c += cost[i+j];
-      if (c < best_cost)
-        best_cost = c, best = i;
-      else if (c == best_cost)
-        same_cost++;
-      /* A null cost won't become better.  */
-      if (c == 0)
-        break;
-    }
-  /* If all places have the same cost we would thrash on slot 0.  Avoid
-     this by doing a round-robin strategy in this case.  */
-  if (same_cost == s->ncanmap - pend + pstart - 1)
-    best = s->rr_counter++ % (s->ncanmap - pend + pstart);
-
-  /* So we want to map our pages from [best] to [best+pend-pstart].
-     Use a very simple strategy, which doesn't make the best use of
-     our resources, but works.  Throw away all pages in that range
-     (even ours) then copy around ours (in case they were outside the 
-     range) or read them in.  */
-  for (i = best; i < best + pend - pstart + 1; i++)
-    {
-      unsigned int pnum = s->mapped[i];
-      if (pnum--
-          /* If this page is exactly at the right place already,
-            no need to evict it.  */
-          && pnum != pstart + i - best)
-       {
-         /* Evict this page.  */
-#ifdef DEBUG_PAGING
-         fprintf (stderr, "PAGE: evict page %d from %d\n", pnum, i);
-#endif
-         cost[i] = 0;
-         s->mapped[i] = 0;
-         s->pages[pnum].mapped_at = -1;
-       }
-    }
-
-  /* Everything is free now.  Read in the pages we want.  */
-  for (i = pstart; i <= pend; i++)
-    {
-      Attrblobpage *p = s->pages + i;
-      unsigned int pnum = i - pstart + best;
-      void *dest = s->blob_store + pnum * BLOB_PAGESIZE;
-      if (p->mapped_at != -1)
-        {
-         if (p->mapped_at != pnum * BLOB_PAGESIZE)
-           {
-#ifdef DEBUG_PAGING
-             fprintf (stderr, "PAGECOPY: %d to %d\n", i, pnum);
-#endif
-             /* Still mapped somewhere else, so just copy it from there.  */
-             memcpy (dest, s->blob_store + p->mapped_at, BLOB_PAGESIZE);
-             s->mapped[p->mapped_at / BLOB_PAGESIZE] = 0;
-           }
-       }
-      else
-        {
-         unsigned int in_len = p->file_size;
-         unsigned int compressed = in_len & 1;
-         in_len >>= 1;
-#ifdef DEBUG_PAGING
-         fprintf (stderr, "PAGEIN: %d to %d", i, pnum);
-#endif
-         /* Not mapped, so read in this page.  */
-         if (fseek (s->file, p->file_offset, SEEK_SET) < 0)
-           {
-             perror ("mapping fseek");
-             exit (1);
-           }
-         if (fread (compressed ? buf : dest, in_len, 1, s->file) != 1)
-           {
-             perror ("mapping fread");
-             exit (1);
-           }
-         if (compressed)
-           {
-             unsigned int out_len;
-             out_len = unchecked_decompress_buf (buf, in_len,
-                                                 dest, BLOB_PAGESIZE);
-             if (out_len != BLOB_PAGESIZE
-                 && i < s->num_pages - 1)
-               {
-                 fprintf (stderr, "can't decompress\n");
-                 exit (1);
-               }
-#ifdef DEBUG_PAGING
-             fprintf (stderr, " (expand %d to %d)", in_len, out_len);
-#endif
-           }
-#ifdef DEBUG_PAGING
-         fprintf (stderr, "\n");
-#endif
-       }
-      p->mapped_at = pnum * BLOB_PAGESIZE;
-      s->mapped[pnum] = i + 1;
-    }
-
-  return s->blob_store + best * BLOB_PAGESIZE;
-}
-
-const void *
-attr_retrieve_blob (Attrstore *s, unsigned int ofs, unsigned int len)
-{
-  if (s->file)
-    {
-      /* Paging!  Yeah!  */
-      unsigned int pstart = ofs / BLOB_PAGESIZE;
-      unsigned int pend = (ofs + len - 1) / BLOB_PAGESIZE;
-      const void *m = load_page_range (s, pstart, pend);
-      return m + (ofs & (BLOB_PAGESIZE - 1));
-    }
-  if (!s->blob_store)
-    return 0;
-  if (ofs >= s->blob_next_free)
-    return 0;
-  return s->blob_store + ofs;
-}
-
-#define FLAT_ATTR_BLOCK 127
-#define KEY_BLOCK 127
-#define SCHEMA_BLOCK 127
-
-#define add_elem(buf,ofs,val,block) do { \
-  if (((ofs) & (block)) == 0) \
-    buf = sat_realloc (buf, ((ofs) + (block) + 1) * sizeof((buf)[0])); \
-  (buf)[(ofs)++] = val; \
-} while (0)
-#define add_u16(buf,ofs,val,block) do {\
-  typedef int __wrong_buf__[(1-sizeof((buf)[0])) * (sizeof((buf)[0])-1)];\
-  add_elem(buf,ofs,(val) & 0xFF,block); \
-  add_elem(buf,ofs,((val) >> 8) & 0xFF,block); \
-} while (0)
-#define add_num(buf,ofs,val,block) do {\
-  typedef int __wrong_buf__[(1-sizeof((buf)[0])) * (sizeof((buf)[0])-1)];\
-  if ((val) >= (1 << 14)) \
-    { \
-      if ((val) >= (1 << 28)) \
-       add_elem (buf,ofs,((val) >> 28) | 128, block); \
-      if ((val) >= (1 << 21)) \
-       add_elem (buf,ofs,((val) >> 21) | 128, block); \
-      add_elem (buf,ofs,((val) >> 14) | 128, block); \
-    } \
-  if ((val) >= (1 << 7)) \
-    add_elem (buf,ofs,((val) >> 7) | 128, block); \
-  add_elem (buf,ofs,(val) & 127, block); \
-} while (0)
-
-static int
-longnv_cmp (const void *pa, const void *pb)
-{
-  const LongNV *a = (const LongNV *)pa;
-  const LongNV *b = (const LongNV *)pb;
-  return a->key - b->key;
-}
-
-static Id
-add_key (Attrstore *s, Id name, unsigned type, unsigned size)
-{
-  unsigned i;
-  for (i = 0; i < s->nkeys; i++)
-    if (s->keys[i].name == name && s->keys[i].type == type
-       && (type != TYPE_VOID || s->keys[i].size == size))
-      break;
-  if (i < s->nkeys)
-    {
-      if (type != TYPE_VOID)
-        s->keys[i].size += size;
-      return i;
-    }
-  if ((s->nkeys & KEY_BLOCK) == 0)
-    s->keys = sat_realloc (s->keys, (s->nkeys + KEY_BLOCK + 1) * sizeof (s->keys[0]));
-  s->keys[i].name = name;
-  s->keys[i].type = type;
-  s->keys[i].size = size;
-  return s->nkeys++;
-}
-
-#define DIR_BLOCK 1023
-#define CACHE_LINE 32
-#define CACHE_LINE_ELEMS (CACHE_LINE / sizeof(unsigned))
-
-static void
-finalize_dirs_rec (Dirtree *d, unsigned dir)
-{
-  unsigned c, parent;
-  if (!d->dirs[dir].child)
-    return;
-  parent = d->dirmap[dir];
-  assert(parent);
-  parent--;
-  for (c = d->dirs[dir].child; c; c = d->dirs[c].sibling)
-    {
-      unsigned id = d->dirs[c].name;
-      if ((d->nflatdirs & (CACHE_LINE_ELEMS - 1)) == CACHE_LINE_ELEMS - 1)
-       add_elem (d->flatdirs, d->nflatdirs, parent * 4 + 2, DIR_BLOCK);
-      d->dirmap[c] = d->nflatdirs + 1;
-      add_elem (d->flatdirs, d->nflatdirs, id * 2 + 1, DIR_BLOCK);
-    }
-  add_elem (d->flatdirs, d->nflatdirs, parent * 4, DIR_BLOCK);
-  for (c = d->dirs[dir].child; c; c = d->dirs[c].sibling)
-    finalize_dirs_rec (d, c);
-}
-
-static void
-finalize_dirtree (Dirtree *d)
-{
-  if (d->nflatdirs || !d->ndirs)
-    return;
-  d->dirmap = sat_calloc (d->ndirs, sizeof (d->dirmap[0]));
-  d->nflatdirs = 0;
-  d->flatdirs = 0;
-  d->flatsons = 0;
-  d->dirmap[1] = d->nflatdirs + 1;
-  finalize_dirs_rec (d, 1);
-  sat_free (d->dirs);
-  d->dirs = 0;
-}
-
-void
-attr_store_pack (Attrstore *s)
-{
-  unsigned i;
-  unsigned int old_mem = 0;
-  if (s->packed)
-    return;
-  finalize_dirtree (&s->dirtree);
-
-  s->ent2attr = sat_calloc (s->entries, sizeof (s->ent2attr[0]));
-  s->flat_attrs = 0;
-  s->attr_next_free = 0;
-  s->nschemata = 0;
-  s->szschemata = 0;
-  s->schemata = 0;
-  s->schemaofs = 0;
-
-  Id id_diskusage = str2id (s->pool, "diskusage", 0);
-
-  add_num (s->flat_attrs, s->attr_next_free, 0, FLAT_ATTR_BLOCK);
-  add_elem (s->schemata, s->szschemata, 0, SCHEMA_BLOCK);
-  add_elem (s->schemaofs, s->nschemata, 0, SCHEMA_BLOCK);
-
-  for (i = 0; i < s->entries; i++)
-    {
-      unsigned int num_attrs = 0, ofs;
-      LongNV *nv = s->attrs[i];
-      if (nv)
-        while (nv->key)
-         nv++, num_attrs++;
-      if (nv)
-        old_mem += (num_attrs + 1) * sizeof (LongNV);
-      if (!num_attrs)
-        continue;
-      nv = s->attrs[i];
-      qsort (s->attrs[i], num_attrs, sizeof (LongNV), longnv_cmp);
-      unsigned int this_schema;
-      for (this_schema = 0; this_schema < s->nschemata; this_schema++)
-        {
-         for (ofs = 0; ofs < num_attrs; ofs++)
-           {
-             Id key = nv[ofs].key;
-             assert (s->schemaofs[this_schema] + ofs < s->szschemata);
-             if (key != s->schemata[s->schemaofs[this_schema]+ofs])
-               break;
-           }
-         if (ofs == num_attrs && !s->schemata[s->schemaofs[this_schema]+ofs])
-           break;
-       }
-      if (this_schema == s->nschemata)
-        {
-         /* This schema not found --> insert it.  */
-         add_elem (s->schemaofs, s->nschemata, s->szschemata, SCHEMA_BLOCK);
-         for (ofs = 0; ofs < num_attrs; ofs++)
-           {
-             Id key = nv[ofs].key;
-             add_elem (s->schemata, s->szschemata, key, SCHEMA_BLOCK);
-           }
-         add_elem (s->schemata, s->szschemata, 0, SCHEMA_BLOCK);
-       }
-      s->ent2attr[i] = s->attr_next_free;
-      add_num (s->flat_attrs, s->attr_next_free, this_schema, FLAT_ATTR_BLOCK);
-      for (ofs = 0; ofs < num_attrs; ofs++)
-       switch (s->keys[nv[ofs].key].type)
-         {
-           case TYPE_VOID:
-             break;
-           case TYPE_ATTR_INT:
-             {
-               unsigned int i = nv[ofs].v.i[0];
-               add_num (s->flat_attrs, s->attr_next_free, i, FLAT_ATTR_BLOCK);
-               break;
-             }
-           case TYPE_ATTR_CHUNK:
-             {
-               unsigned int i = nv[ofs].v.i[0];
-               add_num (s->flat_attrs, s->attr_next_free, i, FLAT_ATTR_BLOCK);
-               i = nv[ofs].v.i[1];
-               add_num (s->flat_attrs, s->attr_next_free, i, FLAT_ATTR_BLOCK);
-               break;
-             }
-           case TYPE_ATTR_STRING:
-             {
-               const char *str = nv[ofs].v.str;
-               for (; *str; str++)
-                 add_elem (s->flat_attrs, s->attr_next_free, *str, FLAT_ATTR_BLOCK);
-               add_elem (s->flat_attrs, s->attr_next_free, 0, FLAT_ATTR_BLOCK);
-               old_mem += strlen ((const char*)nv[ofs].v.str) + 1;
-               sat_free ((void*)nv[ofs].v.str);
-               break;
-             }
-           case TYPE_ATTR_INTLIST:
-             {
-               const int *il = nv[ofs].v.intlist;
-               int len = *il++;
-               if (s->dirtree.dirmap
-                   && s->keys[nv[ofs].key].name == id_diskusage)
-                 {
-                   unsigned i;
-                   assert (!(len % 3));
-                   for (i = 1; i <= len; i += 3)
-                     nv[ofs].v.intlist[i] = s->dirtree.dirmap[nv[ofs].v.intlist[i]] - 1;
-                 }
-               old_mem += 4 * (len + 1);
-               while (len--)
-                 {
-                   int i = *il++;
-                   if (i >= 64)
-                     i = (i & 63) | ((i & ~63) << 1);
-                   if (len)
-                     i |= 64;
-                   add_num (s->flat_attrs, s->attr_next_free, i, FLAT_ATTR_BLOCK);
-                 }
-               sat_free (nv[ofs].v.intlist);
-               break;
-             }
-           case TYPE_ATTR_LOCALIDS:
-             {
-               const Id *il = nv[ofs].v.localids;
-               Id i;
-               for (; (i = *il) != 0; il++, old_mem += 4)
-                 add_num (s->flat_attrs, s->attr_next_free, i, FLAT_ATTR_BLOCK);
-               add_num (s->flat_attrs, s->attr_next_free, 0, FLAT_ATTR_BLOCK);
-               old_mem += 4;
-               sat_free (nv[ofs].v.localids);
-               break;
-             }
-           default:
-             break;
-         }
-      sat_free (nv);
-    }
-  old_mem += s->entries * sizeof (s->attrs[0]);
-  free (s->attrs);
-  s->attrs = 0;
-  sat_free (s->dirtree.dirmap);
-  s->dirtree.dirmap = 0;
-
-  /* Remove the hashtable too, it will be build on demand in str2localid
-     the next time we call it, which should not happen while in packed mode.  */
-  old_mem += (s->ss.stringhashmask + 1) * sizeof (s->ss.stringhashtbl[0]);
-  free (s->ss.stringhashtbl);
-  s->ss.stringhashtbl = 0;
-  s->ss.stringhashmask = 0;
-
-  fprintf (stderr, "%d\n", old_mem);
-  fprintf (stderr, "%zd\n", s->entries * sizeof(s->ent2attr[0]));
-  fprintf (stderr, "%d\n", s->attr_next_free);
-  fprintf (stderr, "%zd\n", s->nschemata * sizeof(s->schemaofs[0]));
-  fprintf (stderr, "%zd\n", s->szschemata * sizeof(s->schemata[0]));
-  fprintf (stderr, "pages %d\n", s->num_pages);
-  s->packed = 1;
-}
-
-/* Pages in all blob pages, and deactivates paging.  */
-static void
-pagein_all (Attrstore *s)
-{
-  /* If we have no backing file everything is there already.  */
-  if (!s->file)
-    return;
-  /*fprintf (stderr, "Aieee!\n");
-  exit (1);*/
-}
-
-void
-attr_store_unpack (Attrstore *s)
-{
-  unsigned int i;
-  if (!s->packed)
-    return;
-
-  pagein_all (s);
-
-  /* Make the store writable right away, so we can use our adder functions.  */
-  s->packed = 0;
-  s->attrs = sat_calloc (s->entries, sizeof (s->attrs[0]));
-
-  for (i = 0; i < s->entries; i++)
-    {
-      attr_iterator ai;
-      FOR_ATTRS (s, i, &ai)
-        {
-         switch (ai.type)
-           {
-           case TYPE_VOID:
-             if (ai.as_int)
-               add_attr_special_int (s, i, ai.name, ai.as_int);
-             else
-               add_attr_void (s, i, ai.name);
-             break;
-           case TYPE_ATTR_INT:
-             add_attr_int (s, i, ai.name, ai.as_int); 
-             break;
-           case TYPE_ATTR_CHUNK:
-             add_attr_chunk (s, i, ai.name, ai.as_chunk[0], ai.as_chunk[1]);
-             break;
-           case TYPE_ATTR_STRING:
-             add_attr_string (s, i, ai.name, ai.as_string);
-             break;
-           case TYPE_ATTR_INTLIST:
-             {
-               while (1)
-                 {
-                   int val;
-                   get_num (ai.as_numlist, val);
-                   add_attr_intlist_int (s, i, ai.name, (val & 63) | ((val >> 1) & ~63));
-                   if (!(val & 64))
-                     break;
-                 }
-               break;
-             }
-           case TYPE_ATTR_LOCALIDS:
-             {
-               while (1)
-                 {
-                   Id val;
-                   get_num (ai.as_numlist, val);
-                   if (!val)
-                     break;
-                   add_attr_localids_id (s, i, ai.name, val);
-                 }
-               break;
-             }
-           default:
-             break;
-           }
-       }
-    }
-
-  sat_free (s->ent2attr);
-  s->ent2attr = 0;
-  sat_free (s->flat_attrs);
-  s->flat_attrs = 0;
-  s->attr_next_free = 0;
-  sat_free (s->schemaofs);
-  s->schemaofs = 0;
-  s->nschemata = 0;
-  sat_free (s->schemata);
-  s->schemata = 0;
-  s->szschemata = 0;
-  /* XXX unpack the dirtree */
-}
-
-static void
-write_u8(FILE *fp, unsigned int x)
-{
-  if (putc(x, fp) == EOF)
-    {
-      perror("write error");
-      exit(1);
-    }
-}
-
-static void
-write_u32(FILE *fp, unsigned int x)
-{
-  if (putc(x >> 24, fp) == EOF ||
-      putc(x >> 16, fp) == EOF ||
-      putc(x >> 8, fp) == EOF ||
-      putc(x, fp) == EOF)
-    {
-      perror("write error");
-      exit(1);
-    }
-}
-
-static void
-write_id(FILE *fp, Id x)
-{
-  if (x >= (1 << 14))
-    {
-      if (x >= (1 << 28))
-       putc((x >> 28) | 128, fp);
-      if (x >= (1 << 21))
-       putc((x >> 21) | 128, fp);
-      putc((x >> 14) | 128, fp);
-    }
-  if (x >= (1 << 7))
-    putc((x >> 7) | 128, fp);
-  if (putc(x & 127, fp) == EOF)
-    {
-      perror("write error");
-      exit(1);
-    }
-}
-
-static Id *
-write_idarray(FILE *fp, Id *ids)
-{
-  Id id;
-  if (!ids)
-    return ids;
-  if (!*ids)
-    {
-      write_u8(fp, 0);
-      return ids + 1;
-    }
-  for (;;)
-    {
-      id = *ids++;
-      if (id >= 64)
-       id = (id & 63) | ((id & ~63) << 1);
-      if (!*ids)
-       {
-         write_id(fp, id);
-         return ids + 1;
-       }
-      write_id(fp, id | 64);
-    }
-}
-
-static void
-write_pages (FILE *fp, Attrstore *s)
-{
-  unsigned int i;
-  unsigned char buf[BLOB_PAGESIZE];
-
-  /* The compressed pages in the file have different sizes, so we need
-     to store these sizes somewhere, either in front of all page data,
-     interleaved with the page data (in front of each page), or after
-     the page data.  At this point we don't yet know the final compressed
-     sizes.  These are the pros and cons:
-     * in front of all page data
-       + when reading back we only have to read this header, and know
-         where every page data is placed
-       - we have to compress all pages first before starting to write them.
-         Our output stream might be unseekable, so we can't simply
-        reserve space for the header, write all pages and then update the
-        header.  This needs memory for all compressed pages at once.
-     * interleaved with page data
-       + we can compress and write per page, low memory overhead
-       - when reading back we have to read at least those numbers,
-         thereby either having to read all page data, or at least seek
-        over it.
-     * after all page data
-       + we can do streamed writing, remembering the sizes per page,
-         and emitting the header (which is a footer then) at the end
-       - reading back is hardest: before the page data we don't know
-         how long it is overall, so we have to put that information
-        also at the end, but it needs a determinate position, so can
-        only be at a known offset from the end.  But that means that
-        we must be able to seek when reading back.  We have this
-        wish anyway in case we want to use on-demand paging then, but
-        it's optional.
-
-     Of all these it seems the best good/bad ratio is with the interleaved
-     storage.  No memory overhead at writing and no unreasonable limitations
-     for read back.  */
-  write_u32 (fp, s->blob_next_free);
-  write_u32 (fp, BLOB_PAGESIZE);
-  assert (((s->blob_next_free + BLOB_PAGESIZE - 1) / BLOB_PAGESIZE) == s->num_pages);
-  for (i = 0; i < s->num_pages; i++)
-    {
-      unsigned int in_len;
-      unsigned int out_len;
-      const void *in;
-      if (i == s->num_pages - 1)
-        in_len = s->blob_next_free & (BLOB_PAGESIZE - 1);
-      else
-        in_len = BLOB_PAGESIZE;
-      if (in_len)
-        {
-          in = attr_retrieve_blob (s, i * BLOB_PAGESIZE, in_len);
-          out_len = compress_buf (in, in_len, buf, in_len - 1);
-          if (!out_len)
-            {
-              memcpy (buf, in, in_len);
-              out_len = in_len;
-           }
-       }
-      else
-        out_len = 0;
-#ifdef DEBUG_PAGING
-      fprintf (stderr, "page %d: %d -> %d\n", i, in_len, out_len);
-#endif
-      write_u32 (fp, out_len * 2 + (out_len != in_len));
-      if (out_len
-          && fwrite (buf, out_len, 1, fp) != 1)
-        {
-         perror("write error");
-         exit(1);
-       }
-    }
-}
-
-void
-write_attr_store (FILE *fp, Attrstore *s)
-{
-  unsigned i;
-  unsigned local_ssize;
-
-  attr_store_pack (s);
-
-  /* Transform our attribute names (pool string IDs) into local IDs.  */
-  for (i = 1; i < s->nkeys; i++)
-    s->keys[i].name = str2localid (s, id2str (s->pool, s->keys[i].name), 1);
-
-  /* write file header */
-  write_u32(fp, 'S' << 24 | 'O' << 16 | 'L' << 8 | 'V');
-  write_u32(fp, SOLV_VERSION_2);
-
-  /* write counts */
-  write_u32(fp, s->ss.nstrings);      // nstrings
-  write_u32(fp, 0);                  // nrels
-  write_u32(fp, s->entries);         // nsolvables
-  write_u32(fp, s->nkeys);
-  write_u32(fp, s->nschemata);
-  write_u32(fp, 0);    /* no info block */
-  unsigned solv_flags = 0;
-  solv_flags |= SOLV_FLAG_PACKEDSIZES;
-  //solv_flags |= SOLV_FLAG_PREFIX_POOL;
-  write_u32(fp, solv_flags);
-
-  for (i = 1, local_ssize = 0; i < (unsigned)s->ss.nstrings; i++)
-    local_ssize += strlen (localid2str (s, i)) + 1;
-
-  write_u32 (fp, local_ssize);
-  for (i = 1; i < (unsigned)s->ss.nstrings; i++)
-    {
-      const char *str = localid2str (s, i);
-      if (fwrite(str, strlen(str) + 1, 1, fp) != 1)
-       {
-         perror("write error");
-         exit(1);
-       }
-    }
-
-  for (i = 1; i < s->nkeys; i++)
-    {
-      write_id (fp, s->keys[i].name);
-      write_id (fp, s->keys[i].type);
-      write_id (fp, s->keys[i].size);
-
-      /* Also transform back the names (now local IDs) into pool IDs,
-        so we can use the pool also after writing.  */
-      s->keys[i].name = str2id (s->pool, localid2str (s, s->keys[i].name), 0);
-    }
-
-  write_id (fp, s->szschemata);
-  Id *ids = s->schemata + 0;
-  for (i = 0; i < s->nschemata; i++)
-    ids = write_idarray (fp, ids);
-  assert (ids == s->schemata + s->szschemata);
-
-  /* Convert our offsets into sizes.  */
-  unsigned end = s->attr_next_free;
-  for (i = s->entries; i > 0;)
-    {
-      i--;
-      if (s->ent2attr[i])
-        {
-          s->ent2attr[i] = end - s->ent2attr[i];
-         end = end - s->ent2attr[i];
-       }
-    }
-  /* The first zero should not have been consumed, but everything else.  */
-  assert (end == 1);
-  /* Write the sizes and convert back to offsets.  */
-  unsigned start = 1;
-  for (i = 0; i < s->entries; i++)
-    {
-      write_id (fp, s->ent2attr[i]);
-      if (s->ent2attr[i])
-        s->ent2attr[i] += start, start = s->ent2attr[i];
-    }
-
-  if (s->entries
-      && fwrite (s->flat_attrs + 1, s->attr_next_free - 1, 1, fp) != 1)
-    {
-      perror ("write error");
-      exit (1);
-    }
-
-  /* XXX write the dirtree as info block.  */
-  write_id (fp, s->dirtree.ndirs);
-  if (s->dirtree.ndirs)
-    {
-      for (i = 1, local_ssize = 0; i < (unsigned)s->dirtree.ss.nstrings; i++)
-        local_ssize += 1 + strlen (s->dirtree.ss.stringspace + s->dirtree.ss.strings[i]);
-
-      write_u32 (fp, s->dirtree.ss.nstrings);
-      write_u32 (fp, local_ssize);
-      for (i = 1; i < (unsigned)s->dirtree.ss.nstrings; i++)
-       {
-         const char *str = s->dirtree.ss.stringspace + s->dirtree.ss.strings[i];
-         if (fwrite(str, strlen(str) + 1, 1, fp) != 1)
-           {
-             perror("write error");
-             exit(1);
-           }
-       }
-      write_id (fp, s->dirtree.nflatdirs);
-      for (i = 0; i < s->dirtree.nflatdirs; i++)
-        write_id (fp, s->dirtree.flatdirs[i]);
-    }
-  write_pages (fp, s);
-}
-
-static unsigned int
-read_u32(FILE *fp)
-{
-  int c, i;
-  unsigned int x = 0;
-
-  for (i = 0; i < 4; i++)
-    {
-      c = getc(fp);
-      if (c == EOF)
-       {
-         fprintf(stderr, "unexpected EOF\n");
-         exit(1);
-       }
-      x = (x << 8) | c;
-    }
-  return x;
-}
-
-static Id
-read_id(FILE *fp, Id max)
-{
-  unsigned int x = 0;
-  int c, i;
-
-  for (i = 0; i < 5; i++)
-    {
-      c = getc(fp);
-      if (c == EOF)
-       {
-         fprintf(stderr, "unexpected EOF\n");
-         exit(1);
-       }
-      if (!(c & 128))
-       {
-         x = (x << 7) | c;
-         if (max && x >= max)
-           {
-             fprintf(stderr, "read_id: id too large (%u/%u)\n", x, max);
-             exit(1);
-           }
-         return x;
-       }
-      x = (x << 7) ^ c ^ 128;
-    }
-  fprintf(stderr, "read_id: id too long\n");
-  exit(1);
-}
-
-static Id *
-read_idarray(FILE *fp, Id max, Id *map, Id *store, Id *end, int relative)
-{
-  unsigned int x = 0;
-  int c;
-  Id old = 0;
-  for (;;)
-    {
-      c = getc(fp);
-      if (c == EOF)
-       {
-         pool_debug(mypool, SAT_FATAL, "unexpected EOF\n");
-         exit(1);
-       }
-      if ((c & 128) == 0)
-       {
-         x = (x << 6) | (c & 63);
-         if (relative)
-           {
-             if (x == 0 && c == 0x40)
-               {
-                 /* prereq hack */
-                 if (store == end)
-                   {
-                     pool_debug(mypool, SAT_FATAL, "read_idarray: array overflow\n");
-                     exit(1);
-                   }
-                 *store++ = SOLVABLE_PREREQMARKER;
-                 old = 0;
-                 x = 0;
-                 continue;
-               }
-             x = (x - 1) + old;
-             old = x;
-           }
-         if (x >= max)
-           {
-             pool_debug(mypool, SAT_FATAL, "read_idarray: id too large (%u/%u)\n", x, max);
-             exit(1);
-           }
-         if (map)
-           x = map[x];
-         if (store == end)
-           {
-             pool_debug(mypool, SAT_FATAL, "read_idarray: array overflow\n");
-             exit(1);
-           }
-         *store++ = x;
-         if ((c & 64) == 0)
-           {
-             if (x == 0)       /* already have trailing zero? */
-               return store;
-             if (store == end)
-               {
-                 pool_debug(mypool, SAT_FATAL, "read_idarray: array overflow\n");
-                 exit(1);
-               }
-             *store++ = 0;
-             return store;
-           }
-         x = 0;
-         continue;
-       }
-      x = (x << 7) ^ c ^ 128;
-    }
-}
-
-/* Try to either setup on-demand paging (using FP as backing
-   file), or in case that doesn't work (FP not seekable) slurps in
-   all pages and deactivates paging.  */
-void
-read_or_setup_pages (FILE *fp, Attrstore *s)
-{
-  unsigned int blobsz;
-  unsigned int pagesz;
-  unsigned int npages;
-  unsigned int i;
-  unsigned int can_seek;
-  long cur_file_ofs;
-  unsigned char buf[BLOB_PAGESIZE];
-  blobsz = read_u32 (fp);
-  pagesz = read_u32 (fp);
-  if (pagesz != BLOB_PAGESIZE)
-    {
-      /* We could handle this by slurping in everything.  */
-      fprintf (stderr, "non matching page size\n");
-      exit (1);
-    }
-  can_seek = 1;
-  if ((cur_file_ofs = ftell (fp)) < 0)
-    can_seek = 0;
-  clearerr (fp);
-  fprintf (stderr, "can %sseek\n", can_seek ? "" : "NOT ");
-  npages = (blobsz + BLOB_PAGESIZE - 1) / BLOB_PAGESIZE;
-
-  s->num_pages = npages;
-  s->pages = sat_malloc (npages * sizeof (s->pages[0]));
-
-  /* If we can't seek on our input we have to slurp in everything.  */
-  if (!can_seek)
-    {
-      s->blob_next_free = blobsz;
-      s->blob_store = sat_realloc (s->blob_store, (s->blob_next_free + BLOB_BLOCK) &~BLOB_BLOCK);
-    }
-  for (i = 0; i < npages; i++)
-    {
-      unsigned int in_len = read_u32 (fp);
-      unsigned int compressed = in_len & 1;
-      Attrblobpage *p = s->pages + i;
-      in_len >>= 1;
-#ifdef DEBUG_PAGING
-      fprintf (stderr, "page %d: len %d (%scompressed)\n",
-              i, in_len, compressed ? "" : "not ");
-#endif
-      if (can_seek)
-        {
-          cur_file_ofs += 4;
-         p->mapped_at = -1;
-         p->file_offset = cur_file_ofs;
-         p->file_size = in_len * 2 + compressed;
-         if (fseek (fp, in_len, SEEK_CUR) < 0)
-           {
-             perror ("fseek");
-             fprintf (stderr, "can't seek after we thought we can\n");
-             /* We can't fall back to non-seeking behaviour as we already
-                read over some data pages without storing them away.  */
-             exit (1);
-           }
-         cur_file_ofs += in_len;
-       }
-      else
-        {
-         unsigned int out_len;
-         void *dest = s->blob_store + i * BLOB_PAGESIZE;
-          p->mapped_at = i * BLOB_PAGESIZE;
-         p->file_offset = 0;
-         p->file_size = 0;
-         /* We can't seek, so suck everything in.  */
-         if (fread (compressed ? buf : dest, in_len, 1, fp) != 1)
-           {
-             perror ("fread");
-             exit (1);
-           }
-         if (compressed)
-           {
-             out_len = unchecked_decompress_buf (buf, in_len,
-                                                 dest, BLOB_PAGESIZE);
-             if (out_len != BLOB_PAGESIZE
-                 && i < npages - 1)
-               {
-                 fprintf (stderr, "can't decompress\n");
-                 exit (1);
-               }
-           }
-       }
-    }
-
-  if (can_seek)
-    {
-      /* If we are here we were able to seek to all page
-         positions, so activate paging by copying FP into our structure.
-        We dup() the file, so that our callers can fclose() it and we
-        still have it open.  But this means that we share file positions
-        with the input filedesc.  So in case our caller reads it after us,
-        and calls back into us we might change the file position unexpectedly
-        to him.  */
-      int fd = dup (fileno (fp));
-      if (fd < 0)
-        {
-         /* Jeez!  What a bloody system, we can't dup() anymore.  */
-         perror ("dup");
-         exit (1);
-       }
-      /* XXX we don't close this yet anywhere.  */
-      s->file = fdopen (fd, "r");
-      if (!s->file)
-        {
-         /* My God!  What happened now?  */
-         perror ("fdopen");
-         exit (1);
-       }
-    }
-}
-
-static void
-read_stringpool (FILE *fp, Stringpool *ss, unsigned nstrings)
-{
-  unsigned i;
-  unsigned local_ssize;
-  /* Slightly hacky.  Our local string pool already contains "<NULL>" and
-     "".  We write out the "" too, so we have to read over it.  We write it
-     out to be compatible with the SOLV file and to not have to introduce
-     merging and mapping the string IDs.  */
-  local_ssize = read_u32 (fp) - 1;
-  char *strsp = (char *)sat_realloc(ss->stringspace, ss->sstrings + local_ssize + 1);
-  Offset *str = (Offset *)sat_realloc(ss->strings, nstrings * sizeof(Offset));
-
-  ss->stringspace = strsp;
-  ss->strings = str;
-  strsp += ss->sstrings;
-
-  unsigned char ignore_char = 1;
-  if (fread(&ignore_char, 1, 1, fp) != 1
-      || (local_ssize && fread(strsp, local_ssize, 1, fp) != 1)
-      || ignore_char != 0)
-    {
-      perror ("read error while reading strings");
-      exit(1);
-    }
-  strsp[local_ssize] = 0;
-
-  /* Don't build hashtable here, it will be built on demand by str2localid
-     should we call that.  */
-
-  strsp = ss->stringspace;
-  ss->nstrings = nstrings;
-  for (i = 0; i < nstrings; i++)
-    {
-      str[i] = strsp - ss->stringspace;
-      strsp += strlen (strsp) + 1;
-    }
-  ss->sstrings = strsp - ss->stringspace;
-}
-
-Attrstore *
-attr_store_read (FILE *fp, Pool *pool)
-{
-  unsigned nentries;
-  unsigned i;
-  unsigned nstrings, nschemata;
-  Attrstore *s = new_store (pool);
-
-  if (read_u32(fp) != ('S' << 24 | 'O' << 16 | 'L' << 8 | 'V'))
-    {
-      pool_debug(pool, SAT_FATAL, "not a SOLV file\n");
-      exit(1);
-    }
-  unsigned solvversion = read_u32(fp);
-  switch (solvversion)
-    {
-      case SOLV_VERSION_2:
-        break;
-      default:
-        pool_debug(pool, SAT_FATAL, "unsupported SOLV version\n");
-        exit(1);
-    }
-
-  nstrings = read_u32(fp);
-  read_u32(fp); //nrels
-  nentries = read_u32(fp);
-  s->nkeys = read_u32(fp);
-  nschemata = read_u32(fp);
-  read_u32(fp); //ninfo
-  unsigned solvflags = read_u32(fp);
-  if (!(solvflags & SOLV_FLAG_PACKEDSIZES))
-    {
-      pool_debug(pool, SAT_FATAL, "invalid attribute store\n");
-      exit (1);
-    }
-
-  read_stringpool (fp, &s->ss, nstrings);
-
-  s->keys = sat_realloc (s->keys, ((s->nkeys + KEY_BLOCK) & ~KEY_BLOCK) * sizeof (s->keys[0]));
-  /* s->keys[0] is initialized in new_store.  */
-  for (i = 1; i < s->nkeys; i++)
-    {
-      s->keys[i].name = read_id (fp, nstrings);
-      s->keys[i].type = read_id (fp, TYPE_ATTR_TYPE_MAX + 1);
-      s->keys[i].size = read_id (fp, 0);
-
-      /* Globalize the attribute names (they are local IDs right now).  */
-      s->keys[i].name = str2id (s->pool, localid2str (s, s->keys[i].name), 1);
-    }
-
-  s->szschemata = read_id (fp, 0);
-  s->nschemata = 0;
-  s->schemata = sat_malloc (((s->szschemata + SCHEMA_BLOCK) & ~SCHEMA_BLOCK) * sizeof (s->schemata[0]));
-  s->schemaofs = 0;
-  Id *ids = s->schemata;
-  //add_elem (s->schemaofs, s->nschemata, 0, SCHEMA_BLOCK);
-  //*ids++ = 0;
-  while (ids < s->schemata + s->szschemata)
-    {
-      add_elem (s->schemaofs, s->nschemata, ids - s->schemata, SCHEMA_BLOCK);
-      ids = read_idarray (fp, s->nkeys, 0, ids, s->schemata + s->szschemata, 0);
-    }
-  assert (ids == s->schemata + s->szschemata);
-  assert (nschemata == s->nschemata);
-
-  s->entries = nentries;
-
-  s->ent2attr = sat_malloc (s->entries * sizeof (s->ent2attr[0]));
-  int start = 1;
-  for (i = 0; i < s->entries; i++)
-    {
-      int d = read_id (fp, 0);
-      if (d)
-        s->ent2attr[i] = start, start += d;
-      else
-        s->ent2attr[i] = 0;
-    }
-
-  s->attr_next_free = start;
-  s->flat_attrs = sat_malloc (((s->attr_next_free + FLAT_ATTR_BLOCK) & ~FLAT_ATTR_BLOCK) * sizeof (s->flat_attrs[0]));
-  s->flat_attrs[0] = 0;
-  if (s->entries && fread (s->flat_attrs + 1, s->attr_next_free - 1, 1, fp) != 1)
-    {
-      perror ("read error");
-      exit (1);
-    }
-
-  s->dirtree.ndirs = read_id (fp, 0);
-  if (s->dirtree.ndirs)
-    {
-      unsigned ndirs = s->dirtree.ndirs;
-      setup_dirs (s);
-      sat_free (s->dirtree.dirs);
-      s->dirtree.dirs = 0;
-      s->dirtree.ndirs = ndirs;
-
-      nstrings = read_u32 (fp);
-      read_stringpool (fp, &s->dirtree.ss, nstrings);
-      s->dirtree.nflatdirs = read_id (fp, 0);
-      s->dirtree.flatdirs = sat_malloc (s->dirtree.nflatdirs * sizeof (s->dirtree.flatdirs[0]));
-      for (i = 0; i < s->dirtree.nflatdirs; i++)
-        s->dirtree.flatdirs[i] = read_id (fp, 0);
-    }
-  read_or_setup_pages (fp, s);
-
-  s->packed = 1;
-
-  return s;
-}
-
-void
-attr_store_search_s (Attrstore *s, const char *pattern, int flags, Id name, cb_attr_search_s cb)
-{
-  unsigned int i;
-  attr_iterator ai;
-  regex_t regex;
-  /* If we search for a glob, but we don't have a wildcard pattern, make this
-     an exact string search.  */
-  if ((flags & 7) == SEARCH_GLOB
-      && !strpbrk (pattern, "?*["))
-    flags = SEARCH_STRING | (flags & ~7);
-  if ((flags & 7) == SEARCH_REGEX)
-    {
-      /* We feed multiple lines eventually (e.g. authors or descriptions),
-         so set REG_NEWLINE.  */
-      if (regcomp (&regex, pattern,
-                  REG_EXTENDED | REG_NOSUB | REG_NEWLINE
-                  | ((flags & SEARCH_NOCASE) ? REG_ICASE : 0)) != 0)
-       return;
-    }
-  for (i = 0; i < s->entries; i++)
-    FOR_ATTRS (s, i, &ai)
-      {
-        const char *str;
-        if (name && name != ai.name)
-         continue;
-       str = 0;
-       switch (ai.type)
-         {
-         case TYPE_ATTR_INT:
-         case TYPE_ATTR_INTLIST:
-           continue;
-         case TYPE_ATTR_CHUNK:
-           if (!(flags & SEARCH_BLOBS))
-             continue;
-           str = attr_retrieve_blob (s, ai.as_chunk[0], ai.as_chunk[1]);
-           break;
-         case TYPE_ATTR_STRING:
-           str = ai.as_string;
-           break;
-         case TYPE_ATTR_LOCALIDS:
-           {
-             Id val;
-             get_num (ai.as_numlist, val);
-             if (val)
-               str = localid2str (s, val);
-             break;
-           }
-         default:
-           break;
-         }
-       while (str)
-         {
-           unsigned int match = 0;
-           switch (flags & 7)
-           {
-             case SEARCH_SUBSTRING:
-               if (flags & SEARCH_NOCASE)
-                 match = !! strcasestr (str, pattern);
-               else
-                 match = !! strstr (str, pattern);
-               break;
-             case SEARCH_STRING:
-               if (flags & SEARCH_NOCASE)
-                 match = ! strcasecmp (str, pattern);
-               else
-                 match = ! strcmp (str, pattern);
-               break;
-             case SEARCH_GLOB:
-               match = ! fnmatch (pattern, str,
-                                  (flags & SEARCH_NOCASE) ? FNM_CASEFOLD : 0);
-               break;
-             case SEARCH_REGEX:
-               match = ! regexec (&regex, str, 0, NULL, 0);
-               break;
-             default:
-               break;
-           }
-           if (match)
-             cb (s, i, ai.name, str);
-           if (ai.type != TYPE_ATTR_LOCALIDS)
-             break;
-           Id val;
-           get_num (ai.as_numlist, val);
-           if (!val)
-             break;
-           str = localid2str (s, val);
-         }
-      }
-  if ((flags & 7) == SEARCH_REGEX)
-    regfree (&regex);
-}
-
-#ifdef MAIN
-int
-main (void)
-{
-  Pool *pool = pool_create ();
-  Attrstore *s = new_store (pool);
-  unsigned int id1 = new_entry (s);
-  unsigned int id2 = new_entry (s);
-  unsigned int id3 = new_entry (s);
-  unsigned int id4 = new_entry (s);
-  add_attr_int (s, id1, str2id (s, "name1", 1), 42);
-  add_attr_chunk (s, id1, str2id (s->pool, "name2", 1), 9876, 1024);
-  add_attr_string (s, id1, str2id (s->pool, "name3", 1), "hallo");
-  add_attr_int (s, id1, str2id (s->pool, "name1", 1), 43);
-  add_attr_intlist_int (s, id1, str2id (s->pool, "intlist1", 1), 3);
-  add_attr_intlist_int (s, id1, str2id (s->pool, "intlist1", 1), 14);
-  add_attr_intlist_int (s, id1, str2id (s->pool, "intlist1", 1), 1);
-  add_attr_intlist_int (s, id1, str2id (s->pool, "intlist1", 1), 59);
-  add_attr_localids_id (s, id1, str2id (s->pool, "l_ids1", 1), str2localid (s, "one", 1));
-  add_attr_localids_id (s, id1, str2id (s->pool, "l_ids1", 1), str2localid (s, "two", 1));
-  add_attr_localids_id (s, id1, str2id (s->pool, "l_ids1", 1), str2localid (s, "three", 1));
-  add_attr_localids_id (s, id1, str2id (s->pool, "l_ids2", 1), str2localid (s, "three", 1));
-  add_attr_localids_id (s, id1, str2id (s->pool, "l_ids2", 1), str2localid (s, "two", 1));
-  add_attr_localids_id (s, id1, str2id (s->pool, "l_ids2", 1), str2localid (s, "one", 1));
-  write_attr_store (stdout, s);
-  return 0;
-}
-#endif
diff --git a/src/attr_store.h b/src/attr_store.h
deleted file mode 100644 (file)
index 07b833b..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2007, Novell Inc.
- *
- * This program is licensed under the BSD license, read LICENSE.BSD
- * for further information
- */
-
-#ifndef ATTR_STORE_H
-#define ATTR_STORE_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdio.h>
-
-#include "poolid.h"
-
-struct _Pool;
-struct _Attrstore;
-typedef struct _Attrstore Attrstore;
-typedef Id LocalId;
-
-Attrstore * new_store (struct _Pool *pool);
-unsigned int new_entry (Attrstore *s);
-Attrstore * attr_store_read (FILE *fp, struct _Pool *pool);
-void ensure_entry (Attrstore *s, unsigned int entry);
-void write_attr_store (FILE *fp, Attrstore *s);
-void attr_store_pack (Attrstore *s);
-void attr_store_unpack (Attrstore *s);
-
-LocalId str2localid (Attrstore *s, const char *str, int create);
-const char * localid2str(Attrstore *s, LocalId id);
-
-void add_attr_int (Attrstore *s, unsigned int entry, Id name, unsigned int val);
-void add_attr_special_int (Attrstore *s, unsigned int entry, Id name, unsigned int val);
-void add_attr_blob (Attrstore *s, unsigned int entry, Id name, const void *ptr, unsigned int len);
-void add_attr_string (Attrstore *s, unsigned int entry, Id name, const char *val);
-void add_attr_intlist_int (Attrstore *s, unsigned int entry, Id name, int val);
-void add_attr_localids_id (Attrstore *s, unsigned int entry, Id name, LocalId id);
-void add_attr_void (Attrstore *s, unsigned int entry, Id name);
-void merge_attrs (Attrstore *s, unsigned dest, unsigned src);
-
-unsigned dir_lookup (Attrstore *s, const char *name, unsigned insert);
-unsigned dir_parent (Attrstore *s, unsigned dir);
-void dir2str (Attrstore *s, unsigned dir, char **str, unsigned *len);
-
-const void * attr_retrieve_blob (Attrstore *s, unsigned int ofs, unsigned int len);
-
-#define SEARCH_SUBSTRING 1
-#define SEARCH_STRING 2
-#define SEARCH_GLOB 3
-#define SEARCH_REGEX 4
-#define SEARCH_NOCASE 8
-#define SEARCH_BLOBS 16
-#define SEARCH_IDS 32
-typedef int (*cb_attr_search_s) (Attrstore *s, unsigned entry, Id name, const char *str);
-void attr_store_search_s (Attrstore *s, const char *pattern, int flags, Id name, cb_attr_search_s cb);
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/src/attr_store_p.h b/src/attr_store_p.h
deleted file mode 100644 (file)
index cbadf55..0000000
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright (c) 2007, Novell Inc.
- *
- * This program is licensed under the BSD license, read LICENSE.BSD
- * for further information
- */
-
-#ifndef ATTR_STORE_P_H
-#define ATTR_STORE_P_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct
-{
-  Id key;
-  union {
-    unsigned int i[2];
-    const char *str;
-    int *intlist;
-    LocalId *localids;
-  } v;
-} LongNV;
-
-#define BLOB_PAGEBITS 15
-#define BLOB_PAGESIZE (1 << BLOB_PAGEBITS)
-
-typedef struct _Attrblobpage
-{
-  /* mapped_at == -1  --> not loaded, otherwise offset into
-     store->blob_store.  The size of the mapping is BLOB_PAGESIZE
-     except for the last page.  */
-  unsigned int mapped_at;
-  long file_offset;
-  /* file_size == 0 means the page is not backed by some file storage.
-     Otherwise it is L*2+(compressed ? 1 : 0), with L being the data
-     length.  */
-  long file_size;
-} Attrblobpage;
-
-typedef struct _Dir
-{
-  unsigned parent;
-  unsigned child;
-  unsigned sibling;
-  Id name;
-} Dir;
-
-typedef struct _Dirtree {
-  Dir *dirs;
-  unsigned ndirs;
-  Stringpool ss;
-  unsigned *dirstack;
-  unsigned ndirstack, dirstack_size;
-  unsigned *flatdirs;
-  unsigned nflatdirs;
-  unsigned *flatsons;
-  unsigned *dirmap;
-} Dirtree;
-
-struct _Attrstore
-{
-  Pool *pool;
-  unsigned int entries;
-  LongNV **attrs;
-  char *blob_store;
-  unsigned int blob_next_free;
-  Attrblobpage *pages;
-  unsigned int num_pages;
-  FILE *file;
-  /* mapped[i] is zero if nothing is mapped at logical page I,
-     otherwise it contains the pagenumber plus one (of the mapped page).  */
-  unsigned int *mapped;
-  unsigned int nmapped, ncanmap;
-  unsigned int rr_counter;
-
-  Stringpool ss;
-
-  Dirtree dirtree;
-
-  /* A space efficient in memory representation.  It's read-only.  */
-  /* flat_attrs[ent2attr[i]] are the attrs for entity i.  */
-  unsigned int *ent2attr;
-  unsigned char *flat_attrs;
-  unsigned int attr_next_free;
-
-  struct {
-    Id name;
-    unsigned type;
-    unsigned size;
-  } *keys;
-  unsigned nkeys;
-  Id *schemata;
-  unsigned *schemaofs;
-  unsigned nschemata, szschemata;
-
-  unsigned int packed:1;
-};
-
-void add_attr_from_file (Attrstore *s, unsigned entry, Id name, int type, Id *idmap, unsigned maxid, FILE *fp, unsigned size);
-void read_or_setup_pages (FILE *fp, Attrstore *s);
-
-#define get_num(ptr,val) do { \
-  typedef int __wrong_buf__[(1-sizeof((ptr)[0])) * (sizeof((ptr)[0])-1)];\
-  val = 0; \
-  while (1) { \
-    unsigned char __c = *((ptr)++); \
-    (val) = ((val) << 7) | (__c & 0x7F); \
-    if ((__c & 0x80) == 0) \
-      break; \
-  } \
-} while (0)
-
-typedef struct {
-  unsigned char *attrs;
-  Id *schema;
-  unsigned char *attrs_next;
-  Id name;
-  unsigned type;
-
-  /* The following fields could be a union, but if we do that GCC
-     doesn't scalarize these fields anymore, hence real memory accesses
-     would remain, so don't do that.  */
-  int as_int;
-  Id as_id;
-  unsigned int as_chunk[2];
-  const char *as_string;
-  const unsigned char *as_numlist;
-} attr_iterator;
-
-static inline void
-ai_init (Attrstore *s, unsigned int i, attr_iterator *ai)
-{
-  ai->attrs = s->flat_attrs + s->ent2attr[i];
-  unsigned int this_schema;
-  get_num (ai->attrs, this_schema);
-  ai->schema = s->schemata + s->schemaofs[this_schema];
-
-  /* Initialize all fields so we get no uninit warnings later.
-     Don't use memset() to initialize this structure, it would make
-     GCC not scalarize it.  */
-  ai->as_int = 0;
-  ai->as_id = 0;
-  ai->as_chunk[0] = ai->as_chunk[1] = 0;
-  ai->as_string = 0;
-  ai->as_numlist = 0;
-}
-
-static inline int
-ai_step (Attrstore *s, attr_iterator *ai)
-{
-  Id key = *(ai->schema);
-  if (!key)
-    return 0;
-  ai->name = s->keys[key].name;
-  ai->type = s->keys[key].type;
-  ai->attrs_next = ai->attrs;
-  switch (ai->type)
-    {
-    case TYPE_VOID:
-      /* No data, except perhaps a constant value.  */
-      ai->as_int = s->keys[key].size;
-      break;
-    case TYPE_ATTR_INT:
-      {
-       int val;
-       get_num (ai->attrs_next, val);
-       ai->as_int = val;
-       break;
-      }
-    case TYPE_ATTR_CHUNK:
-      {
-       unsigned int val1, val2;
-       get_num (ai->attrs_next, val1);
-       ai->as_chunk[0] = val1;
-       get_num (ai->attrs_next, val2);
-       ai->as_chunk[1] = val2;
-       break;
-      }
-    case TYPE_ATTR_STRING:
-      {
-       ai->as_string = (const char *) ai->attrs_next;
-       ai->attrs_next += strlen ((const char*)ai->attrs_next) + 1;
-       break;
-      }
-    case TYPE_ATTR_INTLIST:
-      {
-       ai->as_numlist = ai->attrs_next;
-       while (1)
-         {
-           int val;
-           get_num (ai->attrs_next, val);
-           if (!(val & 64))
-             break;
-         }
-       break;
-      }
-    case TYPE_ATTR_LOCALIDS:
-      {
-        ai->as_numlist = ai->attrs_next;
-       while (1)
-         {
-           Id val;
-           get_num (ai->attrs_next, val);
-           if (!val)
-             break;
-         }
-       break;
-      }
-    default:
-      break;
-    }
-  return 1;
-}
-
-#define FOR_ATTRS(s,i,ai) \
-  for (ai_init (s, i, ai); ai_step (s, ai); (ai)->schema++,(ai)->attrs = (ai)->attrs_next)
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif