Logo Search packages:      
Sourcecode: ksh version File versions

codex.c

/***********************************************************************
*                                                                      *
*               This software is part of the ast package               *
*           Copyright (c) 2003-2007 AT&T Knowledge Ventures            *
*                      and is licensed under the                       *
*                  Common Public License, Version 1.0                  *
*                      by AT&T Knowledge Ventures                      *
*                                                                      *
*                A copy of the License is available at                 *
*            http://www.opensource.org/licenses/cpl1.0.txt             *
*         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
*                                                                      *
*              Information and Software Systems Research               *
*                            AT&T Research                             *
*                           Florham Park NJ                            *
*                                                                      *
*                 Glenn Fowler <gsf@research.att.com>                  *
*                  David Korn <dgk@research.att.com>                   *
*                   Phong Vo <kpv@research.att.com>                    *
*                                                                      *
***********************************************************************/
#pragma prototyped

/*
 * sfio decode/encode discipline wrapper
 */

static const char id[] = "codex";

#include <sfio_t.h>
#include <codex.h>
#include <namval.h>

static int
copy_close(Codex_t* code)
{
      return 0;
}

static Codexmeth_t      codex_copy =
{
      "copy",
      "No-op copy.",
      0,
      CODEX_DECODE|CODEX_ENCODE,
      0,
      0,
      0,
      copy_close,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
};

Codexstate_t      codexstate =
{
      "codex",
      codex_first,
      { CODEX_VERSION },
      { {0}, 0, 0, -1, 0, &codex_copy, 0},
};

static int
codex_except(Sfio_t* sp, int op, void* data, Sfdisc_t* disc)
{
      register Codex_t* code = CODEX(disc);
      int               f;
      int               r;

      r = 0;
      switch (op)
      {
      case SF_ATEXIT:
            sfdisc(sp, SF_POPDISC);
            break;
      case SF_CLOSING:
      case SF_DPOP:
      case SF_FINAL:
            if (code->meth->syncf)
            {
                  SFDCNEXT(sp, f);
                  if (r = (*code->meth->syncf)(code))
                        sp->_flags |= SF_ERROR;
                  SFDCPREV(sp, f);
            }
            if (op != SF_CLOSING)
            {
                  if (code->meth->donef)
                  {
                        SFDCNEXT(sp, f);
                        r = (*code->meth->donef)(code);
                        SFDCPREV(sp, f);
                  }
                  if (code->dp)
                  {
                        sfclose(code->dp);
                        code->dp = 0;
                  }
                  if (code->flags & CODEX_ACTIVE)
                        code->flags &= ~CODEX_ACTIVE;
                  else
                  {
                        if (code->meth->closef)
                              r = (*code->meth->closef)(code);
                        else if (code->data)
                              free(code->data);
                        free(code);
                  }
            }
            break;
      case SF_DBUFFER:
            r = 1;
            break;
      case SF_SYNC:
            if (code->meth->syncf && !(code->flags & CODEX_FLUSH))
            {
                  SFDCNEXT(sp, f);
                  if ((r = (*code->meth->syncf)(code)) < 0)
                        sp->_flags |= SF_ERROR;
                  SFDCPREV(sp, f);
            }
            break;
      case CODEX_DATA:
            code->flags |= CODEX_FLUSH;
            sfsync(sp);
            code->flags &= ~CODEX_FLUSH;
            if (data && code->meth->dataf && !(r = (*code->meth->dataf)(code, (Codexdata_t*)data)) && ((Codexdata_t*)data)->size)
                  r = 1;
            break;
      case CODEX_GETPOS:
            if (!code->meth->seekf || (*((Sfoff_t*)data) = (*code->meth->seekf)(code, (Sfoff_t)0, SEEK_CUR)) < 0)
                  r = -1;
            break;
      case CODEX_SETPOS:
            if (!code->meth->seekf || (*code->meth->seekf)(code, *((Sfoff_t*)data), SEEK_SET) < 0)
                  r = -1;
            break;
      case CODEX_SIZE:
            if (!data)
                  r = -1;
            else
                  code->size = *((Sfoff_t*)data);
            break;
      }
      return r;
}

