v23i099: ABC interactive programming environment, Part20/25

Rich Salz rsalz at bbn.com
Thu Dec 20 04:55:00 AEST 1990


Submitted-by: Steven Pemberton <steven at cwi.nl>
Posting-number: Volume 23, Issue 99
Archive-name: abc/part20

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then feed it
# into a shell via "sh file" or similar.  To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix at uunet.uu.net if you want that tool.
# Contents:  abc/bed/e1erro.c abc/bed/e1eval.c abc/bed/e1line.c
#   abc/bint1/i1nur.c abc/bint3/i3fil.c abc/bio/i4fil.c
#   abc/boot/Makefile abc/ihdrs/i1num.h abc/keys/keyhlp.c
#   abc/stc/i2tcu.c abc/unix/u1file.c
# Wrapped by rsalz at litchi.bbn.com on Mon Dec 17 13:28:18 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo If this archive is complete, you will see the following message:
echo '          "shar: End of archive 20 (of 25)."'
if test -f 'abc/bed/e1erro.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'abc/bed/e1erro.c'\"
else
  echo shar: Extracting \"'abc/bed/e1erro.c'\" \(4638 characters\)
  sed "s/^X//" >'abc/bed/e1erro.c' <<'END_OF_FILE'
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1986. */
X
X/*
X * B editor -- Handle error messages.
X */
X
X#include "b.h"
X#include "bedi.h"
X#include "feat.h"
X#include "bmem.h"
X#include "bobj.h"
X#include "erro.h"
X#include "node.h"
X
Xextern bool hushbaby;
X
Xstring querepr();
X
Xextern int winheight; /* From scrn.c */
Xextern int winstart; /* From scrn.c */
Xextern int llength; /* From scrn.c */
X
X#define SOBIT 0200 /* Interface with wind.c */
X
X#define MAXMSG 1000
X#define MAXBUF 50
Xstatic char *msgbuffer;
Xstatic bool ringbell;
Xstatic int priority;
X
X#define M_RECORDING	MESS(6400, "Recording")
X#define M_COPYBUF	MESS(6401, "Copy buffer")
X
Xstatic char *mrecbuf;
Xstatic char *mcopybuf;
X
X/*
X * Status line.  A combination of scroll bar, error message etc.
X * Put the message on the screen and clear the buffers for next time.
X * If there is no message, show status and copy buffer and recording mode.
X */
X
XVisible Procedure
Xstsline(totlines, topline, scrlines, copybuffer, recording)
X	int totlines;
X	int topline;
X	int scrlines;
X	value copybuffer;
X	bool recording;
X{
X	register string bp;
X
X	if (ringbell && !hushbaby)
X		trmbell();
X	if (msgbuffer[0]) {
X		msgbuffer[llength-1] = '\0'; /* Truncate */
X		if (ringbell) {
X			for (bp = msgbuffer; *bp; ++bp)
X				*bp |= SOBIT;
X		}
X	}
X	else {
X		bp = msgbuffer;
X#ifdef SCROLLBAR
X		bp += addscrollbar(totlines, topline, scrlines);
X#endif /* SCROLLBAR */
X		if (recording) {
X			if (!mrecbuf[0])
X				strcpy(mrecbuf, getmess(M_RECORDING));
X			sprintf(bp, "[%s] ", mrecbuf);
X			while (*bp)
X				++bp;
X		}
X		if (copybuffer) {
X			if (!mcopybuf[0])
X				strcpy(mcopybuf, getmess(M_COPYBUF));
X#ifdef SHOWBUF
X			sprintf(bp, "[%s: %.80s]", mcopybuf, querepr(copybuffer));
X			while (*bp)
X				++bp;
X			if (bp >= msgbuffer+80)
X				strcpy(msgbuffer+75, "...]");
X#else /* !SHOWBUF */
X			sprintf(bp, "[%s]", mcopybuf);
X#endif /* !SHOWBUF */
X		}
X	}
X	trmputdata(winheight, winheight, 0, msgbuffer);
X	msgbuffer[0] = '\0';
X	priority = 0;
X	ringbell = No;
X}
X
X#ifdef SCROLLBAR
X
X/*
X * Paint a beautiful scroll bar so the user can see about what part of the
X * unit is visible on the screen (considering logical lines).
X */
X
XHidden int
Xaddscrollbar(totlines, topline, scrlines)
X	int totlines;
X	int topline;
X	int scrlines;
X{
X	int endline;
X	register int i;
X
X	if (winstart > 0 || scrlines > totlines)
X		return 0; /* Nothing outside screen */
X	if (totlines <= 0)
X		totlines = 1; /* Don't want to divide by 0 */
X	topline = topline*winheight / totlines;
X	endline = topline + (scrlines*winheight + totlines-1) / totlines;
X	if (endline > winheight)
X		endline = winheight;
X	if (topline >= endline)
X		topline = endline-1;
X	for (i = 0; i < topline; ++i)
X		msgbuffer[i] = '-';
X	for (; i < endline; ++i)
X		msgbuffer[i] = '#';
X	for (; i < winheight; ++i)
X		msgbuffer[i] = '-';
X	msgbuffer[i++] = ' ';
X	msgbuffer[i] = '\0';
X	return i;
X}
X
X#endif /* SCROLLBAR */
X
X/*
X * Issue an error message.  These have highest priority.
X * Once an error message is in the buffer, further error messages are ignored
X * until it has been displayed.
X */
X
XHidden Procedure
Xederr1(s)
X	string s;
X{
X	ringbell = Yes;
X	if (s && priority < 3) {
X		priority = 3;
X		strcpy(msgbuffer, s);
X	}
X}
X
XVisible Procedure
Xederr(m)
X	int m;
X{
X	if (m == 0) ringbell= Yes;
X	else ederr1(getmess(m));
X}
X
XVisible Procedure
XederrS(m, s)
X	int m;
X	string s;
X{
X	sprintf(messbuf, getmess(m), s);
X	ederr1(messbuf);	
X}
X
XVisible Procedure
XederrC(m, c)
X	int m;
X	char c;
X{
X	sprintf(messbuf, getmess(m), c);
X	ederr1(messbuf);
X}
X
X/*
X * Issue an informative message.  These have medium priority.
X * Unlike error messages, the last such message is displayed.
X */
X
XVisible Procedure
Xedmessage(s)
X	string s;
X{
X	if (s && priority <= 2) {
X		priority = 2;
X		strcpy(msgbuffer, s);
X	}
X}
X
X
X/*
X * Issue a debugging message.  These  have lowest priority and
X * are not shown to ordinary users.
X */
X
X#ifndef NDEBUG
X
X/* VARARGS 1 */
XVisible Procedure
Xdebug(fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
X	string fmt;
X{
X	if (fmt && priority <= 1) {
X		priority = 1;
X		sprintf(msgbuffer,
X			fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
X	}
X}
X
X#endif /* NDEBUG */
X
X/*
X * Dump any error message still remaining to console or stderr.
X */
X
XVisible Procedure
Xenderro()
X{
X	if (!msgbuffer)
X		return;
X	if (msgbuffer[0])
X		putSstr(errfile, "%s\n", msgbuffer);
X	msgbuffer[0] = '\0';
X	priority = 0;
X	ringbell = No;
X}
X
XVisible Procedure init_erro() {
X	msgbuffer= (char*) getmem(MAXMSG);
X	msgbuffer[0]= '\0';
X	mrecbuf= (char*) getmem(MAXBUF);
X	mrecbuf[0]= '\0';
X	mcopybuf= (char*) getmem(MAXBUF);
X	mcopybuf[0]= '\0';
X}
X
XVisible Procedure end_erro() {
X	freemem((ptr) msgbuffer);
X	freemem((ptr) mrecbuf);
X	freemem((ptr) mcopybuf);
X}
END_OF_FILE
  if test 4638 -ne `wc -c <'abc/bed/e1erro.c'`; then
    echo shar: \"'abc/bed/e1erro.c'\" unpacked with wrong size!
  fi
  # end of 'abc/bed/e1erro.c'
fi
if test -f 'abc/bed/e1eval.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'abc/bed/e1eval.c'\"
else
  echo shar: Extracting \"'abc/bed/e1eval.c'\" \(4245 characters\)
  sed "s/^X//" >'abc/bed/e1eval.c' <<'END_OF_FILE'
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1986. */
X
X/*
X * B editor -- Width attribute evaluation.
X */
X
X#include "b.h"
X#include "b0lan.h"
X#include "bedi.h"
X#include "etex.h"
X#include "node.h"
X#include "gram.h"
X
X
X/*
X * The following convention is used throughout the editor to indicate
X * the sizes of objects.
X * - A zero or positive `width' value means the object contains no
X *   linefeeds.  The width is counted in characters.
X * - A negative `width' means the object (or its children) contains
X *   at leasty one linefeed (return is treated as a linefeed here).
X *   The number of linefeeds is -width.
X *   There is no indication whether the object fits on that number of
X *   physical lines, as logical lines may have arbitrary length.
X *
X * For coordinates the following convention is used.
X * (Note that, in accordance to the convention in curses(3), the
X * `y' coordinate always precedes the `x' coorxdinate.)
X * - `Y' is the line number, counted from the beginning of the unit.
X *   These are logical lines rather than physical lines.
X *   The first line has line number 0.
X * - `X' is the column number.  The first column is 0.  For x < 0,
X *   see the important notice below.
X * - `Level' is the indentation level, indicating where a new line
X *   would start if inserted at the current position.
X *   The initial `x' position of such a line is `level*INDENTSIZE'.
X *
X * ***** IMPORTANT NOTICE *****
X * A special case is x = -1.  This means that the current x position is
X * unknown.  Further output on the same line is suppressed, until a
X * linefeed is encountered.  This feature is necessary because while
X * calculating coordinates, when an object has width < 0, only the y
X * coordinate of the end of that object is known.  In this case, the
X * next non-empty object MUST START WITH A LINEFEED, or it will not
X * be visible on the screen (in practice, a space is sometimes present
X * in the parse tree which is not shown then).
X */
X
X
X/*
X * Compute the (y, x) coordinates and indent level just before
X * the beginning of the j'th child, if the current node starts
X * at the initial values of (y, x) and level.
X */
X
XVisible Procedure
Xevalcoord(n, jch, py, px, plevel)
X	register node n;
X	register int jch;
X	int *py;
X	int *px;
X	int *plevel;
X{
X	node nn;
X	register int i;
X	register string *rp = noderepr(n);
X	register int k;
X	register int y = 0;
X	int x = *px;
X	int level = *plevel;
X	int nch;
X	
X	nch = Is_etext(n) ? 0 : nchildren(n);
X	if (jch > nch)
X		jch = nch+1;
X	for (i = 0; i < jch; ++i) {
X		if (i) {
X			nn = child(n, i);
X			k = nodewidth(nn);
X			if (k < 0) {
X				y += -k;
X				x = k;
X			}
X			else if (x >= 0)
X				x += k;
X		}
X		k = Fwidth(rp[i]);
X		if (k < 0) {
X			y += -k;
X			/* The \r in the next line is actually a
X			   \n on the Mac.  I forgot what \r was meant
X			   for; believe it isn't used. */
X			x = /*rp[i][0] == '\r' ? 0 :*/ INDENTSIZE*level;
X			x += strlen(rp[i]) - 1;
X		}
X		else {
X			if (x >= 0)
X				x += k;
X			if (rp[i]) {
X				if (rp[i][k] == '\t')
X					++level;
X				else if (rp[i][k] == '\b')
X					--level;
X			}
X		}
X	}
X
X	*py += y;
X	*px = x;
X	*plevel = level;
X}
X
X
X/*
X * Yield the width of a piece of fixed text as found in a node's repr,
X * excluding \b or \t.  If \n or \r is found, -1 is returned.
X * It assumes that \n or \r only occur as first
X * character, and \b or \t only as last.
X */
X
XVisible int
Xfwidth(str)
X	register string str;
X{
X	register int c;
X	register int n = 0;
X
X	if (!str)
X		return 0;
X	c = str[0];
X	if (c == '\r' || c == '\n')
X		return -1;
X	for (; c; c = *++str)
X		++n;
X	if (n > 0) {
X		c = str[-1];
X		if (c == '\t' || c == '\b')
X			--n;
X	}
X	return n;
X}
X
X
X/*
X * Evaluate the width of node n, assuming the widths of its children
X * have correctly been calculated.
X */
X
XVisible int
Xevalwidth(n)
X	register node n;
X{
X	register int w;
X	register int i;
X	register string *rp;
X	register int y = 0;
X	register int x = 0;
X	register int nch;
X	register node nn;
X
X	rp = noderepr(n);
X	nch = Is_etext(n) ? 0 : nchildren(n);
X	for (i = 0; i <= nch; ++i) {
X		if (i) {
X			nn = child(n, i);
X			w = nodewidth(nn);
X			if (w < 0) {
X				y += -w;
X				x = w;
X			}
X			else
X				x += w;
X		}
X		w = Fwidth(rp[i]);
X		if (w < 0) {
X			y += -w;
X			x = 0;
X		}
X		else
X			x += w;
X	}
X	if (y > 0)
X		return -y;
X	return x;
X}
END_OF_FILE
  if test 4245 -ne `wc -c <'abc/bed/e1eval.c'`; then
    echo shar: \"'abc/bed/e1eval.c'\" unpacked with wrong size!
  fi
  # end of 'abc/bed/e1eval.c'
fi
if test -f 'abc/bed/e1line.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'abc/bed/e1line.c'\"
else
  echo shar: Extracting \"'abc/bed/e1line.c'\" \(4243 characters\)
  sed "s/^X//" >'abc/bed/e1line.c' <<'END_OF_FILE'
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1986. */
X
X/*
X * B editor -- Routines for treating the parse tree as a sequence of lines.
X *
X * WARNING: The routines in this file (and many others!) assume that a
X * `newline' can only occur in the zero'th representation string of a node
X * (i.e., rp[0]).
X */
X
X#include "b.h"
X#include "bedi.h"
X#include "etex.h"
X#include "bobj.h"
X#include "node.h"
X#include "gram.h"
X#include "supr.h"
X
X
X/*
X * Compute equality of subtrees, based on common descent.
X * Strings are not checked for characterwise equality, but must
X * be the same pointer; other nodes must have the same symbol and
X * their children must be equal in this sense (equal pointers are
X * always used as a shortcut).
X *
X * (Used by screen update algorithm only.)
X */
X
XVisible bool
Xeqlines(n1, n2)
X	node n1;
X	node n2;
X{
X	register node nn1;
X	register node nn2;
X	register int w1;
X	register int w2;
X	register int nch;
X	register int i;
X
X	if (n1 == n2)
X		return Yes;
X	if (!Is_Node(n1) || !Is_Node(n2))
X		return No;
X	if (symbol(n1) != symbol(n2))
X		return No;
X	nch = nchildren(n1);
X	Assert(nch == nchildren(n2));
X	for (i = 1; i <= nch; ++i) {
X		nn1 = child(n1, i);
X		nn2 = child(n2, i);
X		w1 = nodewidth(nn1);
X		w2 = nodewidth(nn2);
X		if (w1 >= 0 && w2 >= 0) {
X			if (!eqlines(nn1, nn2))
X				return No;
X		}
X		else {
X			if (nn1 == nn2)
X				return Yes;
X			if (fwidth(noderepr(nn1)[0]) < 0 || fwidth(noderepr(nn2)[0]) < 0)
X				return linelen(n1) == linelen(n2);
X			return eqlines(nn1, nn2);
X		}
X	}
X	return Yes;
X}
X
X
X/*
X * Compute the length of the line beginning at the current node.
X */
X
XVisible int
Xlinelen(n)
X	node n;
X{
X	register node nn;
X	register string *rp = noderepr(n);
X	register int w;
X	register int nch = nchildren(n);
X	register int i;
X	register int len = fwidth(rp[0]);
X
X	if (len < 0)
X		len = 0;
X	for (i = 1; i <= nch; ++i) {
X		nn = child(n, i);
X		w = nodewidth(nn);
X		if (w >= 0)
X			len += w;
X		else {
X			n = nn;
X			i = 0;
X			nch = nchildren(n);
X			rp = noderepr(n);
X		}
X		w = Fwidth(rp[i]);
X		if (w < 0)
X			break;
X		len += w;
X	}
X	return len;
X}
X
X
X/*
X * Move the focus to the next line.
X * NB: This is a building block for use in the 'show' module;
X * it cannot set ep->mode or call higher() properly!
X */
X
XVisible bool
Xnextline(pp)
X	register path *pp;
X{
X	register node n;
X	register node nn;
X	register int w;
X	register int nch;
X	register int i = 0;
X
X	for (;;) {
X		n = tree(*pp);
X		if (nodewidth(n) < 0) {
X			nch = nchildren(n);
X			while (++i <= nch) {
X				nn = child(n, i);
X				w = nodewidth(nn);
X				if (w < 0) {
X					if (!downi(pp, i)) Abort();
X					n = tree(*pp);
X					if (fwidth(noderepr(n)[0]) < 0)
X						return Yes;
X					nch = nchildren(n);
X					i = 0;
X				}
X			}
X		}
X		/* Must go upward in the tree */
X		i = ichild(*pp);
X		if (!up(pp))
X			return No;
X	}
X}
X
X
X/*
X * Compute the current line number.  If the current node begins with
X * a `newline', add one because the first character is actually
X * on the next line.
X */
X
XVisible int
Xlineno(ep)
X	register environ *ep;
X{
X	register int y;
X
X	y = -focoffset(ep);
X	if (y < 0)
X		y = 0;
X	if (focchar(ep) == '\n')
X		++y;
X	return y + Ycoord(ep->focus);
X}
X
X
X/*
X * Similarly, compute the current column number.
X * (Hope the abovementioned trick isn't necessary.)
X */
X
XVisible int
Xcolno(ep)
X	environ *ep;
X{
X	int x= focoffset(ep);
X
X	if (x < 0)
X		x= 0; /* In fact, give up */
X	return x + Xcoord(ep->focus);
X}
X
X
X/*
X * Make the focus exactly one line wide (if at all possible).
X */
X
XVisible Procedure
Xoneline(ep)
X	register environ *ep;
X{
X	register node n;
X	node nn;
X	register string *rp;
X	register int s1;
X	register int s2;
X	register int len;
X	int ich;
X	int nch;
X
X	ich = 1;
X	while (nodewidth(tree(ep->focus)) >= 0) {
X		ich = ichild(ep->focus);
X		if (!up(&ep->focus)) {
X			ep->mode = WHOLE;
X			higher(ep);
X			return;
X		}
X	}
X	higher(ep);
X	n = tree(ep->focus);
X	nch = nchildren(n);
X	rp = noderepr(n);
X	for (s1 = 2*ich-1; s1 >= 1; --s1) {
X		if (s1&1)
X			len = fwidth(rp[s1/2]);
X		else {
X			nn = child(n, s1/2);
X			len = nodewidth(nn);
X		}
X		if (len < 0)
X			break;
X	}
X	for (s2 = 2*ich+1; s2 <= 2*nch+1; ++s2) {
X		if (s2&1)
X			len = fwidth(rp[s2/2]);
X		else {
X			nn = child(n, s2/2);
X			len = nodewidth(nn);
X		}
X		if (len < 0)
X			break;
X	}
X	ep->mode = SUBSET;
X	ep->s1 = s1+1;
X	ep->s2 = s2-1;
X}
END_OF_FILE
  if test 4243 -ne `wc -c <'abc/bed/e1line.c'`; then
    echo shar: \"'abc/bed/e1line.c'\" unpacked with wrong size!
  fi
  # end of 'abc/bed/e1line.c'
fi
if test -f 'abc/bint1/i1nur.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'abc/bint1/i1nur.c'\"
else
  echo shar: Extracting \"'abc/bint1/i1nur.c'\" \(5345 characters\)
  sed "s/^X//" >'abc/bint1/i1nur.c' <<'END_OF_FILE'
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1986. */
X
X/* Rational arithmetic */
X
X#include "b.h"
X#include "feat.h" 	/* for EXT_RANGE */
X#include "bobj.h"
X#include "i0err.h"
X#include "i1num.h"
X
X/* Length calculations used for fraction sizes: */
X
X#define Maxlen(u, v) \
X	(Roundsize(u) > Roundsize(v) ? Roundsize(u) : Roundsize(v))
X#define Sumlen(u, v) (Roundsize(u)+Roundsize(v))
X#define Difflen(u, v) (Roundsize(u)-Roundsize(v))
X
X/* To shut off lint and other warnings: */
X#undef Copy
X#define Copy(x) ((integer)copy((value)(x)))
X
X/* Globally used constants */
X
Xrational rat_half;
X
X/* Make a normalized rational from two integers */
X
XVisible rational mk_rat(x, y, len, simplify)
X		integer x, y; int len; bool simplify; {
X	rational a;
X	integer u,v;
X
X	if (y == int_0) {
X		if (interrupted)
X			return rat_zero();
X		syserr(MESS(1200, "mk_rat(x, y) with y=0"));
X	}
X
X	if (x == int_0 && len <= 0) return rat_zero();
X
X	if (Msd(y) < 0) {	/* interchange signs */
X		u = int_neg(x);
X		v = int_neg(y);
X	} else {
X		u = Copy(x);
X		v = Copy(y);
X	}
X
X	a = (rational) grab_rat(len);
X
X	if (u == int_0 || v == int_1) {
X		/* No simplification possible */
X		Numerator(a) = Copy(u);
X		Denominator(a) = int_1;
X	}
X	else if (!simplify) {
X		Numerator(a) = Copy(u);
X		Denominator(a) = Copy(v);
X	}
X	else {
X		integer g, abs_u;
X
X		if (Msd(u) < 0) abs_u = int_neg(u);
X		else abs_u = Copy(u);
X		g = int_gcd(abs_u, v);
X		Release(abs_u);
X
X		if (g != int_1) {
X			Numerator(a) = int_quot(u, g);
X			Denominator(a) = int_quot(v, g);
X		} else {
X			Numerator(a) = Copy(u);
X			Denominator(a) = Copy(v);
X		}
X		Release(g);
X	}
X
X	Release(u); Release(v);
X
X	return a;
X}
X
X
X/* Arithmetic on rational numbers */
X
X/* Shorthands: */
X#define N(u) Numerator(u)
X#define D(u) Denominator(u)
X
XVisible rational rat_sum(u, v) register rational u, v; {
X	integer t1, t2, t3, t4;
X	rational a;
X
X	t2= int_prod(N(u), D(v));
X	t3= int_prod(N(v), D(u));
X	t1= int_sum(t2, t3);
X	t4= int_prod(D(u), D(v));
X	a= mk_rat(t1, t4, Maxlen(u, v), Yes);
X	Release(t1); Release(t2);
X	Release(t3); Release(t4);
X
X	return a;
X}
X
X
XVisible rational rat_diff(u, v) register rational u, v; {
X	integer t1, t2, t3, t4;
X	rational a;
X
X	t2= int_prod(N(u), D(v));
X	t3= int_prod(N(v), D(u));
X	t1= int_diff(t2, t3);
X	t4= int_prod(D(u), D(v));
X	a= mk_rat(t1, t4, Maxlen(u, v), Yes);
X	Release(t1); Release(t2);
X	Release(t3); Release(t4);
X
X	return a;
X}
X
X
XVisible rational rat_prod(u, v) register rational u, v; {
X	integer t1, t2;
X	rational a;
X
X	t1= int_prod(N(u), N(v));
X	t2= int_prod(D(u), D(v));
X	a= mk_rat(t1, t2, Sumlen(u, v), Yes);
X	Release(t1); Release(t2);
X
X	return a;
X}
X
X
XVisible rational rat_quot(u, v) register rational u, v; {
X	integer t1, t2;
X	rational a;
X
X	if (N(v) == int_0) {
X		interr(ZERO_DIVIDE);
X		return rat_zero();
X	}
X
X	t1= int_prod(N(u), D(v));
X	t2= int_prod(D(u), N(v));
X	a= mk_rat(t1, t2, Difflen(u, v), Yes);
X	Release(t1); Release(t2);
X
X	return a;
X}
X
X
XVisible rational rat_neg(u) register rational u; {
X	register rational a;
X
X	/* Avoid a real subtraction from zero */
X
X	if (N(u) == int_0) return (rational) Copy(u);
X
X	a = (rational) grab_rat(0);
X	N(a) = int_neg(N(u));
X	D(a) = Copy(D(u));
X	Length(a) = Length(u);
X
X	return a;
X}
X
X/* Rational number to the integral power */
X
XVisible rational rat_power(a, n) rational a; integer n; {
X	integer u, v, tu, tv, temp;
X
X	if (n == int_0) return mk_rat(int_1, int_1, 0, Yes);
X
X	if (Msd(n) < 0) {
X		if (N(a) == int_0) {
X			interr(NEG_POWER);
X			return (rational) Copy(a);
X		}
X		if (Msd(N(a)) < 0) {
X			u= int_neg(D(a));
X			v = int_neg(N(a));
X		}
X		else {
X			u = Copy(D(a));
X			v = Copy(N(a));
X		}
X		n = int_neg(n);
X	} else {
X		if (N(a) == int_0) return (rational) Copy(a);
X			/* To avoid necessary simplification later on */
X		u = Copy(N(a));
X		v = Copy(D(a));
X		n = Copy(n);
X	}
X
X	tu = int_1;
X	tv = int_1;
X	
X	while (n != int_0 && !Interrupted()) {
X		if (Odd(Lsd(n))) {
X			if (u != int_1) {
X				temp = tu;
X				tu = int_prod(u, tu);
X				Release(temp);
X			}
X			if (v != int_1) {
X				temp = tv;
X				tv = int_prod(v, tv);
X				Release(temp);
X			}
X			if (n == int_1)
X				break; /* Avoid useless last squaring */
X		}
X
X		/* Square u, v */
X
X		if (u != int_1) {
X			temp = u;
X			u = int_prod(u, u);
X			Release(temp);
X		}
X		if (v != int_1) {
X			temp = v;
X			v = int_prod(v, v);
X			Release(temp);
X		}
X
X		n = int_half(n);
X	} /* while (n!=0) */
X
X	Release(n);
X	Release(u);
X	Release(v);
X	a = mk_rat(tu, tv, 0, No);
X	Release(tu); Release(tv);
X
X	return a;
X}
X
X
X/* Compare two rational numbers */
X
XVisible relation rat_comp(u, v) register rational u, v; {
X	int sd, su, sv;
X	integer nu, nv;
X
X	/* 1. Compare pointers */
X	if (u == v || N(u) == N(v) && D(u) == D(v)) return 0;
X
X	/* 2. Either zero? */
X	if (N(u) == int_0) return int_comp(int_0, N(v));
X	if (N(v) == int_0) return int_comp(N(u), int_0);
X
X	/* 3. Compare signs */
X	su = Msd(N(u));
X	sv = Msd(N(v));
X	su = (su>0) - (su<0);
X	sv = (sv>0) - (sv<0);
X	if (su != sv) return su > sv ? 1 : -1;
X
X	/* 4. Compute numerator of difference and return sign */
X	nu= int_prod(N(u), D(v));
X	nv= int_prod(N(v), D(u));
X	sd= int_comp(nu, nv);
X	Release(nu); Release(nv);
X	return sd;
X}
X
XVisible rational rat_zero() {
X	rational r= (rational) grab_rat(0);
X	N(r) = int_0;
X	D(r) = int_1;
X	return r;
X}
X
XVisible Procedure rat_init() {
X	rat_half = (rational) grab_rat(0);
X	N(rat_half) = int_1;
X	D(rat_half) = int_2;
X}
X
XVisible Procedure endrat() {
X	Release(rat_half);
X}
END_OF_FILE
  if test 5345 -ne `wc -c <'abc/bint1/i1nur.c'`; then
    echo shar: \"'abc/bint1/i1nur.c'\" unpacked with wrong size!
  fi
  # end of 'abc/bint1/i1nur.c'
fi
if test -f 'abc/bint3/i3fil.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'abc/bint3/i3fil.c'\"
else
  echo shar: Extracting \"'abc/bint3/i3fil.c'\" \(4560 characters\)
  sed "s/^X//" >'abc/bint3/i3fil.c' <<'END_OF_FILE'
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1986. */
X
X/* Facilities supplied by the file system */
X
X#include "b.h"
X#include "bmem.h"
X#include "bint.h"
X#include "bobj.h"
X#include "i2nod.h"
X#include "i2par.h"
X#include "i3scr.h"
X#include "i3sou.h"
X
XVisible Procedure f_rename(fname, nfname) value fname, nfname; {
X	char *f1, f2[100];
X	
X	strcpy(f2, strval(nfname));
X	unlink(f2);
X	f1= strval(fname);
X	VOID rename(f1, f2); 
X	/* what if it fails??? */
X}
X
XVisible Procedure f_delete(fname) value fname; {
X	unlink(strval(fname));
X}
X
XVisible unsigned f_size(file) FILE *file; {
X	long s, ftell();
X	fseek(file, 0l, 2);
X	s= ftell(file);
X	fseek(file, 0l, 0); /* rewind */
X	return s;
X}
X
XVisible Procedure f_close(ofile) FILE *ofile; {
X	bool ok= fflush(ofile) != EOF;
X	if (fclose(ofile) == EOF || !ok)
X		interr(MESS(3700, "write error (disk full?)"));
X}
X
XVisible bool f_interactive(file) FILE *file; {
X	return isatty(fileno(file));
X}
X
X/* f_getline() returns a line from a file with the newline character */
X
X#define LINESIZE 200
X
XVisible char *f_getline(file) FILE *file; {
X	char line[LINESIZE];
X	char *pline= NULL;
X	
X	while (fgets(line, LINESIZE, file) != NULL) {
X		if (pline == NULL)
X			pline= (char *) savestr(line);
X		else {
X			int len= strlen(pline) + strlen(line) + 1;
X			regetmem(&pline, (unsigned) len);
X			strcat(pline, line);
X		}
X		if (strchr(pline, '\n') != NULL)
X			return pline;
X	}
X	if (pline != NULL)
X		freestr(pline);
X	return NULL;
X}
X
XHidden struct class { literal type; char *suffix; };
X
XHidden struct class classes[]= {
X	{Cmd, Cmd_ext},
X	{Zfd, Zfd_ext},
X	{Mfd, Mfd_ext},
X	{Dfd, Dfd_ext},
X	{Zpd, Zpd_ext},
X	{Mpd, Mpd_ext},
X	{Dpd, Dpd_ext},
X	{Tar, Cts_ext},
X	{Wsp, Wsp_ext}
X};
X
X#define NCLASSES (sizeof classes / sizeof classes[0])
X
XHidden char *filesuffix(type) literal type; {
X	register struct class *cp;
X
X	for (cp= classes; cp < &classes[NCLASSES]; ++cp) {
X		if (type == cp->type)
X			return cp->suffix;
X	}
X	return "";
X}
X
X/*
X * the following constants were moved here from all os.h's
X * to use more portable filenames;
X * e.g. MSDOS conventions, since these are the most limited.
X */
X#define FNMLEN 8
X#define SUFFIXLEN 4
X
XVisible value new_fname(name, type) value name; literal type; {
X	char fname[FNMLEN + SUFFIXLEN + 1];
X	char *suffix= filesuffix(type);
X	string sname= strval(name);
X	char *sp= strchr(sname, ' ');
X	intlet len= sp ? sp-sname : strlen(sname);
X		/* if a command name only the first keyword */
X	
X	if (len > FNMLEN) len= FNMLEN;
X	strncpy(fname, sname, len); fname[len]= '\0';
X	strcat(fname, suffix);
X	/* convert also if not MSDOS, to make abc-ws's portable: */
X	conv_fname(fname, suffix);
X	if (type != Wsp &&
X		F_exists(fname) &&
X		!fnm_extend(fname, len, suffix) &&
X		!fnm_narrow(fname, len)
X	   )
X		return Vnil;
X	return mk_text(fname);
X}
X
XHidden bool fnm_extend(fname, n, suffix) char *fname, *suffix; int n; {
X	/* e.g. "ABC.cmd" => "ABC1.cmd" */
X	int m;
X	int k= n;
X	
X	do {
X		for (m= k-1; fname[m] == '9'; --m);
X		if (isdigit(fname[m])) {
X			++fname[m];
X			while (++m < k) fname[m]= '0';
X		}
X		else if (k >= FNMLEN) {
X			/* reset */
X			fname[n]= '\0';
X			strcat(fname, suffix);
X			return No;
X		}
X		else {
X			fname[++m]= '1';
X			while (++m <= k) fname[m]= '0';
X			fname[++k]= '\0';
X			strcat(fname, suffix);
X		}
X	}
X	while (F_exists(fname));
X	return Yes;
X}
X
XHidden bool fnm_narrow(fname, n) char *fname; int n; {
X	/* e.g. "ABC.cmd" => "AB1.cmd" */
X	int m;
X	
X	do {
X		for (m= n-1; ; --m) {
X			if (m < 1)
X				return No;
X			else if (!isdigit(fname[m])) { 
X				fname[m]= '1'; 
X				break; 
X			}
X			else if (fname[m] != '9') { 
X				++fname[m]; 
X				break; 
X			}
X			else fname[m]= '0';
X		}
X	}
X	while (F_exists(fname));
X	return Yes;
X}
X
X/* Conversion of characters:
X *  . uppercase to lowercase
X *  . point to CONVP_SIGN
X *  . double quote to CONVDQ_SIGN
X *  . single quote can stay
X *  the latter is as portably unspecial as possible.
X */
X
XHidden Procedure conv_fname(fname, suffix) char *fname, *suffix; {
X	char *ext_point= fname + strlen(fname) - strlen(suffix);
X	
X	while (fname < ext_point) {
X		if (isupper(*fname)) 
X			*fname= tolower(*fname);
X		else if (*fname == C_QUOTE)
X			*fname= CONVDQ_SIGN;
X		else if (*fname == C_POINT)
X			*fname= CONVP_SIGN;
X		fname++;
X	}
X}
X
X/* recover location or workspace name from filename */
X
XVisible value mkabcname(name) char *name; {
X	char *p;
X	
X	for (p= name; *p != '\0'; ++p) {
X		if (Cap(*p))
X			*p= tolower(*p);
X		else if (*p == CONVP_SIGN)
X			*p= (*(p+1) == '\0' ? '\0' : C_POINT);
X		else if (*p == CONVDQ_SIGN)
X			*p= C_QUOTE;
X		else if (!Tagmark(p))
X			*p= C_QUOTE;
X	}
X	return mk_text(name);
X}
END_OF_FILE
  if test 4560 -ne `wc -c <'abc/bint3/i3fil.c'`; then
    echo shar: \"'abc/bint3/i3fil.c'\" unpacked with wrong size!
  fi
  # end of 'abc/bint3/i3fil.c'
fi
if test -f 'abc/bio/i4fil.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'abc/bio/i4fil.c'\"
else
  echo shar: Extracting \"'abc/bio/i4fil.c'\" \(4420 characters\)
  sed "s/^X//" >'abc/bio/i4fil.c' <<'END_OF_FILE'
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1988. */
X
X#include "b.h"
X#include "bfil.h"
X#include "bmem.h"
X#include "bobj.h"
X#include "i3sou.h"
X
X#ifdef HAS_READDIR
X#include <sys/dir.h>
X#else
X#include "dir.h"
X#endif
X
X/**************************************************************************/
X/* get_names() is used to get at the names of all ABC files/workspaces	  */
X/* in a given directory.						  */
X/*									  */
X/* This version of the file is supposed to work for any kind of Unix	  */
X/* and for MS-DOS.							  */
X/**************************************************************************/
X
X	/* Note: it uses readdir so isn't portable to non-BSD
X	   Unix, unless you also port readdir and friends.
X	   Luckily, public-domain versions are available,
X	   and one should be distributed with ABC.
X	   It works for MS-DOS because I have ported readdir
X	   to MS-DOS, too.  Guido. */
X
XVisible value get_names(path, isabc) char *path; bool (*isabc)(); {
X	DIR *dp;
X	struct direct *dirp;
X	value v;
X	value name;
X	
X	dp= opendir(path);
X	if (dp == (DIR *) NULL)
X		return Vnil;
X	v= mk_elt();
X	for (;;) {
X		dirp= readdir(dp);
X		if (dirp == (struct direct *) NULL) {
X			closedir(dp);
X			break;
X		}
X		if ((*isabc)(path, dirp->d_name)) {
X			name= mk_text(dirp->d_name);
X			insert(name, &v);
X			release(name);
X		}
X	}
X	return v;
X}
X
X/**************************************************************************/
X/* Is this the name of a target, a unit or something else?		  */
X/*									  */
X/* For compatibility, we recognize files starting with =, <, ", > and ',  */
X/* and files ending with ".how", ".zer", ".mon", ".dya" and ".tar".	  */
X/* Otherwise, unit names must end in ".cmd", ".zfd", ".mfd", ".dfd",	  */
X/* ".zpd", ".mpd" or ".dpd",                                              */
X/* and target names must end in ".cts" (all ignoring case).		  */
X/**************************************************************************/
X
X#define DumClass '\0'
X
XHidden struct class { char *suffix; literal type; };
X
XHidden struct class classes[]= {
X	{".cmd", Cmd},
X	{".zfd", Zfd},
X	{".mfd", Mfd},
X	{".dfd", Dfd},
X	{".zpd", Zpd},
X	{".mpd", Mpd},
X	{".dpd", Dpd},
X	{".cts", Tar},
X	
X	{".CMD", Cmd},
X	{".ZFD", Zfd},
X	{".MFD", Mfd},
X	{".DFD", Dfd},
X	{".ZPD", Zpd},
X	{".MPD", Mpd},
X	{".DPD", Dpd},
X	{".CTS", Tar},
X	
X	{".how", OldHow},
X	{".zer", OldHow},
X	{".mon", OldHow},
X	{".dya", OldHow},
X	{".tar", OldTar},
X
X	{".HOW", OldHow},
X	{".ZER", OldHow},
X	{".MON", OldHow},
X	{".DYA", OldHow},
X	{".TAR", OldTar}
X};
X
X#define NCLASSES (sizeof classes / sizeof classes[0])
X
XHidden literal classfile(fname) value fname; {
X	char *sfname, *end;
X	struct class *cp;
X
X	sfname= strval(fname);
X	switch (sfname[0]) {
X		case '\'': case '<': case '"': case '>':
X			return OldHow;
X		case '=':
X			return OldTar;
X		default:
X			break;
X	}
X	end= sfname + strlen(sfname);
X	for (cp= classes; cp < &classes[NCLASSES]; ++cp) {
X		if (end-strlen(cp->suffix) >= sfname
X		    && strcmp(end-strlen(cp->suffix), cp->suffix) == 0)
X			return cp->type;
X	}
X	return DumClass;
X}
X
XVisible bool abcfile(path, name) char *path, *name; {
X	/* path argument needed, but not used */
X	bool isfile;
X	value f= mk_text(name);
X	
X	isfile= classfile(f) != DumClass ? Yes : No;
X	release(f);
X	return isfile;
X}
X
XVisible bool abcworkspace(path, name) char *path, *name; {
X	struct stat statbuf;
X	char *path1, *path2;
X	bool isws= No;
X	
X	path1= makepath(path, name);
X	if (stat(path1, &statbuf) == 0 &&
X		((statbuf.st_mode & S_IFMT) == S_IFDIR) &&
X		(strcmp(name, CURDIR) != 0) &&
X		(strcmp(name, PARENTDIR) != 0)
X	   ) {
X		path2= makepath(path1, permfile);
X		isws= F_exists(path2) ? Yes : No;
X		freepath(path2);
X	}
X	freepath(path1);
X	return isws;
X}
X
XVisible bool targetfile(fname) value fname; {
X	switch (classfile(fname)) {
X		case Tar: case OldTar:
X			return Yes;
X		default:
X			return No;
X	}
X}
X
XVisible bool unitfile(fname) value fname; {
X	switch (classfile(fname)) {
X		case Tar: case OldTar: case DumClass:
X			return No;
X		default: 
X			return Yes;
X	}
X}
X
XVisible char *base_fname(fname) value fname; {
X	char *sname;
X	char *base;
X	char *pext;
X	
X	sname= strval(fname);
X	switch (*sname) {
X		case '\'': case '<': case '"': case '>': case '=':
X			++sname;
X		default:
X			break;
X	}
X	base= savestr(sname);
X	if ((pext= strrchr(base, '.')) != NULL)
X		*pext= '\0';
X	return base;
X}
X
XVisible bool typeclash(pname, fname) value pname, fname; {
X	return classfile(fname) != Permtype(pname) ? Yes : No;
X}
END_OF_FILE
  if test 4420 -ne `wc -c <'abc/bio/i4fil.c'`; then
    echo shar: \"'abc/bio/i4fil.c'\" unpacked with wrong size!
  fi
  # end of 'abc/bio/i4fil.c'
fi
if test -f 'abc/boot/Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'abc/boot/Makefile'\"
else
  echo shar: Extracting \"'abc/boot/Makefile'\" \(4701 characters\)
  sed "s/^X//" >'abc/boot/Makefile' <<'END_OF_FILE'
X# EDIT MY ANCESTOR Makefile.bsd
X# AND SAY 'make -f Makefile.bsd Makefile'
X#
X# BSD Makefile for booting grammar tables with mktable from grammar file.
X#
X
X# --- Where to install the stuff ---
X
XCFILE=../bed/e1tabl.c
XHFILE=../ehdrs/tabl.h
X
X# --- What is the C preprocessor called ---
X#
X# ../scripts/mkdep has the right CPP if Setup succeeded and your UNIX ain't BSD
X
XCPP=	/bin/cc -E
X
X# --- Flags to the C compiler ---
X
XBINCL=	-I../bhdrs -I../ehdrs -I../uhdrs
XDEFS=	-DNDEBUG -DBSD
XCFLAGS= -O $(DEFS) $(BINCL)
XLDFLAGS=-s
XLIBS=	
XGDEFS=
X
X# --- Stuff for lint ---
X
XLINT=		lint
XLINTFLAGS=	-abh
XLBINCL=		$(BINCL)
X
X# --- Relevant files ---
X
XOBJS=	main.o alloc.o read.o fill.o comp.o dump.o code.o
X
XSRCS=	main.c alloc.c read.c fill.c comp.c dump.c ../bed/e1code.c
X
XHDRS=	../bhdrs/b.h main.h ../ehdrs/code.h lang.h
X
X# --- Main entries of the makefile ---
X
Xall: tabl.c.out tabl.h.out
X
Xtabl.c.out tabl.h.out: grammar mktable
X	mktable -g grammar -h tabl.h -t tabl.c.out -i tabl.h.out
X
Xgrammar: grammar.abc lang.h
X	$(CPP) $(GDEFS) grammar.abc 2>/dev/null | sed -e "/^$$/d" -e "/^#/d" >grammar
X
Xmktable: $(OBJS)
X	$(CC) $(LDFLAGS) $(OBJS) $(LIBS) -o mktable
X
Xinstall: $(CFILE) $(HFILE)
X
X$(CFILE): tabl.c.out
X	cp tabl.c.out $(CFILE)
X
X$(HFILE): tabl.h.out
X	cp tabl.h.out $(HFILE)
X
Xclean:
X	rm -f *.o mktable grammar tabl.c.out tabl.h.out tabl.c tabl.h
X
Xclobber: clean
X	rm -f lint tags
X
Xcode.o: ../bed/e1code.c
X	$(CC) -c $(CFLAGS) ../bed/e1code.c -o code.o
X
X# --- Utilities for the programmer ---
X
Xmflags:
X	echo MFLAGS=\"$(MFLAGS)\", MAKEFLAGS=\"$(MAKEFLAGS)\"
X
X# If your UNIX isn't BSD4.2 or higher, use:
X# MKDEP=../scripts/mkdep
XMKDEP=$(CC) -M
X
XMakefile: ALWAYS
X	rm -f Makefile
X	(echo "# EDIT MY ANCESTOR Makefile.bsd"; \
X	 echo "# AND SAY 'make -f Makefile.bsd Makefile'"; \
X	 cat Makefile.bsd; \
X	 $(MKDEP) $(DEFS) $(BINCL) $(SRCS); \
X	) >Makefile
X
Xlint:	$(SRCS) $(HDRS)
X	$(LINT) $(LINTFLAGS) $(DEFS) $(LBINCL) $(SRCS) >lint
X
Xtags:	$(HDRS) $(SRCS)
X	rm -f tags
X	ctags $(HDRS) $(SRCS)
X
Xtest:	all
X	cp tabl.h.out tabl.h
X	cp tabl.c.out tabl.c
X	cc -c $(CFLAGS) tabl.c
X
XALWAYS:	#dummy
X
X###
Xmain.o: main.c
Xmain.o: ../bhdrs/b.h
Xmain.o: ../uhdrs/osconf.h
Xmain.o: /usr/include/stdio.h
Xmain.o: ../uhdrs/os.h
Xmain.o: /usr/include/math.h
Xmain.o: /usr/include/ctype.h
Xmain.o: /usr/include/strings.h
Xmain.o: /usr/include/sys/types.h
Xmain.o: /usr/include/sys/stat.h
Xmain.o: /usr/include/sys/file.h
Xmain.o: ../uhdrs/conf.h
Xmain.o: ../uhdrs/config.h
Xmain.o: ./main.h
Xalloc.o: alloc.c
Xalloc.o: ../bhdrs/b.h
Xalloc.o: ../uhdrs/osconf.h
Xalloc.o: /usr/include/stdio.h
Xalloc.o: ../uhdrs/os.h
Xalloc.o: /usr/include/math.h
Xalloc.o: /usr/include/ctype.h
Xalloc.o: /usr/include/strings.h
Xalloc.o: /usr/include/sys/types.h
Xalloc.o: /usr/include/sys/stat.h
Xalloc.o: /usr/include/sys/file.h
Xalloc.o: ../uhdrs/conf.h
Xalloc.o: ../uhdrs/config.h
Xalloc.o: ./main.h
Xread.o: read.c
Xread.o: ../bhdrs/b.h
Xread.o: ../uhdrs/osconf.h
Xread.o: /usr/include/stdio.h
Xread.o: ../uhdrs/os.h
Xread.o: /usr/include/math.h
Xread.o: /usr/include/ctype.h
Xread.o: /usr/include/strings.h
Xread.o: /usr/include/sys/types.h
Xread.o: /usr/include/sys/stat.h
Xread.o: /usr/include/sys/file.h
Xread.o: ../uhdrs/conf.h
Xread.o: ../uhdrs/config.h
Xread.o: ./main.h
Xfill.o: fill.c
Xfill.o: ../bhdrs/b.h
Xfill.o: ../uhdrs/osconf.h
Xfill.o: /usr/include/stdio.h
Xfill.o: ../uhdrs/os.h
Xfill.o: /usr/include/math.h
Xfill.o: /usr/include/ctype.h
Xfill.o: /usr/include/strings.h
Xfill.o: /usr/include/sys/types.h
Xfill.o: /usr/include/sys/stat.h
Xfill.o: /usr/include/sys/file.h
Xfill.o: ../uhdrs/conf.h
Xfill.o: ../uhdrs/config.h
Xfill.o: ./main.h
Xcomp.o: comp.c
Xcomp.o: ../bhdrs/b.h
Xcomp.o: ../uhdrs/osconf.h
Xcomp.o: /usr/include/stdio.h
Xcomp.o: ../uhdrs/os.h
Xcomp.o: /usr/include/math.h
Xcomp.o: /usr/include/ctype.h
Xcomp.o: /usr/include/strings.h
Xcomp.o: /usr/include/sys/types.h
Xcomp.o: /usr/include/sys/stat.h
Xcomp.o: /usr/include/sys/file.h
Xcomp.o: ../uhdrs/conf.h
Xcomp.o: ../uhdrs/config.h
Xcomp.o: ./main.h
Xcomp.o: ../ehdrs/code.h
Xdump.o: dump.c
Xdump.o: ../bhdrs/b.h
Xdump.o: ../uhdrs/osconf.h
Xdump.o: /usr/include/stdio.h
Xdump.o: ../uhdrs/os.h
Xdump.o: /usr/include/math.h
Xdump.o: /usr/include/ctype.h
Xdump.o: /usr/include/strings.h
Xdump.o: /usr/include/sys/types.h
Xdump.o: /usr/include/sys/stat.h
Xdump.o: /usr/include/sys/file.h
Xdump.o: ../uhdrs/conf.h
Xdump.o: ../uhdrs/config.h
Xdump.o: ./main.h
Xe1code.o: ../bed/e1code.c
Xe1code.o: ../bhdrs/b.h
Xe1code.o: ../uhdrs/osconf.h
Xe1code.o: /usr/include/stdio.h
Xe1code.o: ../uhdrs/os.h
Xe1code.o: /usr/include/math.h
Xe1code.o: /usr/include/ctype.h
Xe1code.o: /usr/include/strings.h
Xe1code.o: /usr/include/sys/types.h
Xe1code.o: /usr/include/sys/stat.h
Xe1code.o: /usr/include/sys/file.h
Xe1code.o: ../uhdrs/conf.h
Xe1code.o: ../uhdrs/config.h
Xe1code.o: ../ehdrs/code.h
END_OF_FILE
  if test 4701 -ne `wc -c <'abc/boot/Makefile'`; then
    echo shar: \"'abc/boot/Makefile'\" unpacked with wrong size!
  fi
  # end of 'abc/boot/Makefile'
fi
if test -f 'abc/ihdrs/i1num.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'abc/ihdrs/i1num.h'\"
else
  echo shar: Extracting \"'abc/ihdrs/i1num.h'\" \(4302 characters\)
  sed "s/^X//" >'abc/ihdrs/i1num.h' <<'END_OF_FILE'
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1986. */
X
X/************************************************************************/
X/* Full numeric package: private definitions                            */
X/*                                                                      */
X/* A number is modelled as one of zero, unbounded integer,              */
X/*        unbounded rational or approximate.                            */
X/*     Zero has a 'length' field of zero, and nothing else.             */
X/*     A length field of +n means the number is an n digit integer,     */
X/*        (with digits to some large base).                             */
X/*     A length of -1 means there follow two floating point numbers,    */
X/*        one the fraction (zero or .5 <= frac <= 1), one the exponent  */
X/*        with respect to base 2 (should be an integral value).         */
X/*        (This is so when EXT_RANGE is defined.  Otherwise, there is   */
X/*        only one field, frac, which is not normalized.  This saves    */
X/*        code and data space on e.g. the IBM PC, where the natural     */
X/*        range of double's is sufficient (~1E307).)                    */
X/*     A length of -2 means there follow two values, pointers to two    */
X/*        unbounded integers, ie a rational number.                     */
X/*     A length of -n, n>2, means it is a rational with a print width   */
X/*        of n-2.                                                       */
X/*                                                                      */
X/************************************************************************/
X
X/*************** Definitions exported for integers *****************/
X
X/* typedef int digit; or short; calculated in mkconfig -> config.h */
X
Xtypedef struct integer {
X	HEADER;
X	digit	dig[1];
X} *integer;
X
X#define FreezeSmallInt(v, vv) \
X	(IsSmallInt(v) && (Freeze1(v, vv), Freeze2(v, vv)))
X#define Freeze1(v, vv) ((vv).type= Num, (vv).refcnt= Maxrefcnt)
X#define Freeze2(v, vv) \
X	((vv).len= (v) != 0, (vv).dig[0]= SmallIntVal(v), (v)= &(vv))
X
Xinteger int_gadd();
Xinteger int_canon();
Xinteger int_sum();
Xinteger int_prod();
Xinteger int_diff();
Xinteger int_quot();
Xinteger int_neg();
Xinteger int_gcd();
Xinteger mk_int();
Xinteger int1mul();
Xinteger int_tento();
Xinteger int_half();
Xinteger int_mod();
Xdigit int_ldiv();
X
X#define int_0 ((integer) MkSmallInt(0))
X#define int_1 ((integer) MkSmallInt(1))
X#define int_2 ((integer) MkSmallInt(2))
X#define int_5 ((integer) MkSmallInt(5))
X#define int_10 ((integer) MkSmallInt(10))
X#define int_min1 ((integer) MkSmallInt(-1))
X
X#define Integral(v) (IsSmallInt(v) || Length(v)>=0)
X#define Modulo(a,b) (((a)%(b)+(b))%(b))
X#define Digit(v,n) ((v)->dig[n])
X#define Msd(v) (IsSmallInt(v) ? SmallIntVal(v) : Digit(v,Length(v)-1))
X#define Lsd(v) (IsSmallInt(v) ? SmallIntVal(v) : Digit(v,0))
X
X#define Odd(x) ((x)&1)
X#define Even(x) (!Odd(x))
X
X/* Provisional definitions */
X
X#define Copy(x) copy((value)(x))
X#define Release(x) release((value)(x))
X
X/***************** Definitions exported for rationals *****************/
X
Xtypedef struct {
X	HEADER;
X	integer	num, den;
X} *rational;
X
X
X#define Numerator(a) ((a)->num)
X#define Denominator(a) ((a)->den)
X#define Rational(a) (!IsSmallInt(a) && Length(a)<-1)
X#define Roundsize(a) (-2-Length(a))
X
Xrational mk_rat();
Xrational rat_sum();
Xrational rat_diff();
Xrational rat_neg();
Xrational rat_prod();
Xrational rat_quot();
Xrational rat_power();
Xrational rat_zero();
X
Xextern rational rat_half;
X
Xvalue tento();
Xvalue mk_exact();
X
X/***************** Definitions exported for approximate numbers *************/
X
Xtypedef struct real {
X	HEADER;
X	double	frac;
X#ifdef EXT_RANGE
X	double	expo;
X#endif /* EXT_RANGE */
X} *real;
X
X#define Frac(v) ((v)->frac)
X#ifdef EXT_RANGE
X#define Expo(v) ((v)->expo)
X#else
X#define Expo(v) 0.0
X#endif
X
X#define Approximate(v) (!IsSmallInt(v) && Length(v)==-1)
X#define Exact(v) (!Approximate(v))
X
Xextern real app_0;
X
Xreal mk_approx();
X
Xreal app_sum();
Xreal app_diff();
Xreal app_prod();
Xreal app_quot();
Xreal app_neg();
X
Xreal app_exp();
Xreal app_log();
Xreal app_power();
X
Xvalue app_frexp();
Xinteger app_floor();
Xvalue app_exactly();
X
Xvalue prod2n();
Xvalue prod10n();
Xrational ratsumhalf();
X
Xvalue grab_num();
Xvalue regrab_num();
Xvalue grab_rat();
X
Xdouble frexp(), ldexp();
END_OF_FILE
  if test 4302 -ne `wc -c <'abc/ihdrs/i1num.h'`; then
    echo shar: \"'abc/ihdrs/i1num.h'\" unpacked with wrong size!
  fi
  # end of 'abc/ihdrs/i1num.h'
fi
if test -f 'abc/keys/keyhlp.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'abc/keys/keyhlp.c'\"
else
  echo shar: Extracting \"'abc/keys/keyhlp.c'\" \(4623 characters\)
  sed "s/^X//" >'abc/keys/keyhlp.c' <<'END_OF_FILE'
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1989. */
X
X/*
X * ABC keys -- Print the bindings.
X */
X
X#include "b.h"
X#include "feat.h"
X#include "bmem.h"
X#include "keys.h"
X#include "getc.h"
X
X/*
X   The following array determines the order of the editor operations
X   in the helpblurb.
X   The names and keyrepresentations are taken from deftab in e1getc.c
X   and ?1keys.c.
X   Printing is done in two columns.
X   Code NOTHING is used to produce an empty place in the second column.
X */
X 
Xint helpcode[]= {
X	WIDEN,		EXTEND,
X	FIRST,		LAST,
X	PREVIOUS,	NEXT,
X	UPLINE,		DOWNLINE,
X	UPARROW,	DOWNARROW,
X	LEFTARROW,	RITEARROW,
X#ifdef GOTOCURSOR
X	GOTO,		NOTHING,
X#endif
X	ACCEPT,		NEWLINE,
X	UNDO,		REDO,
X	COPY,		DELETE,
X	RECORD,		PLAYBACK,
X	LOOK,		HELP,
X#ifdef CANSUSPEND
X	EXIT,		NOTHING,
X	CANCEL,		SUSPEND,
X#else
X	EXIT,		CANCEL,
X#endif
X	TERMINIT,	TERMDONE,
X	IGNORE,		NOTHING
X};
X
XHidden struct helpitem {
X	string data;	/* "[name] repr's string" */
X	int bindmark;	/* position in data of more bindings marker */
X	bool changed;	/* status of item */
X} helpitem[(sizeof(helpcode))/(sizeof(int))];
X
XHidden int nitems= 0;
X
XHidden int namewidth;		/* width of name field */
X#define GAP_FIELDS 1		/* nr of spaces between two fields */
X/*Hidden int bindwidth;*/	/* width of bindings field */
X
XHidden int helpwidth;		/* width of a column */
X#define GAP_COLUMNS 1		/* nr of spaces between the two columns */
X
X#define BINDMARK '*'		/* set after name if too many bindings */
XHidden int bindstart;		/* offset bindings field */
X#define BINDSEP ", "		/* separator bindings */
X
X/*
X * Print the bindings.
X */
X
XVisible Procedure putbindings(yfirst) int yfirst; {
X	int h;
X	bool h_changed;
X	
X	for (h= 0; h < nitems; h+= 2, yfirst++) {
X
X		if (h_changed= helpitem[h].changed) {
X			getbindings(h);
X			trmputdata(yfirst, yfirst, 0, helpitem[h].data);
X		}
X		if (h+1 < nitems) {
X			if (helpitem[h+1].changed)
X				getbindings(h+1);
X			else if (!h_changed)
X				continue;
X			trmputdata(yfirst, yfirst,
X				helpwidth+GAP_COLUMNS, helpitem[h+1].data);
X		}
X	}
X	trmsync(yfirst, 0);
X}
X
XVisible Procedure setup_bindings(width, nlines) int width, *nlines; {
X	int h;
X	int code;
X	int len;
X	string buffer;
X	string name;
X	string getname();
X
X	helpwidth= (width - GAP_COLUMNS)/2;
X	nitems= ((sizeof(helpcode))/(sizeof(int)));
X	namewidth= 0;
X
X	for (h= 0; h < nitems; h++) {
X		buffer= (string) getmem((unsigned) helpwidth+1);
X		code= helpcode[h];
X		name= getname(code);
X		strcpy(buffer, name);
X		len= strlen(buffer);
X		if (len > namewidth) /* find max name length */
X			namewidth= len;
X		helpitem[h].data= buffer;
X		helpitem[h].bindmark= len;
X		helpitem[h].changed= Yes;
X		confirm_operation(code, name);
X	}
X
X	namewidth++;
X		/* one extra space for a marker after the name
X		 * if there are too many bindings to show
X		 */
X	bindstart= namewidth + GAP_FIELDS;
X/*	bindwidth= helpwidth - bindstart; */
X
X	/* extend with spaces */
X	for (h= 0; h < nitems; h++)
X		extendwithspaces(helpitem[h].data, bindstart);
X	
X	/* set nlines */
X
X	*nlines= (nitems+1)/2;
X}
X
X#ifdef MEMTRACE
X
XVisible Procedure fini_bindings() {
X	int h;
X	
X	for (h= 0; h < nitems; h++) {
X		free(helpitem[h].data);
X	}
X}
X
X#endif /* MEMTRACE */
X
XHidden string getname(code) int code; {
X	tabent *d;
X	
X	for (d= deftab; d < deftab+ndefs; d++) {
X		if (code == d->code)
X			return d->name;
X	}
X	return "";
X}
X
XHidden Procedure extendwithspaces(buffer, bound) string buffer; int bound; {
X	int len= strlen(buffer);
X	string pbuf= buffer+len;
X
X	for (; len < bound; len++)
X		*pbuf++= ' ';
X	*pbuf= '\0';
X}
X
XVisible Procedure bind_changed(code) int code; {
X	int h;
X	
X	for (h= 0; h < nitems; h++) {
X		if (code == helpcode[h]) {
X			helpitem[h].changed= Yes;
X			break;
X		}
X	}
X}
X
XVisible Procedure bind_all_changed() { /* for redrawing the screen */
X	int h;
X	
X	for (h= 0; h < nitems; h++) {
X		helpitem[h].changed= Yes;
X	}
X}
X	
X
X#define Def(d)	((d)->def != NULL && (d)->def[0] != '\0')
X#define Rep(d)	((d)->rep != NULL && (d)->rep[0] != '\0')
X
XHidden Procedure getbindings(h) int h; {
X	tabent *d;
X	int code= helpcode[h];
X	string buffer= helpitem[h].data;
X	bool all_showed= Yes;
X	string repr;
X	
X	buffer[bindstart]= '\0';
X	for (d= deftab+ndefs-1; d >= deftab; d--) {
X
X		if (code != d->code || !Def(d) || !Rep(d))
X			continue;
X		if (!addbinding(d->rep, buffer))
X			all_showed= No;
X	}
X	/* set marker */
X	buffer[helpitem[h].bindmark]= !all_showed ? BINDMARK : ' ';
X
X	helpitem[h].changed= No;
X}
X
XHidden bool addbinding(repr, buffer) string repr, buffer; {
X	string sep= buffer[bindstart] == '\0' ? "" : BINDSEP;
X	
X	if (strlen(buffer) + strlen(sep) + strlen(repr) > helpwidth)
X		return No;
X	strcat(buffer, sep);
X	strcat(buffer, repr);
X	return Yes;
X}
END_OF_FILE
  if test 4623 -ne `wc -c <'abc/keys/keyhlp.c'`; then
    echo shar: \"'abc/keys/keyhlp.c'\" unpacked with wrong size!
  fi
  # end of 'abc/keys/keyhlp.c'
fi
if test -f 'abc/stc/i2tcu.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'abc/stc/i2tcu.c'\"
else
  echo shar: Extracting \"'abc/stc/i2tcu.c'\" \(4424 characters\)
  sed "s/^X//" >'abc/stc/i2tcu.c' <<'END_OF_FILE'
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1986. */
X
X/* unification of polytypes */
X
X#include "b.h"
X#include "bobj.h"
X#include "i2stc.h"
X
XHidden bool bad;
X
XVisible Procedure unify(a, b, pu)
Xpolytype a, b, *pu;
X{
X	bad = No;
X	setreprtable();
X	starterrvars();
X#ifdef TYPETRACE
X	s_unify(a, b);
X#endif
X	u_unify(a, b, pu);
X#ifdef TYPETRACE
X	e_unify(a, b, *pu);
X#endif
X	if (bad) badtyperr(a, b);
X	enderrvars();
X	delreprtable();
X}
X
XHidden Procedure u_unify(a, b, pu)
Xpolytype a, b, *pu;
X{
X	typekind a_kind, b_kind;
X	polytype res;
X	
X	a_kind = kind(a);
X	b_kind = kind(b);
X	
X	if (are_same_types(a, b)) {
X		*pu = p_copy(a);
X	}
X	else if (t_is_var(a_kind) || t_is_var(b_kind)) {
X		substitute_for(a, b, pu);
X	}
X	else if (have_same_structure(a, b)) {
X		unify_subtypes(a, b, pu);
X	}
X	else if (has_number(a_kind) && has_number(b_kind)) {
X		*pu = mkt_number();
X	}
X	else if (has_text(a_kind) && has_text(b_kind)) {
X		*pu = mkt_text();
X	}
X	else if (has_text(a_kind) && t_is_tlt(b_kind)) {
X		u_unify(asctype(b), (res = mkt_text()), pu);
X		p_release(res);
X	}
X	else if (has_text(b_kind) && t_is_tlt(a_kind)) {
X		u_unify(asctype(a), (res = mkt_text()), pu);
X		p_release(res);
X	}
X	else if ((t_is_list(a_kind) && has_lt(b_kind))
X		 ||
X		 (t_is_list(b_kind) && has_lt(a_kind))
X	)
X	{
X		u_unify(asctype(a), asctype(b), &res);
X		*pu = mkt_list(res);
X	}
X	else if (t_is_table(a_kind) && has_lt(b_kind)) {
X		u_unify(asctype(a), asctype(b), &res);
X		*pu = mkt_table(p_copy(keytype(a)), res);
X	}
X	else if (t_is_table(b_kind) && has_lt(a_kind)) {
X		u_unify(asctype(a), asctype(b), &res);
X		*pu = mkt_table(p_copy(keytype(b)), res);
X	}
X	else if ((t_is_tlt(a_kind) && t_is_lt(b_kind))
X		 || 
X		 (t_is_lt(a_kind) && t_is_tlt(b_kind)))
X	{
X		u_unify(asctype(a), asctype(b), &res);
X		*pu = mkt_lt(res);
X	}
X	else if (t_is_error(a_kind) || t_is_error(b_kind)) {
X		*pu = mkt_error();
X	}
X	else {
X		*pu = mkt_error();
X		bad = Yes;
X	}
X	if (t_is_var(a_kind) && t_is_error(kind(bottomtype(*pu))))
X		adderrvar(a);
X	if (t_is_var(b_kind) && t_is_error(kind(bottomtype(*pu))))
X		adderrvar(b);
X}
X
XHidden Procedure unify_subtypes(a, b, pu)
Xpolytype a, b, *pu;
X{
X	polytype sa, sb, s;
X	intlet nsub, is;
X	bool err = No;
X	
X	nsub = nsubtypes(a);
X	*pu = mkt_polytype(kind(a), nsub);
X	for (is = 0; is < nsub; is++) {
X		sa = subtype(a, is);
X		sb = subtype(b, is);
X		u_unify(sa, sb, &s);
X		putsubtype(s, *pu, is);
X		if (t_is_error(kind(s)))
X			err = Yes;
X	}
X	if (err == Yes) {
X		p_release(*pu);
X		*pu = mkt_error();
X	}
X}
X
XForward bool contains();
XForward bool equal_vars();
X
XHidden Procedure substitute_for(a, b, pu)
Xpolytype a, b, *pu;
X{
X	typekind a_kind, b_kind;
X	polytype ta, tb, tu, tt;
X	
X	a_kind = kind(a);
X	b_kind = kind(b);
X	
X	ta = bottomtype(a);
X	tb = bottomtype(b);
X	
X	if (!t_is_var(kind(ta)) && !t_is_var(kind(tb)))
X		u_unify(ta, tb, &tu);
X	else if (!t_is_var(kind(ta)))
X		tu = p_copy(ta);
X	else
X		tu = p_copy(tb);
X	
X	if (t_is_var(a_kind)) {
X		if (contains(tu, bottomvar(a)))
X			textify(a, &tu);
X	}
X	if (t_is_var(b_kind)) {
X		if (contains(tu, bottomvar(b)))
X			textify(b, &tu);
X	}
X	
X	if (t_is_var(a_kind) && t_is_var(b_kind)
X	    && !are_same_types(bottomvar(a), bottomvar(b)))
X	{
X	    	repl_type_of(bottomvar(a), bottomvar(b));
X	}
X	
X	tt= bottomtype(tu);
X	
X	if (t_is_var(a_kind)) {
X		if (!are_same_types(tt, bottomtype(a)))
X			repl_type_of(bottomvar(a), tt);
X		*pu= p_copy(a);
X	}
X	else { /* t_is_var(b_kind) */
X		if (!are_same_types(tt, bottomtype(b)))
X			repl_type_of(bottomvar(b), tt);
X		*pu= p_copy(b);
X	}
X	
X	p_release(tu);
X}
X
XHidden Procedure textify(a, pu)
Xpolytype a, *pu;
X{
X	polytype ttext, text_hopefully;
X	
X	ttext = mkt_text();
X	u_unify(*pu, ttext, &text_hopefully);
X	if (bad == No) {
X		p_release(text_hopefully);
X		u_unify(a, ttext, &text_hopefully);
X	}
X	p_release(*pu);
X	if (bad == No) {
X		*pu = ttext;
X	}
X	else {
X		*pu = mkt_error();
X		/* cyclic type errors now reported through normal mechanism */
X		p_release(ttext);
X	}
X	p_release(text_hopefully);
X}
X
XVisible bool contains(u, a) polytype u, a; {
X	bool result;
X	
X	result = No;
X	if (t_is_var(kind(u))) {
X		if (table_has_type_of(u)) {
X			result = contains(bottomtype(u), a);
X		}
X	}
X	else {
X		polytype s;
X		intlet is, nsub;
X		nsub = nsubtypes(u);
X		for (is = 0; is < nsub; is++) {
X			s = subtype(u, is);
X			if (equal_vars(s, a) || contains(s, a)) {
X				result = Yes;
X				break;
X			}
X		}
X	}
X	return (result);
X}
X
XVisible bool equal_vars(s, a) polytype s, a; {
X	return (are_same_types(bottomvar(s), a));
X}
END_OF_FILE
  if test 4424 -ne `wc -c <'abc/stc/i2tcu.c'`; then
    echo shar: \"'abc/stc/i2tcu.c'\" unpacked with wrong size!
  fi
  # end of 'abc/stc/i2tcu.c'
fi
if test -f 'abc/unix/u1file.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'abc/unix/u1file.c'\"
else
  echo shar: Extracting \"'abc/unix/u1file.c'\" \(1744 characters\)
  sed "s/^X//" >'abc/unix/u1file.c' <<'END_OF_FILE'
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1988. */
X
X#include "b.h"
X#include "bmem.h"
X#include "dest.h"
X#include "bfil.h"
X
Xextern char *getenv();
Xextern char *getwd();
X
XVisible char *curdir() {
X	static char buffer[SIZE_PATH];
X	return getwd(buffer);
X}
X
XHidden string searchfile(base, abclib) string base; string abclib; {
X	char *file;
X	
X	/* search first in startup directory */
X	file= makepath(startdir, base);
X	if (F_readable(file))
X		return (string) file;
X	freepath(file);
X
X	/* then in bwsdefault */
X	if (bwsdefault != NULL) {
X		file= makepath(bwsdefault, base);
X		if (F_readable(file))
X			return (string) file;
X		freepath(file);
X	}
X		
X	/* next first in abclib */
X	file= makepath(abclib, base);
X	if (F_readable(file))
X		return (string) file;
X	freepath(file);
X
X	/* else fail */
X	return (string) NULL;
X}
X
XVisible Procedure initfile() {
X	char *homedir= getenv("HOME");
X	char *termname;
X	string termfile;
X	
X	startdir= savepath(curdir());
X	bwsdefault= homedir ? makepath(homedir, BWSNAME) : (char *) NULL;
X	messfile= searchfile(MESSFILE, ABCLIB);
X	helpfile= searchfile(HELPFILE, ABCLIB);
X	buffile= homedir ? makepath(homedir, BUFFILE) : savepath(BUFFILE);
X	
X	if (editor != (string) NULL)
X		return;	/* we don't need the keydefinitions file */
X
X	if ((termname= getenv("TERM")) != NULL) {
X		termfile= (string) getmem((unsigned) strlen(KEYSPREFIX)+strlen(termname));
X		strcpy(termfile, KEYSPREFIX);
X		strcat(termfile, termname);
X		keysfile= searchfile(termfile, ABCLIB);
X		freemem(termfile);
X	}
X	if (keysfile == (string)NULL) {
X		keysfile= searchfile(KEYSFILE, ABCLIB);
X	}
X}
X
XVisible Procedure endfile() {
X	freepath(startdir);
X	freepath(bwsdefault);
X	freepath(messfile);
X	freepath(keysfile);
X	freepath(helpfile);
X	freepath(buffile);
X}
END_OF_FILE
  if test 1744 -ne `wc -c <'abc/unix/u1file.c'`; then
    echo shar: \"'abc/unix/u1file.c'\" unpacked with wrong size!
  fi
  # end of 'abc/unix/u1file.c'
fi
echo shar: End of archive 20 \(of 25\).
cp /dev/null ark20isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 25 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still must unpack the following archives:
    echo "        " ${MISSING}
fi
exit 0 # Just in case...
-- 
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.



More information about the Comp.sources.unix mailing list