diff -rNU3 src.orig/Makefile src/Makefile
--- src.orig/Makefile	Thu Oct 18 22:39:19 2001
+++ src/Makefile	Sat Nov 10 14:29:42 2001
@@ -4,8 +4,54 @@
 	rm -f accuracy accuracy.o choose compile floatasm.h hasgethr.h \
 	hasmftb.h hasrdtick.h hasrdtsc.h hasrpcc.h it load main.o makelib \
 	myrandom.o nistp224 nistp224-56 nistp224-56.o nistp224.a nistp224.c \
+	buffer.o buffer_0.o buffer_1.o buffer_2.o buffer_get.o buffer_put.o \
+	buffer_read.o buffer_write.o byte_copy.o byte_cr.o error.o str_len.o \
+	buffer.a \
 	nistp224.h nistp224.o rts speed speed.o sysdeps systype
 
+buffer.o: buffer.c buffer.h compile
+	./compile buffer.c
+
+buffer_0.o: buffer.h buffer_0.c compile
+	./compile buffer_0.c
+
+buffer_1.o: buffer.h buffer_1.c compile
+	./compile buffer_1.c
+
+buffer_2.o: buffer.h buffer_2.c compile
+	./compile buffer_2.c
+
+buffer_get.o: buffer.h buffer_get.c byte.h compile error.h
+	./compile buffer_get.c
+
+buffer_put.o: buffer.h buffer_put.c byte.h compile error.h str.h
+	./compile buffer_put.c
+
+buffer_read.o: buffer.h buffer_read.c compile
+	./compile buffer_read.c
+
+buffer_write.o: buffer.h buffer_write.c compile
+	./compile buffer_write.c
+
+byte_copy.o: byte.h byte_copy.c compile
+	./compile byte_copy.c
+
+byte_cr.o: byte.h byte_cr.c compile
+	./compile byte_cr.c
+
+error.o: error.h compile
+	./compile error.c
+
+str_len.o: compile str.h str_len.c
+	./compile str_len.c
+
+buffer.a: makelib buffer.o buffer_0.o buffer_1.o buffer_2.o buffer_get.o \
+buffer_put.o buffer_read.o buffer_write.o byte_copy.o byte_cr.o error.o \
+str_len.o
+	./makelib buffer.a buffer.o buffer_0.o buffer_1.o buffer_2.o \
+	buffer_get.o buffer_put.o buffer_read.o buffer_write.o \
+	byte_copy.o byte_cr.o error.o str_len.o
+
 accuracy: accuracy.o load myrandom.o nistp224.a
 	./load accuracy myrandom.o nistp224.a 
 
@@ -50,7 +96,7 @@
 	sh print-ld.sh > load
 	chmod 555 load
 
-main.o: compile main.c nistp224.h
+main.o: compile main.c nistp224.h buffer.h
 	./compile main.c
 
 makelib: print-ar.sh systype warn-auto.sh
@@ -61,13 +107,13 @@
 myrandom.o: compile myrandom.c myrandom.h
 	./compile myrandom.c
 
-nistp224: load main.o nistp224.o
-	./load nistp224 main.o 
+nistp224: load main.o nistp224.o buffer.a
+	./load nistp224 main.o buffer.a
 
-nistp224-56: load nistp224-56.o nistp224.o
-	./load nistp224-56 nistp224.o 
+nistp224-56: load nistp224-56.o nistp224.o buffer.a
+	./load nistp224-56 nistp224.o buffer.a
 
-nistp224-56.o: compile nistp224-56.c nistp224.h
+nistp224-56.o: compile nistp224-56.c nistp224.h buffer.h
 	./compile nistp224-56.c
 
 nistp224.a: makelib nistp224.o