static int
trace_close(Codex_t* code)
{
      Codexmeth_t*      meth = code->meth->next;
      int         r;

      if (!meth->closef)
            return 0;
      r = (*meth->closef)(code);
      sfprintf(sfstderr, "codex: %d: %s: close()=%d\n", code->index, meth->name, r);
      free(meth);
      return r;
}

static int
trace_init(Codex_t* code)
{
      Codexmeth_t*      meth = code->meth->next;
      int         r;

      if (!meth->initf)
            return 0;
      r = (*meth->initf)(code);
      sfprintf(sfstderr, "codex: %d: %s: init()=%d\n", code->index, meth->name, r);
      return r;
}

static int
trace_done(Codex_t* code)
{
      Codexmeth_t*      meth = code->meth->next;
      int         r;

      if (!meth->donef)
            return 0;
      r = (*meth->donef)(code);
      sfprintf(sfstderr, "codex: %d: %s: done()=%d\n", code->index, meth->name, r);
      return r;
}

static ssize_t
trace_read(Sfio_t* f, void* buf, size_t n, Sfdisc_t* disc)
{
      Codexmeth_t*      meth = CODEX(disc)->meth->next;
      ssize_t           r;

      if (!meth->readf)
            return 0;
      r = (*meth->readf)(f, buf, n, disc);
      sfprintf(sfstderr, "codex: %d: %s: read(%I*u)=%I*d\n", CODEX(disc)->index, meth->name, sizeof(n), n, sizeof(r), r);
      return r;
}

static ssize_t
trace_write(Sfio_t* f, const void* buf, size_t n, Sfdisc_t* disc)
{
      Codexmeth_t*      meth = CODEX(disc)->meth->next;
      ssize_t           r;

      if (!meth->writef)
            return 0;
      r = (*meth->writef)(f, buf, n, disc);
      sfprintf(sfstderr, "codex: %d: %s: write(%I*u)=%I*d\n", CODEX(disc)->index, meth->name, sizeof(n), n, sizeof(r), r);
      return r;
}

static int
trace_except(Sfio_t* f, int op, void* data, Sfdisc_t* disc)
{
      Codexmeth_t*      meth = CODEX(disc)->meth->next;
      char*       event;
      int         r;
      char        tmp[8];

      r = codex_except(f, op, data, disc);
      switch (op)
      {
      case SF_ATEXIT:
            event = "ATEXIT";
            break;
      case SF_CLOSING:
            event = "CLOSING";
            break;
      case SF_DBUFFER:
            event = "DBUFFER";
            break;
      case SF_DPOLL:
            event = "DPOLL";
            break;
      case SF_DPOP:
            event = "DPOP";
            break;
      case SF_DPUSH:
            event = "DPUSH";
            break;
      case SF_FINAL:
            event = "FINAL";
            break;
      case SF_LOCKED:
            event = "LOCKED";
            break;
      case SF_NEW:
            event = "NEW";
            break;
      case SF_PURGE:
            event = "PURGE";
            break;
      case SF_READ:
            event = "READ";
            break;
      case SF_READY:
            event = "READY";
            break;
      case SF_SEEK:
            event = "SEEK";
            break;
      case SF_SYNC:
            event = "SYNC";
            break;
      case SF_WRITE:
            event = "WRITE";
            break;
      case CODEX_DATA:
            event = "CODEX_DATA";
            break;
      case CODEX_GETPOS:
            event = "CODEX_GETPOS";
            break;
      case CODEX_SETPOS:
            event = "CODEX_SETPOS";
            break;
      case CODEX_SIZE:
            event = "CODEX_SIZE";
            break;
      default:
            sfsprintf(event = tmp, sizeof(tmp), "%d", op);
            break;
      }
      sfprintf(sfstderr, "codex: %d: %s: except(%s,%p)=%d\n", CODEX(disc)->index, meth->name, event, data, r);
      return r;
}

