summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorItamar Reis Peixoto <itamar@itamar.ispbrasil.com.br>2009-10-02 20:35:54 -0300
committerItamar Reis Peixoto <itamar@itamar.ispbrasil.com.br>2009-10-02 20:35:54 -0300
commit580c2e160be238f4abb46bd75fcf24bdd9768c2e (patch)
tree58d8c94f27e48d8aee8ff20ac7babb132b8eedee
downloadcdb-580c2e160be238f4abb46bd75fcf24bdd9768c2e.zip
cdb-580c2e160be238f4abb46bd75fcf24bdd9768c2e.tar.gz
cdb-580c2e160be238f4abb46bd75fcf24bdd9768c2e.tar.xz
initial importHEADmaster
-rw-r--r--CHANGES16
-rw-r--r--FILES78
-rw-r--r--Makefile320
-rw-r--r--README7
-rw-r--r--SYSDEPS3
-rw-r--r--TARGETS66
-rw-r--r--TODO1
-rw-r--r--VERSION1
-rw-r--r--alloc.c32
-rw-r--r--alloc.h8
-rw-r--r--auto-str.c44
-rw-r--r--auto_home.h6
-rw-r--r--buffer.c10
-rw-r--r--buffer.h56
-rw-r--r--buffer_0.c12
-rw-r--r--buffer_1.c6
-rw-r--r--buffer_1s.c6
-rw-r--r--buffer_2.c6
-rw-r--r--buffer_copy.c16
-rw-r--r--buffer_get.c67
-rw-r--r--buffer_put.c88
-rw-r--r--byte.h13
-rw-r--r--byte_copy.c14
-rw-r--r--byte_cr.c16
-rw-r--r--byte_diff.c16
-rw-r--r--cdb.c136
-rw-r--r--cdb.h37
-rw-r--r--cdb_hash.c21
-rw-r--r--cdb_make.c153
-rw-r--r--cdb_make.h39
-rw-r--r--cdbdump.c83
-rw-r--r--cdbget.c67
-rw-r--r--cdbmake-12.sh8
-rw-r--r--cdbmake-sv.sh22
-rw-r--r--cdbmake.c110
-rw-r--r--cdbstats.c125
-rw-r--r--cdbtest.c119
-rw-r--r--choose.sh18
-rw-r--r--conf-cc3
-rw-r--r--conf-home3
-rw-r--r--conf-ld3
-rw-r--r--error.c109
-rw-r--r--error.h25
-rw-r--r--error_str.c271
-rw-r--r--exit.h6
-rw-r--r--find-systype.sh159
-rw-r--r--fmt.h25
-rw-r--r--fmt_ulong.c13
-rw-r--r--hier.c15
-rw-r--r--install.c149
-rw-r--r--instcheck.c108
-rw-r--r--open.h10
-rw-r--r--open_read.c6
-rw-r--r--open_trunc.c6
-rw-r--r--random.cdbbin0 -> 35520 bytes
-rw-r--r--readwrite.h7
-rw-r--r--rts.exp251
-rw-r--r--rts.sh1
-rw-r--r--rts.tests210
-rw-r--r--scan.h28
-rw-r--r--scan_ulong.c11
-rw-r--r--seek.h15
-rw-r--r--seek_cur.c7
-rw-r--r--seek_set.c7
-rw-r--r--str.h14
-rw-r--r--str_len.c14
-rw-r--r--strerr.h78
-rw-r--r--strerr_die.c31
-rw-r--r--strerr_sys.c12
-rw-r--r--testzero.c35
-rw-r--r--trycpp.c7
-rw-r--r--tryulong32.c11
-rw-r--r--uint32.h111
-rw-r--r--uint32.h211
-rw-r--r--uint32_pack.c21
-rw-r--r--uint32_unpack.c31
-rw-r--r--warn-auto.sh2
-rw-r--r--x86cpuid.c38
78 files changed, 3610 insertions, 0 deletions
diff --git a/CHANGES b/CHANGES
new file mode 100644
index 0000000..a7d65cf
--- /dev/null
+++ b/CHANGES
@@ -0,0 +1,16 @@
+20000215
+ api: rewrote almost everything from scratch. tnx Ken Lalonde for
+ suggesting mmap.
+20000216
+ ui: cdbget supports skip.
+ version: cdb 0.70, beta.
+20000219
+ bug: cdb_make_addbegin() didn't explicitly return 0. impact:
+ database creation could fail on systems that didn't
+ follow the traditional C return behavior. fix: obvious.
+ tnx Uwe Ohse.
+ internal: increased bspace in cdb_make.h from 1024 to 8192.
+ internal: switched cdbmake to PUTC, GETC. 3x speedup here.
+ internal: added testzero to rts.
+ ui: posplus() sets nomem if it passes 4GB.
+ version: cdb 0.75, beta.
diff --git a/FILES b/FILES
new file mode 100644
index 0000000..baceb86
--- /dev/null
+++ b/FILES
@@ -0,0 +1,78 @@
+README
+TODO
+CHANGES
+VERSION
+FILES
+SYSDEPS
+TARGETS
+conf-cc
+conf-ld
+conf-home
+Makefile
+cdbget.c
+cdbmake.c
+cdbdump.c
+cdbstats.c
+cdbtest.c
+cdbmake-12.sh
+cdbmake-sv.sh
+cdb.h
+cdb.c
+cdb_hash.c
+cdb_make.h
+cdb_make.c
+rts.sh
+rts.tests
+rts.exp
+testzero.c
+random.cdb
+choose.sh
+warn-auto.sh
+find-systype.sh
+trycpp.c
+x86cpuid.c
+alloc.c
+alloc.h
+auto-str.c
+auto_home.h
+buffer.c
+buffer.h
+buffer_0.c
+buffer_1.c
+buffer_1s.c
+buffer_2.c
+buffer_copy.c
+buffer_get.c
+buffer_put.c
+byte.h
+byte_copy.c
+byte_cr.c
+byte_diff.c
+error.c
+error.h
+error_str.c
+exit.h
+fmt.h
+fmt_ulong.c
+hier.c
+install.c
+instcheck.c
+open.h
+open_read.c
+open_trunc.c
+readwrite.h
+scan.h
+scan_ulong.c
+seek.h
+seek_cur.c
+seek_set.c
+str.h
+str_len.c
+strerr.h
+strerr_die.c
+strerr_sys.c
+tryulong32.c
+uint32.h1
+uint32.h2
+uint32_pack.c
+uint32_unpack.c
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..27d9701
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,320 @@
+# Don't edit Makefile! Use conf-* for configuration.
+
+SHELL=/bin/sh
+
+default: it
+
+alloc.a: \
+makelib alloc.o
+ ./makelib alloc.a alloc.o
+
+alloc.o: \
+compile alloc.c alloc.h error.h
+ ./compile alloc.c
+
+auto-str: \
+load auto-str.o buffer.a unix.a byte.a
+ ./load auto-str buffer.a unix.a byte.a
+
+auto-str.o: \
+compile auto-str.c buffer.h readwrite.h exit.h
+ ./compile auto-str.c
+
+auto_home.c: \
+auto-str conf-home
+ ./auto-str auto_home `head -1 conf-home` > auto_home.c
+
+auto_home.o: \
+compile auto_home.c
+ ./compile auto_home.c
+
+buffer.a: \
+makelib strerr_sys.o buffer.o buffer_put.o buffer_2.o strerr_die.o \
+buffer_get.o buffer_copy.o buffer_1.o buffer_0.o buffer_1s.o
+ ./makelib buffer.a strerr_sys.o buffer.o buffer_put.o \
+ buffer_2.o strerr_die.o buffer_get.o buffer_copy.o \
+ buffer_1.o buffer_0.o buffer_1s.o
+
+buffer.o: \
+compile buffer.c buffer.h
+ ./compile buffer.c
+
+buffer_0.o: \
+compile buffer_0.c readwrite.h buffer.h
+ ./compile buffer_0.c
+
+buffer_1.o: \
+compile buffer_1.c readwrite.h buffer.h
+ ./compile buffer_1.c
+
+buffer_1s.o: \
+compile buffer_1s.c readwrite.h buffer.h
+ ./compile buffer_1s.c
+
+buffer_2.o: \
+compile buffer_2.c readwrite.h buffer.h
+ ./compile buffer_2.c
+
+buffer_copy.o: \
+compile buffer_copy.c buffer.h
+ ./compile buffer_copy.c
+
+buffer_get.o: \
+compile buffer_get.c buffer.h byte.h error.h
+ ./compile buffer_get.c
+
+buffer_put.o: \
+compile buffer_put.c buffer.h str.h byte.h error.h
+ ./compile buffer_put.c
+
+byte.a: \
+makelib byte_copy.o byte_cr.o str_len.o fmt_ulong.o uint32_unpack.o \
+byte_diff.o uint32_pack.o scan_ulong.o
+ ./makelib byte.a byte_copy.o byte_cr.o str_len.o \
+ fmt_ulong.o uint32_unpack.o byte_diff.o uint32_pack.o \
+ scan_ulong.o
+
+byte_copy.o: \
+compile byte_copy.c byte.h
+ ./compile byte_copy.c
+
+byte_cr.o: \
+compile byte_cr.c byte.h
+ ./compile byte_cr.c
+
+byte_diff.o: \
+compile byte_diff.c byte.h
+ ./compile byte_diff.c
+
+cdb.a: \
+makelib cdb.o cdb_hash.o cdb_make.o
+ ./makelib cdb.a cdb.o cdb_hash.o cdb_make.o
+
+cdb.o: \
+compile cdb.c readwrite.h error.h seek.h byte.h cdb.h uint32.h
+ ./compile cdb.c
+
+cdb_hash.o: \
+compile cdb_hash.c cdb.h uint32.h
+ ./compile cdb_hash.c
+
+cdb_make.o: \
+compile cdb_make.c readwrite.h seek.h error.h alloc.h cdb.h uint32.h \
+cdb_make.h buffer.h uint32.h
+ ./compile cdb_make.c
+
+cdbdump: \
+load cdbdump.o buffer.a unix.a byte.a
+ ./load cdbdump buffer.a unix.a byte.a
+
+cdbdump.o: \
+compile cdbdump.c uint32.h fmt.h buffer.h strerr.h
+ ./compile cdbdump.c
+
+cdbget: \
+load cdbget.o cdb.a buffer.a unix.a byte.a
+ ./load cdbget cdb.a buffer.a unix.a byte.a
+
+cdbget.o: \
+compile cdbget.c exit.h scan.h str.h buffer.h strerr.h cdb.h uint32.h
+ ./compile cdbget.c
+
+cdbmake: \
+load cdbmake.o cdb.a alloc.a buffer.a unix.a byte.a
+ ./load cdbmake cdb.a alloc.a buffer.a unix.a byte.a
+
+cdbmake-12: \
+warn-auto.sh cdbmake-12.sh conf-home
+ cat warn-auto.sh cdbmake-12.sh \
+ | sed s}HOME}"`head -1 conf-home`"}g \
+ > cdbmake-12
+ chmod 755 cdbmake-12
+
+cdbmake-sv: \
+warn-auto.sh cdbmake-sv.sh conf-home
+ cat warn-auto.sh cdbmake-sv.sh \
+ | sed s}HOME}"`head -1 conf-home`"}g \
+ > cdbmake-sv
+ chmod 755 cdbmake-sv
+
+cdbmake.o: \
+compile cdbmake.c error.h open.h strerr.h cdb_make.h buffer.h \
+uint32.h cdb.h uint32.h
+ ./compile cdbmake.c
+
+cdbstats: \
+load cdbstats.o cdb.a buffer.a unix.a byte.a
+ ./load cdbstats cdb.a buffer.a unix.a byte.a
+
+cdbstats.o: \
+compile cdbstats.c uint32.h fmt.h buffer.h strerr.h seek.h cdb.h \
+uint32.h
+ ./compile cdbstats.c
+
+cdbtest: \
+load cdbtest.o cdb.a buffer.a unix.a byte.a
+ ./load cdbtest cdb.a buffer.a unix.a byte.a
+
+cdbtest.o: \
+compile cdbtest.c uint32.h fmt.h buffer.h strerr.h seek.h cdb.h \
+uint32.h
+ ./compile cdbtest.c
+
+check: \
+it instcheck
+ ./instcheck
+
+compile: \
+warn-auto.sh conf-cc
+ ( cat warn-auto.sh; \
+ echo exec "`head -1 conf-cc`" '-c $${1+"$$@"}' \
+ ) > compile
+ chmod 755 compile
+
+error.o: \
+compile error.c error.h
+ ./compile error.c
+
+error_str.o: \
+compile error_str.c error.h
+ ./compile error_str.c
+
+fmt_ulong.o: \
+compile fmt_ulong.c fmt.h
+ ./compile fmt_ulong.c
+
+hier.o: \
+compile hier.c auto_home.h
+ ./compile hier.c
+
+install: \
+load install.o hier.o auto_home.o buffer.a unix.a byte.a
+ ./load install hier.o auto_home.o buffer.a unix.a byte.a
+
+install.o: \
+compile install.c buffer.h strerr.h error.h open.h readwrite.h exit.h
+ ./compile install.c
+
+instcheck: \
+load instcheck.o hier.o auto_home.o buffer.a unix.a byte.a
+ ./load instcheck hier.o auto_home.o buffer.a unix.a byte.a
+
+instcheck.o: \
+compile instcheck.c strerr.h error.h readwrite.h exit.h
+ ./compile instcheck.c
+
+it: \
+prog install instcheck
+
+load: \
+warn-auto.sh conf-ld
+ ( cat warn-auto.sh; \
+ echo 'main="$$1"; shift'; \
+ echo exec "`head -1 conf-ld`" \
+ '-o "$$main" "$$main".o $${1+"$$@"}' \
+ ) > load
+ chmod 755 load
+
+makelib: \
+warn-auto.sh systype
+ ( cat warn-auto.sh; \
+ echo 'main="$$1"; shift'; \
+ echo 'rm -f "$$main"'; \
+ echo 'ar cr "$$main" $${1+"$$@"}'; \
+ case "`cat systype`" in \
+ sunos-5.*) ;; \
+ unix_sv*) ;; \
+ irix64-*) ;; \
+ irix-*) ;; \
+ dgux-*) ;; \
+ hp-ux-*) ;; \
+ sco*) ;; \
+ *) echo 'ranlib "$$main"' ;; \
+ esac \
+ ) > makelib
+ chmod 755 makelib
+
+open_read.o: \
+compile open_read.c open.h
+ ./compile open_read.c
+
+open_trunc.o: \
+compile open_trunc.c open.h
+ ./compile open_trunc.c
+
+prog: \
+cdbget cdbmake cdbdump cdbstats cdbtest cdbmake-12 cdbmake-sv rts \
+testzero
+
+rts: \
+warn-auto.sh rts.sh conf-home
+ cat warn-auto.sh rts.sh \
+ | sed s}HOME}"`head -1 conf-home`"}g \
+ > rts
+ chmod 755 rts
+
+scan_ulong.o: \
+compile scan_ulong.c scan.h
+ ./compile scan_ulong.c
+
+seek_cur.o: \
+compile seek_cur.c seek.h
+ ./compile seek_cur.c
+
+seek_set.o: \
+compile seek_set.c seek.h
+ ./compile seek_set.c
+
+setup: \
+it install
+ ./install
+
+str_len.o: \
+compile str_len.c str.h
+ ./compile str_len.c
+
+strerr_die.o: \
+compile strerr_die.c buffer.h exit.h strerr.h
+ ./compile strerr_die.c
+
+strerr_sys.o: \
+compile strerr_sys.c error.h strerr.h
+ ./compile strerr_sys.c
+
+systype: \
+find-systype.sh conf-cc conf-ld trycpp.c x86cpuid.c
+ ( cat warn-auto.sh; \
+ echo CC=\'`head -1 conf-cc`\'; \
+ echo LD=\'`head -1 conf-ld`\'; \
+ cat find-systype.sh; \
+ ) | sh > systype
+
+testzero: \
+load testzero.o cdb.a alloc.a buffer.a unix.a byte.a
+ ./load testzero cdb.a alloc.a buffer.a unix.a byte.a
+
+testzero.o: \
+compile testzero.c uint32.h scan.h strerr.h cdb_make.h buffer.h \
+uint32.h
+ ./compile testzero.c
+
+uint32.h: \
+tryulong32.c compile load uint32.h1 uint32.h2
+ ( ( ./compile tryulong32.c && ./load tryulong32 && \
+ ./tryulong32 ) >/dev/null 2>&1 \
+ && cat uint32.h2 || cat uint32.h1 ) > uint32.h
+ rm -f tryulong32.o tryulong32
+
+uint32_pack.o: \
+compile uint32_pack.c uint32.h
+ ./compile uint32_pack.c
+
+uint32_unpack.o: \
+compile uint32_unpack.c uint32.h
+ ./compile uint32_unpack.c
+
+unix.a: \
+makelib error.o open_read.o open_trunc.o error_str.o seek_set.o \
+seek_cur.o
+ ./makelib unix.a error.o open_read.o open_trunc.o \
+ error_str.o seek_set.o seek_cur.o
diff --git a/README b/README
new file mode 100644
index 0000000..f65d429
--- /dev/null
+++ b/README
@@ -0,0 +1,7 @@
+cdb 0.75, beta.
+20000219
+Copyright 2000
+D. J. Bernstein
+
+cdb home page: http://cr.yp.to/cdb.html
+Installation instructions: http://cr.yp.to/cdb/install.html
diff --git a/SYSDEPS b/SYSDEPS
new file mode 100644
index 0000000..d8e1bcf
--- /dev/null
+++ b/SYSDEPS
@@ -0,0 +1,3 @@
+VERSION
+systype
+uint32.h
diff --git a/TARGETS b/TARGETS
new file mode 100644
index 0000000..9516870
--- /dev/null
+++ b/TARGETS
@@ -0,0 +1,66 @@
+load
+compile
+uint32.h
+cdbget.o
+systype
+makelib
+cdb.o
+cdb_hash.o
+cdb_make.o
+cdb.a
+strerr_sys.o
+buffer.o
+buffer_put.o
+buffer_2.o
+strerr_die.o
+buffer_get.o
+buffer_copy.o
+buffer_1.o
+buffer_0.o
+buffer_1s.o
+buffer.a
+error.o
+open_read.o
+open_trunc.o
+error_str.o
+seek_set.o
+seek_cur.o
+unix.a
+byte_copy.o
+byte_cr.o
+str_len.o
+fmt_ulong.o
+uint32_unpack.o
+byte_diff.o
+uint32_pack.o
+scan_ulong.o
+byte.a
+cdbget
+cdbmake.o
+alloc.o
+alloc.a
+cdbmake
+cdbdump.o
+cdbdump
+cdbstats.o
+cdbstats
+cdbtest.o
+cdbtest
+cdbmake-12
+cdbmake-sv
+rts
+testzero.o
+testzero
+prog
+install.o
+hier.o
+auto-str.o
+auto-str
+auto_home.c
+auto_home.o
+install
+instcheck.o
+instcheck
+it
+setup
+check
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..3725be6
--- /dev/null
+++ b/TODO
@@ -0,0 +1 @@
+more rts
diff --git a/VERSION b/VERSION
new file mode 100644
index 0000000..7001427
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+cdb 0.75
diff --git a/alloc.c b/alloc.c
new file mode 100644
index 0000000..c661453
--- /dev/null
+++ b/alloc.c
@@ -0,0 +1,32 @@
+#include "alloc.h"
+#include "error.h"
+extern char *malloc();
+extern void free();
+
+#define ALIGNMENT 16 /* XXX: assuming that this alignment is enough */
+#define SPACE 4096 /* must be multiple of ALIGNMENT */
+
+typedef union { char irrelevant[ALIGNMENT]; double d; } aligned;
+static aligned realspace[SPACE / ALIGNMENT];
+#define space ((char *) realspace)
+static unsigned int avail = SPACE; /* multiple of ALIGNMENT; 0<=avail<=SPACE */
+
+/*@null@*//*@out@*/char *alloc(n)
+unsigned int n;
+{
+ char *x;
+ n = ALIGNMENT + n - (n & (ALIGNMENT - 1)); /* XXX: could overflow */
+ if (n <= avail) { avail -= n; return space + avail; }
+ x = malloc(n);
+ if (!x) errno = error_nomem;
+ return x;
+}
+
+void alloc_free(x)
+char *x;
+{
+ if (x >= space)
+ if (x < space + SPACE)
+ return; /* XXX: assuming that pointers are flat */
+ free(x);
+}
diff --git a/alloc.h b/alloc.h
new file mode 100644
index 0000000..1b1d893
--- /dev/null
+++ b/alloc.h
@@ -0,0 +1,8 @@
+#ifndef ALLOC_H
+#define ALLOC_H
+
+extern /*@null@*//*@out@*/char *alloc();
+extern void alloc_free();
+extern int alloc_re();
+
+#endif
diff --git a/auto-str.c b/auto-str.c
new file mode 100644
index 0000000..93b51ca
--- /dev/null
+++ b/auto-str.c
@@ -0,0 +1,44 @@
+#include "buffer.h"
+#include "readwrite.h"
+#include "exit.h"
+
+char buf1[256];
+buffer ss1 = BUFFER_INIT(write,1,buf1,sizeof(buf1));
+
+void puts(s)
+char *s;
+{
+ if (buffer_puts(&ss1,s) == -1) _exit(111);
+}
+
+main(argc,argv)
+int argc;
+char **argv;
+{
+ char *name;
+ char *value;
+ unsigned char ch;
+ char octal[4];
+
+ name = argv[1];
+ if (!name) _exit(100);
+ value = argv[2];
+ if (!value) _exit(100);
+
+ puts("char ");
+ puts(name);
+ puts("[] = \"\\\n");
+
+ while (ch = *value++) {
+ puts("\\");
+ octal[3] = 0;
+ octal[2] = '0' + (ch & 7); ch >>= 3;
+ octal[1] = '0' + (ch & 7); ch >>= 3;
+ octal[0] = '0' + (ch & 7);
+ puts(octal);
+ }
+
+ puts("\\\n\";\n");
+ if (buffer_flush(&ss1) == -1) _exit(111);
+ _exit(0);
+}
diff --git a/auto_home.h b/auto_home.h
new file mode 100644
index 0000000..a756cd0
--- /dev/null
+++ b/auto_home.h
@@ -0,0 +1,6 @@
+#ifndef AUTO_HOME_H
+#define AUTO_HOME_H
+
+extern char auto_home[];
+
+#endif
diff --git a/buffer.c b/buffer.c
new file mode 100644
index 0000000..f44a697
--- /dev/null
+++ b/buffer.c
@@ -0,0 +1,10 @@
+#include "buffer.h"
+
+void buffer_init(buffer *s,int (*op)(),int fd,char *buf,unsigned int len)
+{
+ s->x = buf;
+ s->fd = fd;
+ s->op = op;
+ s->p = 0;
+ s->n = len;
+}
diff --git a/buffer.h b/buffer.h
new file mode 100644
index 0000000..12539b3
--- /dev/null
+++ b/buffer.h
@@ -0,0 +1,56 @@
+#ifndef BUFFER_H
+#define BUFFER_H
+
+typedef struct buffer {
+ char *x;
+ unsigned int p;
+ unsigned int n;
+ int fd;
+ int (*op)();
+} buffer;
+
+#define BUFFER_INIT(op,fd,buf,len) { (buf), 0, (len), (fd), (op) }
+#define BUFFER_INSIZE 8192
+#define BUFFER_OUTSIZE 8192
+
+extern void buffer_init(buffer *,int (*)(),int,char *,unsigned int);
+
+extern int buffer_flush(buffer *);
+extern int buffer_put(buffer *,char *,unsigned int);
+extern int buffer_putalign(buffer *,char *,unsigned int);
+extern int buffer_putflush(buffer *,char *,unsigned int);
+extern int buffer_puts(buffer *,char *);
+extern int buffer_putsalign(buffer *,char *);
+extern int buffer_putsflush(buffer *,char *);
+
+#define buffer_PUTC(s,c) \
+ ( ((s)->n != (s)->p) \
+ ? ( (s)->x[(s)->p++] = (c), 0 ) \
+ : buffer_put((s),&(c),1) \
+ )
+
+extern int buffer_get(buffer *,char *,unsigned int);
+extern int buffer_bget(buffer *,char *,unsigned int);
+extern int buffer_feed(buffer *);
+
+extern char *buffer_peek(buffer *);
+extern void buffer_seek(buffer *,unsigned int);
+
+#define buffer_PEEK(s) ( (s)->x + (s)->n )
+#define buffer_SEEK(s,len) ( ( (s)->p -= (len) ) , ( (s)->n += (len) ) )
+
+#define buffer_GETC(s,c) \
+ ( ((s)->p > 0) \
+ ? ( *(c) = (s)->x[(s)->n], buffer_SEEK((s),1), 1 ) \
+ : buffer_get((s),(c),1) \
+ )
+
+extern int buffer_copy(buffer *,buffer *);
+
+extern buffer *buffer_0;
+extern buffer *buffer_0small;
+extern buffer *buffer_1;
+extern buffer *buffer_1small;
+extern buffer *buffer_2;
+
+#endif
diff --git a/buffer_0.c b/buffer_0.c
new file mode 100644
index 0000000..6c5365a
--- /dev/null
+++ b/buffer_0.c
@@ -0,0 +1,12 @@
+#include "readwrite.h"
+#include "buffer.h"
+
+int buffer_0_read(fd,buf,len) int fd; char *buf; int len;
+{
+ if (buffer_flush(buffer_1) == -1) return -1;
+ return read(fd,buf,len);
+}
+
+char buffer_0_space[BUFFER_INSIZE];
+static buffer it = BUFFER_INIT(buffer_0_read,0,buffer_0_space,sizeof buffer_0_space);
+buffer *buffer_0 = &it;
diff --git a/buffer_1.c b/buffer_1.c
new file mode 100644
index 0000000..3104e22
--- /dev/null
+++ b/buffer_1.c
@@ -0,0 +1,6 @@
+#include "readwrite.h"
+#include "buffer.h"
+
+char buffer_1_space[BUFFER_OUTSIZE];
+static buffer it = BUFFER_INIT(write,1,buffer_1_space,sizeof buffer_1_space);
+buffer *buffer_1 = &it;
diff --git a/buffer_1s.c b/buffer_1s.c
new file mode 100644
index 0000000..92f0621
--- /dev/null
+++ b/buffer_1s.c
@@ -0,0 +1,6 @@
+#include "readwrite.h"
+#include "buffer.h"
+
+char buffer_1small_space[256];
+static buffer it = BUFFER_INIT(write,1,buffer_1small_space,sizeof buffer_1small_space);
+buffer *buffer_1small = &it;
diff --git a/buffer_2.c b/buffer_2.c
new file mode 100644
index 0000000..297825c
--- /dev/null
+++ b/buffer_2.c
@@ -0,0 +1,6 @@
+#include "readwrite.h"
+#include "buffer.h"
+
+char buffer_2_space[256];
+static buffer it = BUFFER_INIT(write,2,buffer_2_space,sizeof buffer_2_space);
+buffer *buffer_2 = &it;
diff --git a/buffer_copy.c b/buffer_copy.c
new file mode 100644
index 0000000..dc4d4b1
--- /dev/null
+++ b/buffer_copy.c
@@ -0,0 +1,16 @@
+#include "buffer.h"
+
+int buffer_copy(buffer *bout,buffer *bin)
+{
+ int n;
+ char *x;
+
+ for (;;) {
+ n = buffer_feed(bin);
+ if (n < 0) return -2;
+ if (!n) return 0;
+ x = buffer_PEEK(bin);
+ if (buffer_put(bout,x,n) == -1) return -3;
+ buffer_SEEK(bin,n);
+ }
+}
diff --git a/buffer_get.c b/buffer_get.c
new file mode 100644
index 0000000..937b75e
--- /dev/null
+++ b/buffer_get.c
@@ -0,0 +1,67 @@
+#include "buffer.h"
+#include "byte.h"
+#include "error.h"
+
+static int oneread(int (*op)(),int fd,char *buf,unsigned int len)
+{
+ int r;
+
+ for (;;) {
+ r = op(fd,buf,len);
+ if (r == -1) if (errno == error_intr) continue;
+ return r;
+ }
+}
+
+static int getthis(buffer *s,char *buf,unsigned int len)
+{
+ if (len > s->p) len = s->p;
+ s->p -= len;
+ byte_copy(buf,len,s->x + s->n);
+ s->n += len;
+ return len;
+}
+
+int buffer_feed(buffer *s)
+{
+ int r;
+
+ if (s->p) return s->p;
+ r = oneread(s->op,s->fd,s->x,s->n);
+ if (r <= 0) return r;
+ s->p = r;
+ s->n -= r;
+ if (s->n > 0) byte_copyr(s->x + s->n,r,s->x);
+ return r;
+}
+
+int buffer_bget(buffer *s,char *buf,unsigned int len)
+{
+ int r;
+
+ if (s->p > 0) return getthis(s,buf,len);
+ if (s->n <= len) return oneread(s->op,s->fd,buf,s->n);
+ r = buffer_feed(s); if (r <= 0) return r;
+ return getthis(s,buf,len);
+}
+
+int buffer_get(buffer *s,char *buf,unsigned int len)
+{
+ int r;
+
+ if (s->p > 0) return getthis(s,buf,len);
+ if (s->n <= len) return oneread(s->op,s->fd,buf,len);
+ r = buffer_feed(s); if (r <= 0) return r;
+ return getthis(s,buf,len);
+}
+
+char *buffer_peek(buffer *s)
+{
+ return s->x + s->n;
+}
+
+void buffer_seek(buffer *s,unsigned int len)
+{
+ s->n += len;
+ s->p -= len;
+}
diff --git a/buffer_put.c b/buffer_put.c
new file mode 100644
index 0000000..a05e1f5
--- /dev/null
+++ b/buffer_put.c
@@ -0,0 +1,88 @@
+#include "buffer.h"
+#include "str.h"
+#include "byte.h"
+#include "error.h"
+
+static int allwrite(int (*op)(),int fd,char *buf,unsigned int len)
+{
+ int w;
+
+ while (len) {
+ w = op(fd,buf,len);
+ if (w == -1) {
+ if (errno == error_intr) continue;
+ return -1; /* note that some data may have been written */
+ }
+ if (w == 0) ; /* luser's fault */
+ buf += w;
+ len -= w;
+ }
+ return 0;
+}
+
+int buffer_flush(buffer *s)
+{
+ int p;
+
+ p = s->p;
+ if (!p) return 0;
+ s->p = 0;
+ return allwrite(s->op,s->fd,s->x,p);
+}
+
+int buffer_putalign(buffer *s,char *buf,unsigned int len)
+{
+ unsigned int n;
+
+ while (len > (n = s->n - s->p)) {
+ byte_copy(s->x + s->p,n,buf); s->p += n; buf += n; len -= n;
+ if (buffer_flush(s) == -1) return -1;
+ }
+ /* now len <= s->n - s->p */
+ byte_copy(s->x + s->p,len,buf);
+ s->p += len;
+ return 0;
+}
+
+int buffer_put(buffer *s,char *buf,unsigned int len)
+{
+ unsigned int n;
+
+ n = s->n;
+ if (len > n - s->p) {
+ if (buffer_flush(s) == -1) return -1;
+ /* now s->p == 0 */
+ if (n < BUFFER_OUTSIZE) n = BUFFER_OUTSIZE;
+ while (len > s->n) {
+ if (n > len) n = len;
+ if (allwrite(s->op,s->fd,buf,n) == -1) return -1;
+ buf += n;
+ len -= n;
+ }
+ }
+ /* now len <= s->n - s->p */
+ byte_copy(s->x + s->p,len,buf);
+ s->p += len;
+ return 0;
+}
+
+int buffer_putflush(buffer *s,char *buf,unsigned int len)
+{
+ if (buffer_flush(s) == -1) return -1;
+ return allwrite(s->op,s->fd,buf,len);
+}
+
+int buffer_putsalign(buffer *s,char *buf)
+{
+ return buffer_putalign(s,buf,str_len(buf));
+}
+
+int buffer_puts(buffer *s,char *buf)
+{
+ return buffer_put(s,buf,str_len(buf));
+}
+
+int buffer_putsflush(buffer *s,char *buf)
+{
+ return buffer_putflush(s,buf,str_len(buf));
+}
diff --git a/byte.h b/byte.h
new file mode 100644
index 0000000..de06c69
--- /dev/null
+++ b/byte.h
@@ -0,0 +1,13 @@
+#ifndef BYTE_H
+#define BYTE_H
+
+extern unsigned int byte_chr();
+extern unsigned int byte_rchr();
+extern void byte_copy();
+extern void byte_copyr();
+extern int byte_diff();
+extern void byte_zero();
+
+#define byte_equal(s,n,t) (!byte_diff((s),(n),(t)))
+
+#endif
diff --git a/byte_copy.c b/byte_copy.c
new file mode 100644
index 0000000..eaad11b
--- /dev/null
+++ b/byte_copy.c
@@ -0,0 +1,14 @@
+#include "byte.h"
+
+void byte_copy(to,n,from)
+register char *to;
+register unsigned int n;
+register char *from;
+{
+ for (;;) {
+ if (!n) return; *to++ = *from++; --n;
+ if (!n) return; *to++ = *from++; --n;
+ if (!n) return; *to++ = *from++; --n;
+ if (!n) return; *to++ = *from++; --n;
+ }
+}
diff --git a/byte_cr.c b/byte_cr.c
new file mode 100644
index 0000000..3e7a1d5
--- /dev/null
+++ b/byte_cr.c
@@ -0,0 +1,16 @@
+#include "byte.h"
+
+void byte_copyr(to,n,from)
+register char *to;
+register unsigned int n;
+register char *from;
+{
+ to += n;
+ from += n;
+ for (;;) {
+ if (!n) return; *--to = *--from; --n;
+ if (!n) return; *--to = *--from; --n;
+ if (!n) return; *--to = *--from; --n;
+ if (!n) return; *--to = *--from; --n;
+ }
+}
diff --git a/byte_diff.c b/byte_diff.c
new file mode 100644
index 0000000..cdbd760
--- /dev/null
+++ b/byte_diff.c
@@ -0,0 +1,16 @@
+#include "byte.h"
+
+int byte_diff(s,n,t)
+register char *s;
+register unsigned int n;
+register char *t;
+{
+ for (;;) {
+ if (!n) return 0; if (*s != *t) break; ++s; ++t; --n;
+ if (!n) return 0; if (*s != *t) break; ++s; ++t; --n;
+ if (!n) return 0; if (*s != *t) break; ++s; ++t; --n;
+ if (!n) return 0; if (*s != *t) break; ++s; ++t; --n;
+ }
+ return ((int)(unsigned int)(unsigned char) *s)
+ - ((int)(unsigned int)(unsigned char) *t);
+}
diff --git a/cdb.c b/cdb.c
new file mode 100644
index 0000000..b09d3a5
--- /dev/null
+++ b/cdb.c
@@ -0,0 +1,136 @@
+/* Public domain. */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include "readwrite.h"
+#include "error.h"
+#include "seek.h"
+#include "byte.h"
+#include "cdb.h"
+
+void cdb_free(struct cdb *c)
+{
+ if (c->map) {
+ munmap(c->map,c->size);
+ c->map = 0;
+ }
+}
+
+void cdb_findstart(struct cdb *c)
+{
+ c->loop = 0;
+}
+
+void cdb_init(struct cdb *c,int fd)
+{
+ struct stat st;
+ char *x;
+
+ cdb_free(c);
+ cdb_findstart(c);
+ c->fd = fd;
+
+ if (fstat(fd,&st) == 0)
+ if (st.st_size <= 0xffffffff) {
+ x = mmap(0,st.st_size,PROT_READ,MAP_SHARED,fd,0);
+ if (x + 1) {
+ c->size = st.st_size;
+ c->map = x;
+ }
+ }
+}
+
+int cdb_read(struct cdb *c,char *buf,unsigned int len,uint32 pos)
+{
+ if (c->map) {
+ if ((pos > c->size) || (c->size - pos < len)) goto FORMAT;
+ byte_copy(buf,len,c->map + pos);
+ }
+ else {
+ if (seek_set(c->fd,pos) == -1) return -1;
+ while (len > 0) {
+ int r;
+ do
+ r = read(c->fd,buf,len);
+ while ((r == -1) && (errno == error_intr));
+ if (r == -1) return -1;
+ if (r == 0) goto FORMAT;
+ buf += r;
+ len -= r;
+ }
+ }
+ return 0;
+
+ FORMAT:
+ errno = error_proto;
+ return -1;
+}
+
+static int match(struct cdb *c,char *key,unsigned int len,uint32 pos)
+{
+ char buf[32];
+ int n;
+
+ while (len > 0) {
+ n = sizeof buf;
+ if (n > len) n = len;
+ if (cdb_read(c,buf,n,pos) == -1) return -1;
+ if (byte_diff(buf,n,key)) return 0;
+ pos += n;
+ key += n;
+ len -= n;
+ }
+ return 1;
+}
+
+int cdb_findnext(struct cdb *c,char *key,unsigned int len)
+{
+ char buf[8];
+ uint32 pos;
+ uint32 u;
+
+ if (!c->loop) {
+ u = cdb_hash(key,len);
+ if (cdb_read(c,buf,8,(u << 3) & 2047) == -1) return -1;
+ uint32_unpack(buf + 4,&c->hslots);
+ if (!c->hslots) return 0;
+ uint32_unpack(buf,&c->hpos);
+ c->khash = u;
+ u >>= 8;
+ u %= c->hslots;
+ u <<= 3;
+ c->kpos = c->hpos + u;
+ }
+
+ while (c->loop < c->hslots) {
+ if (cdb_read(c,buf,8,c->kpos) == -1) return -1;
+ uint32_unpack(buf + 4,&pos);
+ if (!pos) return 0;
+ c->loop += 1;
+ c->kpos += 8;
+ if (c->kpos == c->hpos + (c->hslots << 3)) c->kpos = c->hpos;
+ uint32_unpack(buf,&u);
+ if (u == c->khash) {
+ if (cdb_read(c,buf,8,pos) == -1) return -1;
+ uint32_unpack(buf,&u);
+ if (u == len)
+ switch(match(c,key,len,pos + 8)) {
+ case -1:
+ return -1;
+ case 1:
+ uint32_unpack(buf + 4,&c->dlen);
+ c->dpos = pos + 8 + len;
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int cdb_find(struct cdb *c,char *key,unsigned int len)
+{
+ cdb_findstart(c);
+ return cdb_findnext(c,key,len);
+}
diff --git a/cdb.h b/cdb.h
new file mode 100644
index 0000000..ff99810
--- /dev/null
+++ b/cdb.h
@@ -0,0 +1,37 @@
+/* Public domain. */
+
+#ifndef CDB_H
+#define CDB_H
+
+#include "uint32.h"
+
+#define CDB_HASHSTART 5381
+extern uint32 cdb_hashadd(uint32,unsigned char);
+extern uint32 cdb_hash(char *,unsigned int);
+
+struct cdb {
+ char *map; /* 0 if no map is available */
+ int fd;
+ uint32 size; /* initialized if map is nonzero */
+ uint32 loop; /* number of hash slots searched under this key */
+ uint32 khash; /* initialized if loop is nonzero */
+ uint32 kpos; /* initialized if loop is nonzero */
+ uint32 hpos; /* initialized if loop is nonzero */
+ uint32 hslots; /* initialized if loop is nonzero */
+ uint32 dpos; /* initialized if cdb_findnext() returns 1 */
+ uint32 dlen; /* initialized if cdb_findnext() returns 1 */
+} ;
+
+extern void cdb_free(struct cdb *);
+extern void cdb_init(struct cdb *,int fd);
+
+extern int cdb_read(struct cdb *,char *,unsigned int,uint32);
+
+extern void cdb_findstart(struct cdb *);
+extern int cdb_findnext(struct cdb *,char *,unsigned int);
+extern int cdb_find(struct cdb *,char *,unsigned int);
+
+#define cdb_datapos(c) ((c)->dpos)
+#define cdb_datalen(c) ((c)->dlen)
+
+#endif
diff --git a/cdb_hash.c b/cdb_hash.c
new file mode 100644
index 0000000..d8e3cb8
--- /dev/null
+++ b/cdb_hash.c
@@ -0,0 +1,21 @@
+/* Public domain. */
+
+#include "cdb.h"
+
+uint32 cdb_hashadd(uint32 h,unsigned char c)
+{
+ h += (h << 5);
+ return h ^ c;
+}
+
+uint32 cdb_hash(char *buf,unsigned int len)
+{
+ uint32 h;
+
+ h = CDB_HASHSTART;
+ while (len) {
+ h = cdb_hashadd(h,*buf++);
+ --len;
+ }
+ return h;
+}
diff --git a/cdb_make.c b/cdb_make.c
new file mode 100644
index 0000000..6d1bd03
--- /dev/null
+++ b/cdb_make.c
@@ -0,0 +1,153 @@
+/* Public domain. */
+
+#include "readwrite.h"
+#include "seek.h"
+#include "error.h"
+#include "alloc.h"
+#include "cdb.h"
+#include "cdb_make.h"
+
+int cdb_make_start(struct cdb_make *c,int fd)
+{
+ c->head = 0;
+ c->split = 0;
+ c->hash = 0;
+ c->numentries = 0;
+ c->fd = fd;
+ c->pos = sizeof c->final;
+ buffer_init(&c->b,write,fd,c->bspace,sizeof c->bspace);
+ return seek_set(fd,c->pos);
+}
+
+static int posplus(struct cdb_make *c,uint32 len)
+{
+ uint32 newpos = c->pos + len;
+ if (newpos < len) { errno = error_nomem; return -1; }
+ c->pos = newpos;
+ return 0;
+}
+
+int cdb_make_addend(struct cdb_make *c,unsigned int keylen,unsigned int datalen,uint32 h)
+{
+ struct cdb_hplist *head;
+
+ head = c->head;
+ if (!head || (head->num >= CDB_HPLIST)) {
+ head = (struct cdb_hplist *) alloc(sizeof(struct cdb_hplist));
+ if (!head) return -1;
+ head->num = 0;
+ head->next = c->head;
+ c->head = head;
+ }
+ head->hp[head->num].h = h;
+ head->hp[head->num].p = c->pos;
+ ++head->num;
+ ++c->numentries;
+ if (posplus(c,8) == -1) return -1;
+ if (posplus(c,keylen) == -1) return -1;
+ if (posplus(c,datalen) == -1) return -1;
+ return 0;
+}
+
+int cdb_make_addbegin(struct cdb_make *c,unsigned int keylen,unsigned int datalen)
+{
+ char buf[8];
+
+ if (keylen > 0xffffffff) { errno = error_nomem; return -1; }
+ if (datalen > 0xffffffff) { errno = error_nomem; return -1; }
+
+ uint32_pack(buf,keylen);
+ uint32_pack(buf + 4,datalen);
+ if (buffer_putalign(&c->b,buf,8) == -1) return -1;
+ return 0;
+}
+
+int cdb_make_add(struct cdb_make *c,char *key,unsigned int keylen,char *data,unsigned int datalen)
+{
+ if (cdb_make_addbegin(c,keylen,datalen) == -1) return -1;
+ if (buffer_putalign(&c->b,key,keylen) == -1) return -1;
+ if (buffer_putalign(&c->b,data,datalen) == -1) return -1;
+ return cdb_make_addend(c,keylen,datalen,cdb_hash(key,keylen));
+}
+
+int cdb_make_finish(struct cdb_make *c)
+{
+ char buf[8];
+ int i;
+ uint32 len;
+ uint32 u;
+ uint32 memsize;
+ uint32 count;
+ uint32 where;
+ struct cdb_hplist *x;
+ struct cdb_hp *hp;
+
+ for (i = 0;i < 256;++i)
+ c->count[i] = 0;
+
+ for (x = c->head;x;x = x->next) {
+ i = x->num;
+ while (i--)
+ ++c->count[255 & x->hp[i].h];
+ }
+
+ memsize = 1;
+ for (i = 0;i < 256;++i) {
+ u = c->count[i] * 2;
+ if (u > memsize)
+ memsize = u;
+ }
+
+ memsize += c->numentries; /* no overflow possible up to now */
+ u = (uint32) 0 - (uint32) 1;
+ u /= sizeof(struct cdb_hp);
+ if (memsize > u) { errno = error_nomem; return -1; }
+
+ c->split = (struct cdb_hp *) alloc(memsize * sizeof(struct cdb_hp));
+ if (!c->split) return -1;
+
+ c->hash = c->split + c->numentries;
+
+ u = 0;
+ for (i = 0;i < 256;++i) {
+ u += c->count[i]; /* bounded by numentries, so no overflow */
+ c->start[i] = u;
+ }
+
+ for (x = c->head;x;x = x->next) {
+ i = x->num;
+ while (i--)
+ c->split[--c->start[255 & x->hp[i].h]] = x->hp[i];
+ }
+
+ for (i = 0;i < 256;++i) {
+ count = c->count[i];
+
+ len = count + count; /* no overflow possible */
+ uint32_pack(c->final + 8 * i,c->pos);
+ uint32_pack(c->final + 8 * i + 4,len);
+
+ for (u = 0;u < len;++u)
+ c->hash[u].h = c->hash[u].p = 0;
+
+ hp = c->split + c->start[i];
+ for (u = 0;u < count;++u) {
+ where = (hp->h >> 8) % len;
+ while (c->hash[where].p)
+ if (++where == len)
+ where = 0;
+ c->hash[where] = *hp++;
+ }
+
+ for (u = 0;u < len;++u) {
+ uint32_pack(buf,c->hash[u].h);
+ uint32_pack(buf + 4,c->hash[u].p);
+ if (buffer_putalign(&c->b,buf,8) == -1) return -1;
+ if (posplus(c,8) == -1) return -1;
+ }
+ }
+
+ if (buffer_flush(&c->b) == -1) return -1;
+ if (seek_begin(c->fd) == -1) return -1;
+ return buffer_putflush(&c->b,c->final,sizeof c->final);
+}
diff --git a/cdb_make.h b/cdb_make.h
new file mode 100644
index 0000000..b8bbe4d
--- /dev/null
+++ b/cdb_make.h
@@ -0,0 +1,39 @@
+/* Public domain. */
+
+#ifndef CDB_MAKE_H
+#define CDB_MAKE_H
+
+#include "buffer.h"
+#include "uint32.h"
+
+#define CDB_HPLIST 1000
+
+struct cdb_hp { uint32 h; uint32 p; } ;
+
+struct cdb_hplist {
+ struct cdb_hp hp[CDB_HPLIST];
+ struct cdb_hplist *next;
+ int num;
+} ;
+
+struct cdb_make {
+ char bspace[8192];
+ char final[2048];
+ uint32 count[256];
+ uint32 start[256];
+ struct cdb_hplist *head;
+ struct cdb_hp *split; /* includes space for hash */
+ struct cdb_hp *hash;
+ uint32 numentries;
+ buffer b;
+ uint32 pos;
+ int fd;
+} ;
+
+extern int cdb_make_start(struct cdb_make *,int);
+extern int cdb_make_addbegin(struct cdb_make *,unsigned int,unsigned int);
+extern int cdb_make_addend(struct cdb_make *,unsigned int,unsigned int,uint32);
+extern int cdb_make_add(struct cdb_make *,char *,unsigned int,char *,unsigned int);
+extern int cdb_make_finish(struct cdb_make *);
+
+#endif
diff --git a/cdbdump.c b/cdbdump.c
new file mode 100644
index 0000000..159d7e7
--- /dev/null
+++ b/cdbdump.c
@@ -0,0 +1,83 @@
+#include "uint32.h"
+#include "fmt.h"
+#include "buffer.h"
+#include "strerr.h"
+
+#define FATAL "cdbdump: fatal: "
+
+void die_write(void)
+{
+ strerr_die2sys(111,FATAL,"unable to write output: ");
+}
+void put(char *buf,unsigned int len)
+{
+ if (buffer_put(buffer_1,buf,len) == -1) die_write();
+}
+void putflush(void)
+{
+ if (buffer_flush(buffer_1) == -1) die_write();
+}
+
+uint32 pos = 0;
+
+void get(char *buf,unsigned int len)
+{
+ int r;
+ while (len > 0) {
+ r = buffer_get(buffer_0,buf,len);
+ if (r == -1)
+ strerr_die2sys(111,FATAL,"unable to read input: ");
+ if (r == 0)
+ strerr_die2x(111,FATAL,"unable to read input: truncated file");
+ pos += r;
+ buf += r;
+ len -= r;
+ }
+}
+
+char buf[512];
+
+void copy(uint32 len)
+{
+ unsigned int x;
+
+ while (len) {
+ x = sizeof buf;
+ if (len < x) x = len;
+ get(buf,x);
+ put(buf,x);
+ len -= x;
+ }
+}
+
+void getnum(uint32 *num)
+{
+ get(buf,4);
+ uint32_unpack(buf,num);
+}
+
+char strnum[FMT_ULONG];
+
+main()
+{
+ uint32 eod;
+ uint32 klen;
+ uint32 dlen;
+
+ getnum(&eod);
+ while (pos < 2048) getnum(&dlen);
+
+ while (pos < eod) {
+ getnum(&klen);
+ getnum(&dlen);
+ put("+",1); put(strnum,fmt_ulong(strnum,klen));
+ put(",",1); put(strnum,fmt_ulong(strnum,dlen));
+ put(":",1); copy(klen);
+ put("->",2); copy(dlen);
+ put("\n",1);
+ }
+
+ put("\n",1);
+ putflush();
+ _exit(0);
+}
diff --git a/cdbget.c b/cdbget.c
new file mode 100644
index 0000000..1c76fe2
--- /dev/null
+++ b/cdbget.c
@@ -0,0 +1,67 @@
+#include "exit.h"
+#include "scan.h"
+#include "str.h"
+#include "buffer.h"
+#include "strerr.h"
+#include "cdb.h"
+
+#define FATAL "cdbget: fatal: "
+
+void die_read(void)
+{
+ strerr_die2sys(111,FATAL,"unable to read input: ");
+}
+void die_write(void)
+{
+ strerr_die2sys(111,FATAL,"unable to write output: ");
+}
+void die_usage(void)
+{
+ strerr_die1x(111,"cdbget: usage: cdbget key [skip]");
+}
+
+static struct cdb c;
+char buf[1024];
+
+main(int argc,char **argv)
+{
+ char *key;
+ int r;
+ uint32 pos;
+ uint32 len;
+ unsigned long u = 0;
+
+ if (!*argv) die_usage();
+
+ if (!*++argv) die_usage();
+ key = *argv;
+
+ if (*++argv) {
+ scan_ulong(*argv,&u);
+ }
+
+ cdb_init(&c,0);
+ cdb_findstart(&c);
+
+ for (;;) {
+ r = cdb_findnext(&c,key,str_len(key));
+ if (r == -1) die_read();
+ if (!r) _exit(100);
+ if (!u) break;
+ --u;
+ }
+
+ pos = cdb_datapos(&c);
+ len = cdb_datalen(&c);
+
+ while (len > 0) {
+ r = sizeof buf;
+ if (r > len) r = len;
+ if (cdb_read(&c,buf,r,pos) == -1) die_read();
+ if (buffer_put(buffer_1small,buf,r) == -1) die_write();
+ pos += r;
+ len -= r;
+ }
+ if (buffer_flush(buffer_1small) == -1) die_write();
+ _exit(0);
+}
diff --git a/cdbmake-12.sh b/cdbmake-12.sh
new file mode 100644
index 0000000..05df698
--- /dev/null
+++ b/cdbmake-12.sh
@@ -0,0 +1,8 @@
+awk '
+ /^[^#]/ {
+ print "+" length($1) "," length($2) ":" $1 "->" $2
+ }
+ END {
+ print ""
+ }
+' | HOME/bin/cdbmake "$@"
diff --git a/cdbmake-sv.sh b/cdbmake-sv.sh
new file mode 100644
index 0000000..241d46c
--- /dev/null
+++ b/cdbmake-sv.sh
@@ -0,0 +1,22 @@
+awk '
+ {
+ if (split($0,x,"#")) {
+ f = split(x[1],y)
+ if (f >= 2) {
+ if (split(y[2],z,"/") >= 2) {
+ a = "@" z[1] "/" z[2]
+ print "+" length(a) "," length(y[1]) ":" a "->" y[1]
+ for (i = 1;i <= f;i += 1) {
+ if (i != 2) {
+ a = y[i] "/" z[2]
+ print "+" length(a) "," length(z[1]) ":" a "->" z[1]
+ }
+ }
+ }
+ }
+ }
+ }
+ END {
+ print ""
+ }
+' | HOME/bin/cdbmake "$@"
diff --git a/cdbmake.c b/cdbmake.c
new file mode 100644
index 0000000..3c1c8bd
--- /dev/null
+++ b/cdbmake.c
@@ -0,0 +1,110 @@
+#include "error.h"
+#include "open.h"
+#include "strerr.h"
+#include "cdb_make.h"
+#include "cdb.h"
+
+#define FATAL "cdbmake: fatal: "
+
+char *fn;
+char *fntmp;
+
+void die_usage(void)
+{
+ strerr_die1x(100,"cdbmake: usage: cdbmake f ftmp");
+}
+void die_write(void)
+{
+ strerr_die4sys(111,FATAL,"unable to create ",fntmp,": ");
+}
+void die_read(void)
+{
+ strerr_die2sys(111,FATAL,"unable to read input: ");
+}
+void die_readformat(void)
+{
+ strerr_die2x(111,FATAL,"unable to read input: bad format");
+}
+
+inline void get(char *ch)
+{
+ switch(buffer_GETC(buffer_0,ch)) {
+ case 0: die_readformat();
+ case -1: die_read();
+ }
+}
+
+static struct cdb_make c;
+
+main(int argc,char **argv)
+{
+ unsigned int klen;
+ unsigned int dlen;
+ unsigned int i;
+ uint32 h;
+ int fd;
+ char ch;
+
+ if (!*argv) die_usage();
+
+ if (!*++argv) die_usage();
+ fn = *argv;
+
+ if (!*++argv) die_usage();
+ fntmp = *argv;
+
+ fd = open_trunc(fntmp);
+ if (fd == -1) die_write();
+
+ if (cdb_make_start(&c,fd) == -1) die_write();
+
+ for (;;) {
+ get(&ch);
+ if (ch == '\n') break;
+ if (ch != '+') die_readformat();
+ klen = 0;
+ for (;;) {
+ get(&ch);
+ if (ch == ',') break;
+ if ((ch < '0') || (ch > '9')) die_readformat();
+ if (klen > 429496720) { errno = error_nomem; die_write(); }
+ klen = klen * 10 + (ch - '0');
+ }
+ dlen = 0;
+ for (;;) {
+ get(&ch);
+ if (ch == ':') break;
+ if ((ch < '0') || (ch > '9')) die_readformat();
+ if (dlen > 429496720) { errno = error_nomem; die_write(); }
+ dlen = dlen * 10 + (ch - '0');
+ }
+
+ if (cdb_make_addbegin(&c,klen,dlen) == -1) die_write();
+ h = CDB_HASHSTART;
+ for (i = 0;i < klen;++i) {
+ get(&ch);
+ if (buffer_PUTC(&c.b,ch) == -1) die_write();
+ h = cdb_hashadd(h,ch);
+ }
+ get(&ch);
+ if (ch != '-') die_readformat();
+ get(&ch);
+ if (ch != '>') die_readformat();
+ for (i = 0;i < dlen;++i) {
+ get(&ch);
+ if (buffer_PUTC(&c.b,ch) == -1) die_write();
+ }
+ if (cdb_make_addend(&c,klen,dlen,h) == -1) die_write();
+
+ get(&ch);
+ if (ch != '\n') die_readformat();
+ }
+
+ if (cdb_make_finish(&c) == -1) die_write();
+ if (fsync(fd) == -1) die_write();
+ if (close(fd) == -1) die_write(); /* NFS silliness */
+ if (rename(fntmp,fn) == -1)
+ strerr_die6sys(111,FATAL,"unable to rename ",fntmp," to ",fn,": ");
+
+ _exit(0);
+}
diff --git a/cdbstats.c b/cdbstats.c
new file mode 100644
index 0000000..b5db527
--- /dev/null
+++ b/cdbstats.c
@@ -0,0 +1,125 @@
+#include "uint32.h"
+#include "fmt.h"
+#include "buffer.h"
+#include "strerr.h"
+#include "seek.h"
+#include "cdb.h"
+
+#define FATAL "cdbstats: fatal: "
+
+void die_read(void)
+{
+ strerr_die2sys(111,FATAL,"unable to read input: ");
+}
+void die_readformat(void)
+{
+ strerr_die2x(111,FATAL,"unable to read input: truncated file");
+}
+void die_write(void)
+{
+ strerr_die2sys(111,FATAL,"unable to write output: ");
+}
+void put(char *buf,unsigned int len)
+{
+ if (buffer_put(buffer_1small,buf,len) == -1) die_write();
+}
+void putflush(void)
+{
+ if (buffer_flush(buffer_1small) == -1) die_write();
+}
+
+uint32 pos = 0;
+
+void get(char *buf,unsigned int len)
+{
+ int r;
+ while (len > 0) {
+ r = buffer_get(buffer_0,buf,len);
+ if (r == -1) die_read();
+ if (r == 0) die_readformat();
+ pos += r;
+ buf += r;
+ len -= r;
+ }
+}
+
+void getnum(uint32 *num)
+{
+ char buf[4];
+ get(buf,4);
+ uint32_unpack(buf,num);
+}
+
+char strnum[FMT_ULONG];
+
+void putnum(char *label,unsigned long count)
+{
+ unsigned int i;
+ put(label,str_len(label));
+ for (i = fmt_ulong(0,count);i < 10;++i) put(" ",1);
+ put(strnum,fmt_ulong(strnum,count));
+ put("\n",1);
+}
+
+char key[1024];
+
+static struct cdb c;
+
+static unsigned long numrecords;
+static unsigned long numd[11];
+
+main()
+{
+ uint32 eod;
+ uint32 klen;
+ uint32 dlen;
+ seek_pos rest;
+ int r;
+
+ cdb_init(&c,0);
+
+ getnum(&eod);
+ while (pos < 2048) getnum(&dlen);
+
+ while (pos < eod) {
+ getnum(&klen);
+ getnum(&dlen);
+ if (klen > sizeof key) {
+ while (klen) { get(key,1); --klen; }
+ }
+ else {
+ get(key,klen);
+ rest = seek_cur(0);
+ cdb_findstart(&c);
+ do {
+ switch(cdb_findnext(&c,key,klen)) {
+ case -1: die_read();
+ case 0: die_readformat();
+ }
+ } while (cdb_datapos(&c) != pos);
+ if (!c.loop) die_readformat();
+ ++numrecords;
+ if (c.loop > 10)
+ ++numd[10];
+ else
+ ++numd[c.loop - 1];
+ if (seek_set(0,rest) == -1) die_read();
+ }
+ while (dlen) { get(key,1); --dlen; }
+ }
+
+ putnum("records ",numrecords);
+ putnum("d0 ",numd[0]);
+ putnum("d1 ",numd[1]);
+ putnum("d2 ",numd[2]);
+ putnum("d3 ",numd[3]);
+ putnum("d4 ",numd[4]);
+ putnum("d5 ",numd[5]);
+ putnum("d6 ",numd[6]);
+ putnum("d7 ",numd[7]);
+ putnum("d8 ",numd[8]);
+ putnum("d9 ",numd[9]);
+ putnum(">9 ",numd[10]);
+ putflush();
+ _exit(0);
+}
diff --git a/cdbtest.c b/cdbtest.c
new file mode 100644
index 0000000..eaefd59
--- /dev/null
+++ b/cdbtest.c
@@ -0,0 +1,119 @@
+#include "uint32.h"
+#include "fmt.h"
+#include "buffer.h"
+#include "strerr.h"
+#include "seek.h"
+#include "cdb.h"
+
+#define FATAL "cdbtest: fatal: "
+
+void die_read(void)
+{
+ strerr_die2sys(111,FATAL,"unable to read input: ");
+}
+void die_write(void)
+{
+ strerr_die2sys(111,FATAL,"unable to write output: ");
+}
+void put(char *buf,unsigned int len)
+{
+ if (buffer_put(buffer_1small,buf,len) == -1) die_write();
+}
+void putflush(void)
+{
+ if (buffer_flush(buffer_1small) == -1) die_write();
+}
+
+uint32 pos = 0;
+
+void get(char *buf,unsigned int len)
+{
+ int r;
+ while (len > 0) {
+ r = buffer_get(buffer_0,buf,len);
+ if (r == -1) die_read();
+ if (r == 0)
+ strerr_die2x(111,FATAL,"unable to read input: truncated file");
+ pos += r;
+ buf += r;
+ len -= r;
+ }
+}
+
+void getnum(uint32 *num)
+{
+ char buf[4];
+ get(buf,4);
+ uint32_unpack(buf,num);
+}
+
+char strnum[FMT_ULONG];
+
+void putnum(char *label,unsigned long count)
+{
+ put(label,str_len(label));
+ put(strnum,fmt_ulong(strnum,count));
+ put("\n",1);
+}
+
+char key[1024];
+
+unsigned long numuntested = 0;
+unsigned long numnotfound = 0;
+unsigned long numotherpos = 0;
+unsigned long numbadlen = 0;
+unsigned long numfound = 0;
+
+static struct cdb c;
+
+main()
+{
+ uint32 eod;
+ uint32 klen;
+ uint32 dlen;
+ seek_pos rest;
+ int r;
+
+ cdb_init(&c,0);
+
+ getnum(&eod);
+ while (pos < 2048) getnum(&dlen);
+
+ while (pos < eod) {
+ getnum(&klen);
+ getnum(&dlen);
+ if (klen > sizeof key) {
+ ++numuntested;
+ while (klen) { get(key,1); --klen; }
+ }
+ else {
+ get(key,klen);
+ rest = seek_cur(0);
+ switch(cdb_find(&c,key,klen)) {
+ case -1:
+ die_read();
+ case 0:
+ ++numnotfound;
+ break;
+ default:
+ if (cdb_datapos(&c) != pos)
+ ++numotherpos;
+ else
+ if (cdb_datalen(&c) != dlen)
+ ++numbadlen;
+ else
+ ++numfound;
+ }
+ if (seek_set(0,rest) == -1) die_read();
+ }
+ while (dlen) { get(key,1); --dlen; }
+ }
+
+ putnum("found: ",numfound);
+ putnum("different record: ",numotherpos);
+ putnum("bad length: ",numbadlen);
+ putnum("not found: ",numnotfound);
+ putnum("untested: ",numuntested);
+ putflush();
+ _exit(0);
+}
diff --git a/choose.sh b/choose.sh
new file mode 100644
index 0000000..feff2da
--- /dev/null
+++ b/choose.sh
@@ -0,0 +1,18 @@
+
+result="$4"
+
+case "$1" in
+ *c*) ./compile $2.c >/dev/null 2>&1 || result="$3" ;;
+esac
+
+case "$1" in
+ *l*) ./load $2 >/dev/null 2>&1 || result="$3" ;;
+esac
+
+case "$1" in
+ *r*) ./$2 >/dev/null 2>&1 || result="$3" ;;
+esac
+
+rm -f $2.o $2
+
+exec cat "$result"
diff --git a/conf-cc b/conf-cc
new file mode 100644
index 0000000..7f41e18
--- /dev/null
+++ b/conf-cc
@@ -0,0 +1,3 @@
+gcc -O2
+
+This will be used to compile .c files.
diff --git a/conf-home b/conf-home
new file mode 100644
index 0000000..2e468c7
--- /dev/null
+++ b/conf-home
@@ -0,0 +1,3 @@
+/usr/local
+
+This is the cdb home directory. Programs will be installed in .../bin.
diff --git a/conf-ld b/conf-ld
new file mode 100644
index 0000000..59a0de7
--- /dev/null
+++ b/conf-ld
@@ -0,0 +1,3 @@
+gcc -s
+
+This will be used to link .o files into an executable.
diff --git a/error.c b/error.c
new file mode 100644
index 0000000..e1ab13c
--- /dev/null
+++ b/error.c
@@ -0,0 +1,109 @@
+#include <errno.h>
+#include "error.h"
+
+/* warning: as coverage improves here, should update error_{str,temp} */
+
+int error_intr =
+#ifdef EINTR
+EINTR;
+#else
+-1;
+#endif
+
+int error_nomem =
+#ifdef ENOMEM
+ENOMEM;
+#else
+-2;
+#endif
+
+int error_noent =
+#ifdef ENOENT
+ENOENT;
+#else
+-3;
+#endif
+
+int error_txtbsy =
+#ifdef ETXTBSY
+ETXTBSY;
+#else
+-4;
+#endif
+
+int error_io =
+#ifdef EIO
+EIO;
+#else
+-5;
+#endif
+
+int error_exist =
+#ifdef EEXIST
+EEXIST;
+#else
+-6;
+#endif
+
+int error_timeout =
+#ifdef ETIMEDOUT
+ETIMEDOUT;
+#else
+-7;
+#endif
+
+int error_inprogress =
+#ifdef EINPROGRESS
+EINPROGRESS;
+#else
+-8;
+#endif
+
+int error_wouldblock =
+#ifdef EWOULDBLOCK
+EWOULDBLOCK;
+#else
+-9;
+#endif
+
+int error_again =
+#ifdef EAGAIN
+EAGAIN;
+#else
+-10;
+#endif
+
+int error_pipe =
+#ifdef EPIPE
+EPIPE;
+#else
+-11;
+#endif
+
+int error_perm =
+#ifdef EPERM
+EPERM;
+#else
+-12;
+#endif
+
+int error_acces =
+#ifdef EACCES
+EACCES;
+#else
+-13;
+#endif
+
+int error_nodevice =
+#ifdef ENXIO
+ENXIO;
+#else
+-14;
+#endif
+
+int error_proto =
+#ifdef EPROTO
+EPROTO;
+#else
+-15;
+#endif
diff --git a/error.h b/error.h
new file mode 100644
index 0000000..e3cc2ae
--- /dev/null
+++ b/error.h
@@ -0,0 +1,25 @@
+#ifndef ERROR_H
+#define ERROR_H
+
+extern int errno;
+
+extern int error_intr;
+extern int error_nomem;
+extern int error_noent;
+extern int error_txtbsy;
+extern int error_io;
+extern int error_exist;
+extern int error_timeout;
+extern int error_inprogress;
+extern int error_wouldblock;
+extern int error_again;
+extern int error_pipe;
+extern int error_perm;
+extern int error_acces;
+extern int error_nodevice;
+extern int error_proto;
+
+extern char *error_str(int);
+extern int error_temp(int);
+
+#endif
diff --git a/error_str.c b/error_str.c
new file mode 100644
index 0000000..92255ec
--- /dev/null
+++ b/error_str.c
@@ -0,0 +1,271 @@
+#include <errno.h>
+#include "error.h"
+
+#define X(e,s) if (i == e) return s;
+
+char *error_str(int i)
+{
+ X(0,"no error")
+ X(error_intr,"interrupted system call")
+ X(error_nomem,"out of memory")
+ X(error_noent,"file does not exist")
+ X(error_txtbsy,"text busy")
+ X(error_io,"input/output error")
+ X(error_exist,"file already exists")
+ X(error_timeout,"timed out")
+ X(error_inprogress,"operation in progress")
+ X(error_again,"temporary failure")
+ X(error_wouldblock,"input/output would block")
+ X(error_pipe,"broken pipe")
+ X(error_perm,"permission denied")
+ X(error_acces,"access denied")
+ X(error_nodevice,"device not configured")
+ X(error_proto,"protocol error")
+#ifdef ESRCH
+ X(ESRCH,"no such process")
+#endif
+#ifdef E2BIG
+ X(E2BIG,"argument list too long")
+#endif
+#ifdef ENOEXEC
+ X(ENOEXEC,"exec format error")
+#endif
+#ifdef EBADF
+ X(EBADF,"file descriptor not open")
+#endif
+#ifdef ECHILD
+ X(ECHILD,"no child processes")
+#endif
+#ifdef EDEADLK
+ X(EDEADLK,"operation would cause deadlock")
+#endif
+#ifdef EFAULT
+ X(EFAULT,"bad address")
+#endif
+#ifdef ENOTBLK
+ X(ENOTBLK,"not a block device")
+#endif
+#ifdef EBUSY
+ X(EBUSY,"device busy")
+#endif
+#ifdef EXDEV
+ X(EXDEV,"cross-device link")
+#endif
+#ifdef ENODEV
+ X(ENODEV,"device does not support operation")
+#endif
+#ifdef ENOTDIR
+ X(ENOTDIR,"not a directory")
+#endif
+#ifdef EISDIR
+ X(EISDIR,"is a directory")
+#endif
+#ifdef EINVAL
+ X(EINVAL,"invalid argument")
+#endif
+#ifdef ENFILE
+ X(ENFILE,"system cannot open more files")
+#endif
+#ifdef EMFILE
+ X(EMFILE,"process cannot open more files")
+#endif
+#ifdef ENOTTY
+ X(ENOTTY,"not a tty")
+#endif
+#ifdef EFBIG
+ X(EFBIG,"file too big")
+#endif
+#ifdef ENOSPC
+ X(ENOSPC,"out of disk space")
+#endif
+#ifdef ESPIPE
+ X(ESPIPE,"unseekable descriptor")
+#endif
+#ifdef EROFS
+ X(EROFS,"read-only file system")
+#endif
+#ifdef EMLINK
+ X(EMLINK,"too many links")
+#endif
+#ifdef EDOM
+ X(EDOM,"input out of range")
+#endif
+#ifdef ERANGE
+ X(ERANGE,"output out of range")
+#endif
+#ifdef EALREADY
+ X(EALREADY,"operation already in progress")
+#endif
+#ifdef ENOTSOCK
+ X(ENOTSOCK,"not a socket")
+#endif
+#ifdef EDESTADDRREQ
+ X(EDESTADDRREQ,"destination address required")
+#endif
+#ifdef EMSGSIZE
+ X(EMSGSIZE,"message too long")
+#endif
+#ifdef EPROTOTYPE
+ X(EPROTOTYPE,"incorrect protocol type")
+#endif
+#ifdef ENOPROTOOPT
+ X(ENOPROTOOPT,"protocol not available")
+#endif
+#ifdef EPROTONOSUPPORT
+ X(EPROTONOSUPPORT,"protocol not supported")
+#endif
+#ifdef ESOCKTNOSUPPORT
+ X(ESOCKTNOSUPPORT,"socket type not supported")
+#endif
+#ifdef EOPNOTSUPP
+ X(EOPNOTSUPP,"operation not supported")
+#endif
+#ifdef EPFNOSUPPORT
+ X(EPFNOSUPPORT,"protocol family not supported")
+#endif
+#ifdef EAFNOSUPPORT
+ X(EAFNOSUPPORT,"address family not supported")
+#endif
+#ifdef EADDRINUSE
+ X(EADDRINUSE,"address already used")
+#endif
+#ifdef EADDRNOTAVAIL
+ X(EADDRNOTAVAIL,"address not available")
+#endif
+#ifdef ENETDOWN
+ X(ENETDOWN,"network down")
+#endif
+#ifdef ENETUNREACH
+ X(ENETUNREACH,"network unreachable")
+#endif
+#ifdef ENETRESET
+ X(ENETRESET,"network reset")
+#endif
+#ifdef ECONNABORTED
+ X(ECONNABORTED,"connection aborted")
+#endif
+#ifdef ECONNRESET
+ X(ECONNRESET,"connection reset")
+#endif
+#ifdef ENOBUFS
+ X(ENOBUFS,"out of buffer space")
+#endif
+#ifdef EISCONN
+ X(EISCONN,"already connected")
+#endif
+#ifdef ENOTCONN
+ X(ENOTCONN,"not connected")
+#endif
+#ifdef ESHUTDOWN
+ X(ESHUTDOWN,"socket shut down")
+#endif
+#ifdef ETOOMANYREFS
+ X(ETOOMANYREFS,"too many references")
+#endif
+#ifdef ECONNREFUSED
+ X(ECONNREFUSED,"connection refused")
+#endif
+#ifdef ELOOP
+ X(ELOOP,"symbolic link loop")
+#endif
+#ifdef ENAMETOOLONG
+ X(ENAMETOOLONG,"file name too long")
+#endif
+#ifdef EHOSTDOWN
+ X(EHOSTDOWN,"host down")
+#endif
+#ifdef EHOSTUNREACH
+ X(EHOSTUNREACH,"host unreachable")
+#endif
+#ifdef ENOTEMPTY
+ X(ENOTEMPTY,"directory not empty")
+#endif
+#ifdef EPROCLIM
+ X(EPROCLIM,"too many processes")
+#endif
+#ifdef EUSERS
+ X(EUSERS,"too many users")
+#endif
+#ifdef EDQUOT
+ X(EDQUOT,"disk quota exceeded")
+#endif
+#ifdef ESTALE
+ X(ESTALE,"stale NFS file handle")
+#endif
+#ifdef EREMOTE
+ X(EREMOTE,"too many levels of remote in path")
+#endif
+#ifdef EBADRPC
+ X(EBADRPC,"RPC structure is bad")
+#endif
+#ifdef ERPCMISMATCH
+ X(ERPCMISMATCH,"RPC version mismatch")
+#endif
+#ifdef EPROGUNAVAIL
+ X(EPROGUNAVAIL,"RPC program unavailable")
+#endif
+#ifdef EPROGMISMATCH
+ X(EPROGMISMATCH,"program version mismatch")
+#endif
+#ifdef EPROCUNAVAIL
+ X(EPROCUNAVAIL,"bad procedure for program")
+#endif
+#ifdef ENOLCK
+ X(ENOLCK,"no locks available")
+#endif
+#ifdef ENOSYS
+ X(ENOSYS,"system call not available")
+#endif
+#ifdef EFTYPE
+ X(EFTYPE,"bad file type")
+#endif
+#ifdef EAUTH
+ X(EAUTH,"authentication error")
+#endif
+#ifdef ENEEDAUTH
+ X(ENEEDAUTH,"not authenticated")
+#endif
+#ifdef ENOSTR
+ X(ENOSTR,"not a stream device")
+#endif
+#ifdef ETIME
+ X(ETIME,"timer expired")
+#endif
+#ifdef ENOSR
+ X(ENOSR,"out of stream resources")
+#endif
+#ifdef ENOMSG
+ X(ENOMSG,"no message of desired type")
+#endif
+#ifdef EBADMSG
+ X(EBADMSG,"bad message type")
+#endif
+#ifdef EIDRM
+ X(EIDRM,"identifier removed")
+#endif
+#ifdef ENONET
+ X(ENONET,"machine not on network")
+#endif
+#ifdef ERREMOTE
+ X(ERREMOTE,"object not local")
+#endif
+#ifdef ENOLINK
+ X(ENOLINK,"link severed")
+#endif
+#ifdef EADV
+ X(EADV,"advertise error")
+#endif
+#ifdef ESRMNT
+ X(ESRMNT,"srmount error")
+#endif
+#ifdef ECOMM
+ X(ECOMM,"communication error")
+#endif
+#ifdef EMULTIHOP
+ X(EMULTIHOP,"multihop attempted")
+#endif
+#ifdef EREMCHG
+ X(EREMCHG,"remote address changed")
+#endif
+ return "unknown error";
+}
diff --git a/exit.h b/exit.h
new file mode 100644
index 0000000..39011c8
--- /dev/null
+++ b/exit.h
@@ -0,0 +1,6 @@
+#ifndef EXIT_H
+#define EXIT_H
+
+extern void _exit();
+
+#endif
diff --git a/find-systype.sh b/find-systype.sh
new file mode 100644
index 0000000..0955c32
--- /dev/null
+++ b/find-systype.sh
@@ -0,0 +1,159 @@
+# oper-:arch-:syst-:chip-:kern-
+# oper = operating system type; e.g., sunos-4.1.4
+# arch = machine language; e.g., sparc
+# syst = which binaries can run; e.g., sun4
+# chip = chip model; e.g., micro-2-80
+# kern = kernel version; e.g., sun4m
+# dependence: arch --- chip
+# \ \
+# oper --- syst --- kern
+# so, for example, syst is interpreted in light of oper, but chip is not.
+# anyway, no slashes, no extra colons, no uppercase letters.
+# the point of the extra -'s is to ease parsing: can add hierarchies later.
+# e.g., *:i386-*:*:pentium-*:* would handle pentium-100 as well as pentium,
+# and i386-486 (486s do have more instructions, you know) as well as i386.
+# the idea here is to include ALL useful available information.
+
+exec 2>/dev/null
+
+sys="`uname -s | tr '/:[A-Z]' '..[a-z]'`"
+if [ x"$sys" != x ]
+then
+ unamer="`uname -r | tr /: ..`"
+ unamem="`uname -m | tr /: ..`"
+ unamev="`uname -v | tr /: ..`"
+
+ case "$sys" in
+ bsd.os)
+ # in bsd 4.4, uname -v does not have useful info.
+ # in bsd 4.4, uname -m is arch, not chip.
+ oper="$sys-$unamer"
+ arch="$unamem"
+ syst=""
+ chip="`sysctl -n hw.model`"
+ kern=""
+ ;;
+ freebsd)
+ # see above about bsd 4.4
+ oper="$sys-$unamer"
+ arch="$unamem"
+ syst=""
+ chip="`sysctl -n hw.model`" # hopefully
+ kern=""
+ ;;
+ netbsd)
+ # see above about bsd 4.4
+ oper="$sys-$unamer"
+ arch="$unamem"
+ syst=""
+ chip="`sysctl -n hw.model`" # hopefully
+ kern=""
+ ;;
+ linux)
+ # as in bsd 4.4, uname -v does not have useful info.
+ oper="$sys-$unamer"
+ syst=""
+ chip="$unamem"
+ kern=""
+ case "$chip" in
+ i386|i486|i586|i686)
+ arch="i386"
+ ;;
+ alpha)
+ arch="alpha"
+ ;;
+ esac
+ ;;
+ aix)
+ # naturally IBM has to get uname -r and uname -v backwards. dorks.
+ oper="$sys-$unamev-$unamer"
+ arch="`arch | tr /: ..`"
+ syst=""
+ chip="$unamem"
+ kern=""
+ ;;
+ sunos)
+ oper="$sys-$unamer-$unamev"
+ arch="`(uname -p || mach) | tr /: ..`"
+ syst="`arch | tr /: ..`"
+ chip="$unamem" # this is wrong; is there any way to get the real info?
+ kern="`arch -k | tr /: ..`"
+ ;;
+ unix_sv)
+ oper="$sys-$unamer-$unamev"
+ arch="`uname -m`"
+ syst=""
+ chip="$unamem"
+ kern=""
+ ;;
+ *)
+ oper="$sys-$unamer-$unamev"
+ arch="`arch | tr /: ..`"
+ syst=""
+ chip="$unamem"
+ kern=""
+ ;;
+ esac
+else
+ $CC -c trycpp.c
+ $LD -o trycpp trycpp.o
+ case `./trycpp` in
+ nextstep)
+ oper="nextstep-`hostinfo | sed -n 's/^[ ]*NeXT Mach \([^:]*\):.*$/\1/p'`"
+ arch="`hostinfo | sed -n 's/^Processor type: \(.*\) (.*)$/\1/p' | tr /: ..`"
+ syst=""
+ chip="`hostinfo | sed -n 's/^Processor type: .* (\(.*\))$/\1/p' | tr ' /:' '...'`"
+ kern=""
+ ;;
+ *)
+ oper="unknown"
+ arch=""
+ syst=""
+ chip=""
+ kern=""
+ ;;
+ esac
+ rm -f trycpp.o trycpp
+fi
+
+case "$chip" in
+80486)
+ # let's try to be consistent here. (BSD/OS)
+ chip=i486
+ ;;
+i486DX)
+ # respect the hyphen hierarchy. (FreeBSD)
+ chip=i486-dx
+ ;;
+i486.DX2)
+ # respect the hyphen hierarchy. (FreeBSD)
+ chip=i486-dx2
+ ;;
+Intel.586)
+ # no, you nitwits, there is no such chip. (NeXTStep)
+ chip=pentium
+ ;;
+i586)
+ # no, you nitwits, there is no such chip. (Linux)
+ chip=pentium
+ ;;
+i686)
+ # STOP SAYING THAT! (Linux)
+ chip=ppro
+esac
+
+if $CC -c x86cpuid.c
+then
+ if $LD -o x86cpuid x86cpuid.o
+ then
+ x86cpuid="`./x86cpuid | tr /: ..`"
+ case "$x86cpuid" in
+ ?*)
+ chip="$x86cpuid"
+ ;;
+ esac
+ fi
+fi
+rm -f x86cpuid x86cpuid.o
+
+echo "$oper-:$arch-:$syst-:$chip-:$kern-" | tr ' [A-Z]' '.[a-z]'
diff --git a/fmt.h b/fmt.h
new file mode 100644
index 0000000..6fd8fef
--- /dev/null
+++ b/fmt.h
@@ -0,0 +1,25 @@
+#ifndef FMT_H
+#define FMT_H
+
+#define FMT_ULONG 40 /* enough space to hold 2^128 - 1 in decimal, plus \0 */
+#define FMT_LEN ((char *) 0) /* convenient abbreviation */
+
+extern unsigned int fmt_uint(char *,unsigned int);
+extern unsigned int fmt_uint0(char *,unsigned int,unsigned int);
+extern unsigned int fmt_xint(char *,unsigned int);
+extern unsigned int fmt_nbbint(char *,unsigned int,unsigned int,unsigned int,unsigned int);
+extern unsigned int fmt_ushort(char *,unsigned short);
+extern unsigned int fmt_xshort(char *,unsigned short);
+extern unsigned int fmt_nbbshort(char *,unsigned int,unsigned int,unsigned int,unsigned short);
+extern unsigned int fmt_ulong(char *,unsigned long);
+extern unsigned int fmt_xlong(char *,unsigned long);
+extern unsigned int fmt_nbblong(char *,unsigned int,unsigned int,unsigned int,unsigned long);
+
+extern unsigned int fmt_plusminus(char *,int);
+extern unsigned int fmt_minus(char *,int);
+extern unsigned int fmt_0x(char *,int);
+
+extern unsigned int fmt_str(char *,char *);
+extern unsigned int fmt_strn(char *,char *,unsigned int);
+
+#endif
diff --git a/fmt_ulong.c b/fmt_ulong.c
new file mode 100644
index 0000000..db48bfd
--- /dev/null
+++ b/fmt_ulong.c
@@ -0,0 +1,13 @@
+#include "fmt.h"
+
+unsigned int fmt_ulong(register char *s,register unsigned long u)
+{
+ register unsigned int len; register unsigned long q;
+ len = 1; q = u;
+ while (q > 9) { ++len; q /= 10; }
+ if (s) {
+ s += len;
+ do { *--s = '0' + (u % 10); u /= 10; } while(u); /* handles u == 0 */
+ }
+ return len;
+}
diff --git a/hier.c b/hier.c
new file mode 100644
index 0000000..f1f7ddd
--- /dev/null
+++ b/hier.c
@@ -0,0 +1,15 @@
+#include "auto_home.h"
+
+void hier()
+{
+ h(auto_home,-1,-1,02755);
+ d(auto_home,"bin",-1,-1,02755);
+
+ c(auto_home,"bin","cdbget",-1,-1,0755);
+ c(auto_home,"bin","cdbmake",-1,-1,0755);
+ c(auto_home,"bin","cdbdump",-1,-1,0755);
+ c(auto_home,"bin","cdbstats",-1,-1,0755);
+ c(auto_home,"bin","cdbtest",-1,-1,0755);
+ c(auto_home,"bin","cdbmake-12",-1,-1,0755);
+ c(auto_home,"bin","cdbmake-sv",-1,-1,0755);
+}
diff --git a/install.c b/install.c
new file mode 100644
index 0000000..605fed3
--- /dev/null
+++ b/install.c
@@ -0,0 +1,149 @@
+#include "buffer.h"
+#include "strerr.h"
+#include "error.h"
+#include "open.h"
+#include "readwrite.h"
+#include "exit.h"
+
+extern void hier();
+
+#define FATAL "install: fatal: "
+
+int fdsourcedir = -1;
+
+void h(home,uid,gid,mode)
+char *home;
+int uid;
+int gid;
+int mode;
+{
+ if (mkdir(home,0700) == -1)
+ if (errno != error_exist)
+ strerr_die4sys(111,FATAL,"unable to mkdir ",home,": ");
+ if (chown(home,uid,gid) == -1)
+ strerr_die4sys(111,FATAL,"unable to chown ",home,": ");
+ if (chmod(home,mode) == -1)
+ strerr_die4sys(111,FATAL,"unable to chmod ",home,": ");
+}
+
+void d(home,subdir,uid,gid,mode)
+char *home;
+char *subdir;
+int uid;
+int gid;
+int mode;
+{
+ if (chdir(home) == -1)
+ strerr_die4sys(111,FATAL,"unable to switch to ",home,": ");
+ if (mkdir(subdir,0700) == -1)
+ if (errno != error_exist)
+ strerr_die6sys(111,FATAL,"unable to mkdir ",home,"/",subdir,": ");
+ if (chown(subdir,uid,gid) == -1)
+ strerr_die6sys(111,FATAL,"unable to chown ",home,"/",subdir,": ");
+ if (chmod(subdir,mode) == -1)
+ strerr_die6sys(111,FATAL,"unable to chmod ",home,"/",subdir,": ");
+}
+
+char inbuf[BUFFER_INSIZE];
+char outbuf[BUFFER_OUTSIZE];
+buffer ssin;
+buffer ssout;
+
+void c(home,subdir,file,uid,gid,mode)
+char *home;
+char *subdir;
+char *file;
+int uid;
+int gid;
+int mode;
+{
+ int fdin;
+ int fdout;
+
+ if (fchdir(fdsourcedir) == -1)
+ strerr_die2sys(111,FATAL,"unable to switch back to source directory: ");
+
+ fdin = open_read(file);
+ if (fdin == -1)
+ strerr_die4sys(111,FATAL,"unable to read ",file,": ");
+ buffer_init(&ssin,read,fdin,inbuf,sizeof inbuf);
+
+ if (chdir(home) == -1)
+ strerr_die4sys(111,FATAL,"unable to switch to ",home,": ");
+ if (chdir(subdir) == -1)
+ strerr_die6sys(111,FATAL,"unable to switch to ",home,"/",subdir,": ");
+
+ fdout = open_trunc(file);
+ if (fdout == -1)
+ strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": ");
+ buffer_init(&ssout,write,fdout,outbuf,sizeof outbuf);
+
+ switch(buffer_copy(&ssout,&ssin)) {
+ case -2:
+ strerr_die4sys(111,FATAL,"unable to read ",file,": ");
+ case -3:
+ strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": ");
+ }
+
+ close(fdin);
+ if (buffer_flush(&ssout) == -1)
+ strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": ");
+ if (fsync(fdout) == -1)
+ strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": ");
+ if (close(fdout) == -1) /* NFS silliness */
+ strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": ");
+
+ if (chown(file,uid,gid) == -1)
+ strerr_die6sys(111,FATAL,"unable to chown .../",subdir,"/",file,": ");
+ if (chmod(file,mode) == -1)
+ strerr_die6sys(111,FATAL,"unable to chmod .../",subdir,"/",file,": ");
+}
+
+void z(home,subdir,file,len,uid,gid,mode)
+char *home;
+char *subdir;
+char *file;
+int len;
+int uid;
+int gid;
+int mode;
+{
+ int fdout;
+
+ if (chdir(home) == -1)
+ strerr_die4sys(111,FATAL,"unable to switch to ",home,": ");
+ if (chdir(subdir) == -1)
+ strerr_die6sys(111,FATAL,"unable to switch to ",home,"/",subdir,": ");
+
+ fdout = open_trunc(file);
+ if (fdout == -1)
+ strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": ");
+ buffer_init(&ssout,write,fdout,outbuf,sizeof outbuf);
+
+ while (len-- > 0)
+ if (buffer_put(&ssout,"",1) == -1)
+ strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": ");
+
+ if (buffer_flush(&ssout) == -1)
+ strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": ");
+ if (fsync(fdout) == -1)
+ strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": ");
+ if (close(fdout) == -1) /* NFS silliness */
+ strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": ");
+
+ if (chown(file,uid,gid) == -1)
+ strerr_die6sys(111,FATAL,"unable to chown .../",subdir,"/",file,": ");
+ if (chmod(file,mode) == -1)
+ strerr_die6sys(111,FATAL,"unable to chmod .../",subdir,"/",file,": ");
+}
+
+main()
+{
+ fdsourcedir = open_read(".");
+ if (fdsourcedir == -1)
+ strerr_die2sys(111,FATAL,"unable to open current directory: ");
+
+ umask(077);
+ hier();
+ _exit(0);
+}
diff --git a/instcheck.c b/instcheck.c
new file mode 100644
index 0000000..c945e67
--- /dev/null
+++ b/instcheck.c
@@ -0,0 +1,108 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "strerr.h"
+#include "error.h"
+#include "readwrite.h"
+#include "exit.h"
+
+extern void hier();
+
+#define FATAL "instcheck: fatal: "
+#define WARNING "instcheck: warning: "
+
+void perm(prefix1,prefix2,prefix3,file,type,uid,gid,mode)
+char *prefix1;
+char *prefix2;
+char *prefix3;
+char *file;
+int type;
+int uid;
+int gid;
+int mode;
+{
+ struct stat st;
+
+ if (stat(file,&st) == -1) {
+ if (errno == error_noent)
+ strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," does not exist",0);
+ else
+ strerr_warn4(WARNING,"unable to stat .../",file,": ",&strerr_sys);
+ return;
+ }
+
+ if ((uid != -1) && (st.st_uid != uid))
+ strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," has wrong owner",0);
+ if ((gid != -1) && (st.st_gid != gid))
+ strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," has wrong group",0);
+ if ((st.st_mode & 07777) != mode)
+ strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," has wrong permissions",0);
+ if ((st.st_mode & S_IFMT) != type)
+ strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," has wrong type",0);
+}
+
+void h(home,uid,gid,mode)
+char *home;
+int uid;
+int gid;
+int mode;
+{
+ perm("","","",home,S_IFDIR,uid,gid,mode);
+}
+
+void d(home,subdir,uid,gid,mode)
+char *home;
+char *subdir;
+int uid;
+int gid;
+int mode;
+{
+ if (chdir(home) == -1)
+ strerr_die4sys(111,FATAL,"unable to switch to ",home,": ");
+ perm("",home,"/",subdir,S_IFDIR,uid,gid,mode);
+}
+
+void p(home,fifo,uid,gid,mode)
+char *home;
+char *fifo;
+int uid;
+int gid;
+int mode;
+{
+ if (chdir(home) == -1)
+ strerr_die4sys(111,FATAL,"unable to switch to ",home,": ");
+ perm("",home,"/",fifo,S_IFIFO,uid,gid,mode);
+}
+
+void c(home,subdir,file,uid,gid,mode)
+char *home;
+char *subdir;
+char *file;
+int uid;
+int gid;
+int mode;
+{
+ if (chdir(home) == -1)
+ strerr_die4sys(111,FATAL,"unable to switch to ",home,": ");
+ if (chdir(subdir) == -1)
+ strerr_die6sys(111,FATAL,"unable to switch to ",home,"/",subdir,": ");
+ perm(".../",subdir,"/",file,S_IFREG,uid,gid,mode);
+}
+
+void z(home,file,len,uid,gid,mode)
+char *home;
+char *file;
+int len;
+int uid;
+int gid;
+int mode;
+{
+ if (chdir(home) == -1)
+ strerr_die4sys(111,FATAL,"unable to switch to ",home,": ");
+ perm("",home,"/",file,S_IFREG,uid,gid,mode);
+}
+
+main()
+{
+ hier();
+ _exit(0);
+}
diff --git a/open.h b/open.h
new file mode 100644
index 0000000..2963fa7
--- /dev/null
+++ b/open.h
@@ -0,0 +1,10 @@
+#ifndef OPEN_H
+#define OPEN_H
+
+extern int open_read(char *);
+extern int open_excl(char *);
+extern int open_append(char *);
+extern int open_trunc(char *);
+extern int open_write(char *);
+
+#endif
diff --git a/open_read.c b/open_read.c
new file mode 100644
index 0000000..7f5ec8b
--- /dev/null
+++ b/open_read.c
@@ -0,0 +1,6 @@
+#include <sys/types.h>
+#include <fcntl.h>
+#include "open.h"
+
+int open_read(char *fn)
+{ return open(fn,O_RDONLY | O_NDELAY); }
diff --git a/open_trunc.c b/open_trunc.c
new file mode 100644
index 0000000..77b99ef
--- /dev/null
+++ b/open_trunc.c
@@ -0,0 +1,6 @@
+#include <sys/types.h>
+#include <fcntl.h>
+#include "open.h"
+
+int open_trunc(char *fn)
+{ return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644); }
diff --git a/random.cdb b/random.cdb
new file mode 100644
index 0000000..81e3e11
--- /dev/null
+++ b/random.cdb
Binary files differ
diff --git a/readwrite.h b/readwrite.h
new file mode 100644
index 0000000..2a64968
--- /dev/null
+++ b/readwrite.h
@@ -0,0 +1,7 @@
+#ifndef READWRITE_H
+#define READWRITE_H
+
+extern int read();
+extern int write();
+
+#endif
diff --git a/rts.exp b/rts.exp
new file mode 100644
index 0000000..835c0b9
--- /dev/null
+++ b/rts.exp
@@ -0,0 +1,251 @@
+--- cdbmake handles simple example
+0
+--- cdbmake-12 handles simple example
+0
+--- cdbmake-sv handles simple example
+0
+--- cdbdump handles simple examples
++3,5:one->Hello
++3,7:two->Goodbye
+
+0
++3,5:one->Hello
++3,7:two->Goodbye
+
+0
++6,4:@7/tcp->echo
++8,1:echo/tcp->7
++6,4:@7/udp->echo
++8,1:echo/udp->7
++6,7:@9/tcp->discard
++11,1:discard/tcp->9
++8,1:sink/tcp->9
++8,1:null/tcp->9
++6,7:@9/udp->discard
++11,1:discard/udp->9
++8,1:sink/udp->9
++8,1:null/udp->9
++7,6:@11/tcp->systat
++10,2:systat/tcp->11
++9,2:users/tcp->11
++7,6:@11/udp->systat
++10,2:systat/udp->11
++9,2:users/udp->11
+
+0
+--- cdbtest handles simple examples
+found: 2
+different record: 0
+bad length: 0
+not found: 0
+untested: 0
+0
+found: 2
+different record: 0
+bad length: 0
+not found: 0
+untested: 0
+0
+found: 18
+different record: 0
+bad length: 0
+not found: 0
+untested: 0
+0
+--- cdbstats handles simple examples
+records 2
+d0 2
+d1 0
+d2 0
+d3 0
+d4 0
+d5 0
+d6 0
+d7 0
+d8 0
+d9 0
+>9 0
+0
+records 2
+d0 2
+d1 0
+d2 0
+d3 0
+d4 0
+d5 0
+d6 0
+d7 0
+d8 0
+d9 0
+>9 0
+0
+records 18
+d0 18
+d1 0
+d2 0
+d3 0
+d4 0
+d5 0
+d6 0
+d7 0
+d8 0
+d9 0
+>9 0
+0
+--- cdbget retrieves data successfully
+Hello
+0
+Goodbye
+0
+echo
+0
+echo
+0
+7
+0
+7
+0
+discard
+0
+discard
+0
+9
+0
+9
+0
+9
+0
+9
+0
+9
+0
+9
+0
+systat
+0
+systat
+0
+11
+0
+11
+0
+11
+0
+11
+0
+--- cdbget exits 100 on nonexistent data
+100
+100
+--- cdbmake handles repeated keys
+0
++3,5:one->Hello
++3,7:one->Goodbye
++3,7:one->Another
+
+0
+--- cdbget handles repeated keys
+Hello
+0
+Hello
+0
+Goodbye
+0
+Another
+0
+
+100
+
+100
+--- cdbmake handles long keys and data
+0
+--- cdbdump handles long keys and data
++320,320:ba483b3442e75cace82def4b5df25bfca887b41687537c21dc4b82cb4c36315e2f6a0661d1af2e05e686c4c595c16561d8c1b3fbee8a6b99c54b3d10d61948445298e97e971f85a600c88164d6b0b09
+b5169a54910232db0a56938de61256721667bddc1c0a2b14f5d063ab586a87a957e87f704acb7246c5e8c25becef713a365efef79bb1f406fecee88f3261f68e239c5903e3145961eb0fbc538ff506a
+->152e113d5deec3638ead782b93e1b9666d265feb5aebc840e79aa69e2cfc1a2ce4b3254b79fa73c338d22a75e67cfed4cd17b92c405e204a48f21c31cdcf7da46312dc80debfbdaf6dc39d74694a711
+6d170c5fde1a81806847cf71732c7f3217a38c6234235951af7b7c1d32e62d480d7c82a63a9d94291d92767ed97dd6a6809d1eb856ce23eda20268cb53fda31c016a19fc20e80aec3bd594a3eb82a5a
+
+
+0
+--- cdbtest handles long keys and data
+found: 1
+different record: 0
+bad length: 0
+not found: 0
+untested: 0
+0
+--- cdbstats handles long keys and data
+records 1
+d0 1
+d1 0
+d2 0
+d3 0
+d4 0
+d5 0
+d6 0
+d7 0
+d8 0
+d9 0
+>9 0
+0
+--- cdbget handles long keys and data
+152e113d5deec3638ead782b93e1b9666d265feb5aebc840e79aa69e2cfc1a2ce4b3254b79fa73c338d22a75e67cfed4cd17b92c405e204a48f21c31cdcf7da46312dc80debfbdaf6dc39d74694a711
+6d170c5fde1a81806847cf71732c7f3217a38c6234235951af7b7c1d32e62d480d7c82a63a9d94291d92767ed97dd6a6809d1eb856ce23eda20268cb53fda31c016a19fc20e80aec3bd594a3eb82a5a
+
+0
+--- cdbmake handles unwritable tmp
+cdbmake: fatal: unable to create loop: symbolic link loop
+111
+--- cdbmake handles unmovable cdb
+cdbmake: fatal: unable to rename test.tmp to loop/test.cdb: symbolic link loop
+111
+--- cdbmake handles nomem
+cdbmake: fatal: unable to create test.tmp: out of memory
+111
+--- cdbmake handles full disk
+cdbmake: fatal: unable to create test.tmp: file too big
+111
+--- cdbmake handles absurd klen
+cdbmake: fatal: unable to create test.tmp: out of memory
+111
+--- cdbget handles empty file
+cdbget: fatal: unable to read input: protocol error
+111
+--- cdbdump and cdbmake handle random.cdb
+0
+--- cdbtest handles random.cdb
+found: 100
+different record: 0
+bad length: 0
+not found: 0
+untested: 0
+0
+--- cdbstats handles random.cdb
+records 100
+d0 96
+d1 4
+d2 0
+d3 0
+d4 0
+d5 0
+d6 0
+d7 0
+d8 0
+d9 0
+>9 0
+0
+--- testzero works
+0
+found: 5
+different record: 0
+bad length: 0
+not found: 0
+untested: 0
+0
+--- testzero can build a database very close to 4GB
+0
+--- testzero complains if hash table passes 4GB
+testzero: fatal: unable to write: out of memory
+111
+--- testzero complains if records pass 4GB
+testzero: fatal: unable to write: out of memory
+111
diff --git a/rts.sh b/rts.sh
new file mode 100644
index 0000000..c71e839
--- /dev/null
+++ b/rts.sh
@@ -0,0 +1 @@
+env - PATH="`pwd`:$PATH" sh rts.tests 2>&1 | cat -v
diff --git a/rts.tests b/rts.tests
new file mode 100644
index 0000000..dae4ff6
--- /dev/null
+++ b/rts.tests
@@ -0,0 +1,210 @@
+# Requirements:
+# You have softlimit in your path.
+# XFSZ is signal 25.
+#
+# Some features not tested here:
+# cdbmake traps 4GB overflows.
+
+
+umask 022
+
+rm -rf rts-tmp
+mkdir rts-tmp
+cd rts-tmp
+
+
+echo '--- cdbmake handles simple example'
+echo '+3,5:one->Hello
++3,7:two->Goodbye
+' | cdbmake test.cdb test.tmp
+echo $?
+
+echo '--- cdbmake-12 handles simple example'
+echo '
+ one Hello
+# comment line
+ two Goodbye
+' | cdbmake-12 12.cdb 12.tmp
+echo $?
+
+echo '--- cdbmake-sv handles simple example'
+echo '
+# Network services, Internet style
+echo 7/tcp
+echo 7/udp
+discard 9/tcp sink null
+discard 9/udp sink null
+systat 11/tcp users #Active Users
+systat 11/udp users #Active Users
+' | cdbmake-sv sv.cdb sv.tmp
+echo $?
+
+echo '--- cdbdump handles simple examples'
+cdbdump < test.cdb
+echo $?
+cdbdump < 12.cdb
+echo $?
+cdbdump < sv.cdb
+echo $?
+
+echo '--- cdbtest handles simple examples'
+cdbtest < test.cdb
+echo $?
+cdbtest < 12.cdb
+echo $?
+cdbtest < sv.cdb
+echo $?
+
+echo '--- cdbstats handles simple examples'
+cdbstats < test.cdb
+echo $?
+cdbstats < 12.cdb
+echo $?
+cdbstats < sv.cdb
+echo $?
+
+echo '--- cdbget retrieves data successfully'
+cdbget one < test.cdb
+echo '
+'$?
+cdbget two < test.cdb
+echo '
+'$?
+for i in @7 echo @9 discard sink null @11 systat users
+do
+ cdbget $i/tcp < sv.cdb
+ echo '
+'$?
+ cdbget $i/udp < sv.cdb
+ echo '
+'$?
+done
+
+echo '--- cdbget exits 100 on nonexistent data'
+cdbget three < test.cdb
+echo $?
+cdbget '#Active' < sv.cdb
+echo $?
+
+
+echo '--- cdbmake handles repeated keys'
+echo '+3,5:one->Hello
++3,7:one->Goodbye
++3,7:one->Another
+' | cdbmake rep.cdb rep.tmp
+echo $?
+cdbdump < rep.cdb
+echo $?
+
+echo '--- cdbget handles repeated keys'
+cdbget one < rep.cdb
+echo '
+'$?
+cdbget one 0 < rep.cdb
+echo '
+'$?
+cdbget one 1 < rep.cdb
+echo '
+'$?
+cdbget one 2 < rep.cdb
+echo '
+'$?
+cdbget one 3 < rep.cdb
+echo '
+'$?
+cdbget one 4 < rep.cdb
+echo '
+'$?
+
+echo '--- cdbmake handles long keys and data'
+echo '+320,320:ba483b3442e75cace82def4b5df25bfca887b41687537c21dc4b82cb4c36315e2f6a0661d1af2e05e686c4c595c16561d8c1b3fbee8a6b99c54b3d10d61948445298e97e971f85a600c88164d6b0b09
+b5169a54910232db0a56938de61256721667bddc1c0a2b14f5d063ab586a87a957e87f704acb7246c5e8c25becef713a365efef79bb1f406fecee88f3261f68e239c5903e3145961eb0fbc538ff506a
+->152e113d5deec3638ead782b93e1b9666d265feb5aebc840e79aa69e2cfc1a2ce4b3254b79fa73c338d22a75e67cfed4cd17b92c405e204a48f21c31cdcf7da46312dc80debfbdaf6dc39d74694a711
+6d170c5fde1a81806847cf71732c7f3217a38c6234235951af7b7c1d32e62d480d7c82a63a9d94291d92767ed97dd6a6809d1eb856ce23eda20268cb53fda31c016a19fc20e80aec3bd594a3eb82a5a
+
+' | cdbmake test.cdb test.tmp
+echo $?
+
+echo '--- cdbdump handles long keys and data'
+cdbdump < test.cdb
+echo $?
+
+echo '--- cdbtest handles long keys and data'
+cdbtest < test.cdb
+echo $?
+
+echo '--- cdbstats handles long keys and data'
+cdbstats < test.cdb
+echo $?
+
+echo '--- cdbget handles long keys and data'
+cdbget 'ba483b3442e75cace82def4b5df25bfca887b41687537c21dc4b82cb4c36315e2f6a0661d1af2e05e686c4c595c16561d8c1b3fbee8a6b99c54b3d10d61948445298e97e971f85a600c88164d6b0b09
+b5169a54910232db0a56938de61256721667bddc1c0a2b14f5d063ab586a87a957e87f704acb7246c5e8c25becef713a365efef79bb1f406fecee88f3261f68e239c5903e3145961eb0fbc538ff506a
+' < test.cdb
+echo '
+'$?
+
+echo '--- cdbmake handles unwritable tmp'
+ln -s loop loop
+echo '' | cdbmake test.cdb loop
+echo $?
+
+echo '--- cdbmake handles unmovable cdb'
+echo '' | cdbmake loop/test.cdb test.tmp
+echo $?
+
+echo '--- cdbmake handles nomem'
+csh -cf 'repeat 5000 echo "+3,5:one->Hello"' \
+| softlimit -d 50000 cdbmake test.cdb test.tmp
+echo $?
+
+echo '--- cdbmake handles full disk'
+(
+ trap '' 25
+ echo '' | softlimit -f 2047 cdbmake test.cdb test.tmp
+ echo $?
+)
+
+echo '--- cdbmake handles absurd klen'
+echo '+4294967210' | cdbmake test.cdb test.tmp
+echo $?
+
+echo '--- cdbget handles empty file'
+cdbget foo </dev/null
+echo $?
+
+
+echo '--- cdbdump and cdbmake handle random.cdb'
+cdbdump < ../random.cdb | cdbmake test.cdb test.tmp
+echo $?
+cmp ../random.cdb test.cdb
+
+echo '--- cdbtest handles random.cdb'
+cdbtest < ../random.cdb
+echo $?
+
+echo '--- cdbstats handles random.cdb'
+cdbstats < ../random.cdb
+echo $?
+
+
+echo '--- testzero works'
+testzero 5 > test.cdb
+echo $?
+cdbtest < test.cdb
+echo $?
+
+echo '--- testzero can build a database very close to 4GB'
+testzero 65507 > /dev/null
+echo $?
+
+echo '--- testzero complains if hash table passes 4GB'
+testzero 65508 > /dev/null
+echo $?
+
+echo '--- testzero complains if records pass 4GB'
+testzero 66000 > /dev/null
+echo $?
+
+
+exit 0
diff --git a/scan.h b/scan.h
new file mode 100644
index 0000000..758138c
--- /dev/null
+++ b/scan.h
@@ -0,0 +1,28 @@
+#ifndef SCAN_H
+#define SCAN_H
+
+extern unsigned int scan_uint(char *,unsigned int *);
+extern unsigned int scan_xint(char *,unsigned int *);
+extern unsigned int scan_nbbint(char *,unsigned int,unsigned int,unsigned int,unsigned int *);
+extern unsigned int scan_ushort(char *,unsigned short *);
+extern unsigned int scan_xshort(char *,unsigned short *);
+extern unsigned int scan_nbbshort(char *,unsigned int,unsigned int,unsigned int,unsigned short *);
+extern unsigned int scan_ulong(char *,unsigned long *);
+extern unsigned int scan_xlong(char *,unsigned long *);
+extern unsigned int scan_nbblong(char *,unsigned int,unsigned int,unsigned int,unsigned long *);
+
+extern unsigned int scan_plusminus(char *,int *);
+extern unsigned int scan_0x(char *,unsigned int *);
+
+extern unsigned int scan_whitenskip(char *,unsigned int);
+extern unsigned int scan_nonwhitenskip(char *,unsigned int);
+extern unsigned int scan_charsetnskip(char *,char *,unsigned int);
+extern unsigned int scan_noncharsetnskip(char *,char *,unsigned int);
+
+extern unsigned int scan_strncmp(char *,char *,unsigned int);
+extern unsigned int scan_memcmp(char *,char *,unsigned int);
+
+extern unsigned int scan_long(char *,long *);
+extern unsigned int scan_8long(char *,unsigned long *);
+
+#endif
diff --git a/scan_ulong.c b/scan_ulong.c
new file mode 100644
index 0000000..c4f03c0
--- /dev/null
+++ b/scan_ulong.c
@@ -0,0 +1,11 @@
+#include "scan.h"
+
+unsigned int scan_ulong(register char *s,register unsigned long *u)
+{
+ register unsigned int pos; register unsigned long result;
+ register unsigned long c;
+ pos = 0; result = 0;
+ while ((c = (unsigned long) (unsigned char) (s[pos] - '0')) < 10)
+ { result = result * 10 + c; ++pos; }
+ *u = result; return pos;
+}
diff --git a/seek.h b/seek.h
new file mode 100644
index 0000000..06aad97
--- /dev/null
+++ b/seek.h
@@ -0,0 +1,15 @@
+#ifndef SEEK_H
+#define SEEK_H
+
+typedef unsigned long seek_pos;
+
+extern seek_pos seek_cur(int);
+
+extern int seek_set(int,seek_pos);
+extern int seek_end(int);
+
+extern int seek_trunc(int,seek_pos);
+
+#define seek_begin(fd) (seek_set((fd),(seek_pos) 0))
+
+#endif
diff --git a/seek_cur.c b/seek_cur.c
new file mode 100644
index 0000000..c2950a1
--- /dev/null
+++ b/seek_cur.c
@@ -0,0 +1,7 @@
+#include <sys/types.h>
+#include "seek.h"
+
+#define CUR 1 /* sigh */
+
+seek_pos seek_cur(int fd)
+{ return lseek(fd,(off_t) 0,CUR); }
diff --git a/seek_set.c b/seek_set.c
new file mode 100644
index 0000000..d08d4f3
--- /dev/null
+++ b/seek_set.c
@@ -0,0 +1,7 @@
+#include <sys/types.h>
+#include "seek.h"
+
+#define SET 0 /* sigh */
+
+int seek_set(int fd,seek_pos pos)
+{ if (lseek(fd,(off_t) pos,SET) == -1) return -1; return 0; }
diff --git a/str.h b/str.h
new file mode 100644
index 0000000..ab4aedd
--- /dev/null
+++ b/str.h
@@ -0,0 +1,14 @@
+#ifndef STR_H
+#define STR_H
+
+extern unsigned int str_copy(char *,char *);
+extern int str_diff(char *,char *);
+extern int str_diffn(char *,char *,unsigned int);
+extern unsigned int str_len(char *);
+extern unsigned int str_chr(char *,int);
+extern unsigned int str_rchr(char *,int);
+extern int str_start(char *,char *);
+
+#define str_equal(s,t) (!str_diff((s),(t)))
+
+#endif
diff --git a/str_len.c b/str_len.c
new file mode 100644
index 0000000..5bd3f62
--- /dev/null
+++ b/str_len.c
@@ -0,0 +1,14 @@
+#include "str.h"
+
+unsigned int str_len(char *s)
+{
+ register char *t;
+
+ t = s;
+ for (;;) {
+ if (!*t) return t - s; ++t;
+ if (!*t) return t - s; ++t;
+ if (!*t) return t - s; ++t;
+ if (!*t) return t - s; ++t;
+ }
+}
diff --git a/strerr.h b/strerr.h
new file mode 100644
index 0000000..702f588
--- /dev/null
+++ b/strerr.h
@@ -0,0 +1,78 @@
+#ifndef STRERR_H
+#define STRERR_H
+
+struct strerr {
+ struct strerr *who;
+ char *x;
+ char *y;
+ char *z;
+} ;
+
+extern struct strerr strerr_sys;
+extern void strerr_sysinit(void);
+
+extern char *strerr(struct strerr *);
+extern void strerr_warn(char *,char *,char *,char *,char *,char *,struct strerr *);
+extern void strerr_die(int,char *,char *,char *,char *,char *,char *,struct strerr *);
+
+#define STRERR(r,se,a) \
+{ se.who = 0; se.x = a; se.y = 0; se.z = 0; return r; }
+
+#define STRERR_SYS(r,se,a) \
+{ se.who = &strerr_sys; se.x = a; se.y = 0; se.z = 0; return r; }
+#define STRERR_SYS3(r,se,a,b,c) \
+{ se.who = &strerr_sys; se.x = a; se.y = b; se.z = c; return r; }
+
+#define strerr_warn6(x1,x2,x3,x4,x5,x6,se) \
+strerr_warn((x1),(x2),(x3),(x4),(x5),(x6),(se))
+#define strerr_warn5(x1,x2,x3,x4,x5,se) \
+strerr_warn((x1),(x2),(x3),(x4),(x5),0,(se))
+#define strerr_warn4(x1,x2,x3,x4,se) \
+strerr_warn((x1),(x2),(x3),(x4),0,0,(se))
+#define strerr_warn3(x1,x2,x3,se) \
+strerr_warn((x1),(x2),(x3),0,0,0,(se))
+#define strerr_warn2(x1,x2,se) \
+strerr_warn((x1),(x2),0,0,0,0,(se))
+#define strerr_warn1(x1,se) \
+strerr_warn((x1),0,0,0,0,0,(se))
+
+#define strerr_die6(e,x1,x2,x3,x4,x5,x6,se) \
+strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),(se))
+#define strerr_die5(e,x1,x2,x3,x4,x5,se) \
+strerr_die((e),(x1),(x2),(x3),(x4),(x5),0,(se))
+#define strerr_die4(e,x1,x2,x3,x4,se) \
+strerr_die((e),(x1),(x2),(x3),(x4),0,0,(se))
+#define strerr_die3(e,x1,x2,x3,se) \
+strerr_die((e),(x1),(x2),(x3),0,0,0,(se))
+#define strerr_die2(e,x1,x2,se) \
+strerr_die((e),(x1),(x2),0,0,0,0,(se))
+#define strerr_die1(e,x1,se) \
+strerr_die((e),(x1),0,0,0,0,0,(se))
+
+#define strerr_die6sys(e,x1,x2,x3,x4,x5,x6) \
+strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),&strerr_sys)
+#define strerr_die5sys(e,x1,x2,x3,x4,x5) \
+strerr_die((e),(x1),(x2),(x3),(x4),(x5),0,&strerr_sys)
+#define strerr_die4sys(e,x1,x2,x3,x4) \
+strerr_die((e),(x1),(x2),(x3),(x4),0,0,&strerr_sys)
+#define strerr_die3sys(e,x1,x2,x3) \
+strerr_die((e),(x1),(x2),(x3),0,0,0,&strerr_sys)
+#define strerr_die2sys(e,x1,x2) \
+strerr_die((e),(x1),(x2),0,0,0,0,&strerr_sys)
+#define strerr_die1sys(e,x1) \
+strerr_die((e),(x1),0,0,0,0,0,&strerr_sys)
+
+#define strerr_die6x(e,x1,x2,x3,x4,x5,x6) \
+strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),0)
+#define strerr_die5x(e,x1,x2,x3,x4,x5) \
+strerr_die((e),(x1),(x2),(x3),(x4),(x5),0,0)
+#define strerr_die4x(e,x1,x2,x3,x4) \
+strerr_die((e),(x1),(x2),(x3),(x4),0,0,0)
+#define strerr_die3x(e,x1,x2,x3) \
+strerr_die((e),(x1),(x2),(x3),0,0,0,0)
+#define strerr_die2x(e,x1,x2) \
+strerr_die((e),(x1),(x2),0,0,0,0,0)
+#define strerr_die1x(e,x1) \
+strerr_die((e),(x1),0,0,0,0,0,0)
+
+#endif
diff --git a/strerr_die.c b/strerr_die.c
new file mode 100644
index 0000000..850028b
--- /dev/null
+++ b/strerr_die.c
@@ -0,0 +1,31 @@
+#include "buffer.h"
+#include "exit.h"
+#include "strerr.h"
+
+void strerr_warn(char *x1,char *x2,char *x3,char *x4,char *x5,char *x6,struct strerr *se)
+{
+ strerr_sysinit();
+
+ if (x1) buffer_puts(buffer_2,x1);
+ if (x2) buffer_puts(buffer_2,x2);
+ if (x3) buffer_puts(buffer_2,x3);
+ if (x4) buffer_puts(buffer_2,x4);
+ if (x5) buffer_puts(buffer_2,x5);
+ if (x6) buffer_puts(buffer_2,x6);
+
+ while(se) {
+ if (se->x) buffer_puts(buffer_2,se->x);
+ if (se->y) buffer_puts(buffer_2,se->y);
+ if (se->z) buffer_puts(buffer_2,se->z);
+ se = se->who;
+ }
+
+ buffer_puts(buffer_2,"\n");
+ buffer_flush(buffer_2);
+}
+
+void strerr_die(int e,char *x1,char *x2,char *x3,char *x4,char *x5,char *x6,struct strerr *se)
+{
+ strerr_warn(x1,x2,x3,x4,x5,x6,se);
+ _exit(e);
+}
diff --git a/strerr_sys.c b/strerr_sys.c
new file mode 100644
index 0000000..b484197
--- /dev/null
+++ b/strerr_sys.c
@@ -0,0 +1,12 @@
+#include "error.h"
+#include "strerr.h"
+
+struct strerr strerr_sys;
+
+void strerr_sysinit(void)
+{
+ strerr_sys.who = 0;
+ strerr_sys.x = error_str(errno);
+ strerr_sys.y = "";
+ strerr_sys.z = "";
+}
diff --git a/testzero.c b/testzero.c
new file mode 100644
index 0000000..ba07865
--- /dev/null
+++ b/testzero.c
@@ -0,0 +1,35 @@
+#include "uint32.h"
+#include "scan.h"
+#include "strerr.h"
+#include "cdb_make.h"
+
+#define FATAL "testzero: fatal: "
+
+void die_write(void)
+{
+ strerr_die2sys(111,FATAL,"unable to write: ");
+}
+
+static char key[4];
+static char data[65536];
+struct cdb_make c;
+
+main(int argc,char **argv)
+{
+ int fd;
+ unsigned long loop;
+
+ if (!*argv) _exit(0);
+ if (!*++argv) _exit(0);
+ scan_ulong(*argv,&loop);
+
+ if (cdb_make_start(&c,1) == -1) die_write();
+
+ while (loop) {
+ uint32_pack(key,--loop);
+ if (cdb_make_add(&c,key,4,data,sizeof data) == -1) die_write();
+ }
+
+ if (cdb_make_finish(&c) == -1) die_write();
+ _exit(0);
+}
diff --git a/trycpp.c b/trycpp.c
new file mode 100644
index 0000000..3ab455b
--- /dev/null
+++ b/trycpp.c
@@ -0,0 +1,7 @@
+main()
+{
+#ifdef NeXT
+ printf("nextstep\n"); exit(0);
+#endif
+ printf("unknown\n"); exit(0);
+}
diff --git a/tryulong32.c b/tryulong32.c
new file mode 100644
index 0000000..a108076
--- /dev/null
+++ b/tryulong32.c
@@ -0,0 +1,11 @@
+void main()
+{
+ unsigned long u;
+ u = 1;
+ u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u;
+ u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u;
+ u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u;
+ u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u;
+ if (!u) _exit(0);
+ _exit(1);
+}
diff --git a/uint32.h1 b/uint32.h1
new file mode 100644
index 0000000..68d7231
--- /dev/null
+++ b/uint32.h1
@@ -0,0 +1,11 @@
+#ifndef UINT32_H
+#define UINT32_H
+
+typedef unsigned int uint32;
+
+extern void uint32_pack(char *,uint32);
+extern void uint32_pack_big(char *,uint32);
+extern void uint32_unpack(char *,uint32 *);
+extern void uint32_unpack_big(char *,uint32 *);
+
+#endif
diff --git a/uint32.h2 b/uint32.h2
new file mode 100644
index 0000000..b5c7f40
--- /dev/null
+++ b/uint32.h2
@@ -0,0 +1,11 @@
+#ifndef UINT32_H
+#define UINT32_H
+
+typedef unsigned long uint32;
+
+extern void uint32_pack(char *,uint32);
+extern void uint32_pack_big(char *,uint32);
+extern void uint32_unpack(char *,uint32 *);
+extern void uint32_unpack_big(char *,uint32 *);
+
+#endif
diff --git a/uint32_pack.c b/uint32_pack.c
new file mode 100644
index 0000000..76bc670
--- /dev/null
+++ b/uint32_pack.c
@@ -0,0 +1,21 @@
+#include "uint32.h"
+
+void uint32_pack(char s[4],uint32 u)
+{
+ s[0] = u & 255;
+ u >>= 8;
+ s[1] = u & 255;
+ u >>= 8;
+ s[2] = u & 255;
+ s[3] = u >> 8;
+}
+
+void uint32_pack_big(char s[4],uint32 u)
+{
+ s[3] = u & 255;
+ u >>= 8;
+ s[2] = u & 255;
+ u >>= 8;
+ s[1] = u & 255;
+ s[0] = u >> 8;
+}
diff --git a/uint32_unpack.c b/uint32_unpack.c
new file mode 100644
index 0000000..f484644
--- /dev/null
+++ b/uint32_unpack.c
@@ -0,0 +1,31 @@
+#include "uint32.h"
+
+void uint32_unpack(char s[4],uint32 *u)
+{
+ uint32 result;
+
+ result = (unsigned char) s[3];
+ result <<= 8;
+ result += (unsigned char) s[2];
+ result <<= 8;
+ result += (unsigned char) s[1];
+ result <<= 8;
+ result += (unsigned char) s[0];
+
+ *u = result;
+}
+
+void uint32_unpack_big(char s[4],uint32 *u)
+{
+ uint32 result;
+
+ result = (unsigned char) s[0];
+ result <<= 8;
+ result += (unsigned char) s[1];
+ result <<= 8;
+ result += (unsigned char) s[2];
+ result <<= 8;
+ result += (unsigned char) s[3];
+
+ *u = result;
+}
diff --git a/warn-auto.sh b/warn-auto.sh
new file mode 100644
index 0000000..36d2313
--- /dev/null
+++ b/warn-auto.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+# WARNING: This file was auto-generated. Do not edit!
diff --git a/x86cpuid.c b/x86cpuid.c
new file mode 100644
index 0000000..900d7d5
--- /dev/null
+++ b/x86cpuid.c
@@ -0,0 +1,38 @@
+#include <signal.h>
+
+void nope()
+{
+ exit(1);
+}
+
+main()
+{
+ unsigned long x[4];
+ unsigned long y[4];
+ int i;
+ int j;
+ char c;
+
+ signal(SIGILL,nope);
+
+ x[0] = 0;
+ x[1] = 0;
+ x[2] = 0;
+ x[3] = 0;
+
+ asm volatile(".byte 15;.byte 162" : "=a"(x[0]),"=b"(x[1]),"=c"(x[3]),"=d"(x[2]) : "0"(0) );
+ if (!x[0]) return 0;
+ asm volatile(".byte 15;.byte 162" : "=a"(y[0]),"=b"(y[1]),"=c"(y[2]),"=d"(y[3]) : "0"(1) );
+
+ for (i = 1;i < 4;++i)
+ for (j = 0;j < 4;++j) {
+ c = x[i] >> (8 * j);
+ if (c < 32) c = 32;
+ if (c > 126) c = 126;
+ putchar(c);
+ }
+
+ printf("-%08x-%08x\n",y[0],y[3]);
+
+ return 0;
+}