diff -rNU3 src.orig/buffer.c src/buffer.c
--- src.orig/buffer.c	Thu Jan  1 01:00:00 1970
+++ src/buffer.c	Sat Nov 10 14:21:24 2001
@@ -0,0 +1,12 @@
+/* Public domain. */
+
+#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 -rNU3 src.orig/buffer.h src/buffer.h
--- src.orig/buffer.h	Thu Jan  1 01:00:00 1970
+++ src/buffer.h	Sat Nov 10 14:21:24 2001
@@ -0,0 +1,61 @@
+/* Public domain. */
+
+#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 *,const char *,unsigned int);
+extern int buffer_putalign(buffer *,const char *,unsigned int);
+extern int buffer_putflush(buffer *,const char *,unsigned int);
+extern int buffer_puts(buffer *,const char *);
+extern int buffer_putsalign(buffer *,const char *);
+extern int buffer_putsflush(buffer *,const 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 int buffer_unixread(int,char *,unsigned int);
+extern int buffer_unixwrite(int,const char *,unsigned int);
+
+extern buffer *buffer_0;
+extern buffer *buffer_0small;
+extern buffer *buffer_1;
+extern buffer *buffer_1small;
+extern buffer *buffer_2;
+
+#endif
diff -rNU3 src.orig/buffer_0.c src/buffer_0.c
--- src.orig/buffer_0.c	Thu Jan  1 01:00:00 1970
+++ src/buffer_0.c	Sat Nov 10 14:21:24 2001
@@ -0,0 +1,13 @@
+/* Public domain. */
+
+#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 buffer_unixread(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 -rNU3 src.orig/buffer_1.c src/buffer_1.c
--- src.orig/buffer_1.c	Thu Jan  1 01:00:00 1970
+++ src/buffer_1.c	Sat Nov 10 14:21:24 2001
@@ -0,0 +1,7 @@
+/* Public domain. */
+
+#include "buffer.h"
+
+char buffer_1_space[BUFFER_OUTSIZE];
+static buffer it = BUFFER_INIT(buffer_unixwrite,1,buffer_1_space,sizeof buffer_1_space);
+buffer *buffer_1 = &it;
diff -rNU3 src.orig/buffer_2.c src/buffer_2.c
--- src.orig/buffer_2.c	Thu Jan  1 01:00:00 1970
+++ src/buffer_2.c	Sat Nov 10 14:21:24 2001
@@ -0,0 +1,7 @@
+/* Public domain. */
+
+#include "buffer.h"
+
+char buffer_2_space[256];
+static buffer it = BUFFER_INIT(buffer_unixwrite,2,buffer_2_space,sizeof buffer_2_space);
+buffer *buffer_2 = &it;
diff -rNU3 src.orig/buffer_get.c src/buffer_get.c
--- src.orig/buffer_get.c	Thu Jan  1 01:00:00 1970
+++ src/buffer_get.c	Sat Nov 10 14:21:24 2001
@@ -0,0 +1,69 @@
+/* Public domain. */
+
+#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 -rNU3 src.orig/buffer_put.c src/buffer_put.c
--- src.orig/buffer_put.c	Thu Jan  1 01:00:00 1970
+++ src/buffer_put.c	Sat Nov 10 14:21:24 2001
@@ -0,0 +1,90 @@
+/* Public domain. */
+
+#include "buffer.h"
+#include "str.h"
+#include "byte.h"
+#include "error.h"
+
+static int allwrite(int (*op)(),int fd,const 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,const 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,const 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,const 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,const char *buf)
+{
+  return buffer_putalign(s,buf,str_len(buf));
+}
+
+int buffer_puts(buffer *s,const char *buf)
+{
+  return buffer_put(s,buf,str_len(buf));
+}
+
+int buffer_putsflush(buffer *s,const char *buf)
+{
+  return buffer_putflush(s,buf,str_len(buf));
+}
diff -rNU3 src.orig/buffer_read.c src/buffer_read.c
--- src.orig/buffer_read.c	Thu Jan  1 01:00:00 1970
+++ src/buffer_read.c	Sat Nov 10 14:21:24 2001
@@ -0,0 +1,9 @@
+/* Public domain. */
+
+#include <unistd.h>
+#include "buffer.h"
+
+int buffer_unixread(int fd,char *buf,unsigned int len)
+{
+  return read(fd,buf,len);
+}
diff -rNU3 src.orig/buffer_write.c src/buffer_write.c
--- src.orig/buffer_write.c	Thu Jan  1 01:00:00 1970
+++ src/buffer_write.c	Sat Nov 10 14:21:24 2001
@@ -0,0 +1,9 @@
+/* Public domain. */
+
+#include <unistd.h>
+#include "buffer.h"
+
+int buffer_unixwrite(int fd,const char *buf,unsigned int len)
+{
+  return write(fd,buf,len);
+}
diff -rNU3 src.orig/byte.h src/byte.h
--- src.orig/byte.h	Thu Jan  1 01:00:00 1970
+++ src/byte.h	Sat Nov 10 14:37:58 2001
@@ -0,0 +1,15 @@
+/* Public domain. */
+
+#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 -rNU3 src.orig/byte_copy.c src/byte_copy.c
--- src.orig/byte_copy.c	Thu Jan  1 01:00:00 1970
+++ src/byte_copy.c	Sat Nov 10 14:21:46 2001
@@ -0,0 +1,16 @@
+/* Public domain. */
+
+#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 -rNU3 src.orig/byte_cr.c src/byte_cr.c
--- src.orig/byte_cr.c	Thu Jan  1 01:00:00 1970
+++ src/byte_cr.c	Sat Nov 10 14:21:52 2001
@@ -0,0 +1,18 @@
+/* Public domain. */
+
+#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 -rNU3 src.orig/error.c src/error.c
--- src.orig/error.c	Thu Jan  1 01:00:00 1970
+++ src/error.c	Sat Nov 10 14:22:02 2001
@@ -0,0 +1,132 @@
+/* Public domain. */
+
+#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
+
+int error_isdir =
+#ifdef EISDIR
+EISDIR;
+#else
+-16;
+#endif
+
+int error_connrefused =
+#ifdef ECONNREFUSED
+ECONNREFUSED;
+#else
+-17;
+#endif
+
+int error_notdir =
+#ifdef ENOTDIR
+ENOTDIR;
+#else
+-18;
+#endif
diff -rNU3 src.orig/error.h src/error.h
--- src.orig/error.h	Thu Jan  1 01:00:00 1970
+++ src/error.h	Sat Nov 10 14:22:15 2001
@@ -0,0 +1,30 @@
+/* Public domain. */
+
+#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 int error_isdir;
+extern int error_connrefused;
+extern int error_notdir;
+
+extern const char *error_str(int);
+extern int error_temp(int);
+
+#endif
diff -rNU3 src.orig/main.c src/main.c
--- src.orig/main.c	Thu Oct 18 22:39:19 2001
+++ src/main.c	Sat Nov 10 14:34:13 2001
@@ -1,4 +1,5 @@
-#include <stdio.h>
+#include <stdlib.h>
+#include "buffer.h"
 #include "nistp224.h"
 
 unsigned char e[28];
@@ -7,14 +8,11 @@
 
 int main(void)
 {
-  int i;
-
-  for (i = 0;i < 28;++i) if (scanf("%c",e + i) < 1) exit(111);
-  for (i = 0;i < 28;++i) if (scanf("%c",x + i) < 1) exit(111);
+  if (buffer_get(buffer_0,e,28) < 28) exit(111);
+  if (buffer_get(buffer_0,x,28) < 28) exit(111);
 
   if (!nistp224(xe,x,e)) exit(100);
 
-  for (i = 0;i < 28;++i) if (putchar(xe[i]) == EOF) exit(111);
-  if (fflush(stdout) == EOF) exit(111);
+  if (buffer_putflush(buffer_1,xe,28) == -1) exit(111);
   exit(0);
 }
diff -rNU3 src.orig/nistp224-56.c src/nistp224-56.c
--- src.orig/nistp224-56.c	Thu Oct 18 22:39:19 2001
+++ src/nistp224-56.c	Sat Nov 10 14:38:37 2001
@@ -1,4 +1,5 @@
-#include <stdio.h>
+#include <stdlib.h>
+#include "buffer.h"
 #include "nistp224.h"
 
 unsigned char e[28];
@@ -7,14 +8,11 @@
 
 int main(void)
 {
-  int i;
-
-  for (i = 0;i < 28;++i) if (scanf("%c",e + i) < 1) exit(111);
-  for (i = 0;i < 56;++i) if (scanf("%c",xy + i) < 1) exit(111);
+  if (buffer_get(buffer_0,e,28) < 28) exit(111);
+  if (buffer_get(buffer_0,xy,56) < 56) exit(111);
 
   if (!nistp224_56(xye,xy,e)) exit(100);
 
-  for (i = 0;i < 56;++i) if (putchar(xye[i]) == EOF) exit(111);
-  if (fflush(stdout) == EOF) exit(111);
+  if (buffer_putflush(buffer_1,xye,56) == -1) exit(111);
   exit(0);
 }
diff -rNU3 src.orig/str.h src/str.h
--- src.orig/str.h	Thu Jan  1 01:00:00 1970
+++ src/str.h	Sat Nov 10 14:22:11 2001
@@ -0,0 +1,16 @@
+/* Public domain. */
+
+#ifndef STR_H
+#define STR_H
+
+extern unsigned int str_copy(char *,const char *);
+extern int str_diff(const char *,const char *);
+extern int str_diffn(const char *,const char *,unsigned int);
+extern unsigned int str_len(const char *);
+extern unsigned int str_chr(const char *,int);
+extern unsigned int str_rchr(const char *,int);
+extern int str_start(const char *,const char *);
+
+#define str_equal(s,t) (!str_diff((s),(t)))
+
+#endif
diff -rNU3 src.orig/str_len.c src/str_len.c
--- src.orig/str_len.c	Thu Jan  1 01:00:00 1970
+++ src/str_len.c	Sat Nov 10 14:22:08 2001
@@ -0,0 +1,16 @@
+/* Public domain. */
+
+#include "str.h"
+
+unsigned int str_len(const char *s)
+{
+  register const 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;
+  }
+}