static int
trace_sync(Codex_t* code)
{
      Codexmeth_t*      meth = code->meth->next;
      int         r;

      if (!meth->syncf)
            return 0;
      r = (*meth->syncf)(code);
      sfprintf(sfstderr, "codex: %d: %s: sync()=%d\n", code->index, meth->name, r);
      return r;
}

static Sfoff_t
trace_seek(Codex_t* code, Sfoff_t pos, int op)
{
      Codexmeth_t*      meth = code->meth->next;
      Sfoff_t           r;

      if (!meth->seekf)
            return 0;
      r = (*meth->seekf)(code, pos, op);
      sfprintf(sfstderr, "codex: %d: %s: seek(%I*d,%d)=%I*d\n", code->index, meth->name, sizeof(pos), pos, op, sizeof(r), r);
      return r;
}

static int
trace_data(Codex_t* code, Codexdata_t* data)
{
      Codexmeth_t*      meth = code->meth->next;
      int         r;
      unsigned char*    e;
      unsigned char*    u;

      if (!meth->dataf)
            return 0;
      r = (*meth->dataf)(code, data);
      sfprintf(sfstderr, "codex: %d: %s: data()=%d", code->index, meth->name, r);
      if (r >= 0)
      {
            if (data->buf)
                  for (e = (u = (unsigned char*)data->buf) + data->size; u < e; u++)
                        sfprintf(sfstderr, "%02x", *u);
            else
                  sfprintf(sfstderr, "%0*I*x", data->size * 2, sizeof(data->num), data->num);
      }
      sfprintf(sfstderr, "\n");
      return r;
}

static Codexmeth_t      codex_trace =
{
      "trace",
      "Debug trace wrapper.",
      0,
      CODEX_DECODE|CODEX_ENCODE,
      0,
      0,
      0,
      trace_close,
      trace_init,
      trace_done,
      trace_read,
      trace_write,
      trace_sync,
      trace_seek,
      trace_data,
};

#define OPT_TRACE 1
#define OPT_VERBOSE     2

static const Namval_t         options[] =
{
      "trace",    OPT_TRACE,
      "verbose",  OPT_VERBOSE,
      0,          0
};

/*
 * called by stropt() to set options
 */

static int
setopt(void* a, const void* p, register int n, register const char* v)
{
      NoP(a);
      if (p)
            switch (((Namval_t*)p)->value)
            {
            case OPT_TRACE:
                  codexstate.trace = n ? strdup(v) : (char*)0;
                  break;
            case OPT_VERBOSE:
                  codexstate.verbose = n ? strdup(v) : (char*)0;
                  break;
            }
      return 0;
}

static void
save(Codexcache_t* cache, Codex_t* code, const char* name, int namelen, Codexnum_t flags)
{
      if (cache->code && cache->code != CODEXERROR)
      {
            if (cache->code->meth->closef)
                  (*cache->code->meth->closef)(cache->code);
            else if (cache->code->data)
                  free(cache->code->data);
            if (cache->code->dp)
                  sfclose(cache->code->dp);
            free(cache->code);
      }
      cache->code = code;
      cache->flags = flags;
      strncopy(cache->name, name, namelen < sizeof(cache->name) ? (namelen + 1) : sizeof(cache->name));
      cache->cached = ++codexstate.cached;
}

/*
 * single sfio method discipline push of meth!=0 onto sp
 */

