|
|
researchv10 Norman
#include "stdio.h"
#include "cbt.h"
#define SZ MXHT+1
typedef struct {
unsigned short mlen;
char mdata[NDSZ]; /* max size of values */
} xbuf;
int address[SZ]; /* where the next address goes in the node */
xbuf curkey[SZ]; /* last key put in the node */
xbuf shortone; /* for compression */
int freecnt[SZ]; /* number of bytes left in node */
dkey *kp[SZ]; /* where to put next dkey in node */
char node[SZ][NDSZ]; /* the nodes */
char used[SZ+1]; /* which nodes have been used */
xbuf nkey; /* as read by getrec */
struct {
unsigned short mlen;
char mdata[32767];
} val;
lfaddr currec; /* where getrec put val */
FILE *tfd, *dfd;
char name[16];
int type;
long reccnt;
extern char *malloc();
char *
prkey(a)
xbuf *a;
{ int i;
unsigned char c;
static char buf[4*NDSZ], *p;
for(i = 0, p = buf; i < a->mlen; i++) {
c = a->mdata[i];
if(c < ' ') {
*p++ = '^';
c += ' ';
}
if(c < 127)
*p++ = (char)c;
else {
*p++ = '\\';
*p++ = (c >> 6) + '0';
*p++ = ((c&63)>>3) + '0';
*p++ = c&7 + '0';
}
}
*p++ = 0;
return(buf);
}
pref(a, b, lev) xbuf *a, *b;
{ register int n;
register char *p, *q;
for(n = 0, p = a->mdata, q = b->mdata; n < a->mlen && n < b->mlen; n++)
if(*p++ != *q++)
break;
p--, q--;
if(lev == 0 && ((n == b->mlen && n >= a->mlen) || *p > *q)) {
fprintf(stderr, "key %ld out of order:\n", reccnt);
fprintf(stderr, "key %ld is %s\n", reccnt - 1, prkey(a));
fprintf(stderr, "key %ld is %s\n", reccnt, prkey(b));
}
return(n);
}
getrec()
{
reccnt++;
if(mget(&nkey))
return(-1);
if(mget((xbuf *)&val))
fail("half a record read");
if((currec.llen = val.mlen) != 0) {
currec.lloc = ftell(dfd);
(void) fwrite(val.mdata, 1, val.mlen, dfd);
if(ferror(dfd))
fail("value write");
}
else currec.lloc = 0;
return(1);
}
mget(a) xbuf *a;
{
(void) fread((char *)&(a->mlen), 1, sizeof(a->mlen), stdin);
if(feof(stdin) || ferror(stdin))
return(1);
if(fread(a->mdata, 1, a->mlen, stdin) != a->mlen)
return(1);
return(0);
}
ndaddr ndwrt(level)
{ ndaddr loc;
int i;
hdr *x;
trailer *t;
loc = ftell(tfd)/NDSZ;
x = (hdr *)(node[level]);
x->hlev = level;
t = (trailer *)(node[level] + NDSZ - sizeof(trailer));
t->tfree = freecnt[level];
x->kcnt = address[level] - (level == 0? 0: 1);
x->htype = type;
(void) fwrite(node[level], 1, NDSZ, tfd);
if(ferror(tfd))
fail("node write");
for(i = 0; i < NDSZ; i++)
node[level][i] = 0;
address[level] = 0;
curkey[level].mlen = 0;
freecnt[level] = NDSZ - sizeof(hdr) - sizeof(trailer);
if(level)
freecnt[level] -= sizeof(ndaddr);
kp[level] = (dkey *)(node[level] + sizeof(hdr));
return(loc);
}
finish(level, ptr) ndaddr ptr;
{ ndaddr loc;
if(!used[level])
return;
*ndadr(node[level], address[level]++) = ptr;
if(!used[level + 1])
fseek(tfd, 0L, 0);
loc = ndwrt(level);
finish(level + 1, loc);
}
insert(level, key, ptr) xbuf *key; ndaddr ptr;
{ int n, len;
char *p;
ndaddr loc;
used[level] = 1;
n = pref(&curkey[level], key, level);
len = DKEYSZ + key->mlen - n + sizeof(ptr);
if(len < freecnt[level]) {
*ndadr(node[level], address[level]++) = ptr;
kp[level]->dlen = len - sizeof(ptr);
kp[level]->dcom = n;
mvgbt(kp[level]->dkey, key->mdata + n, key->mlen - n);
p = (char *)(kp[level]) + kp[level]->dlen;
kp[level] = (dkey *)p;
freecnt[level] -= len;
curkey[level] = *key;
}
else {
*ndadr(node[level],address[level]++) = ptr;
loc = ndwrt(level);
insert(level+1, key, loc);
curkey[level].mlen = 0;
}
}
doit()
{ int n, len;
ndaddr loc;
char *p;
for(;;) {
if(getrec() == -1)
break;
used[0] = 1;
n = pref(&curkey[0], &nkey, 0);
len = DKEYSZ + nkey.mlen - n + sizeof(currec);
if(type & INDEX)
len -= sizeof(currec);
if(len < freecnt[0]) {
freecnt[0] -= len;
if(!(type & INDEX))
*lfadr(node[0], address[0]++) = currec;
else
address[0]++;
kp[0]->dlen = DKEYSZ + nkey.mlen - n;
kp[0]->dcom = n;
mvgbt(kp[0]->dkey, nkey.mdata + n, nkey.mlen - n);
p = (char *)(kp[0]) + kp[0]->dlen;
kp[0] = (dkey *)p;
curkey[0] = nkey;
}
else {
shortest(&curkey[0], &nkey);
loc = ndwrt(0);
freecnt[0] -= DKEYSZ + nkey.mlen + sizeof(currec);
if(type & INDEX)
freecnt[0] += sizeof(currec);
insert(1, &shortone, loc);
if(!(type & INDEX))
*lfadr(node[0], address[0]++) = currec;
else
address[0]++;
kp[0]->dlen = DKEYSZ + nkey.mlen;
kp[0]->dcom = 0;
mvgbt(kp[0]->dkey, nkey.mdata, nkey.mlen);
p = (char *)(kp[0]) + kp[0]->dlen;
kp[0] = (dkey *)p;
curkey[0] = nkey;
}
}
if(!used[1])
(void) fseek(tfd, 0L, 0);
loc = ndwrt(0);
finish(1, loc);
}
init(s)
char *s;
{ int i;
hdr *b;
char xx[NDSZ];
(void) sprintf(name, "%s.T", s);
tfd = fopen(name, "r");
if(tfd == NULL) {
perror(s);
exit(1);
}
fread(xx, 1, NDSZ, tfd);
fclose(tfd);
tfd = fopen(name, "w");
(void) fseek(tfd, (long)NDSZ, 0);
b = (hdr *)xx;
type = b->htype;
(void) sprintf(name, "%s.F", s);
if((type & INDEX) != INDEX)
dfd = fopen(name, "w");
for(i = 0; i < SZ; i++) {
freecnt[i] = NDSZ - sizeof(hdr) - sizeof(trailer);
if(i)
freecnt[i] -= sizeof(ndaddr);
kp[i] = (dkey *)(node[i] + sizeof(hdr));
}
}
main(argc, argv)
char **argv;
{
if(argc != 2) {
fprintf(stderr, "%s: too many arguments\n", argv[1]);
exit(1);
}
init(argv[1]);
doit();
exit(0);
}
shortest(a, b) xbuf *a, *b;
{ int n;
char *p, *q, *s;
p = a->mdata;
q = b->mdata;
s = shortone.mdata;
for(n = 0; n < a->mlen && n < b->mlen; n++, p++, q++)
if(*p == *q)
*s++ = *p;
else break;
if(n < a->mlen) {
again:
if(n + 1 == a->mlen)
*s++ = *p;
else if(*p + 1 < *q)
*s++ = *p + 1;
else {
*s++ = *p++;
n++;
if(*p + 1 > *p)
*s++ = *p + 1;
else goto again;
}
}
shortone.mlen = s - shortone.mdata;
}
prbuf(x) xbuf *x;
{ int i;
for(i = 0; i < x->mlen; i++)
printf("%3.3o ", x->mdata[i]);
putchar('\n');
}
fail(s)
char *s;
{
perror(s);
exit(2);
}
static struct D { struct D *a; char *b;} VER = {&VER,"\n81/8/9:btbuild.c\n"};
/*1101000110100100*/
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.