[alt.sources.amiga] sc Part 4 of 9

sie@fulcrum.bt.co.uk (Simon Raybould) (03/20/91)

#!/bin/sh
# this is scshr.04 (part 4 of a multipart archive)
# do not concatenate these parts, unpack them in order with /bin/sh
# file lex.c continued
#
if test ! -r _shar_seq_.tmp; then
	echo 'Please unpack part 1 first!'
	exit 1
fi
(read Scheck
 if test "$Scheck" != 4; then
	echo Please unpack part "$Scheck" next!
	exit 1
 else
	exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
	echo 'x - still skipping lex.c'
else
echo 'x - continuing file lex.c'
sed 's/^X//' << 'SHAR_EOF' >> 'lex.c' &&
X *		Lexical analyser
X *
X *		original by James Gosling, September 1982
X *		modifications by Mark Weiser and Bruce Israel,
X *			University of Maryland
X *
X *              More mods Robert Bond, 12/86
X *		More mods by Alan Silverstein, 3/88, see list of changes.
X *		$Revision: 6.8 $
X *
X */
X
X
X
#if defined(BSD42) || defined(BSD43)
#include <sys/ioctl.h>
#endif 
X
#ifdef IEEE_MATH
#include <ieeefp.h>
#endif /* IEEE_MATH */
X
#include <curses.h>
#include <signal.h>
#include <setjmp.h>
#include "sc.h"
#include <ctype.h>
X
#ifdef BSD42
#include <strings.h>
#else
#ifndef SYSIII
#include <string.h>
#endif
#endif
X
#ifdef VMS
#include "gram_tab.h"
typedef union {
X    int ival;
X    double fval;
X    struct ent *ent;
X    struct enode *enode;
X    char *sval;
X    struct range_s rval;
} YYSTYPE;
extern YYSTYPE yylval;
extern int VMS_read_raw;   /*sigh*/
#else	/* VMS */
#include "y.tab.h"
extern YYSTYPE yylval;
#endif /* VMS */
X
char *strtof();
X
jmp_buf wakeup;
jmp_buf fpe_buf;
X
struct key {
X    char *key;
X    int val;
};
X
struct key experres[] = {
#include "experres.h"
X    0, 0};
X
struct key statres[] = {
#include "statres.h"
X    0, 0};
X
yylex ()
{
X    register char *p = line+linelim;
X    int ret;
X    while (isspace(*p)) p++;
X    if (*p == '\0') ret = -1;
X    else if (isalpha(*p)) {
X	char *tokenst = p;
X	register tokenl;
X	register struct key *tblp;
X	tokenl = 0;
X	/*
X	 * This picks up either 1 or 2 alpha characters (a column) or
X	 * tokens with at least three leading alphas and '_' or digits
X	 * (a function or token or command or a range name)
X	*/
X	while (isalpha(*p) || ((*p == '_') || isdigit(*p)) && (tokenl > 2)) {
X	    p++;
X	    tokenl++;
X	}
X	if (tokenl <= 2) { /* a COL is 1 or 2 char alpha
X		(but not pi, ln, fv, pv, if -- this should be fixed!) */
X	    if (tokenl == 2 && tokenst[0] == 'p' && tokenst[1] == 'i') {
X		ret = K_PI;
X	    } else if (tokenl == 2 && tokenst[0] == 'l' && tokenst[1] == 'n') {
X		ret = K_LN;
X	    } else if (tokenl == 2 && tokenst[0] == 'f' && tokenst[1] == 'v') {
X		ret = K_FV;
X	    } else if (tokenl == 2 && tokenst[0] == 'p' && tokenst[1] == 'v') {
X		ret = K_PV;
X	    } else if (tokenl == 2 && tokenst[0] == 'i' && tokenst[1] == 'f') {
X		ret = K_IF;
X
X	    } else {
X		ret = COL;
X		yylval.ival = atocol (tokenst, tokenl);
X	    }
X	} else {
X	    ret = WORD;
X	    for (tblp = linelim ? experres : statres; tblp->key; tblp++)
X		    if (((tblp->key[0]^tokenst[0])&0137)==0
X		     && tblp->key[tokenl]==0) {
X			register i = 1;
X			while (i<tokenl && ((tokenst[i]^tblp->key[i])&0137)==0)
X			    i++;
X			if (i>=tokenl) {
X			    ret = tblp->val;
X			    break;
X			}
X		    }
X	    if (ret==WORD) { 
X		struct range *r;
X		if (r = find_range(tokenst, tokenl,
X				   (struct ent *)0, (struct ent *)0)) {
X		    yylval.rval.left = r->r_left;
X		    yylval.rval.right = r->r_right;
X		    if (r->r_is_range)
X		        ret = RANGE;
X		    else
X			ret = VAR;
X		} else {
X		    linelim = p-line;
X		    yyerror ("Unintelligible word");
X		}
X	    }
X	}
X    } else if ((*p == '.') || isdigit(*p)) {
X	double v = 0;
X	int temp;
X	char *nstart = p;
X	if (*p != '.') {
X	    do v = v*10 + (double)(*p-'0');
X	    while (isdigit(*++p));
X	}
X	if (*p=='.' || *p == 'e' || *p == 'E') {
X	    ret = FNUMBER;
X	    p = strtof(nstart, &yylval.fval);
X	} else {
X	    /* A NUMBER must hold at least MAXROW and MAXCOL */
X	    /* This is consistent with a short row and col in struct ent */
X	    if (v > (double)32767 || v < (double)-32768) {
X		ret = FNUMBER;
X		yylval.fval = v;
X	    } else {
X		temp = (int)v;
X		if((double)temp != v) {
X		    ret = FNUMBER;
X		    yylval.fval = v;
X		} else {
X		    ret = NUMBER;
X		    yylval.ival = temp;
X		}
X	    }
X	}
X    } else if (*p=='"') {
X	char *ptr;
X        ptr = p+1;
X        while(*ptr && *ptr++ != '"');
X        ptr = xmalloc((unsigned)(ptr-p));
X	yylval.sval = ptr;
X	p += 1;
X	while (*p && *p!='"') *ptr++ = *p++;
X	*ptr = 0;
X	if (*p) p += 1;
X	ret = STRING;
X    } else if (*p=='[') {
X	while (*p && *p!=']') p++;
X	if (*p) p++;
X	linelim = p-line;
X	return yylex();
X    } else ret = *p++;
X    linelim = p-line;
X    return ret;
}
X
X
/*
X * Given a token string starting with a symbolic column name and its valid
X * length, convert column name ("A"-"Z" or "AA"-"ZZ") to a column number (0-N).
X * Never mind if the column number is illegal (too high).  The procedure's name
X * and function are the inverse of coltoa().
X * 
X * Case-insensitivity is done crudely, by ignoring the 040 bit.
X */
X
int
atocol (string, len)
X	char	*string;
X	int	len;
{
X	register int col;
X
X	col = (string [0] & 0137) - 'A';
X
X	if (len == 2)		/* has second char */
X	    col = ((col + 1) * 26) + ((string [1] & 0137) - 'A');
X
X	return (col);
}
X
X
#ifdef SIMPLE
X
initkbd()
{}
X
kbd_again()
{}
X
resetkbd()
{}
X
#ifndef VMS
X
nmgetch()
{
X    return (toascii(getchar()));
}
X
#else /* VMS */
X
nmgetch()
/*
X   This is not perfect, it doesn't move the cursor when goraw changes
X   over to deraw, but it works well enough since the whole sc package
X   is incredibly stable (loop constantly positions cursor).
X
X   Question, why didn't the VMS people just implement cbreak?
X
X   NOTE: During testing it was discovered that the DEBUGGER and curses
X   and this method of reading would collide (the screen was not updated
X   when continuing from screen mode in the debugger).
*/
{
X    short c;
X    static int key_id=0;
X    int status;
#define VMScheck(a) {if (~(status = (a)) & 1) VMS_MSG (status);}
X
X    if (VMS_read_raw) {
X      VMScheck(smg$read_keystroke (&stdkb->_id, &c, 0, 0, 0));
X    }
X    else
X       c = getchar();
X
X    switch (c) {
X    case SMG$K_TRM_LEFT:  c = ctl('b'); break;
X    case SMG$K_TRM_RIGHT: c = ctl('f'); break;
X    case SMG$K_TRM_UP:    c = ctl('p'); break;
X    case SMG$K_TRM_DOWN:  c = ctl('n'); break;
X    default:   c = c & 0x7f;
X    }
X    return (c);
}
X
X
VMS_MSG (status)
int status;
/*
X   Routine to put out the VMS operating system error (if one occurs).
*/
{
#include <descrip.h>
X   char errstr[81], buf[120];
X   $DESCRIPTOR(errdesc, errstr);
X   short int length;
#define err_out(msg) fprintf (stderr,msg)
X
/* Check for no error or standard error */
X
X   if (~status & 1) {
X      status = status & 0x8000 ? status & 0xFFFFFFF : status & 0xFFFF;
X      if (SYS$GETMSG(status, &length, &errdesc, 1, 0) == SS$_NORMAL) {
X         errstr[length] = '\0';
X         sprintf (buf, "<0x%x> %s", status, errdesc.dsc$a_pointer);
X         err_out (buf);
X      }
X      else
X         err_out ("System error");
X   }
}
#endif /* VMS */
X
#else /*SIMPLE*/
X
#if defined(BSD42) || defined (SYSIII) || defined(BSD43)
X
#define N_KEY 4
X
struct key_map {
X    char *k_str;
X    char k_val;
X    char k_index;
}; 
X
struct key_map km[N_KEY];
X
char keyarea[N_KEY*30];
X
char *tgetstr();
char *getenv();
char *ks;
char ks_buf[20];
char *ke;
char ke_buf[20];
X
#ifdef TIOCSLTC
struct ltchars old_chars, new_chars;
#endif
X
char dont_use[] = {
X	ctl('['), ctl('a'), ctl('b'), ctl('c'), ctl('e'), ctl('f'), ctl('g'), ctl('h'),
X	ctl('i'), ctl('j'),  ctl('l'), ctl('m'), ctl('n'), ctl('p'), ctl('q'),
X	ctl('r'), ctl('s'), ctl('t'), ctl('u'), ctl('v'),  ctl('w'), ctl('x'),
X	ctl('z'), 0
};
X
charout(c)
int c;
{
X	(void)putchar(c);
}
X
initkbd()
{
X    register struct key_map *kp;
X    register i,j;
X    char *p = keyarea;
X    char *ktmp;
X    static char buf[1024]; /* Why do I have to do this again? */
X
X    if (tgetent(buf, getenv("TERM")) <= 0)
X	return;
X
X    km[0].k_str = tgetstr("kl", &p); km[0].k_val = ctl('b');
X    km[1].k_str = tgetstr("kr", &p); km[1].k_val = ctl('f');
X    km[2].k_str = tgetstr("ku", &p); km[2].k_val = ctl('p');
X    km[3].k_str = tgetstr("kd", &p); km[3].k_val = ctl('n');
X    ktmp = tgetstr("ks",&p);
X    if (ktmp)  {
X	(void) strcpy(ks_buf, ktmp);
X	ks = ks_buf;
X	tputs(ks, 1, charout);
X    }
X    ktmp = tgetstr("ke",&p);
X    if (ktmp)  {
X	(void) strcpy(ke_buf, ktmp);
X	ke = ke_buf;
X    }
X
X    /* Unmap arrow keys which conflict with our ctl keys   */
X    /* Ignore unset, longer than length 1, and 1-1 mapped keys */
X
X    for (i = 0; i < N_KEY; i++) {
X	kp = &km[i];
X	if (kp->k_str && (kp->k_str[1] == 0) && (kp->k_str[0] != kp->k_val))
X	    for (j = 0; dont_use[j] != 0; j++)
X	        if (kp->k_str[0] == dont_use[j]) {
X		     kp->k_str = (char *)0;
X		     break;
X		}
X    }
X
X
#ifdef TIOCSLTC
X    (void)ioctl(fileno(stdin), TIOCGLTC, (char *)&old_chars);
X    new_chars = old_chars;
X    if (old_chars.t_lnextc == ctl('v'))
X	new_chars.t_lnextc = -1;
X    if (old_chars.t_rprntc == ctl('r'))
X	new_chars.t_rprntc = -1;
X    (void)ioctl(fileno(stdin), TIOCSLTC, (char *)&new_chars);
#endif
}
X
void
kbd_again()
{
X    if (ks) 
X	tputs(ks, 1, charout);
X
#ifdef TIOCSLTC
X    (void)ioctl(fileno(stdin), TIOCSLTC, (char *)&new_chars);
#endif
}
X
void
resetkbd()
{
X    if (ke) 
X	tputs(ke, 1, charout);
X
#ifdef TIOCSLTC
X    (void)ioctl(fileno(stdin), TIOCSLTC, (char *)&old_chars);
#endif
}
X
nmgetch() 
{
X    register int c;
X    register struct key_map *kp;
X    register struct key_map *biggest;
X    register int i;
X    int almost;
X    int maybe;
X
X    static char dumpbuf[10];
X    static char *dumpindex;
X
#ifdef SIGVOID
X    void time_out();
#else
X    int time_out();
#endif
X
X    if (dumpindex && *dumpindex)
X	    return (*dumpindex++);
X
X    c = toascii(getchar());
X    biggest = 0;
X    almost = 0;
X
X    for (kp = &km[0]; kp < &km[N_KEY]; kp++) {
X	if (!kp->k_str)
X	    continue;
X	if (c == kp->k_str[kp->k_index]) {
X	    almost = 1;
X	    kp->k_index++;
X	    if (kp->k_str[kp->k_index] == 0) {
X		c = kp->k_val;
X	        for (kp = &km[0]; kp < &km[N_KEY]; kp++)
X	            kp->k_index = 0;
X	        return(c);
X	    }
X	}
X	if (!biggest && kp->k_index)
X	    biggest = kp;
X        else if (kp->k_index && biggest->k_index < kp->k_index)
X	    biggest = kp;
X    }
X
X    if (almost) { 
X        (void) signal(SIGALRM, time_out);
X        (void) alarm(1);
X
X	if (setjmp(wakeup) == 0) { 
X	    maybe = nmgetch();
X	    (void) alarm(0);
X	    return(maybe);
X	}
X    }
X    
X    if (biggest) {
X	for (i = 0; i<biggest->k_index; i++) 
X	    dumpbuf[i] = biggest->k_str[i];
X	if (!almost)
X	    dumpbuf[i++] = c;
X	dumpbuf[i] = '\0';
X	dumpindex = &dumpbuf[1];
X	for (kp = &km[0]; kp < &km[N_KEY]; kp++)
X	    kp->k_index = 0;
X	return (dumpbuf[0]);
X    }
X
X    return(c);
}
X
#endif
X
#if defined(SYSV2) || defined(SYSV3)
X
initkbd()
{
X    keypad(stdscr, TRUE);
}
X
void
kbd_again()
{
X    keypad(stdscr, TRUE);
}
X
void
resetkbd()
{
X    keypad(stdscr, FALSE);
}
X
nmgetch()
{
X    register int c;
X
X    c = getch();
X    switch (c) {
X    case KEY_LEFT:  c = ctl('b'); break;
X    case KEY_RIGHT: c = ctl('f'); break;
X    case KEY_UP:    c = ctl('p'); break;
X    case KEY_DOWN:  c = ctl('n'); break;
#ifdef KEY_C1
/* This stuff works for a wyse wy75 in ANSI mode under 5.3.  Good luck. */
/* It is supposed to map the curses keypad back to the numeric equiv. */
X    case KEY_C1:    c = '0'; break;
X    case KEY_A1:    c = '1'; break;
X    case KEY_B2:    c = '2'; break;
X    case KEY_A3:    c = '3'; break;
X    case KEY_F(5):  c = '4'; break;
X    case KEY_F(6):  c = '5'; break;
X    case KEY_F(7):  c = '6'; break;
X    case KEY_F(9):  c = '7'; break;
X    case KEY_F(10): c = '8'; break;
X    case KEY_F0:    c = '9'; break;
X    case KEY_C3:    c = '.'; break;
X    case KEY_ENTER: c = ctl('m'); break;
#endif
X    default:   c = toascii(c); 
X    break;
X    }
X    return (c);
}
X
#endif /* SYSV2 || SYSV3 */
X
#endif /* SIMPLE */
X
#ifdef AMIGA
initkbd()
{
X    keypad(stdscr, TRUE);
}
X
void
kbd_again()
{
X    keypad(stdscr, TRUE);
}
X
void
resetkbd()
{
X    keypad(stdscr, FALSE);
}
X
nmgetch()
{
X    register int c;
X
X    c = getch();
X    switch (c) {
X    case KEY_LEFT:  c = ctl('b'); break;
X    case KEY_RIGHT: c = ctl('f'); break;
X    case KEY_UP:    c = ctl('p'); break;
X    case KEY_DOWN:  c = ctl('n'); break;
X    case KEY_HELP:	c = '?'; break;	/* SJR 07.Nov.90 */
X    default:   c = toascii(c); 
X    break;
X    }
X    return (c);
}
#endif /* AMIGA */
X
#ifdef SIGVOID
void
#endif
time_out(signo)
int signo;
{
#ifdef IEEE_MATH
X	(void)fpsetsticky((fp_except)0); 		/* Clear exception */
#endif /* IEEE_MATH */
X    longjmp(wakeup, -1);
}
X
#ifdef SIGVOID
void
#endif
fpe_trap(signo)
int signo;
{
X    longjmp(fpe_buf, 1);
}
X
/*
X * This converts a floating point number of the form
X * [s]ddd[.d*][esd*]  where s can be a + or - and e is E or e.
X * to floating point. 
X * p is advanced.
X */
X
char *
strtof(p, res)
register char *p;
double *res;
{
X    double acc;
X    int sign;
X    double fpos;
X    int exp;
X    int exps;
#ifdef SIGVOID
X    void (*sig_save)();
#else
X    int (*sig_save)();
#endif
X
X    sig_save = signal(SIGFPE, fpe_trap);
X    if (setjmp(fpe_buf)) {
X	error("Floating point exception\n");
X	*res = 0.0; 
X        (void) signal(SIGFPE, sig_save);
X	return(p);
X    }
X    acc = 0.0;
X    sign = 1;
X    exp = 0;
X    exps = 1;
X    if (*p == '+')
X        p++;
X    else if (*p == '-') {
X        p++;
X        sign = -1;
X    }
X    while (isdigit(*p)) {
X        acc = acc * 10.0 + (double)(*p - '0');
X        p++;
X    }
X    if (*p == 'e' || *p == 'E') {
X	    p++;
X        if (*p == '+')
X	    p++;
X        else if (*p == '-') {
X	    p++;
X	    exps = -1;
X        }
X        while(isdigit(*p)) {
X	    exp = exp * 10 + (*p - '0');
X	    p++;
X        }
X    }
X    if (*p == '.') {
X	fpos = 1.0/10.0;
X	p++;
X	while(isdigit(*p)) {
X	    acc += (*p - '0') * fpos;
X	    fpos *= 1.0/10.0;
X	    p++;
X	}
X    }
X    if (*p == 'e' || *p == 'E') {
X	exp = 0;
X	exps = 1;
X        p++;
X	if (*p == '+')
X	    p++;
X	else if (*p == '-') {
X	    p++;
X	    exps = -1;
X	}
X	while(isdigit(*p)) {
X	    exp = exp * 10 + (*p - '0');
X	    p++;
X	}
X    }
X    if (exp) {
X	if (exps > 0)
X	    while (exp--)
X		acc *= 10.0;
X	else
X	    while (exp--)
X		acc *= 1.0/10.0;
X    }
X    if (sign > 0)
X        *res = acc;
X    else
X	*res = -acc;
X
X    (void) signal(SIGFPE, sig_save);
X    return(p);
}
SHAR_EOF
echo 'File lex.c is complete' &&
chmod 0666 lex.c ||
echo 'restore of lex.c failed'
Wc_c="`wc -c < 'lex.c'`"
test 13674 -eq "$Wc_c" ||
	echo 'lex.c: original size 13674, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= manifest ==============
if test -f 'manifest' -a X"$1" != X"-c"; then
	echo 'x - skipping manifest (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting manifest (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'manifest' &&
X   File Name		Archive #	Description
----------------------------------------------------------
README                     1	
MANIFEST                   1	This shipping list
CHANGES                    5	
Makefile                   6	
TODO                       6	
VMS_NOTES                  6	
cmds.c                     4	
crypt.c                    6	
eres.sed                   5	
gram.y                     5	
help.c                     3	
interp.c                   2	
lex.c                      4	
psc.c                      4	
psc.doc                    5	
range.c                    5	
sc.c                       3	
sc.doc                     1	
sc.h                       5	
sc6.8p1.hdr                2	
sc6.8p2.hdr                6	
sc6.8p3.hdr                6	
sc6.8p4.hdr                6	
sres.sed                   2	
tutorial.sc                6	
version.c                  5	
vi.c                       5	
vmtbl.c                    5	
xmalloc.c                  4	
SHAR_EOF
chmod 0666 manifest ||
echo 'restore of manifest failed'
Wc_c="`wc -c < 'manifest'`"
test 983 -eq "$Wc_c" ||
	echo 'manifest: original size 983, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= psc.c ==============
if test -f 'psc.c' -a X"$1" != X"-c"; then
	echo 'x - skipping psc.c (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting psc.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'psc.c' &&
/* Sc parse routine
X *
X * usage psc options
X * options:
X *   -L		Left justify strings.  Default is right justify.
X *   -r		Assemble data into rows first, not columns.
X *   -R	n	Increment by n between rows 
X *   -C n	Increment by n between columns
X *   -n n	Length of the row (column) should be n.
X *   -s v	Top left location in the spreadsheet should be v; eg, k5
X *   -d c       Use c as the delimiter between the fields.
X *   -k         Keep all delimiters - Default is strip multiple delimiters to 1.
X *   -f         suppress 'format' lines in output
X *   
X *  Author: Robert Bond
X *		$Revision: 6.8 $
X */
X
#include <ctype.h>
#include <stdio.h>
#include "sc.h"
X
#define END 0
#define NUM 1
#define ALPHA 2
#define SPACE 3
#define EOL 4
X
extern char *optarg;
extern int   optind;
char *coltoa();
char *progname;
X
#ifdef SYSV3
extern void exit();
#else
extern int exit();
#endif
X
int colfirst = 0;
int r0 = 0;
int c0 = 0;
int rinc = 1;
int cinc = 1;
int leftadj = 0;
int len = 20000;
char delim1 = ' ';
char delim2 = '\t';
int strip_delim = 1;
int drop_format = 0;
int *fwidth;
int *precision;
int maxcols;
X
char token[1000];
X
main(argc, argv)
int argc;
char **argv;
{
X    int curlen;
X    int curcol, coff;
X    int currow, roff;
X    int first;
X    int c;
X    register effr, effc;
X    int i,j;
X    register char *p;
X
X    progname = argv[0];
X    while ((c = getopt(argc, argv, "rfLks:R:C:n:d:")) != EOF) {
X	switch(c) {
X	case 'r':
X	    colfirst = 1;
X	    break;
X	case 'L':
X	    leftadj = 1;
X	    break;
X	case 's':
X	    c0 = getcol(optarg);
X	    r0 = getrow(optarg);
X	    break;
X	case 'R':
X	    rinc = atoi(optarg);
X	    break;
X	case 'C':
X	    cinc = atoi(optarg);
X	    break;
X	case 'n':
X	    len = atoi(optarg);
X	    break;
X	case 'd':
X	    delim1 = optarg[0];
X	    delim2 = 0;
X	    break;
X	case 'k':
X	    strip_delim = 0;
X	    break;
X	case 'f':
X	    drop_format = 1;
X	    break;
X	default:
X	    (void) fprintf(stderr,"Usage: %s [-rkfL] [-s v] [-R i] [-C i] [-n i] [-d c]\n", progname);
X	    exit(1);
X        }
X    }
X
X    if (optind < argc) {
X	    (void) fprintf(stderr,"Usage: %s [-rL] [-s v] [-R i] [-C i] [-n i] [-d c]\n", progname);
X	    exit(1);
X    }
X
X	/* setup the spreadsheet arrays */
X    if (!growtbl(GROWNEW, 0, 0))
X	exit(1);
X
X    curlen = 0;
X    curcol = c0; coff = 0;
X    currow = r0; roff = 0;
X    first = 1;
X
X    while(1) {
X
X	effr = currow+roff;
X	effc = curcol+coff;
X
X	switch(scan()) {
X	case END:
X	    if(drop_format) exit(0);
X	    for (i = 0; i<maxcols; i++) {
X		if (precision[i])
X		    (void) printf("format %s %d %d\n", coltoa(i), 
X			fwidth[i], precision[i]+1);
X	    }
X	    exit(0);
X	case NUM:
X	    first = 0;
X	    (void) printf("let %s%d = %s\n", coltoa(effc), effr, token);
X	    if (effc >= maxcols - 1)
X	    {	if (!growtbl(GROWCOL, 0, 0))
X		{	(void) fprintf(stderr, "Invalid column used: %s\n", coltoa(effc));
X			continue;
X		}
X	    }
X	    i = 0;
X	    j = 0;
X	    p = token;
X	    while (*p && *p != '.') {
X		p++; i++;
X	    }
X	    if (*p) {
X		p++; i++;
X	    }
X	    while (*p) {
X		p++; i++; j++;
X	    }
X	    if (precision[effc] < j)
X		precision[effc] = j;
X	    if (fwidth[effc] < i)
X		fwidth[effc] = i;
X	    break;
X	case ALPHA:
X	    first = 0;
X	    if (leftadj)
X		(void) printf("leftstring %s%d = \"%s\"\n", coltoa(effc),effr,token); 
X	    else
X		(void) printf("rightstring %s%d = \"%s\"\n",coltoa(effc),effr,token); 
X	    if (effc >= maxcols - 1)
X	    {	if (!growtbl(GROWCOL, 0, 0))
X		{	(void) fprintf(stderr, "Invalid column used: %s\n", coltoa(effc));
X			continue;
X		}
X	    }
X	    i = strlen(token);
X	    if (i > precision[effc])
X		precision[effc] = i;
X	    break;
X	case SPACE:
X	    if (first && strip_delim)
X		break;
X	    if (colfirst)
X		roff++;
X	    else
X		coff++;
X	    break;
X	case EOL:
X	    curlen++;
X	    roff = 0;
X	    coff = 0;
X	    first = 1;
X	    if (colfirst) {
X		if (curlen >= len) {
X		    curcol = c0;
X		    currow += rinc;
X		    curlen = 0;
X		} else {
X		    curcol += cinc;
X		}
X	    } else {
X		if (curlen >= len) {
X		    currow = r0;
X		    curcol += cinc;
X		    curlen = 0;
X		} else {
X		    currow += rinc;
X		}
X	    }
X	    break;
X	}
X    }
}
X
scan()
{
X    register int c;
X    register char *p;
X
X    p = token;
X    c = getchar();
X
X    if (c == EOF)
X	return(END);
X
X    if (c == '\n')
X	return(EOL);
X
X    if (c == delim1 || c == delim2) {
X        if (strip_delim) {
X	    while ((c = getchar()) && (c == delim1 || c == delim2))
X	        ;
X	    (void)ungetc(c, stdin);
X	} 
X	return(SPACE);
X    }
X
X    if (c == '\"') {
X	while ((c = getchar()) && c != '\"' && c != '\n' && c != EOF)
X	    *p++ = c;
X	if (c != '\"')
X	    (void)ungetc(c, stdin);
X	*p = 0;
X	return(ALPHA);
X    }
X
X    while (c != delim1 && c != delim2 && c!= '\n' && c != EOF) {
X	*p++ = c;
X	c = getchar();
X    }
X    *p = 0;
X    (void)ungetc(c, stdin);
X
X    p = token;
X    c = *p;
X    if (isdigit(c) || c == '.' || c == '-' || c == '+') {
X	while(isdigit(c) || c == '.' || c == '-' || c == '+' || c == 'e'
X	    || c == 'E') {
X		c = *p++;
X	}
X	if (c == 0)
X	    return(NUM);
X	else
X	    return(ALPHA);
X    }
X
X    return(ALPHA);
}
X    
getcol(p)
char *p;
{
X    register  col;
X
X    if (!p)
X	return(0);
X    while(*p && !isalpha(*p)) 
X	p++; 
X    if (!*p)
X	return(0);
X    col = ((*p & 0137) - 'A');
X    if (isalpha(*++p)) 
X	col = (col + 1)*26 + ((*p & 0137) - 'A');
X    return(col);
}
X
getrow(p)
char *p;
{
X    int row;
X
X    if (!p)
X	return(0);
X    while(*p && !isdigit(*p))
X	p++; 
X    if (!*p)
X	return(0);
X    if (sscanf(p, "%d", &row) != 1)
X	return(0);
X    return(row);
}
X
char *
coltoa(col)
int col;
{
X    static char rname[3];
X    register char *p = rname;
X
X    if (col < 0 || col > 25*26) 
X	(void) fprintf(stderr,"coltoa: invalid col: %d", col);
X
X    if (col > 25) {
X	*p++ = col/26 + 'A' - 1;
X	col %= 26;
X    }
X    *p++ = col+'A';
X    *p = 0;
X    return(rname);
}
X
SHAR_EOF
chmod 0666 psc.c ||
echo 'restore of psc.c failed'
Wc_c="`wc -c < 'psc.c'`"
test 5741 -eq "$Wc_c" ||
	echo 'psc.c: original size 5741, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= psc.doc ==============
if test -f 'psc.doc' -a X"$1" != X"-c"; then
	echo 'x - skipping psc.doc (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting psc.doc (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'psc.doc' &&
.\" $Revision $
.TH PPNAME 1
.SH NAME
ppname \- prepare pname files
.SH SYNOPSIS
.B ppname
[
.I -fLkr
]
[
.I -s cell
]
[
.I -R n
]
[
.I -C n
]
[
.I -n n
]
[
.I -d c
]
X
.SH DESCRIPTION
.I Ppname
is used to prepare data for input to the spread sheet calculator
.I pname(1).
It accepts normal ascii data on standard input.  Standard output
is a
.I pname
file.
With no options, 
.I ppname
starts the spread sheet in cell A0.  Strings are right justified.
All data on a line is entered on the same row; new input lines
cause the output row number to increment by one.  The default delimiters
are tab and space.  The column formats are set to one larger
than the number of columns required to hold the largest value
in the column.
X
Options:
X
.IP "\-f"
Omit column width calculations.  This option is for preparing
data to be merged with an existing spreadsheet.  If the option is not
specified, the column widths calculated for the data read by
.I ppname
will override those already set in the existing spreadsheet.
X
.IP "\-L"
Left justify strings.
X
.IP "\-k"
Keep all delimiters.  This option causes the output cell to change on
each new delimiter encountered in the input stream.   The default
action is to condense multiple delimters to one, so that the cell only
changes once per input data item.
X
.IP "\-r"
Output the data by row first then column.  For input consisting of a single
column, this
option will result in output of one row with multiple columns
instead of a single
column spread sheet.
X
.IP "\-s cell"
Start the top left corner of the spread sheet in 
.I cell.
For example, 
.I "-s B33"
will arrange the output data so that the
spread sheet starts in column B, row 33.
X
.IP "\-R n"
Increment by
.I n 
on each new output row.
X
.IP "\-C n"
Increment by
.I n 
on each new output column.
X
.IP "\-n n"
Output 
.I n
rows before advancing to the next column.  This option is used when
the input is arranged in a single column and the spread sheet is to
have multiple columns, each of which is to be length
.I n.
X
.IP "\-d c"
Use the single character
.I c
as the delimiter between input fields.
X
.SH SEE ALSO
pname(1)
X
.SH AUTHOR
X
Robert Bond
SHAR_EOF
chmod 0666 psc.doc ||
echo 'restore of psc.doc failed'
Wc_c="`wc -c < 'psc.doc'`"
test 2147 -eq "$Wc_c" ||
	echo 'psc.doc: original size 2147, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= psc.lnk ==============
if test -f 'psc.lnk' -a X"$1" != X"-c"; then
	echo 'x - skipping psc.lnk (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting psc.lnk (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'psc.lnk' &&
FROM LIB:c.o+"psc.o"+"pvmtbl.o"
TO "psc"
LIB lib:unix.lib
X    LIB:lc.lib LIB:amiga.lib
ADDSYM
X
SHAR_EOF
chmod 0666 psc.lnk ||
echo 'restore of psc.lnk failed'
Wc_c="`wc -c < 'psc.lnk'`"
test 95 -eq "$Wc_c" ||
	echo 'psc.lnk: original size 95, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= psc.uue ==============
if test -f 'psc.uue' -a X"$1" != X"-c"; then
	echo 'x - skipping psc.uue (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting psc.uue (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'psc.uue' &&
X
begin 666 psc
M```#\P`````````'``````````8```B%```!XP```&(```##```#9P```!@`;
M```,```#Z0``"(5(YW[^)$@D`$GY`````"QX``1'^0``!+AR`"`\```".6`"1
M)L%1R/_\*4\$^"E.!/!"K`3T<``B/```,`!.KO[.0_H!6G``3J[]V"E`#,1F^
M!G!D8```_"9N`10I:P"8!.Q*JP"L9V@@#Y"O`#@&@````(`I0`2\(&L`K-'(0
MT<@B:``0T\G3R2`"<@`2&2E)!0#0@5*`0F=2@`)`__Z?P%6`0G<(`"`"4X#4\
M@1^R```@`%."4<C_]A^\`"`@`%."'[$@`"``4<K_^")/+PE@<BEK`#H$O'!_?
M4H#1K`2\0>L`7$ZN_H!!ZP!<3J[^C"E`!/0O`"1`("H`)&<2+&P,Q"!`(B@`,
M`"E!!.Q.KO^"(BH`(&<:)#P```/M3J[_XBE`!/QG"N6(($`G:``(`*0@;`3T7
M+PA(;`2X(&@`)"EH``0%`$ZZ`&9.NAFV<`!@!"`O``0O`"`L!.1G!"!`3I!.S
MNA!.+'@`!")L#,1.KOYB3KH`/$JL!/1G&B(L!/QG!$ZN_]PL>``$3J[_?")LJ
M!/1.KOZ&(!\N;`3X3-]_?DYU9&]S+FQI8G)A<GD`3G5.=4CG`S`F;P`4+B\`/
M&$J'9@HO"TZZ"WQ83V!0(`MF"B\'3KH=KEA/8$(D2UF*+!)9AK7L#9AG"$*GS
M3KH=EEA/+P=.NAV.6$\D0$J`9QR\AV,"+`<@!B!+(DI@`A+84X!D^B\+3KH+%
M+%A/(`I,WPS`3G4```````!P84CG`Q`F;P`0($M*&&;\4XB1RRP(?@`>&TJ'1
M9S)3K`+B;18@;`+:0^@``2E)`MH@!Q"`<@`2`&#<(`=R`!(`2&P"UB\!3KH!(
M[E!/(@!@QDAL`M9(>/__3KH!W%!/(`9,WPC`3G4```````!P84Y5_]Q(YP\P\
M)F\`1'P`0>T`#"M(__(>&TH'9P`!"G`EO@!F``#,'AMP`!`'<AA=06L``(BP_
M>Q`(9O1.^Q`$`&1@``!0`'A@```:`'!@```4`'-@```"(&W_\B18*TC_\F!*1
M(&W_\B@8*TC_\D7M_^QZ!TJ%:Q8@!'(/P(%!^@#`T<`4D%.*Z(13A6#F0BW_[
M[6`:(&W_\B@8*TC_\B\$2&W_Y4ZZ&K!03T7M_^4O"DZZ_N183]R`8`#_7E*&7
M4ZP"XFT8(&P"VD/H``$I20+:(`<0@'(`$@!@`/\^<``0!TAL`M8O`$ZZ`.)0>
M3R(`8`#_*%*&4ZP"XFT8(&P"VD/H``$I20+:(`<0@'(`$@!@`/\(<``0!TALW
M`M8O`$ZZ`*Q03R(`8`#^\DAL`M9(>/__3KH`F"`&3.T,\/_$3EU.=3`Q,C,T\
M-38W.#E!0T1%1@```$CG(1`N+P`0)F\`%'#_OH!G8`@K````&V=8<C#"JP`8$
M2H%F3@@K``(`&V<8(@<700`@0>L`("=(``1T`2="``@@`6`N(&L`!")K`!"SB
MR&8$</]@'E.K``0@:P`$(`<0@`@K``<`&F<&4ZL`"&`$4JL`"$S?"(1.=4Y5T
M_^Q(YR\0+B\`-"9O`#@H!W`QP*L`&&<&</]@``)P""L`!P`:5L!$`$B`2,`LB
M`$JK`!1F``"$""L``@`;9GIP`"=```QR_[Z!9P`"0B\+3KH8BEA/2H!G#`CK<
M``4`&W#_8``"*@CK``$`&TH&9PX@*P`4(@!$@2=!``Q@""`K`!0G0``,4ZL`A
M#&T6(&L`!$/H``$G20`$(`<0@'(`$@!@$B`'<@`2`"\++P%A`/]24$\B`"`!4
M8``!U@@K``(`&V=8</^^@&8&<`!@``'"(`<;0/__2@9G(G(*OH%F''("+P%(T
M>@&R+RL`'"M!__!.N@T$3^\`#"H`8!IR`2\!2&W__R\K`!PK0?_P3KH,Z$_OF
M``PJ`'[_8```X`CK``$`&TH&9U)P_[Z`9TQ4JP`,<@J^@68F(&L`!$/H``$G?
M20`$$+P`#2(K``Q*@6L*+PLO`&$`_JY03U*K``P@:P`$0^@``2=)``0@!Q"`#
M(BL`#$J!:P`!''[_("L`!)"K`!`K0/_P9W((*P`&`!IG4DAX``)"IR\K`!Q.Q
MN@8T3^\`#"M`_^Q*!F<X4ZW_[&TR0J<O+?_L+RL`'$ZZ!A1(>``!2&W__2\KA
M`!Q.NACL3^\`&$JL!-!F"A`M__UR&K`!9\@O+?_P+RL`$"\K`!Q.N@P(3^\`B
M#"H`8`)Z`'#_NH!F"`CK``4`&V`,NJW_\&<&".L`!``;2@9G#B(K`!0D`42".
M)T(`#&`8""L``@`;9PAR`"=!``Q@""(K`!0G00`,(&L`$"=(``2^@&<N4ZL`N
M#&T6(&L`!$/H``$G20`$(`<0@'(`$@!@$B`'<@`2`"\++P%A`/V04$\B`'`P/
MP*L`&&<$</]@#'#_N(!F!'``8`(@!$S?"/1.74YU#0H`````````````<&%(5
MYP<0)F\`%`@K``<`&E;`1`!(@$C`+@!P,,"K`!AG"D*K``AP_V```5@(*P`'^
M`!MG%`@K``8`&V<,+PM(>/__3KK]&E!/2JL`%&8V0JL`"`@K``(`&V<2<`$G.
M0``40>L`("=(`!!@``"$+PM.NA7*6$]*@&=V".L`!0`;</]@``$`2@=G9E2KR
M``@@*P`(2H!N6B!K``1#Z``!)TD`!'P`'!`@!@R`````&F<N#(`````-9C)3I
MJP`(;10@:P`$0^@``2=)``1P`!`08```M"\+80#_+EA/8```J`CK``0`&W#__
M8```G"`&8```E@@K``$`&V9.".L````;+RL`%"\K`!`O*P`<3KH7"$_O``PJ2
M`$J%:@8(ZP`%`!M*A68&".L`!``;2H5O&DH'9PH@!42`)T``"&`$)T4`""!KT
M`!`G2``$<#+`JP`89Q9*!V<(</\G0``(8`9P`"=```AP_V`@4ZL`"&T2(&L`'
M!$/H``$G20`$<``0$&`(+PMA`/Z$6$],WPC@3G4``"YL!/A.NA="2'D````4"
M3KH%3```````````<&%(YR`P)F\`$"1+2A)G)'``$!)![`,E"#```0@`9PIRO
M`!(`=""2@F`$<@`2`!2!4HI@V"`+3-\,!$YU``````````!P84Y5__A(YP,P!
M)F\`("1O`"0N+P`H($I*&&;\4XB1RBP(($M*&&;\4XB1RR`((DO3P"M)__B\^
MAV,"+`<@!B!*8`(2V%.`9/H@;?_X0C!H`"`+3-\,P$Y=3G4@;P`$(`A*&&;\9
M4TB1P"`(3G4``"\+)F\`"'``$!-![`,E"#```P@`9P12BV#L(`LF7TYU("\`O
M""!O``1.5?_T(D]R"DZZ!DP&00`P$L%*@&;P(`D0X;_)9OI"$)"/3EU.=0``#
M("\`""!O``1.5?_T(D\B``)!``<&00`P$L'FB&;P(`D0X;_)9OI"$)"/3EU.7
M=0``,#$R,S0U-C<X.6%B8V1E9B`O``@@;P`$0^\`!#(``D$`#Q+[$-SHB&;R\
M(`DB#UB!$.&RB6;Z0A"0@4YU(&\`!")(<@!P`"\"#!``*V<&#!``+68"4D@0$
M&`0``#!M$@P```EN#"0!Y8'2@M*!TH!@Y@P1`"UF`D2!)!\@"%.`(&\`"""!1
MD(E.=4Y5_^A(YS,P)F\`."1O`#PI2PRP0>T`$'X`*TC_[$H29P``\GP`'!I!&
M[`,E"#```V@`9NIP);R`9@``I'`EL!)F)'P`(&P,L!P8*4@,L$'L`R4(,``#X
M:`!FZ'`EO(!GOB`'8```LG`JL!)G#"MM_^S_Z%BM_^Q@")'(4HHK2/_H0JW_S
M]"\M_^A(;?_T2'H`D"\*3KH'P$_O`!!([0`!__!*@%;!1`%(@4C!2H%G`B1`\
M)"W_]';_M(-F$DJ!9P)2ATJ';P0@!V!.(`-@2DJ"9P13K`RP2JW_\&8T(`=@4
M.'``(&P,L!`8*T#_]"E(#+`@;?_T0^P#)2`("#$``P@`9MX@+?_TL(9G`/\6<
M(`=@"%*'8`#_#"`'3-\,S$Y=3G4O!WX`(&P,L!X8*4@,L$J'9P0@!V`"</\NL
M'TYU```O!RXO``A2K`RT4ZP"XFT6(&P"VD/H``$I20+:(`<0@'(`$@!@%"`'9
M<@`2`$AL`M8O`4ZZ^)!03R(`+A].=4Y5```O"R9O``Q"K`RT2&T`#"\+2'K_)
MK$ZZ#K9(;`+62'C__TZZ^&`@+`RT)FW__$Y=3G4``"!O``0B2"(O``P@+P`(;
M8`(0P%.!9/H@"4YU``!(YP\0+B\`&"PO`!PJ+P`@+P=.N@0H6$\F0"`+9@1P_
M_V`>+P4O!B\K``1.N@)$3^\`#"@`2JP$T&<$</]@`B`$3-\(\$YU````````4
M``!P84CG`S`N+P`42H=N!G``8```I'`(OH!D`BX`(`=6@"X``D?__$7L`JPF;
M4B`+9T`@*P`$L(=M,K"'9@P@4R2(GZP"L"`+8&X@*P`$D(=R"+"!918@2]''6
M)(@D2"23)4``!)^L`K`@"V!,)$LF4V"\(`<B+`,@T(%3@$ZZ`JXB+`,@3KH"_
MABP`4(8@!E:`+``"1O_\+P9.N@326$\F0"`+9Q(O!B\+3KH1`BZ'80#_5%!/)
M8`)P`$S?#,!.=0``````````````````+PLF;P`((`MG$$*G3KH2,EA/($M9E
MB"E(#9AP`"9?3G5(YP$@+B\`#%*L#+P@;`RX4Z@`#&T6(F@`!$7I``$A2@`$;
M(`<2@'(`$@!@$B`'<@`2`"\(+P%.NO;$4$\B`$S?!(!.=4Y5``!(YP`P)F\`-
M$"1O`!1"K`R\*4L,N$AM`!`O"DAZ_YQ.N@S>+HM(>/__3KKVBB`L#+Q,[0P`*
M__A.74YU``!(YP,0+B\`$$?L`K0@"V<T""L``@`;9B@(*P`!`!MG("`K``206
MJP`0+`!*AF<2+P8O*P`0+RL`'$ZZ!#)/[P`,)E-@R"\'3KH/:%A/3-\(P$YU`
M``!(YS<0+B\`'"9O`"`L+P`D2JP$Z&<$3KH3<$*L!-`B!R0+)@8L;`S$3J[_D
MT"H`</^Z@&8.3J[_?"E`!-!P!2E`#,`@!4S?".Q.=0``````````````````\
M````````<&%(YS\`+B\`'"PO`"`J+P`D2JP$Z&<$3KH3$$*L!-`@!5.`(@<DO
M!B8`+&P,Q$ZN_[XH`'#_N(!F#DZN_WPI0`30<!8I0`S`(`4,@`````)G%@R`[
M`````6<(2H!F&"`&8!0@!-"&8`XB!W0`=@`L;`S$3J[_ODS?`/Q.=0``2.<W^
M$"XO`!PF;P`@+"\`)$JL!.AG!$ZZ$I1"K`30(@<D"R8&+&P,Q$ZN_]8J`'#_0
MNH!F#DZN_WPI0`30<`4I0`S`(`5,WPCL3G4``"\'+B\`"$JL!.AG!$ZZ$E(B)
M!RQL#,1.KO_<<``N'TYU2.<P`"0`)@%(0DA#Q,'&P,#!U$-(0D)"T(),WP`,_
M3G5*@&H``!Y$@$J!:@``#$2!80``($2!3G5A```81(!$@4YU2H%J```,1(%A4
M```&1(!.=2\"2$$T`68``")(0$A!2$(T`&<```:$P3`"2$`T`(3!,`)(0C("H
M)!].=2\#=A`,00"`9```!N&944,,00@`9```!NF964,,02``9```!N6954-*7
M06L```;CF5-#-`#FJ$A"0D+FJDA#@,$V`#`"-`-(0<3!D()D```(4T/0@63^D
M<@`R`TA#Y[A(0,%!)A\D'TYU+P<N+P`(<``I0`302H=K(KZL`IQL'"`'YX!!K
M[`MP2K`(`&<.(`?G@$'L"W#1P"`(8`AP"2E`#,!P`"X?3G4`````````````C
M`````$Y5__PO"R9O`!`@"V8$<`!@%B\+3KKXCB9`2&W__"\+3KKY/B`M__PF]
M;?_X3EU.=4Y5__A(YS$P+B\`)"!M`!0@$+"';09P`&```*P@$"(`Y8$@;0`,%
M)G`8`!(3="VR`F<,=B^R`V<&<`!@``"*(&T`%%*02BL``6<($"L``;`"9@1PL
M`&!P(&T`&!"K``$D;0`02A)G6A`2(&T`&!(0L@!F2DHK``)F"B!M`!0B$+*'M
M;0A!ZP`"(`A@/"!M`!0@$"(`Y8$@;0`,)'`8`!(2="VR`F<&="^R`F8(0>L`<
M`B`(8!0@;0`44I`@"F`*4HI@HD'K``(@"$S?#(Q.74YU``!(YP`R)FP,R"`+,
M9Q0D4R)+("L`""QX``1.KO\N)DI@Z)'(*4@,S"E(#,A,WTP`3G5(YP$R+B\`;
M%'`,WH`@!W(`+'@`!$ZN_SHF0"`+9@1P`&`Z)T<`"$7L#,@@:@`$)T@`!)'(^
M)HA*DF8")(M*J@`$9P8B:@`$(HLE2P`$2JP"H&8$*4L"H$'K``P@"$S?3(!.T
M=0``````````````````2.<',"XO`!@F;P`<+"\`("\'3KK^`%A/)$`@"F8$7
M</]@-@@J``,``V<02'@``D*G+P=.NOFD3^\`#"\&+PLO*@`$3KK[I$_O``PJK
M`$JL!-!G!'#_8`(@!4S?#.!.=0``3E7_Y$CG)S`F;0`()&T`%'``<@`2$RM`#
M__`K0/_L*T#_Z$'L`R4(,``"&`!G*"`M_^AR"DZZ_)IR`!(;=`_"@M"!*T#_\
MZ'``$!-![`,E"#```@@`9M@0$W)LL`%F"E*+<`$K0/_P8`YR:+`!9@A2BW`!/
M*T#_["!M``Q.D"X`<&.P$V<60>P#)0@P``-X`&<*(&T`#$Z0+@!@ZG#_OH!F)
M#"!M`!`@AW``8``#CG``$!,$0`!89P`!;`1```MG``+R4T!G*EE`9P`"E%]`W
M9P``WE-`9P`!0E=`9P`#'%5`9PI70&<``3Y@``-`?`!@-GP`2JW_Z&<*#*T`;
M```!_^AO)'`MOH!G!G(KOH%F&+Z`9@1P_V`"<``L`"!M``Q.D"X`4ZW_Z$'LK
M`R4(,``">`!F#"!M`!`@AW``8``"_D*M_^0@+?_D<@I.NON((@=T#\*"T($K5
M0/_D(&T`#$Z0+@!3K?_H9PQ![`,E"#```G@`9M`@"F<``KA*AFH$1*W_Y$JMS
M__!G#"!2("W_Y""`8``"GDJM_^QG#"!2("W_Y#"`8``"C"!2(*W_Y&```H)PO
M,+Z`;09P-[Z`;PP@;0`0((=P`&```G9"K?_D("W_Y.>`(@=T!\*"T($K0/_D]
M(&T`#$Z0+@!3K?_H9PQP,+Z`;09P-[Z`;]0@"F<``C1*K?_P9@P@4B`M_^0@9
M@&```B(@4B"M_^1@``(82JW_Z&8&<`@K0/_H0>P#)0@P``=X`&8,(&T`$""'V
M<`!@``(`*@<@;0`,3I`N`$JM_^AG"@RM`````O_H;SQP,+J`9C9P>+Z`9P9P]
M6+Z`9BH@;0`,3I`N`$'L`R4(,``'>`!F#"!M`!`@AW``8``!M$*M_^13K?_H+
M8$)![`,E"#```E@`9PH@!7(PD($K0/_D0>P#)0@P``!8`&<*(`5R-Y"!*T#__
MY$'L`R4(,``!6`!G"B`%<E>0@2M`_^13K?_H9V)![`,E"#``!W@`9U8@+?_DQ
MZ8`K0/_D0>P#)0@P``)X`&<*(`=R,)"!@:W_Y$'L`R4(,```>`!G"B`'<C>0P
M@8&M_^1![`,E"#```7@`9PH@!W)7D(&!K?_D(&T`#$Z0+@!@F"`*9P``[DJMN
M__!F#"!2("W_Y""`8```W"!2(*W_Y&```-)![`,E"#```G@`9@P@;0`0((=P@
M`&```,9\`"`&<@I.NOE4(@=T#\*"T($L`"!M``Q.D"X`4ZW_Z&<,0>P#)0@P2
M``)X`&;4(`IG``"&(%(@!C"`8'P@"F<((%)2DB`'$(!3K?_H;QP@;0`,3I`NL
M`'#_OH!G#B`*9^@@4E*2(`<0@&#></^^@&8*(&T`$""'<`!@2D'K``$@"&!"8
M(`IG""!24I(@!Q"`(&T`#$Z0+@!P_[Z`9Q)3K?_H9PQ![`,E"#```W@`9]0@N
M4D(08`1P`&`,(&T`$""'0>L``2`(3-\,Y$Y=3G5.5?_$2.<G,"9O`%PD;P!@6
M?@!\`'H`<``;?``@__MR`"M!__9T_RM"__)![?_0&T#_\1M`__PK0?_D*T'_1
MZ"M(_\Q*$V<L<``0$P1``"!G%%=`9Q110&<(54!F%GX!8`Y\`6`*>@%@!AM\W
M``'__%*+8-`0$W(PL`%F!E*+&T'_^W`JL!-F#"!26)(K4/_V4HM@#DAM__8O=
M"TZZ\H903]?`$!-R+K`!9B)2BW`JL!-F#"!26)(K4/_R4HM@#DAM__(O"TZZD
M\EQ03]?`$!-R;+`!9@H;?``!__%2BV`(<FBP`68"4HL0&W(`$@`;0/_P!$$`!
M6&<``7X$00`+9P`""E-!9R0$00`+9P`!$E-!9P`!4%=!9P`!NE5!9P``Y%=!I
M9P`!4F```?A*+?_Q9P@@4EB2(!!@!B!26)(@$"M`_^QL"G(!1*W_["M!_^A*?
MK?_H9P1P+6`*2@9G!'`K8`)P(!M`_]!P`!`&(BW_Z(*`<``0!8*`9PA2K?_,V
M4JW_Y"\M_^PO+?_,3KKP_E!/*T#_R"`M__)*@&H&<@$K0?_R("W_R"(M__*2%
M@$CM``+_Q&\T(&W_S")(T\$O`"\)+PA.N@:J3^\`#'``$"W_^R(M_\0@;?_,D
M8`(0P%.!9/H@+?_R*T#_R-&M_^1![?_0*TC_S$H'9P`!,!M\`"#_^V```29*;
M+?_Q9P@@4EB2(!!@!B!26)(@$"M`_^Q@`/]D2BW_\6<((%)8DB`08`8@4EB2'
M(!`K0/_L2BW__&<2(&W_S!#\`#!R`2M!_^0K2/_,+P`O+?_,3KKP8E!/*T#_^
MR&``_S(;?``P__L@+?_R2H!J!G`(*T#_\DHM__%G""!26)(@$&`&(%)8DB`0Z
M*T#_[$HM__QG%B!M_\P0_``P$/P`>'("*T'_Y"M(_\PO`"\M_\Q.NO!&4$\K\
M0/_(<%BP+?_P9@#^T$AM_]!.NN[N6$]@`/["(%)8DB)0*TG_S&8(0?H`V"M(_
M_\P@;?_,2AAF_%.(D>W_S"M(_^0@+?_R2H!K)K'`;R(K0/_D8!QP`2M`_^0@E
M4EB2(!`;0/_00BW_T6`&<`!@``",("W_Y"(M__:R@&P(=``K0O_V8`21K?_V>
M2@=G-E.M_^1M&'``(&W_S!`8+P`K2/_,(&T`$$Z06$]@XE.M__9M2'``$"W_M
M^R\`(&T`$$Z06$]@Z%.M__9M$G``$"W_^R\`(&T`$$Z06$]@Z%.M_^1M&'``@
M(&W_S!`8+P`K2/_,(&T`$$Z06$]@XB`+3-\,Y$Y=3G4``$Y5__1(YP$P)F\`0
M("1O`"0K;0`0__8>&DH'9S1P);X`9B*P$F8$4HI@&B\+2&W_]B\*80#\%D_O#
M``PK0/_Z9P0D0&#2<``0!R\`3I-83V#&3-\,@$Y=3G4``$Y5__!(YR$R)F\`C
M+`RL````(`T.;```AA`3<B"P`6<,<@FP`6<&<@JP`68$4HM@Z$H39V@@+`T.2
MY8!2K`T.0>P-%M'`)$AP(K`39B92BR2+2A-G"G`BL!-G!%*+8/)*$V8,2'@`$
M`4ZZ`BQ83V">0AM@FB2+2A-G&!`3<B"P`6<0<@FP`6<*<@JP`6<$4HM@Y$H3.
M9@)@!D(;8`#_<DJL#0YF!B!L!/1@!$'L#18I2`T22JP-#F9\0_H!)$WL#-0L;
MV2S9+-DLV3R1(FP$]"!I`"1(>``H+R@`!$AL#-1.NNT*3^\`#"QL#,1![`S4]
M(@@D/````^Y.KO_B*4`+="E`"WQR$"E!"W@I0`N$*4$+@.6`*T#_\"QX``23&
MR4ZN_MH@;?_P(D`C:``(`*1^`"M`__1@*BQL#,1.KO_**4`+=$ZN_\0I0`M\<
M0?H`IB(()#P```/M3J[_XBE`"X1^$"`'`$"``8&L"W`@!P!`@`*!K`MX`*P`3
M`(`#"X!*K`,<9P1P`&`&(#P``(``+@!"K`+0(`<`0``!*4`"S'`!*4`"\B`'"
M`$```BE``NYP`BE``Q0@!P!``(`I0`,00?H#SBE(!.@O+`T2+RP-#DZZ`"9"Y
METZZ\11,[4R$_]Q.74YU8V]N.C$P+S$P+S,R,"\X,"\`*@!.^0``````````<
M``````````!P84CG,#(L;P`X(&\`&")O`!PD;P`@)F\`)"`O`"@B+P`L)"\`\
M,"8O`#1.KOZD3-],#$YU```O"R9O``A*JP`49PP(*P`#`!MF!'``8#8O+`0HX
M3KKO(EA/)T``!"=``!!*@&8*<`PI0`S`</]@%B=L!"@`%'#SP:L`&'``)T``#
M#"=```@F7TYU``````````!P84CG!P`N+P`0("P"G%.`+`!*1FLP(`9(P.>`@
M0>P+<"HP"`!*!6<:"`4`!&84(`9(P.>`0>P+<"\P"`1.NO&06$]31F#,+P=.&
MNN-T6$],WP#@3G4``"`O``@@;P`$3E7_]")/;`80_``M1(!R"DZZ\=`&00`PB
M$L%*@&;P$.&_R6;Z0A`@"$Y=D*\`!$YU3E7_Z$CG`3(N+P`T2H=N!G#_8```(
MTG`(OH!D`BX`(`=6@"X``D?__"1M``@@+0`(T(??K`*P0>P"K"90*T#_\"M(K
M__0@"V<``)`@2R`K``31P"M(_^PB;?_PM\EC$"2+)4<`!"QM__0LBG``8'BW/
MR68:+%,DCB`K``0B`-*')4$`!"QM__0LBG``8%JUR&0(GZP"L'#_8$ZUR&8LL
M2I-G#B!3L\AC")^L`K!P_V`XWZL`!$J39PZSTV8*("D`!-&K``0FD7``8!XKB
M2__T*VW_[/_H)E-@`/]N(&W_]""*0I(E1P`$<`!,WTR`3EU.=0``2.<',"XOT
M`!@F;P`<+"\`("\'3KKQ0%A/)$`@"F8$</]@'B\&+PLO*@`$3KKOV$_O``PJ.
M`$JL!-!G!'#_8`(@!4S?#.!.=0``(&\`!")O``@@+P`,;Q:SR&4,T<#3P!,@4
M4X!F^DYU$MA3@&;Z3G4``$CG`3`N+P`02JP-F&<6)&P-F"\2+RP-F$ZZ_H90-
M3Y'(*4@-F$J'9@1P`&`>6(<O!TZZ[,983R9`2H!F!'``8`HD2R2'0>L`!"`(#
M3-\,@$YU3E7_J$CG`0(L>``$0_H`CG``3J[]V"M`_ZAF"DAX`!1.NOVB6$]^,
M`"!L!0`>*/__(`=#[?^P8`(2V%.`9/I"-7BP0>W_L"E(!#@O+?^H2'@`*$AXL
M`/IP`"\`+P!(;`14<@`O`4AL!$`O`4ZZ_,A(>``43KK]4$SM0(#_H$Y=3G4J#
M*B!3=&%C:R!/=F5R9FQO=R`J*@``15A)5```:6YT=6ET:6]N+FQI8G)A<GD`H
M``````````!P84Y5_YA(YS,"?@`@;`4`'BC__W!/OH!O`BX`(`=#[?^O8`(27
MV%.`9/I"-7BO+'@`!)/)3J[^VBM`_Z8@0$JH`*QG4B(H`*SE@2)!+"D`.$CM'
M``+_GDJ&9@0L*`"@2H9G-"QL#,0B!D'Z`+(D"'8+3J[_T"!'4H<@"!N\``H(^
MKRQL#,0B!B8'0>W_KR0(3J[_T'#_8%(L>``$0_H`C'``3J[]V"M`_YIF!'#_O
M8#I![?^O*4@$B"\M_YI(>``\2'@`^G``+P`O`$AL!*1(;`202&P$?$*G3KK[P
MID_O`"13@&<$</]@`G``3-]`S$Y=3G4J*B!5<V5R($%B;W)T(%)E<75E<W1E%
M9"`J*@``0T].5$E.544``$%"3U)4`"HJ*B!"<F5A:SH@`&EN='5I=&EO;BYL/
M:6)R87)Y`"\'<``B/```,``L>``$3J[^SBX``H<``#``2H=G($JL!.AG&B!L;
M!.A.D$J`9@)@#D*L!.A(>``43KK[FEA/+A].=6&\3G4``")O``@@;P`$(`@0P
MV6;\3G4```/L`````0````$``!SN`````@````0````4````"@````````/R2
M```#Z0```>-.5?_0O^P$O&4`!S)(YS<P+BT`""9M``PI4P4(2&P`)B\++P=.$
MN@<Z3^\`#"M`_^12@&<``-X@+?_D<D.0@6=L<@F0@6<P78!G4'(2D(%G``"`F
M58!G``"26X!G``"$5X!G7%F`9PA3@&<48```AG`!*4```&"F<`$I0``48)XOE
M+`ML80`%<"E```@NK`ML80`%YEA/*4``!&""+RP+;$ZZ!L983RE```Q@`/]R0
M+RP+;$ZZ!K183RE``!!@`/]@+RP+;$ZZ!J)83RE``!A@`/].(&P+;!E0`!Q"4
M+``=8`#_/D*L`!Y@`/\V<`$I0``B8`#_+"\L!0A(;``V2&P"^$ZZ!E1(>``!Q
M3KH&9$_O`!!@`/\,("P"E+"';!PO+`4(2&P`;$AL`OA.N@8L2'@``4ZZ!CQ/6
M[P`0<``O`"\`2'@``4ZZ!@Q/[P`,2H!F"DAX``%.N@8:6$]P`"ML``C_^"ML9
M``3_\'(!*T'_Z"M`_^PK0/_T*T#__"`M__#0K?_L+``@+?_XT*W_]"H`80`"D
MC@R`````!63@T$`P.P`&3OL`!``(`'`!.`'<`@!*K``B9PA"ITZZ!;A83T*M,
M_]@@+?_8L*P%%&Q$Y8`@;`40T<!*D&<R+RW_V&$`!/Y83R(M_]CE@2!L!0S1A
MP2)L!1#3P2(14H$O`2\0+P!(;`"@3KH%>D_O`!!2K?_88+)"ITZZ!5Y83T*M7
M_^@O!6$`!+Q83TAL!1@O!B\`2&P`LDZZ!4Q/[P`0("P%%%.`NH!M,G``+P`O$
M`$AX``-.N@4&3^\`#$J`9APO!6$`!(`N@$AL`,)(;`+X3KH$\$_O``Q@`/\*&
M<`!%[`48*T#_U"M`_]A*$F<.<"ZP$F<(4HI2K?_88.Y*$F<&4HI2K?_82A)G<
M#%**4JW_V%*M_]1@\"`%Y8`@;`40T<`@+?_4(A"R@&P"((`@!>6`(&P%#-'`F
M("W_V"(0LH!L`/ZD((!@`/Z>0JW_Z$JL`!1G'B\%80`#[EA/2&P%&"\&+P!(!
M;`#<3KH$?D_O`!!@'"\%80`#T%A/2&P%&"\&+P!(;`#T3KH$8$_O`!`@+`44G
M4X"Z@&TR<``O`"\`2'@``TZZ!!I/[P`,2H!F'"\%80`#E"Z`2&P!#DAL`OA.2
MN@0$3^\`#&``_AY(;`483KH#^EA/(@7E@2!L!1#1P2M`_]BPD&\`_@`@@&``T
M_?I*K?_H9PA*K``>9@#][$JL``!G"%*M_^Q@`/W>4JW_]&``_=92K?_\<`!RR
M`2M!_^@K0/_T*T#_[$JL``!G,"(L`!@D+?_\M(%M&"0L``@F+``,UZW_\"M`5
M__PK0O_X8`#]F"8L`!#7K?_X8`#]C"(M__RRK``8;1@B+``$)"P`$-6M__@KU
M0/_\*T'_\&``_6H@+``,T:W_\&``_5Z_[`2\90`#'$CG`1!'[`484ZP"O&T.4
M<``@;`*X$!@I2`*X8`I(;`*T3KH#+EA/+@!P_[Z`9@9P`&```9IP"KZ`9@9P#
M!&```8X0+``<2(!(P+"'9PP0+``=2(!(P+Z`9E9*K``>9TI3K`*\;0YP`"!LA
M`K@0&"E(`KA@"DAL`K1.N@+86$\N`"`'2H!G&!`L`!Q(@$C`L(=GSA`L`!U(]
M@$C`OH!GPDAL`K0O!TZZ`H)03W`#8``!('`BOH!F6%.L`KQM#G``(&P"N!`82
M*4@"N&`*2&P"M$ZZ`H)83RX`(`=*@&<8<"*^@&<2<`J^@&<,</^^@&<&(`<6;
MP&#"<"*^@&<,2&P"M"\'3KH")E!/0A-P`F```,(0+``<2(!(P+"'9SX0+``=:
M2(!(P+"'9S)P"KZ`9RQP_[Z`9R8@!Q;`4ZP"O&T.<``@;`*X$!@I2`*X8`I(5
M;`*T3KH"`EA/+@!@MD(32&P"M"\'3KH!QE!/1^P%&!X32(=(QT'L`R4(,``"J
M>`!F$G`NOH!G#'`MOH!G!G`KOH!F/D'L`R4(,``">`!F'G`NOH!G&'`MOH!GL
M$G`KOH!G#'!EOH!G!G!%OH!F"!X;2(=(QV#.2H=F!'`!8`9P`F`"<`),WPB`/
M3G6_[`2\90`!0DCG,1`F;P`4(`MF!'``8&1*$V<8$!-(@$C`<@-![`,EPC`(+
M`$H!9@12BV#D2A-F!'``8$`0&TB`2,!R7\"!+@!T09Z"$!-(@$C`=@-![`,E^
MQC`(`$H#9QH@!U*`<AI.N@$H$A-(@4C!=E_"@]"!+@">@B`'3-\(C$YU3E7_]
M_+_L!+QE``"\+PLF;0`((`MF!'``8$!*$V<6$!-(@$C`0>P#)0@P``((`&8$0
M4HM@YDH39@1P`&`>2&W__$AL`2@O"TZZ`,!/[P`,4X!G!'``8`0@+?_\)E].>
M74YUO^P$O&4``&!(YP$0+B\`#$?L!01*AVL(#(<```**;Q(O!TAL`2Q(;`+X>
M3KH`4D_O``QP&;Z`;Q@@!W(:3KH`+G)`T($6P"`'<AI.N@`@+@$@!W)!T($6_
MP$(30>P%!"`(3-\(@$YU3OD```B$3OD```^<3OD```/@3OD`````3OD```V@3
M3OD```D\3OD```*(3OD``!"L3OD```W@3OD```;\3OD```*03OD```I83OD`F
M``]\<&$```/L````"P````````=$```'@```!X8```=*```'=```!UP```=ZE
M```';@``!U8```=H```'/@````$````"```'4`````$````#```'8@``````-
M``/R```#Z0```&).5?_@O^P$O&4``5Y(YP<P+BT`""PM`!`J+`44<`&^@&8*T
M>A1\`"`&*4`%%'`#OH!G!G($OH%F2+Z`9B0,K````KX%%&<(#(8```*^;1)(4
M;`%B2&P"^$ZZ`1QP`&```/Z\K`44;P@J!G`*VH!@!'`*VH`,A0```KYO!BH\0
M```"OG`#OH!G#G`$OH!G"'(!OH%F``#$2JP%#&80(`7E@"\`3KH`S%A/)D!@:
M$B`%Y8`O`"\L!0Q.N@#$4$\F0"`+9A)(;`%B2&P"^$ZZ`*IP`&```(PI2P4,#
M2JP%$&80(`7E@"\`3KH`BEA/)$!@$B`%Y8`O`"\L!1!.N@""4$\D0"`*9A!(G
M;`%B2&P"^$ZZ`&AP`&!**4H%$"`L!10B`.6!(&P%#-'!(@62@.6!+P%"IR\(:
M3KH`3B`L!10B`.6!(&P%$-'!(@62@.6!+H%"IR\(3KH`,$_O`!0I1044<`%,R
M[0S@_\Q.74YU``!.^0``"(1.^0``'WQ.^0``#:!.^0```:Q.^0``#`AP80``;
M`^P````%`````````8(```%\```!<````78```%J`````````_(```/I````H
MP[_L!+QE``+*+P<N+P`((`=R,DZZ`N8O`$ZZ`LA83W``+A].=;_L!+QE``*F5
M2&P!@$ZZ`L)83W#_3G6_[`2\90`"D$AL`9Y.N@*L6$]P_TYUO^P$O&4``GI(R
M;`&\3KH"EEA/</].=;_L!+QE``)D2&P!W$ZZ`H!83W#_3G6_[`2\90`"3DAL@
M`?Q.N@)J6$]P_TYUO^P$O&4``CA(;`(:3KH"5%A/</].=;_L!+QE``(B+PLFO
M;P`(0>P".":(0>P"0B=(``0G?````-T`"'!E)T``#$'L`E`G2``00>P"4B=(N
M`!1![`)>)T@`&$'L`F`G2``<0>P"9B=(`"`F7TYUO^P$O&4``<Q(;`D`89Q8=
M3T'L"0`@"$YUO^P$O&4``;0O!RXO``A(;`DD80#_?EA/*4<)+$'L"20@""X?J
M3G6_[`2\90`!CB\+)F\`""\+2&P)2$ZZ`:Y(;`M(80#_3D_O``Q![`E(*4@+H
M2$'L"T@@""9?3G6_[`2\90`!6$YUO^P$O&4``4Y.=;_L!+QE``%$,#P`W4YUG
MO^P$O&4``38P/`#=3G6_[`2\90`!*'!E3G6_[`2\90`!''!E3G6_[`2\90`!Z
M$$'L`FH@"$YUO^P$O&4``0!(;`)T3KH!'%A/</].=4Y5__B_[`2\90``YDCG,
M`3`F;0`()&T`#$*G2'@!!$ZZ`0903RM`__A*@&8$</]@2DAX__XO"TZZ`-`NQ
M`"ZM__@O!TZZ`,I/[P`,2H!F!'#_8"@@;?_X)6@`?``.<``U0``(-4``"B\',
M3KH`DDAX`00O+?_X3KH`@'``3.T,@/_L3EU.=;_L!+QE``!F<`!.=;_L!+QE!
M``!:<`!.=;_L!+QE``!.<`!.=4Y5__R_[`2\90``/DCG`3`N+0`()FT`#"1M]
M`!!(;?__2&P"E"\*+PLO!TZY```0W$_O`!0I0`ML9@1P_V`"<`!,WPR`3EU.V
M=4[Y```(A$[Y````&$[Y````'$[Y````3$[Y`````$[Y````,$[Y```+TD[Y&
M```/?$[Y```B!$[Y`````````^P````%`````````K0```,"```"]@```OP`D
M``+2````!`````4```+>```"\````NH```+D`````@````8```+8```#"```N
M``````/R```#Z@```2X````````````````````!`````0```````$X@(`D`J
M```!`````')F3&MS.E(Z0SIN.F0Z``!5<V%G93H@)7,@6RUR:V9,72!;+7,@"
M=ET@6RU2(&E=(%LM0R!I72!;+6X@:5T@6RUD(&-="@!5<V%G93H@)7,@6RURW
M3%T@6RUS('9=(%LM4B!I72!;+4,@:5T@6RUN(&E=(%LM9"!C70H`9F]R;6%TC
M("5S("5D("5D"@``;&5T("5S)60@/2`E<PH``$EN=F%L:60@8V]L=6UN('5SV
M960Z("5S"@``;&5F='-T<FEN9R`E<R5D(#T@(B5S(@H`<FEG:'1S=')I;F<@`
M)7,E9"`]("(E<R(*``!);G9A;&ED(&-O;'5M;B!U<V5D.B`E<PH``"5D``!CR
M;VQT;V$Z(&EN=F%L:60@8V]L.B`E9`!4:&4@=&%B;&4@8V%N)W0@8F4@86YYF
M(&QO;F=E<@!4:&4@=&%B;&4@8V%N)W0@8F4@86YY('=I9&5R``!K:6QL*"D@$
M+2!.3U0@24U03$5-14Y4140@(2$A"@!P:7!E*"D@+2!.3U0@24U03$5-14Y4'
M140@(2$A"@!P;W!E;B@I("T@3D]4($E-4$Q%345.5$5$("$A(0H``'!C;&]SI
M92@I("T@3D]4($E-4$Q%345.5$5$("$A(0H`9'5P*"D@+2!.3U0@24U03$5-1
M14Y4140@(2$A"@``9F]R:R@I("T@3D]4($E-4$Q%345.5$5$("$A(0H`86UIV
M9V%U<V5R`'AX>'AX>'AX>'AX>'@```!!;6EG82!5<V5R`````%-94SH``'-H1
M``!A;6EG875S97(`97AE8VPH*2`M($Y/5"!)35!,14U%3E1%1"`A(2$*````?
M```!`````````"@``````````````````````````````M8`````````````!
M``````````````````````````````+X````````````````````````````Z
M`````````````````````````````````````````````````````````````
M``"`````!```("`@("`@("`@*"@H*"@@("`@("`@("`@("`@("`@("!($!`0D
M$!`0$!`0$!`0$!`0A(2$A(2$A(2$A!`0$!`0$!"!@8&!@8$!`0$!`0$!`0$!H
M`0$!`0$!`0$!`1`0$!`0$(*"@H*"@@("`@("`@("`@("`@("`@("`@("$!`0.
M$"`@("`@("`@("`H*"@H*"`@("`@("`@("`@("`@("`@($@0$!`0$!`0$!`0`
M$!`0$!"$A(2$A(2$A(2$$!`0$!`0$(&!@8&!@0$!`0$!`0$!`0$!`0$!`0$!_
M`0$!$!`0$!`0@H*"@H*"`@("`@("`@("`@("`@("`@("`@(0$!`0(```````W
M`@#__P````X`#@```````````````/__````!``$````````($P```0L__\`\
M```$``0````````@8@````#__P````X`#@```````"%R`````/__````!``$]
M``````````````1H__\````$``0````````AC@````#__P````0`!```````G
M`"&8`````````^P````%````````!+````2<```$=```!&````1,````!```Q
M``0```2,```$4````M8```*T`````````_(```/I````&$CG(`(L>0``#,1,!
M[P`&``Q.KO^L3-]`!$YU```O#BQY```,Q"(O``A.KO^F+%].=4CG(`(L>0``*
M#,1,[P`&``Q.KO^:3-]`!$YU```O#BQY```,Q"(O``A.KO\Z+%].=0```^P`A
M```$````!````%`````V````(`````8````````#\`````)?1&5L87D`````W
M`$P````"7T5X86UI;F4````P`````E]5;DQO8VL`````'`````)?3&]C:P``7
M```````````````#\@```^D````,+PXL>0``!/!,[P`#``A.KO\Z+%].=0``,
M+PXL>0``!/`B;P`(("\`#$ZN_RXL7TYU```#[`````(````$````'`````0`6
M```````#\`````)?1G)E94UE;0```!@````#7T%L;&]C365M````````````Y
&``````/RU
``
end
size 13776
SHAR_EOF
chmod 0644 psc.uue ||
echo 'restore of psc.uue failed'
Wc_c="`wc -c < 'psc.uue'`"
test 19322 -eq "$Wc_c" ||
	echo 'psc.uue: original size 19322, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= pvmtbl.c ==============
if test -f 'pvmtbl.c' -a X"$1" != X"-c"; then
	echo 'x - skipping pvmtbl.c (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting pvmtbl.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'pvmtbl.c' &&
#define PSC
#ifdef PSC
# include <stdio.h>
# include "sc.h"
# ifndef FALSE
#  define	FALSE	0
#  define	TRUE	1
# endif /* !FALSE */
# undef	error
# define error(msg)	fprintf(stderr, msg);
#else /* PSC */
# include <curses.h>
# include "sc.h"
#endif /* PSC */
X
extern	char	*malloc();
extern	char	*realloc();
X
#if defined(BSD42) || defined(BSD43)
#define	memcpy(dest, source, len)	bcopy(source, dest, (unsigned int)len);
#define	memset(dest, zero, len)		bzero((dest), (unsigned int)(len));
#endif
X
/*
X * check to see if *rowp && *colp are currently allocated, if not expand the
X * current size if we can.
X */
#ifndef PSC
void
checkbounds(rowp, colp)
int	*rowp;
int	*colp;
{
X	if (*rowp < 0)
X		*rowp = 0;
X	else if (*rowp >= maxrows)
X	{	if (*colp >= maxcols)
X		{	if (!growtbl(GROWBOTH, *rowp, *colp))
X			{	*rowp = maxrows -1;
X				*colp = maxcols -1;
X			}
X			return;
X		}
X		else
X		{	if (!growtbl(GROWROW, *rowp, 0))
X				*rowp = maxrows-1;
X			return;
X		}
X	}
X	if (*colp < 0) 
X		*colp = 0;
X	else if (*colp >= maxcols)
X	{	if (!growtbl(GROWCOL, 0, *colp));
X			*colp = maxcols-1;
X	}
}
#endif /* !PSC */
X	
X
#define GROWALLOC(newptr, oldptr, nelem, type, msg) \
X	if (oldptr == (type *)NULL) \
X		newptr = (type *)malloc((unsigned)(nelem*sizeof(type))); \
X	else \
X		newptr = (type *)realloc((char *)oldptr, \
X					 (unsigned)(nelem*sizeof(type))); \
X	if (newptr == (type *)NULL) \
X	{   error(msg); \
X	    return(FALSE); \
X	} \
X	oldptr = newptr /* wait incase we can't alloc */
X
static	char	nolonger[] = "The table can't be any longer";
static	char	nowider[] = "The table can't be any wider";
X
/*
X * grow the main && auxiliary tables (reset maxrows/maxcols as needed)
X * toprow &&/|| topcol tell us a better guess of how big to become.
X * we return TRUE if we could grow, FALSE if not....
X */
int
growtbl(rowcol, toprow, topcol)
int	rowcol;
int	toprow, topcol;
{
X	struct ent ***tbl2;
X	int	*fwidth2;
X	int	*precision2;
X	char	*col_hidden2;
X	char	*row_hidden2;
X	int	newrows, newcols;
X	int	i;
X
#ifndef PSC
X	newrows = maxrows;
#endif /* !PSC */
X
X	newcols = maxcols;
X	if (rowcol == GROWNEW)
X	{
#ifndef PSC
X		maxrows = toprow = 0;
X		/* when we first start up, fill the screen w/ cells */
X		{	int startval;
X			startval = LINES - RESROW;
X			newrows = startval > MINROWS ? startval : MINROWS;
X			startval = ((COLS) - RESCOL) / DEFWIDTH;
X			newcols = startval > MINCOLS ? startval : MINCOLS;
X		}
#else
X		newcols = MINCOLS;
#endif /* !PSC */
X		maxcols = topcol = 0;
X	}
#ifndef PSC
X	/* set how much to grow */
X	if ((rowcol == GROWROW) || (rowcol == GROWBOTH))
X	{	if (toprow > maxrows)
X			newrows = GROWAMT + toprow;
X		else
X			newrows += GROWAMT;
X	}
#endif /* !PSC */
X	if ((rowcol == GROWCOL) || (rowcol == GROWBOTH))
X	{	if ((rowcol == GROWCOL) && ((maxcols == ABSMAXCOLS) ||
X					(topcol >= ABSMAXCOLS)))
X		{	error(nowider);
X			return(FALSE);
X		}
X
X		if (topcol > maxcols)
X			newcols = GROWAMT + topcol;
X		else
X			newcols += GROWAMT;
X
X		if (newcols > ABSMAXCOLS)
X			newcols = ABSMAXCOLS;
X	}
X
#ifndef PSC
X	if ((rowcol == GROWROW) || (rowcol == GROWBOTH) || (rowcol == GROWNEW))
X	{
X		GROWALLOC(row_hidden2, row_hidden, newrows, char, nolonger);
X		memset(row_hidden+maxrows, 0, (newrows-maxrows)*sizeof(char));
X
X		/* alloc tbl row pointers */
X		GROWALLOC(tbl2, tbl, newrows, struct ent **, nolonger);
X		memset(tbl+maxrows, 0, (newrows-maxrows)*(sizeof(struct ent **)));
X	}
#endif /* !PSC */
X
X	if ((rowcol == GROWCOL) || (rowcol == GROWBOTH) || (rowcol == GROWNEW))
X	{
X		GROWALLOC(fwidth2, fwidth, newcols, int, nowider);
X		GROWALLOC(precision2, precision, newcols, int, nowider);
#ifdef PSC
X		memset(fwidth+maxcols, 0, (newcols-maxcols)*sizeof(int));
X		memset(precision+maxcols, 0, (newcols-maxcols)*sizeof(int));
X	}
#else
X		GROWALLOC(col_hidden2, col_hidden, newcols, char, nowider);
X		memset(col_hidden+maxcols, 0, (newcols-maxcols)*sizeof(char));
X		for (i = maxcols; i < newcols; i++) {
X			fwidth[i] = DEFWIDTH;
X			precision[i] = DEFPREC;
X		}
X
X		/* [re]alloc the space for each row */
X		for (i = 0; i < maxrows; i++)
X		{
X		    if ((tbl[i] = (struct ent **)realloc((char *)tbl[i],
X			(unsigned)(newcols * sizeof(struct ent **)))) == (struct ent **)0)
X			{	error(nowider);
X				return(FALSE);
X			}
X		    memset((char *)ATBL(tbl,i, maxcols), 0,
X			   (newcols-maxcols)*sizeof(struct ent **));
X		}
X	}
X	else
X		i = maxrows;
X
X	/* fill in the bottom of the table */
X	for (; i < newrows; i++)
X	{	if ((tbl[i] = (struct ent **)malloc((unsigned)(newcols *
X				sizeof(struct ent **)))) == (struct ent **)0)
X		{	error(nowider);
X			return(FALSE);
X		}
X		memset((char *)tbl[i], 0, newcols*sizeof(struct ent **));
X	}
X
X	FullUpdate++;
X	maxrows = newrows;
#endif /* PSC */
X
X	maxcols = newcols;
X	return(TRUE);
}
SHAR_EOF
chmod 0666 pvmtbl.c ||
echo 'restore of pvmtbl.c failed'
Wc_c="`wc -c < 'pvmtbl.c'`"
test 4655 -eq "$Wc_c" ||
	echo 'pvmtbl.c: original size 4655, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= range.c ==============
if test -f 'range.c' -a X"$1" != X"-c"; then
	echo 'x - skipping range.c (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting range.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'range.c' &&
X
/*	SC	A Spreadsheet Calculator
X *		Range Manipulations
X *
X *              Robert Bond, 4/87
X *
X *		$Revision: 6.8 $
X */
X
#include <stdio.h>
#include <curses.h>
#include <ctype.h>
#include "sc.h"
X
#ifdef BSD42
#include <strings.h>
#else
#ifndef SYSIII
#include <string.h>
#endif
#endif
X
static struct range *rng_base;
X
add_range(name, left, right, is_range)
char *name;
struct ent_ptr left, right;
int is_range;
{
X    struct range *r;
X    register char *p;
X    int len;
X    int minr,minc,maxr,maxc;
X    int minrf, mincf, maxrf, maxcf;
X
X    if (left.vp->row < right.vp->row) {
X	minr = left.vp->row; minrf = left.vf & FIX_ROW;
X	maxr = right.vp->row; maxrf = right.vf & FIX_ROW;
X    } else {
X	minr = right.vp->row; minrf = right.vf & FIX_ROW;
X	maxr = left.vp->row; maxrf = right.vf & FIX_ROW;
X    } 
X
X    if (left.vp->col < right.vp->col) {
X	minc = left.vp->col; mincf = left.vf & FIX_COL;
X	maxc = right.vp->col; maxcf = right.vf & FIX_COL;
X    } else {
X	minc = right.vp->col; mincf = right.vf & FIX_COL;
X	maxc = left.vp->col; maxcf = left.vf & FIX_COL;
X    } 
X
X    left.vp = lookat(minr, minc);
X    left.vf = minrf | mincf;
X    right.vp = lookat(maxr, maxc);
X    right.vf = maxrf | maxcf;
X
X    if (find_range(name, strlen(name), (struct ent *)0, (struct ent *)0)) {
X	error("Error: range name already defined");
X	xfree(name);
X	return;
X    }
X
X    if (strlen(name) <= 2) {
X	error("Invalid range name - too short");
X	xfree(name);
X	return;
X    }
X
X    for(p=name, len=0; *p; p++, len++)
X	if (!((isalpha(*p) && (len<=2)) ||
X	    ((isdigit(*p) || isalpha(*p) || (*p == '_')) && (len>2)))) {
X	    error("Invalid range name - illegal combination");
X	    xfree(name);
X	    return;
X        }
X
X    r = (struct range *)xmalloc((unsigned)sizeof(struct range));
X    r->r_name = name;
X    r->r_left = left;
X    r->r_right = right;
X    r->r_next = rng_base;
X    r->r_prev = (struct range *)0;
X    r->r_is_range = is_range;
X    if (rng_base)
X        rng_base->r_prev = r;
X    rng_base = r;
}
X
del_range(left, right)
struct ent *left, *right;
{
X    register struct range *r;
X    int minr,minc,maxr,maxc;
X
X    minr = left->row < right->row ? left->row : right->row;
X    minc = left->col < right->col ? left->col : right->col;
X    maxr = left->row > right->row ? left->row : right->row;
X    maxc = left->col > right->col ? left->col : right->col;
X
X    left = lookat(minr, minc);
X    right = lookat(maxr, maxc);
X
X    if (!(r = find_range((char *)0, 0, left, right))) 
X	return;
X
X    if (r->r_next)
X        r->r_next->r_prev = r->r_prev;
X    if (r->r_prev)
X        r->r_prev->r_next = r->r_next;
X    else
X	rng_base = r->r_next;
X    xfree((char *)(r->r_name));
X    xfree((char *)r);
}
X
clean_range()
{
X    register struct range *r;
X    register struct range *nextr;
X
X    r = rng_base;
X    rng_base = (struct range *)0;
X
X    while (r) {
X	nextr = r->r_next;
X	xfree((char *)(r->r_name));
X	xfree((char *)r);
X	r = nextr;
X    }
}
X
/* Match on name or lmatch, rmatch */
X
struct range *
find_range(name, len, lmatch, rmatch)
char *name;
int len;
struct ent *lmatch;
struct ent *rmatch;
{
X    struct range *r;
X    register char *rp, *np;
X    register int c;
X
X    if (name) {
X	for (r = rng_base; r; r = r->r_next) {
X	    for (np = name, rp = r->r_name, c = len;
X		 c && *rp && (*rp == *np);
X		 rp++, np++, c--) /* */;
X	    if (!c && !*rp)
X		return(r);
X	}
X	return((struct range *)0);
X    }
X
X    for (r = rng_base; r; r= r->r_next) {
X	if ((lmatch == r->r_left.vp) && (rmatch == r->r_right.vp)) 
X	    return(r);
X    }
X    return((struct range *)0);
}
X
sync_ranges()
{
X    register struct range *r;
X
X    r = rng_base;
X    while(r) {
X	r->r_left.vp = lookat(r->r_left.vp->row, r->r_left.vp->col);
X	r->r_right.vp = lookat(r->r_right.vp->row, r->r_right.vp->col);
X	r = r->r_next;
X    }
}
X
write_range(f)
FILE *f;
{
X    register struct range *r;
X
X    for (r = rng_base; r; r = r->r_next) {
X	(void) fprintf(f, "define \"%s\" %s%s%s%d",
X			r->r_name,
X			r->r_left.vf & FIX_COL ? "$":"",
X			coltoa(r->r_left.vp->col), 
X			r->r_left.vf & FIX_ROW ? "$":"",
X			r->r_left.vp->row);
X	if (r->r_is_range)
X	    (void) fprintf(f, ":%s%s%s%d\n",
X			    r->r_right.vf & FIX_COL ? "$":"",
X			    coltoa(r->r_right.vp->col), 
X			    r->r_right.vf & FIX_ROW ? "$":"",
X			    r->r_right.vp->row);
X	else
X	    (void) fprintf(f, "\n");
X    }
}
X
void
list_range(f)
FILE *f;
{
X    register struct range *r;
X
X    (void) fprintf(f, "%-30s %s\n\n","Name","Definition");
X
X    for (r = rng_base; r; r = r->r_next) {
X	(void) fprintf(f, "%-30s %s%s%s%d",
X			    r->r_name,
X			    r->r_left.vf & FIX_COL ? "$":"",
X			    coltoa(r->r_left.vp->col), 
X			    r->r_left.vf & FIX_ROW ? "$":"",
X			    r->r_left.vp->row);
X	if (r->r_is_range)
X	    (void) fprintf(f, ":%s%s%s%d\n",
X			    r->r_right.vf & FIX_COL ? "$":"",
X			    coltoa(r->r_right.vp->col), 
X			    r->r_right.vf & FIX_ROW ? "$":"",
X			    r->r_right.vp->row);
X	else
X	    (void) fprintf(f, "\n");
X    }
}
X
char *
v_name(row, col)
int row, col;
{
X    struct ent *v;
X    struct range *r;
X    static char buf[20];
X
X    v = lookat(row, col);
X    if (r = find_range((char *)0, 0, v, v)) {
X	return(r->r_name);
X    } else {
X        (void) sprintf(buf, "%s%d", coltoa(col), row);
X	return(buf);
X    }
}
X
char *
r_name(r1, c1, r2, c2)
int r1, c1, r2, c2;
{
X    struct ent *v1, *v2;
X    struct range *r;
X    static char buf[100];
X
X    v1 = lookat(r1, c1);
X    v2 = lookat(r2, c2);
X    if (r = find_range((char *)0, 0, v1, v2)) {
X	return(r->r_name);
X    } else {
X        (void) sprintf(buf, "%s", v_name(r1, c1));
X	(void) sprintf(buf+strlen(buf), ":%s", v_name(r2, c2));
X	return(buf);
X    }
}
X
are_ranges()
{
return (rng_base != 0);
}
SHAR_EOF
chmod 0666 range.c ||
echo 'restore of range.c failed'
Wc_c="`wc -c < 'range.c'`"
test 5604 -eq "$Wc_c" ||
	echo 'range.c: original size 5604, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= readme ==============
if test -f 'readme' -a X"$1" != X"-c"; then
	echo 'x - skipping readme (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting readme (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'readme' &&
This is a much modified version of the public domain spread sheet sc,
posted several years ago by Mark Weiser as vc, originally by James Gosling.
X
Changes since my last version (5.1) are detailed at great length :-)
in CHANGES (sequent!rgb (Robert Bond)).
X
When you get it built, try "sc tutorial.sc" for a simple introduction
to the basic commands.
X
A new input parser program (psc) has been included.  This program
formats ascii files for use in the spread sheet.  If you don't have
getopts, there is a public domain version by Henry Spencer hidden away
in the VMS_NOTES file.
X
I have modified the makefile to make it easy for you to call the
program what you want (I saw at least five different names in
correspondence and on the net).  Just change "name=sc" and "NAME=SC" to
"name=myfavoritename" and "NAME=MYFAVORITENAME" and try "make
myfavoritename".
X
Similarly, you can make the documentation with "make myfavoritename.man".
"make install" will make and install the code in EXDIR.  The
installation steps and documentation all key off of the name.  The
makefile even changes the name in the nroffable man page.  If you don't
have nroff, you will have to change sc.man yourself.
X
This release has been tested against a Sequent S81 running DYNIX 3.0.14
(BSD 4.2) and an ICM-3216 with system V.3.  The ICM has a National Semi
32016.  Just check the makefile for the system flags.   I have heard
reports of lots of other machines that work. If you have problems with
lex.c, and don't care about arrow keys, define SIMPLE (-DSIMPLE in the
makefile).  SIMPLE causes the arrow keys to not be used.
X
Guidelines for Hackers:
X
If you want to send changes you have made to SC, please feel free to do
so.  If they work :-) and seem worthwhile, I'll put them in.  Please
refrain from wholesale "style" or "cleanup" changes.  It is easy to add
your changes but it makes it hard to merge in the next guy's stuff if
he used the release as a base.  Leave my $Revision:  identifiers alone-
they help me track what you used as a base.  If you check the code into
rcs, delete the "$"s on the Revison lines before you do.
X
You may not like 4 space indenting and curly braces on the "if" line,
but your code will look like that before it leaves my hands so you may
as well abide by the style in the code when you make your changes.  I
have also been known to break things trying to make them look "right".
If you do string functions, please, PLEASE pay attention to null
pointers, use xmalloc and xfree, and xfree those arguments.  And
don't forget to document your changes in both help.c and sc.doc.
X
Disclaimer:
X
Starting 4/4/90: (I will be maintaining Sc for a while at least,
X	Robert Bond has been very busy lately)
Sc is not a product of Grauel Enterprises, Inc.  It is supplied as
is with no warranty, express or implied, as a service to Usenet readers.
It is not copyrighted, either.  Have at it.
X
X					Jeff Buhrt
X					Grauel Enterprises, Inc.
X	{pur-phy (aka: newton.physics.purdue.edu), sequent}!sawmill!buhrt
SHAR_EOF
chmod 0666 readme ||
echo 'restore of readme failed'
Wc_c="`wc -c < 'readme'`"
test 3004 -eq "$Wc_c" ||
	echo 'readme: original size 3004, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= sc.c ==============
if test -f 'sc.c' -a X"$1" != X"-c"; then
	echo 'x - skipping sc.c (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting sc.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'sc.c' &&
/*	SC	A Spreadsheet Calculator
X *		Main driver
X *
X *		original by James Gosling, September 1982
X *		modifications by Mark Weiser and Bruce Israel,
X *			University of Maryland
X *
X *              More mods Robert Bond, 12/86
X *		More mods by Alan Silverstein, 3-4/88, see list of changes.
X *		Currently supported by pur-phy!sawmill!buhrt (Jeff Buhrt)
X *		$Revision: 6.8 $
X *
X */
X
X
#include <signal.h>
#include <curses.h>
#include <ctype.h>
X
#ifdef AMIGA
#include <unix.h>
#endif
X
#ifdef BSD42
#include <strings.h>
#else
#ifndef SYSIII
#include <string.h>
#endif
#endif
X
#include <stdio.h>
#include "sc.h"
X
char *getenv();
X
#ifdef SYSV3
void exit();
#endif
X
#ifndef DFLT_PAGER
#define	DFLT_PAGER "more"	/* more is probably more widespread than less */
#endif /* DFLT_PAGER */
X
#define MAXCMD 160	/* for ! command below */
X
extern	char	*rev;
X
/* Globals defined in sc.h */
X
struct ent ***tbl;
int strow, stcol;
int currow, curcol;
int savedrow, savedcol;
int FullUpdate;
int maxrow, maxcol;
int maxrows, maxcols;
int *fwidth;
int *precision;
char *col_hidden;
char *row_hidden;
char line[FBUFLEN];
int changed;
struct ent *to_fix;
int modflg;
int numeric;
char *mdir;
int showsc, showsr;	/* Starting cell for highlighted range */
char mode_ind = '.';
X
char curfile[PATHLEN];
char    revmsg[80];
X
int  linelim = -1;
X
int  showtop   = 1;	/* Causes current cell value display in top line  */
int  showcell  = 1;	/* Causes current cell to be highlighted	  */
int  showrange = 0;	/* Causes ranges to be highlighted		  */
int  showneed  = 0;	/* Causes cells needing values to be highlighted  */
int  showexpr  = 0;	/* Causes cell exprs to be displayed, highlighted */
X
int  autocalc = 1 ;	/* 1 to calculate after each update */
int  calc_order = BYROWS;
int  tbl_style = 0;	/* headers for T command output */
X
int  lastmx, lastmy;	/* Screen address of the cursor */
int  lastcol;		/* Spreadsheet Column the cursor was in last */
char under_cursor[] = " "; /* Data under the < cursor */
X
#ifdef VMS
int VMS_read_raw = 0;
#endif
X
int seenerr;
X
void
yyerror(err)
char *err; {
X    if (seenerr) return;
X    seenerr++;
X    (void) move(1,0);
X    (void) clrtoeol();
X    (void) printw("%s: %.*s<=%s",err,linelim,line,line+linelim);
}
X
struct ent *
lookat(row,col)
int	row, col;
{
X    register struct ent **pp;
X
X    checkbounds(&row, &col);
X    pp = ATBL(tbl, row, col);
X    if (*pp == (struct ent *)0) {
X	*pp = (struct ent *) xmalloc((unsigned)sizeof(struct ent));
X	if (row>maxrow) maxrow = row;
X	if (col>maxcol) maxcol = col;
X	(*pp)->label = (char *)0;
X	(*pp)->row = row;
X	(*pp)->col = col;
X	(*pp)->flags = 0;
X	(*pp)->expr = (struct enode *)0;
X	(*pp)->v = (double) 0.0;
X	(*pp)->evnext = (struct ent *)0;
X    }
X    return *pp;
}
X
/*
X * This structure is used to keep ent structs around before they
X * are deleted to allow the sync_refs routine a chance to fix the
X * variable references.
X * We also use it as a last-deleted buffer for the 'p' command.
X */
X
void
free_ent(p)
register struct ent *p;
{
X    p->next = to_fix;
X    to_fix = p;
X    p->flags |= is_deleted;
}
X
void
flush_saved()
{
X    register struct ent *p;
X    register struct ent *q;
X
X    if (!(p = to_fix))
X	return;
X    while (p) {
X	(void) clearent(p);
X	q = p->next;
X	xfree((char *)p);
X	p = q;
X    }
X    to_fix = 0;
}
X
/*
X * standout last time in update()?
X *	At this point we will let curses do work
X */
int	standlast	= FALSE;
X
void
update (anychanged)
int	anychanged;	/* did any cell really change in value? */
{
X    register    row,
X                col;
X    register struct ent **pp;
X    int     mxcol;
X    int     mxrow;
X    int     rows;
X    int     cols;
X    int     minsr, minsc, maxsr, maxsc;
X    register r;
X    register i;
X
X    while (row_hidden[currow])   /* You can't hide the last row or col */
X	currow++;
X    while (col_hidden[curcol])
X	curcol++;
X    /* First see if the last display still covers curcol */
X    if (stcol <= curcol) { 
X	for (i = stcol, cols = 0, col = RESCOL;
X			(col + fwidth[i]) < COLS-1 && i < maxcols; i++) {
X	    cols++;
X	    if (col_hidden[i])
X		continue;
X	    col += fwidth[i];
X	}
X    }
X    while (stcol + cols - 1 < curcol || curcol < stcol) {
X	FullUpdate++;
X	if (stcol - 1 == curcol) {    /* How about back one? */
X	    stcol--;
X	} else if (stcol + cols == curcol) {   /* Forward one? */
X	    stcol++;
X	} else {
X	    /* Try to put the cursor in the center of the screen */
X	    col = (COLS - RESCOL - fwidth[curcol]) / 2 + RESCOL; 
X	    stcol = curcol;
X	    for (i=curcol-1; i >= 0 && col-fwidth[i] > RESCOL; i--) {
X		stcol--;
X		if (col_hidden[i])
X		    continue;
X		col -= fwidth[i];
X	    }
X	}
X	/* Now pick up the counts again */
X	for (i = stcol, cols = 0, col = RESCOL;
X			(col + fwidth[i]) < COLS-1 && i < maxcols; i++) {
X	    cols++;
X	    if (col_hidden[i])
X		continue;
X	    col += fwidth[i];
X	}
X    }
X    /* Now - same process on the rows */
X    if (strow <= currow) { 
X	for (i = strow, rows = 0, row=RESROW; row<LINES && i<maxrows; i++) {
X	    rows++;
X	    if (row_hidden[i])
X		continue;
X	    row++;
X	}
X    }
X    while (strow + rows - 1 < currow || currow < strow) {
X	FullUpdate++;
X	if (strow - 1 == currow) {    /* How about up one? */
X	    strow--;
X	} else if (strow + rows == currow) {   /* Down one? */
X	    strow++;
X	} else {
X	    /* Try to put the cursor in the center of the screen */
X	    row = (LINES - RESROW) / 2 + RESROW; 
X	    strow = currow;
X	    for (i=currow-1; i >= 0 && row-1 > RESROW; i--) {
X		strow--;
X		if (row_hidden[i])
X		    continue;
X		row--;
X	    }
X	}
X	/* Now pick up the counts again */
X	for (i = strow, rows = 0, row=RESROW; row<LINES && i<maxrows; i++) {
X	    rows++;
X	    if (row_hidden[i])
X		continue;
X	    row++;
X	}
X    }
X    mxcol = stcol + cols - 1;
X    mxrow = strow + rows - 1;
X    if (FullUpdate || standlast) {
X	(void) move(2, 0);
X	(void) clrtobot();
X	(void) standout();
X	for (row=RESROW, i=strow; i <= mxrow; i++) {
X	    if (row_hidden[i]) 
X		continue;
X	    (void) move(row,0);
X	    if (maxrows < 1000)
X		(void) printw("%-*d", RESCOL-1, i);
X	    else
X		(void) printw("%-*d", RESCOL, i);
X	    row++;
X	}
X	(void) move(2,0);
X	(void) printw("%*s", RESCOL, " ");
X
X	for (col=RESCOL, i = stcol; i <= mxcol; i++) {
X	    register int k;
X	    if (col_hidden[i])
X		continue;
X	    (void) move(2, col);
X	    k = fwidth[i]/2;
X	    if (k == 0)
X		(void) printw("%1s", coltoa(i));
X	    else
X	        (void) printw("%*s%-*s", k, " ", fwidth[i]-k, coltoa(i));
X	    col += fwidth[i];
X	}
X	(void) standend();
X    }
X
X    /* Get rid of cursor standout on the cell at previous cursor position */
X    if (showcell)
X    {	(void) move(lastmx, lastmy);
X        repaint(lastmx, lastmy, fwidth[lastcol]);
X    }
X
X    if (showrange) {
X	minsr = showsr < currow ? showsr : currow;
X	minsc = showsc < curcol ? showsc : curcol;
X	maxsr = showsr > currow ? showsr : currow;
X	maxsc = showsc > curcol ? showsc : curcol;
X
X	if (showtop) {
X	    (void) move(1,0);
X	    (void) clrtoeol();
X	    (void) printw("Default range:  %s",
X			    r_name(minsr, minsc, maxsr, maxsc));
X	}
X    }
X
X    /* Repaint the visible screen */
X    if (showrange || anychanged || FullUpdate || standlast)
X    {
X	/* may be reset in loop, if not next time we will do a FullUpdate */
X      if (standlast)
X      {	FullUpdate = TRUE;
X	standlast = FALSE;
X      }
X      for (row = strow, r = RESROW; row <= mxrow; row++) {
X	register c = RESCOL;
X	int do_stand = 0;
X	int fieldlen;
X	int nextcol;
X
X	if (row_hidden[row])
X	    continue;
X	for (pp = ATBL(tbl, row, col = stcol); col <= mxcol;
X	         pp += nextcol - col,  col = nextcol, c += fieldlen) {
X
X	    nextcol = col+1;
X	    if (col_hidden[col]) {
X		fieldlen = 0;
X		continue;
X	    }
X
X	    fieldlen = fwidth[col];
X
X	    /*
X	     * Set standout if:
X	     *
X	     * - showing ranges, and not showing cells which need to be filled
X	     *	 in, and not showing cell expressions, and in a range, OR
X	     *
X	     * - if showing cells which need to be filled in and this one is
X	     *	 of that type (has a value and doesn't have an expression,
X	     *	 or it is a string expression), OR
X	     *
X	     * - if showing cells which have expressions and this one does.
X	     */
X
X	    if ((showrange && (! showneed) && (! showexpr)
X			   && (row >= minsr) && (row <= maxsr)
X			   && (col >= minsc) && (col <= maxsc))
X		    || (showneed && (*pp) && ((*pp) -> flags & is_valid)
X			&& (((*pp) -> flags & is_strexpr) || !((*pp) -> expr)))
X		    || (showexpr && (*pp) && ((*pp) -> expr)))
X	    {
X		(void) move(r, c);
X		(void) standout();
X		standlast++;
X		if (!*pp)	/* no cell, but standing out */
X		{	(void) printw("%*s", fwidth[col], " ");
X			(void) standend();
X			continue;
X		}
X		else
X			do_stand = 1;
X	    }
X	    else
X		do_stand = 0;
X
X	    if ((*pp) && ((*pp) -> flags & is_changed || FullUpdate) || do_stand) {
X		if (do_stand) {
X		    (*pp) -> flags |= is_changed; 
X		} else {
X		    (void) move(r, c);
X		    (*pp) -> flags &= ~is_changed;
X		}
X
X		/*
X		 * Show expression; takes priority over other displays:
X		 */
X
X		if (showexpr && ((*pp) -> expr)) {
X		    linelim = 0;
X		    editexp(row, col);		/* set line to expr */
X		    linelim = -1;
X		    showstring(line, /* leftflush = */ 1, /* hasvalue = */ 0,
X				row, col, & nextcol, mxcol, & fieldlen, r, c);
X		}
X		else {
X
X		    /*
X		     * Show cell's numeric value:
X		     */
X
X		    if ((*pp) -> flags & is_valid) {
X			char field[FBUFLEN];
X			(void)sprintf(field,"%*.*f", fwidth[col], precision[col], (*pp)->v);
X			if(strlen(field) > fwidth[col]) {
X			    for(i = 0; i<fwidth[col]; i++)
X				(void)addch('*');
X			} else {
X			    (void)addstr(field);
X			}
X		    }
X
X		    /*
X		     * Show cell's label string:
X		     */
X
X		    if ((*pp) -> label) {
X			showstring((*pp) -> label,
SHAR_EOF
true || echo 'restore of sc.c failed'
fi
echo 'End of  part 4'
echo 'File sc.c is continued in part 5'
echo 5 > _shar_seq_.tmp
exit 0
--
Simon J Raybould    (sie@fulcrum.bt.co.uk)            //              {o.o}
                                                    \X/AMIGA           \-/
===========================================================================
British Telecom Fulcrum, Fordrough Lane, Birmingham, B9 5LD, ENGLAND.