codex.c revision 3f54fd611f536639ec30dd53c48e5ec1897cc7d9
/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 2003-2011 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* 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
/*
*/
static const char id[] = "codex";
#include <sfio_t.h>
#include <codex.h>
#include <namval.h>
static int
{
return 0;
}
static Codexmeth_t codex_copy =
{
"copy",
"No-op copy.",
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
};
{
"codex",
{ CODEX_VERSION },
{ {0}, 0, 0, -1, 0, &codex_copy, 0},
};
static int
{
int f;
int r;
r = 0;
switch (op)
{
case SF_ATEXIT:
break;
case SF_CLOSING:
case SF_DPOP:
case SF_FINAL:
{
}
if (op != SF_CLOSING)
{
{
}
{
}
{
{
}
}
}
break;
case SF_DBUFFER:
r = 1;
break;
case SF_SYNC:
{
}
break;
case CODEX_DATA:
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:
r = -1;
break;
case CODEX_SIZE:
if (!data)
r = -1;
else
break;
}
return r;
}
static int
{
int r;
return 0;
return r;
}
static int
{
int r;
return 0;
return r;
}
static int
{
int r;
return 0;
return r;
}
static ssize_t
{
ssize_t r;
return 0;
sfprintf(sfstderr, "codex: %d: %s: read(%I*u,%s)=%I*d\n", CODEX(disc)->index, meth->name, sizeof(n), n, (CODEX(disc)->flags & CODEX_VERBOSE) ? fmtquote(buf, "\"", "\"", r, 0) : "''", sizeof(r), r, buf);
return r;
}
static ssize_t
{
ssize_t r;
return 0;
sfprintf(sfstderr, "codex: %d: %s: write(%I*u,%s)=%I*d\n", CODEX(disc)->index, meth->name, sizeof(n), n, (CODEX(disc)->flags & CODEX_VERBOSE) ? fmtquote(buf, "\"", "\"", r, 0) : "''", sizeof(r), r);
return r;
}
static int
{
char* event;
int r;
char tmp[8];
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:
break;
}
sfprintf(sfstderr, "codex: %d: %s: except(%s,%p%s%s)=%d\n", CODEX(disc)->index, meth->name, event, data, (CODEX(disc)->flags & CODEX_ACTIVE) ? "|ACTIVE" : "", (CODEX(disc)->flags & CODEX_CACHED) ? "|CACHED" : "", r);
return r;
}
static int
{
int r;
return 0;
return r;
}
static Sfoff_t
{
Sfoff_t r;
return 0;
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
{
int r;
unsigned char* e;
unsigned char* u;
{
return 0;
}
if (r >= 0)
{
else
}
return r;
}
static Codexmeth_t codex_trace =
{
"trace",
"Debug trace wrapper.",
0,
0,
0,
0,
};
#define OPT_TRACE 1
#define OPT_VERBOSE 2
{
"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)
{
case OPT_TRACE:
break;
case OPT_VERBOSE:
break;
}
return 0;
}
static void
{
{
}
}
/*
* single sfio method discipline push of meth!=0 onto sp
*/
static int
{
register char** a;
register char* s;
register char* b;
register int c;
register int q;
char* v;
int f;
int namelen;
int serial;
char* arg[CODEX_ARGS];
/*
* check for matching inactive method in the cache
*/
code = 0;
cache = 0;
s = (char*)name;
q = 0;
b = s;
while (c = *b++)
if (c == q)
q = 0;
else if (c == '"' || c == '\'')
q = c;
else if (!q && c == '+')
break;
namelen = b - s - 1;
{
if (strneq(s, cp->name, namelen) && (cp->flags & deen) && (!cp->name[namelen] || cp->name[namelen] == '-' || cp->name[namelen] == '+'))
{
{
goto bad;
}
break;
}
}
size = -1;
if (!code)
{
{
goto bad;
}
a = arg;
*a++ = (char*)s;
*a++ = b = can;
q = -1;
do
{
c = *s++;
if (c == q)
q = -1;
else if (c == '"' || c == '\'')
q = c;
else if (c == 0 || q < 0 && (c == '-' || c == '+'))
{
*b++ = 0;
v = *(a - 1);
{
b = v;
}
else if (streq(v, "RETAIN"))
{
flags |= CODEX_RETAIN;
b = v;
}
{
b = v;
}
{
{
goto bad;
}
b = v;
}
else if (streq(v, "TRACE"))
{
flags |= CODEX_TRACE;
b = v;
}
else if (streq(v, "VERBOSE"))
{
flags |= CODEX_VERBOSE;
b = v;
}
else
{
break;
*a++ = b;
}
}
else
*b++ = c;
*b = 0;
if (!**(a - 1))
a--;
*a = 0;
s = arg[1];
{
{
}
code = 0;
}
{
flags |= CODEX_TRACE;
flags |= CODEX_VERBOSE;
}
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)
goto bad;
}
if (trace)
{
}
else
{
}
if (cache)
}
else if (b)
while (*b++)
{
v = b;
for (v = b; *b && *b != '-' && *b != '+'; b++);
{
v += 7;
if ((b - v) >= sizeof(can))
{
(*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "%-.*s: cannot delta source pathname too long", b - v, v);
goto bad;
}
else
{
{
goto bad;
}
}
}
}
if (cache)
{
c = 0;
goto done;
}
{
goto bad;
}
{
if (c)
goto bad;
}
return serial;
bad:
c = -1;
done:
if (code)
{
if (cache)
else
{
{
}
}
}
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
{
register Codexmeth_t* meth;
void* hdr;
int serial;
int i;
char buf[CODEX_NAME];
serial = 0;
for (;;)
{
siz = CODEX_IDENT;
break;
if (!meth)
break;
{
if (serial)
return -1;
}
if (i)
{
serial = i;
}
}
return serial;
}
typedef struct Part_s
{
char* name;
} Part_t;
/*
*/
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;
register int q;
char* m;
Part_t* b;
Part_t* e;
Codexnum_t f;
int invert;
if (!codexstate.initialized)
{
}
if (!(flags & CODEX_SERIAL))
{
flags |= CODEX_SERIAL;
if (++codexstate.serial < 0)
}
if (!disc)
{
if (!meth)
}
/*
* 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)))
{
return -1;
}
m = s;
if (flags & CODEX_INVERT)
{
flags &= ~CODEX_INVERT;
invert = -1;
e = &part[0];
}
else
{
invert = 1;
b = &part[0];
}
p = b;
if (*s == '<')
{
s++;
}
else if (*s == '>')
{
s++;
}
else
p->flags = 0;
p->name = s;
q = 0;
do
{
if (!(c = *s++))
;
else if (c == q)
{
q = 0;
continue;
}
else if (q)
continue;
else if (c == '"' || c == '\'')
{
q = c;
continue;
}
else if (c == '<')
f = decode;
else if (c == '>')
f = encode;
else if (c == '|' || c == '^')
f = 0;
else
continue;
*(s - 1) = 0;
{
{
free(m);
return -1;
}
if (!c)
break;
if (p == e)
{
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 (;;)
{
{
p->flags = CODEX_ENCODE;
f &= ~CODEX_DECODE;
}
else
p->flags = CODEX_DECODE;
{
{
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 0
p = b;
for (;;)
{
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;
{
free(m);
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;
{
free(m);
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
{
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))
pop++;
if (op)
while (op->disc && (op->disc->exceptf == codex_except || op->disc->exceptf == trace_except) && (!serial || CODEX(op->disc)->serial == serial))
pop++;
}
return pop;
}