static int
push(Sfio_t* sp, const char* name, Codexnum_t flags, Codexdisc_t* disc, Codexmeth_t* meth)
{
      register char**         a;
      register char*          s;
      register char*          b;
      register int            c;
      char*             v;
      int               f;
      int               namelen;
      int               serial;
      Codexnum_t        deen;
      Sfoff_t                 size;
      Codex_t*          code;
      Codexcache_t*           cache;
      Codexcache_t*           cp;
      Codexmeth_t*            trace;
      char*             arg[CODEX_ARGS];
      char              can[CODEX_NAME+CODEX_ARGS];

      /*
       * check for matching inactive method in the cache
       * this avoids openf/closef thrashing
       */

      code = 0;
      cache = 0;
      deen = flags & (CODEX_DECODE|CODEX_ENCODE);
      s = (char*)name;
      namelen = (b = strchr(s, '+')) ? (b - s) : strlen(s);
      for (cp = codexstate.cache; cp < &codexstate.cache[elementsof(codexstate.cache)]; cp++)
            if (!cp->code)
                  (cache = cp)->cached = 0;
            else if (!(cp->code->flags & CODEX_ACTIVE))
            {
                  if (strneq(s, cp->name, namelen) && (cp->flags & deen) && (!cp->name[namelen] || cp->name[namelen] == '-' || cp->name[namelen] == '+'))
                  {
                        cp->cached = ++codexstate.cached;
                        if ((code = (cache = cp)->code) == CODEXERROR)
                        {
                              if (disc->errorf)
                                    (*disc->errorf)(NiL, disc, 2, "%s: invalid method", s);
                              goto bad;
                        }
                        break;
                  }
                  else if (!cache || cp->cached < cache->cached)
                        cache = cp;
            }
      sfset(sp, SF_SHARE|SF_PUBLIC, 0);
      size = -1;
      if (!code)
      {
            if (!(code = newof(0, Codex_t, 1, 0)))
            {
                  if (disc->errorf)
                        (*disc->errorf)(NiL, disc, 2, "out of space");
                  goto bad;
            }
            code->flags = deen;
            code->index = ++codexstate.index;
            code->sp = sp;
            code->disc = disc;
            code->meth = meth;
            a = arg;
            *a++ = (char*)s;
            *a++ = b = can;
            do
            {
                  c = *s++;
                  if (c == '-' || c == '+' || c == 0)
                  {
                        *b++ = 0;
                        if (streq(*(a - 1), "RETAIN"))
                        {
                              flags |= CODEX_RETAIN;
                              b = *(a - 1);
                        }
                        else if (strneq(*(a - 1), "SIZE=", 5))
                        {
                              size = strtoll(*(a - 1) + 5, NiL, 0);
                              b = *(a - 1);
                        }
                        else if (strneq(*(a - 1), "SOURCE=", 7))
                        {
                              if (!(code->dp = sfopen(NiL, *(a - 1) + 7, "r")))
                              {
                                    if (disc->errorf)
                                          (*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "%s: cannot read delta source", *(a - 1) + 7);
                                    goto bad;
                              }
                              b = *(a - 1);
                        }
                        else if (streq(*(a - 1), "TRACE"))
                        {
                              flags |= CODEX_TRACE;
                              b = *(a - 1);
                        }
                        else if (streq(*(a - 1), "VERBOSE"))
                        {
                              flags |= CODEX_VERBOSE;
                              b = *(a - 1);
                        }
                        else
                        {
                              if (a >= &arg[elementsof(arg)-1] || b >= &can[sizeof(can)-1])
                                    break;
                              *a++ = b;
                        }
                  }
                  else
                        *b++ = c;
            } while (c && b < &can[sizeof(can)-1]);
            *b = 0;
            if (!**(a - 1))
                  a--;
            *a = 0;
            s = arg[1];
            if ((*meth->openf)(code, arg, deen))
            {
                  free(code);
                  code = 0;
            }
            if (((flags & (CODEX_TRACE|CODEX_VERBOSE)) || codexstate.trace && strmatch(name, codexstate.trace) && (flags |= CODEX_TRACE) || codexstate.verbose && strmatch(name, codexstate.verbose) && (flags |= CODEX_VERBOSE)) && (trace = memdup(&codex_trace, sizeof(codex_trace))))
                  sfprintf(sfstderr, "codex: %d: %s: open(\"%s\",%s,%s)\n", code ? code->index : 0, meth->name, arg[0], (sp->_flags & SF_READ) ? "READ" : "WRITE", (deen & CODEX_DECODE) ? "DECODE" : "ENCODE");
            else
                  trace = 0;
            if (!code)
            {
                  if (cache)
                        save(cache, CODEXERROR, name, namelen, deen);
                  goto bad;
            }
            if (!(meth = code->meth))
                  meth = code->meth = &codex_copy;
            code->flags = deen | (code->meth->flags & ~(CODEX_DECODE|CODEX_ENCODE));
            if (trace)
            {
                  trace->next = meth;
                  code->meth = meth = trace;
                  code->sfdisc.readf = trace_read;
                  code->sfdisc.writef = trace_write;
                  code->sfdisc.exceptf = (flags & CODEX_VERBOSE) ? trace_except : codex_except;
            }
            else
            {
                  code->sfdisc.readf = meth->readf;
                  code->sfdisc.writef = meth->writef;
                  code->sfdisc.exceptf = codex_except;
            }
            if (cache)
                  save(cache, code, name, namelen, deen);
      }
      else if (b)
            while (*b++)
            {
                  v = b;
                  for (v = b; *b && *b != '-' && *b != '+'; b++);
                  if (strneq(v, "SIZE=", 5))
                        size = strtoll(v + 5, NiL, 0);
                  else if (strneq(v, "SOURCE=", 7))
                  {
                        v += 7;
                        if ((b - v) >= sizeof(can))
                        {
                              if (disc->errorf)
                                    (*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "%-.*s: cannot delta source pathname too long", b - v, v);
                              goto bad;
                        }
                        else
                        {
                              strncopy(can, v, b - v);
                              if (!(code->dp = sfopen(NiL, can, "r")))
                              {
                                    if (disc->errorf)
                                          (*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "%s: cannot read delta source", can);
                                    goto bad;
                              }
                        }
                  }
            }
      if (cache)
            code->flags |= CODEX_ACTIVE;
      if (code->meth == &codex_copy)
      {
            c = 0;
            goto done;
      }
      code->sp = sp;
      code->size = size;
      code->disc = disc;
      code->flags |= CODEX_FLUSH;
      if (sfdisc(sp, &code->sfdisc) != &code->sfdisc)
      {
            if (disc->errorf)
                  (*disc->errorf)(NiL, disc, 2, "%s: sfio discipline push error", name);
            goto bad;
      }
      code->serial = serial = codexstate.serial;
      code->flags &= ~CODEX_FLUSH;
      if (!(sp->_flags & SF_READ))
            sfset(sp, SF_IOCHECK, 1);
      if (code->meth->initf)
      {
            SFDCNEXT(sp, f);
            c = (*code->meth->initf)(code);
            SFDCPREV(sp, f);
            if (c)
                  goto bad;
      }
      code->flags |= flags & (CODEX_RETAIN|CODEX_TRACE|CODEX_VERBOSE);
      return serial;
 bad:
      c = -1;
      codexpop(sp, NiL, serial);
 done:
      if (code)
      {
            if (cache)
                  code->flags &= ~CODEX_ACTIVE;
            else
            {
                  if (meth->closef)
                        (*meth->closef)(code);
                  else if (code->data)
                        free(code->data);
                  if (code->dp)
                        sfclose(code->dp);
                  free(code);
            }
      }
      return c;
}

