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<``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.