/*
 * recursively identify and push sfcode() disciplines
 * to decode the SF_READ stream ip
 *
 * return:
 *    -1    error
 *     0    no discipline pushed
 *    >0    discipline serial number
 */

static int
decodex(Sfio_t* ip, Codexnum_t flags, Codexdisc_t* disc)
{
      register Codexmeth_t*   meth;
      void*             hdr;
      size_t                  siz;
      int               serial;
      int               i;
      char              buf[CODEX_NAME];

      sfset(ip, SF_SHARE|SF_PUBLIC, 0);
      serial = 0;
      for (;;)
      {
            siz = CODEX_IDENT;
            if (!(hdr = sfreserve(ip, siz, 1)) && (!(siz = sfvalue(ip)) || !(hdr = sfreserve(ip, siz, 1))))
                  break;
            meth = codexid(hdr, siz, buf, sizeof(buf));
            sfread(ip, hdr, 0);
            if (!meth)
                  break;
            if ((i = codex(ip, NiL, buf, flags, disc, meth)) < 0)
            {
                  if (serial)
                        codexpop(ip, NiL, serial);
                  return -1;
            }
            if (i)
                  serial = i;
      }
      return serial;
}

typedef struct Part_s
{
      char*       name;
      Codexmeth_t*      meth;
      Codexnum_t  flags;
} Part_t;

/*
 * push the codex method composition name onto ip/op
 */

int
codex(Sfio_t* ip, Sfio_t* op, const char* name, Codexnum_t flags, Codexdisc_t* disc, Codexmeth_t* meth)
{
      register char*          s;
      register Part_t*  p;
      register int            c;
      char*             m;
      Part_t*                 b;
      Part_t*                 e;
      Codexnum_t        f;
      Codexnum_t        decode;
      Codexnum_t        encode;
      int               invert;
      Part_t                  part[256];

      if (!codexstate.initialized)
      {
            codexstate.initialized = 1;
            stropt(getenv("CODEX_OPTIONS"), options, sizeof(*options), setopt, NiL);
      }
      flags &= CODEX_INVERT|CODEX_RETAIN|CODEX_SERIAL|CODEX_TRACE|CODEX_VERBOSE;
      if (!(flags & CODEX_SERIAL))
      {
            flags |= CODEX_SERIAL;
            if (++codexstate.serial < 0)
                  codexstate.serial = 1;
      }
      if (!disc)
            disc = &codexstate.disc;
      if (!(s = (char*)name) || !s[0] || s[0] == '-' && !s[1])
      {
            if (!meth)
                  return ip ? decodex(ip, flags, disc) : -1;
            s = (char*)(name = meth->name);
      }

      /*
       * split the method name into component parts
       * and verify that each part is a known method
       * CODEX_INVERT is dispatched here
       */

      if (!(s = strdup(s)))
      {
            if (disc->errorf)
                  (*disc->errorf)(NiL, disc, 2, "out of space");
            return -1;
      }
      m = s;
      if (flags & CODEX_INVERT)
      {
            flags &= ~CODEX_INVERT;
            invert = -1;
            decode = CODEX_ENCODE;
            encode = CODEX_DECODE;
            b = &part[elementsof(part)-1];
            e = &part[0];
      }
      else
      {
            invert = 1;
            decode = CODEX_DECODE;
            encode = CODEX_ENCODE;
            b = &part[0];
            e = &part[elementsof(part)-1];
      }
      p = b;
      if (*s == '<')
      {
            s++;
            p->flags = decode;
      }
      else if (*s == '>')
      {
            s++;
            p->flags = encode;
      }
      else
            p->flags = 0;
      p->name = s;
      do
      {
            if (!(c = *s++))
                  ;
            else if (c == '<')
                  f = decode;
            else if (c == '>')
                  f = encode;
            else if (c == '|' || c == '^')
                  f = 0;
            else
                  continue;
            *(s - 1) = 0;
            if (codexcmp(p->name, "copy"))
            {
                  if (!(p->meth = codexmeth(p->name)))
                  {
                        if (disc->errorf)
                              (*disc->errorf)(NiL, disc, 2, "%s: unknown coder", p->name);
                        free(m);
                        return -1;
                  }
                  if (!c)
                        break;
                  if (p == e)
                  {
                        if (disc->errorf)
                              (*disc->errorf)(NiL, disc, 2, "%s: too many method components -- %d max", name, elementsof(part));
                        free(m);
                        return -1;
                  }
                  p += invert;
            }
            p->flags = f;
            p->name = s;
      } while (c);
      if (!*b->name)
      {
            free(m);
            return 0;
      }
      if (invert < 0)
      {
            e = b;
            b = p;
      }
      else
            e = p;

      /*
       * assign CODEX_DECODE or CODEX_ENCODE to each part and
       * verfy that the method supports the assignment
       * vcodex methods give us some leeway here
       * otherwise CODEX_DECODE must be on the left and
       * CODEX_ENCODE must be on the right
       * CODEX_INVERT has already been handled in the previous loop
       */

      f = 0;
      if (ip)
            f |= CODEX_DECODE;
      if (op)
            f |= CODEX_ENCODE;
      p = b;
      for (;;)
      {
            if (p->flags == CODEX_ENCODE || p->flags != CODEX_DECODE && !(f & CODEX_DECODE))
            {
                  p->flags = CODEX_ENCODE;
                  f &= ~CODEX_DECODE;
            }
            else
                  p->flags = CODEX_DECODE;
            if (!(p->flags & p->meth->flags) || !p->meth->vcmeth && !(p->flags & f))
            {
                  if (disc->errorf)
                  {
                        if (e != &part[0])
                              (*disc->errorf)(NiL, disc, 2, "%s: %s: cannot %s", name, p->name, p->flags == CODEX_DECODE ? ERROR_translate(NiL, NiL, id, "decode") : ERROR_translate(NiL, NiL, id, "encode"));
                        else
                              (*disc->errorf)(NiL, disc, 2, "%s: cannot %s", p->name, p->flags == CODEX_DECODE ? ERROR_translate(NiL, NiL, id, "decode") : ERROR_translate(NiL, NiL, id, "encode"));
                  }
                  free(m);
                  return -1;
            }
            if (p == e)
                  break;
            p++;
      }
#if 1
      p = b;
      for (;;)
      {
            error(-1, "AHA codex [%d] %u %s \"%s\"", p - b, p->flags, p->meth->name, p->name);
            if (p == e)
                  break;
            p++;
      }
#endif

      /*
       * input decode method sfio disciplines pushed from left to right
       */

      p = b;
      for (;;)
      {
            if (p->flags == CODEX_ENCODE)
                  break;
            if (push(ip, p->name, CODEX_DECODE|flags, disc, p->meth) < 0)
            {
                  free(m);
                  codexpop(ip, op, codexstate.serial);
                  return -1;
            }
            if (p == e)
                  break;
            p++;
      }

      /*
       * output encode method sfio disciplines pushed from right to left
       */

      p = e;
      for (;;)
      {
            if (p->flags == CODEX_DECODE)
                  break;
            if (push(op, p->name, CODEX_ENCODE|flags, disc, p->meth) < 0)
            {
                  free(m);
                  codexpop(ip, op, codexstate.serial);
                  return -1;
            }
            if (p == b)
                  break;
            p--;
      }
      free(m);
      return codexstate.serial;
}

/*
 * pop contiguous ip and op codex disciplines matching serial number
 * serial==0 pops all contiguous codex disciplines
 */

int
codexpop(register Sfio_t* ip, register Sfio_t* op, int serial)
{
      int   pop;

      pop = 0;
      if (serial >= 0)
      {
            if (ip)
                  while (ip->disc && (ip->disc->exceptf == codex_except || ip->disc->exceptf == trace_except) && (!serial || CODEX(ip->disc)->serial == serial))
                        if (sfdisc(ip, SF_POPDISC))
                              pop++;
            if (op)
                  while (op->disc && (op->disc->exceptf == codex_except || op->disc->exceptf == trace_except) && (!serial || CODEX(op->disc)->serial == serial))
                        if (sfdisc(op, SF_POPDISC))
                              pop++;
      }
      return pop;
}

Generated by  Doxygen 1.6.0   Back to index