rsalz@bbn.com (Rich Salz) (09/05/90)
Submitted-by: Jeff Buhrt <sawmill!buhrt> Posting-number: Volume 23, Issue 24 Archive-name: sc6.8/part04 #! /bin/sh # This is a shell archive. Remove anything before this line, then feed it # into a shell via "sh file" or similar. To overwrite existing files, # type "sh file -c". # The tool that generated this appeared in the comp.sources.unix newsgroup; # send mail to comp-sources-unix@uunet.uu.net if you want that tool. # Contents: cmds.c lex.c psc.c xmalloc.c # Wrapped by rsalz@litchi.bbn.com on Fri Jul 13 15:24:21 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH echo If this archive is complete, you will see the following message: echo ' "shar: End of archive 4 (of 6)."' if test -f 'cmds.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'cmds.c'\" else echo shar: Extracting \"'cmds.c'\" \(30867 characters\) sed "s/^X//" >'cmds.c' <<'END_OF_FILE' X/* SC A Spreadsheet Calculator X * Command routines 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 * X * $Revision: 6.8 $ X */ X X#include <curses.h> X#if defined(BSD42) || defined(BSD43) X#include <sys/file.h> X#else X#include <fcntl.h> X#endif X#include "sc.h" X#include <signal.h> X#include <errno.h> X X#ifdef BSD42 X#include <strings.h> X#else X#ifndef SYSIII X#include <string.h> X#endif X#endif X X#ifdef SYSV3 Xextern void exit(); X#else Xextern int exit(); X#endif X Xextern int errno; X X#define DEFCOLDELIM ':' X Xvoid Xduprow() X{ X if (currow >= maxrows - 1 || maxrow >= maxrows - 1) { X if (!growtbl(GROWROW, 0, 0)) X return; X } X modflg++; X currow++; X openrow (currow); X for (curcol = 0; curcol <= maxcol; curcol++) { X register struct ent *p = *ATBL(tbl, currow - 1, curcol); X if (p) { X register struct ent *n; X n = lookat (currow, curcol); X (void)copyent ( n, p, 1, 0); X } X } X for (curcol = 0; curcol <= maxcol; curcol++) { X register struct ent *p = *ATBL(tbl, currow, curcol); X if (p && (p -> flags & is_valid) && !p -> expr) X break; X } X if (curcol > maxcol) X curcol = 0; X} X Xvoid Xdupcol() X{ X if (curcol >= maxcols - 1 || maxcol >= maxcols - 1) { X if (!growtbl(GROWCOL, 0, 0)) X return; X } X modflg++; X curcol++; X opencol (curcol, 1); X for (currow = 0; currow <= maxrow; currow++) { X register struct ent *p = *ATBL(tbl, currow, curcol - 1); X if (p) { X register struct ent *n; X n = lookat (currow, curcol); X copyent ( n, p, 0, 1); X } X } X for (currow = 0; currow <= maxrow; currow++) { X register struct ent *p = *ATBL(tbl, currow, curcol); X if (p && (p -> flags & is_valid) && !p -> expr) X break; X } X if (currow > maxrow) X currow = 0; X} X Xvoid Xinsertrow(arg) Xregister int arg; X{ X while (--arg>=0) openrow (currow); X} X Xvoid Xdeleterow(arg) Xregister int arg; X{ X flush_saved(); X erase_area(currow, 0, currow + arg - 1, maxcol); X currow += arg; X while (--arg>=0) closerow (--currow); X sync_refs(); X} X Xvoid Xrowvalueize(arg) Xregister int arg; X{ X valueize_area(currow, 0, currow + arg - 1, maxcol); X} X Xvoid Xcolvalueize(arg) Xregister int arg; X{ X valueize_area(0, curcol, maxrow, curcol + arg - 1); X} X Xvoid Xerase_area(sr, sc, er, ec) Xint sr, sc, er, ec; X{ X register int r, c; X register struct ent **pp; X X if (sr > er) { X r = sr; sr = er; er= r; X } X X if (sc > ec) { X c = sc; sc = ec; ec= c; X } X X if (sr < 0) X sr = 0; X if (sc < 0) X sc = 0; X checkbounds(&er, &ec); X X for (r = sr; r <= er; r++) { X for (c = sc; c <= ec; c++) { X pp = ATBL(tbl, r, c); X if (*pp) { X free_ent(*pp); X *pp = (struct ent *)0; X } X } X } X} X Xvoid Xvalueize_area(sr, sc, er, ec) Xint sr, sc, er, ec; X{ X register int r, c; X register struct ent *p; X X if (sr > er) { X r = sr; sr = er; er= r; X } X X if (sc > ec) { X c = sc; sc = ec; ec= c; X } X X if (sr < 0) X sr = 0; X if (sc < 0) X sc = 0; X checkbounds(&er, &ec); X X for (r = sr; r <= er; r++) { X for (c = sc; c <= ec; c++) { X p = *ATBL(tbl, r, c); X if (p && p->expr) { X efree(p, p->expr); X p->expr = (struct enode *)0; X p->flags &= ~is_strexpr; X } X } X } X X} X Xvoid Xpullcells(to_insert) Xint to_insert; X{ X register struct ent *p, *n; X register int deltar, deltac; X int minrow, mincol; X int mxrow, mxcol; X int numrows, numcols; X X if (! to_fix) X { X error ("No data to pull"); X return; X } X X minrow = maxrows; X mincol = maxcols; X mxrow = 0; X mxcol = 0; X X for (p = to_fix; p; p = p->next) { X if (p->row < minrow) X minrow = p->row; X if (p->row > mxrow) X mxrow = p->row; X if (p->col < mincol) X mincol = p->col; X if (p->col > mxcol) X mxcol = p->col; X } X X numrows = mxrow - minrow + 1; X numcols = mxcol - mincol + 1; X deltar = currow - minrow; X deltac = curcol - mincol; X X if (to_insert == 'r') { X insertrow(numrows); X deltac = 0; X } else if (to_insert == 'c') { X opencol(curcol, numcols); X deltar = 0; X } X X FullUpdate++; X modflg++; X X for (p = to_fix; p; p = p->next) { X n = lookat (p->row + deltar, p->col + deltac); X (void) clearent(n); X copyent( n, p, deltar, deltac); X n -> flags = p -> flags & ~is_deleted; X } X} X Xvoid Xcolshow_op() X{ X register int i,j; X for (i=0; i<maxcols; i++) X if (col_hidden[i]) X break; X for(j=i; j<maxcols; j++) X if (!col_hidden[j]) X break; X j--; X if (i>=maxcols) X error ("No hidden columns to show"); X else { X (void) sprintf(line,"show %s:", coltoa(i)); X (void) sprintf(line + strlen(line),"%s",coltoa(j)); X linelim = strlen (line); X } X} X Xvoid Xrowshow_op() X{ X register int i,j; X for (i=0; i<maxrows; i++) X if (row_hidden[i]) X break; X for(j=i; j<maxrows; j++) X if (!row_hidden[j]) { X break; X } X j--; X X if (i>=maxrows) X error ("No hidden rows to show"); X else { X (void) sprintf(line,"show %d:%d", i, j); X linelim = strlen (line); X } X} X X/* X * Given a row/column command letter, emit a small menu, then read a qualifier X * character for a row/column command and convert it to 'r' (row), 'c' X * (column), or 0 (unknown). If ch is 'p', an extra qualifier 'm' is allowed. X */ X Xint Xget_rcqual (ch) X int ch; X{ X error ("%sow/column: r: row c: column%s", X X (ch == 'i') ? "Insert r" : X (ch == 'a') ? "Append r" : X (ch == 'd') ? "Delete r" : X (ch == 'p') ? "Pull r" : X (ch == 'v') ? "Values r" : X (ch == 'z') ? "Zap r" : X (ch == 's') ? "Show r" : "R", X X (ch == 'p') ? " m: merge" : ""); X X (void) refresh(); X X switch (nmgetch()) X { X case 'r': X case 'l': X case 'h': X case ctl('f'): X case ctl('b'): return ('r'); X X case 'c': X case 'j': X case 'k': X case ctl('p'): X case ctl('n'): return ('c'); X X case 'm': return ((ch == 'p') ? 'm' : 0); X X case ESC: X case ctl('g'): return (ESC); X X default: return (0); X } X /*NOTREACHED*/ X} X Xvoid Xopenrow (rs) Xint rs; X{ X register r, c; X struct ent **tmprow, **pp; X X if (rs > maxrow) maxrow = rs; X if (maxrow >= maxrows - 1 || rs > maxrows - 1) { X if (!growtbl(GROWROW, rs, 0)) X return; X } X /* X * save the last active row+1, shift the rows downward, put the last X * row in place of the first X */ X tmprow = tbl[++maxrow]; X for (r = maxrow; r > rs; r--) { X row_hidden[r] = row_hidden[r-1]; X tbl[r] = tbl[r-1]; X pp = ATBL(tbl, r, 0); X for (c = 0; c < maxcols; c++, pp++) X if (*pp) X (*pp)->row = r; X } X tbl[r] = tmprow; /* the last row was never used.... */ X FullUpdate++; X modflg++; X} X Xvoid Xcloserow (r) Xregister r; X{ X register struct ent **pp; X register c; X struct ent **tmprow; X X if (r > maxrow) return; X X /* save the row and empty it out */ X tmprow = tbl[r]; X pp = ATBL(tbl, r, 0); X for (c=maxcol+1; --c>=0; pp++) { X if (*pp) X { free_ent(*pp); X *pp = (struct ent *)0; X } X } X X /* move the rows, put the deleted row at the end */ X for (; r < maxrows - 1; r++) { X row_hidden[r] = row_hidden[r+1]; X tbl[r] = tbl[r+1]; X pp = ATBL(tbl, r, 0); X for (c = 0; c < maxcols; c++, pp++) X if (*pp) X (*pp)->row = r; X } X tbl[r] = tmprow; X X maxrow--; X FullUpdate++; X modflg++; X} X Xvoid Xopencol (cs, numcol) Xint cs; Xint numcol; X{ X register r; X register struct ent **pp; X register c; X register lim = maxcol-cs+1; X int i; X X if (cs > maxcol) X maxcol = cs; X maxcol += numcol; X X if ((maxcol >= maxcols - 1) && !growtbl(GROWCOL, 0, maxcol)) X return; X X for (i = maxcol; i > cs; i--) { X fwidth[i] = fwidth[i-numcol]; X precision[i] = precision[i-numcol]; X col_hidden[i] = col_hidden[i-numcol]; X } X for (c = cs; c - cs < numcol; c++) X { fwidth[c] = DEFWIDTH; X precision[c] = DEFPREC; X } X X for (r=0; r<=maxrow; r++) { X pp = ATBL(tbl, r, maxcol); X for (c=lim; --c>=0; pp--) X if (pp[0] = pp[-numcol]) X pp[0]->col += numcol; X X pp = ATBL(tbl, r, cs); X for (c = cs; c - cs < numcol; c++, pp++) X *pp = (struct ent *)0; X } X FullUpdate++; X modflg++; X} X Xvoid Xclosecol (cs, numcol) Xint cs; Xint numcol; X{ X register r; X register struct ent **pp; X register struct ent *q; X register c; X register lim = maxcol-cs; X int i; X char buf[50]; X X if (lim - numcol < -1) X { sprintf(buf, "Can't delete %d column%s %d columns left", numcol, X (numcol > 1 ? "s," : ","), lim+1); X error(buf); X return; X } X flush_saved(); X erase_area(0, curcol, maxrow, curcol + numcol - 1); X sync_refs(); X X /* clear then copy the block left */ X lim = maxcols - numcol - 1; X for (r=0; r<=maxrow; r++) { X for (c = cs; c - cs < numcol; c++) X if (q = *ATBL(tbl, r, c)) X free_ent(q); X X pp = ATBL(tbl, r, cs); X for (c=cs; c <= lim; c++, pp++) X { if (c > lim) X *pp = (struct ent *)0; X else X if (pp[0] = pp[numcol]) X pp[0]->col -= numcol; X } X X c = numcol; X for (; --c >= 0; pp++) X *pp = (struct ent *)0; X } X X for (i = cs; i < maxcols - numcol - 1; i++) { X fwidth[i] = fwidth[i+numcol]; X precision[i] = precision[i+numcol]; X col_hidden[i] = col_hidden[i+numcol]; X } X for (; i < maxcols - 1; i++) { X fwidth[i] = DEFWIDTH; X precision[i] = DEFPREC; X col_hidden[i] = 0; X } X X maxcol -= numcol; X FullUpdate++; X modflg++; X} X Xvoid Xdoend(rowinc, colinc) Xint rowinc, colinc; X{ X register struct ent *p; X int r, c; X X if (VALID_CELL(p, currow, curcol)) { X r = currow + rowinc; X c = curcol + colinc; X if (r >= 0 && r < maxrows && X c >= 0 && c < maxcols && X !VALID_CELL(p, r, c)) { X currow = r; X curcol = c; X } X } X X if (!VALID_CELL(p, currow, curcol)) { X switch (rowinc) { X case -1: X while (!VALID_CELL(p, currow, curcol) && currow > 0) X currow--; X break; X case 1: X while (!VALID_CELL(p, currow, curcol) && currow < maxrows-1) X currow++; X break; X case 0: X switch (colinc) { X case -1: X while (!VALID_CELL(p, currow, curcol) && curcol > 0) X curcol--; X break; X case 1: X while (!VALID_CELL(p, currow, curcol) && curcol < maxcols-1) X curcol++; X break; X } X break; X } X X error (""); /* clear line */ X return; X } X X switch (rowinc) { X case -1: X while (VALID_CELL(p, currow, curcol) && currow > 0) X currow--; X break; X case 1: X while (VALID_CELL(p, currow, curcol) && currow < maxrows-1) X currow++; X break; X case 0: X switch (colinc) { X case -1: X while (VALID_CELL(p, currow, curcol) && curcol > 0) X curcol--; X break; X case 1: X while (VALID_CELL(p, currow, curcol) && curcol < maxcols-1) X curcol++; X break; X } X break; X } X if (!VALID_CELL(p, currow, curcol)) { X currow -= rowinc; X curcol -= colinc; X } X} X Xvoid Xdoformat(c1,c2,w,p) Xint c1,c2,w,p; X{ X register int i; X X if (w > COLS - RESCOL - 2) { X error("Format too large - Maximum = %d", COLS - RESCOL - 2); X w = COLS-RESCOL-2; X } X X if (p > w) { X error("Precision too large"); X p = w; X } X X for(i = c1; i<=c2; i++) X fwidth[i] = w, precision[i] = p; X X FullUpdate++; X modflg++; X} X Xvoid Xprint_options(f) XFILE *f; X{ X if( X autocalc && X propagation == 10 && X calc_order == BYROWS && X !numeric && X prescale == 1.0 && X !extfunc && X showcell && X showtop && X tbl_style == 0 X ) X return; /* No reason to do this */ X X (void) fprintf(f, "set"); X if(!autocalc) X (void) fprintf(f," !autocalc"); X if(propagation != 10) X (void) fprintf(f, " iterations = %d", propagation); X if(calc_order != BYROWS ) X (void) fprintf(f, " bycols"); X if (numeric) X (void) fprintf(f, " numeric"); X if (prescale != 1.0) X (void) fprintf(f, " prescale"); X if (extfunc) X (void) fprintf(f, " extfun"); X if (!showcell) X (void) fprintf(f, " !cellcur"); X if (!showtop) X (void) fprintf(f, " !toprow"); X if (tbl_style) X (void) fprintf(f, " tblstyle = %s", tbl_style == TBL ? "tbl" : X tbl_style == LATEX ? "latex" : X tbl_style == TEX ? "tex" : "0" ); X (void) fprintf(f, "\n"); X} X Xvoid Xprintfile (fname, r0, c0, rn, cn) Xchar *fname; Xint r0, c0, rn, cn; X{ X FILE *f; X char pline[FBUFLEN]; X int plinelim; X int pid; X int fieldlen, nextcol; X register row, col; X register struct ent **pp; X X if ((strcmp(fname, curfile) == 0) && X !yn_ask("Confirm that you want to destroy the data base: (y,n)")) X return; X X if ((f = openout(fname, &pid)) == (FILE *)0) X { error ("Can't create file \"%s\"", fname); X return; X } X for (row=r0;row<=rn; row++) { X register c = 0; X X if (row_hidden[row]) X continue; X X pline[plinelim=0] = '\0'; X for (pp = ATBL(tbl, row, col=c0); col<=cn; 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 if (*pp) { X char *s; X X while (plinelim<c) pline[plinelim++] = ' '; X plinelim = c; X if ((*pp)->flags&is_valid) { X (void)sprintf (pline+plinelim,"%*.*f",fwidth[col], X precision[col], (*pp)->v); X plinelim += strlen (pline+plinelim); X } X if (s = (*pp)->label) { X int slen; X char *start, *last; X register char *fp; X struct ent *nc; X X /* Figure out if the label slops over to a blank field */ X slen = strlen(s); X while (slen > fieldlen && nextcol <= cn && X !((nc = lookat(row,nextcol))->flags & is_valid) && X !(nc->label)) { X X if (!col_hidden[nextcol]) X fieldlen += fwidth[nextcol]; X X nextcol++; X } X if (slen > fieldlen) X slen = fieldlen; X X /* Now justify and print */ X start = (*pp)->flags & is_leftflush ? pline + c X : pline + c + fieldlen - slen; X last = pline + c + fieldlen; X fp = plinelim < c ? pline + plinelim : pline + c; X while (fp < start) X *fp++ = ' '; X while (slen--) X *fp++ = *s++; X if (!((*pp)->flags & is_valid) || fieldlen != fwidth[col]) X while(fp < last) X *fp++ = ' '; X if (plinelim < fp - pline) X plinelim = fp - pline; X } X } X } X pline[plinelim++] = '\n'; X pline[plinelim] = '\0'; X (void) fputs (pline, f); X } X X closeout(f, pid); X} X Xvoid Xtblprintfile (fname, r0, c0, rn, cn) Xchar *fname; Xint r0, c0, rn, cn; X{ X FILE *f; X int pid; X register row, col; X register struct ent **pp; X char coldelim = DEFCOLDELIM; X X if ((strcmp(fname, curfile) == 0) && X !yn_ask("Confirm that you want to destroy the data base: (y,n)")) X return; X X if ((f = openout(fname, &pid)) == (FILE *)0) X { error ("Can't create file \"%s\"", fname); X return; X } X X if ( tbl_style == TBL ) { X fprintf(f,".\\\" ** %s spreadsheet output \n.TS\n",progname); X fprintf(f,"tab(%c);\n",coldelim); X for (col=c0;col<=cn; col++) fprintf(f," n"); X fprintf(f, ".\n"); X } X else if ( tbl_style == LATEX ) { X fprintf(f,"%% ** %s spreadsheet output\n\\begin{tabular}{",progname); X for (col=c0;col<=cn; col++) fprintf(f,"c"); X fprintf(f, "}\n"); X coldelim = '&'; X } X else if ( tbl_style == TEX ) { X fprintf(f,"{\t%% ** %s spreadsheet output\n\\settabs %d \\columns\n", X progname, cn-c0+1); X coldelim = '&'; X } X X for (row=r0; row<=rn; row++) { X if ( tbl_style == TEX ) X (void) fprintf (f, "\\+"); X X for (pp = ATBL(tbl, row, col=c0); col<=cn; col++, pp++) { X if (*pp) { X char *s; X if ((*pp)->flags&is_valid) { X (void) fprintf (f,"%.*f",precision[col], X (*pp)->v); X } X if (s = (*pp)->label) { X (void) fprintf (f,"%s",s); X } X } X if ( col < cn ) X (void) fprintf(f,"%c",coldelim); X } X if ( tbl_style == LATEX ) { X if ( row < rn ) (void) fprintf (f, "\\\\"); X } X else if ( tbl_style == TEX ) { X (void) fprintf (f, "\\cr"); X } X (void) fprintf (f,"\n"); X } X X if ( tbl_style == TBL ) X (void) fprintf (f,".TE\n.\\\" ** end of %s spreadsheet output\n", progname); X else if ( tbl_style == LATEX ) X (void) fprintf (f,"\\end{tabular}\n%% ** end of %s spreadsheet output\n", progname); X else if ( tbl_style == TEX ) X (void) fprintf (f,"}\n%% ** end of %s spreadsheet output\n", progname); X X closeout(f, pid); X} X Xstruct enode * Xcopye (e, Rdelta, Cdelta) Xregister struct enode *e; Xint Rdelta, Cdelta; X{ X register struct enode *ret; X X if (e == (struct enode *)0) { X ret = (struct enode *)0; X } else if (e->op & REDUCE) { X int newrow, newcol; X ret = (struct enode *) xmalloc ((unsigned) sizeof (struct enode)); X ret->op = e->op; X newrow=e->e.r.left.vf & FIX_ROW ? e->e.r.left.vp->row : X e->e.r.left.vp->row+Rdelta; X newcol=e->e.r.left.vf & FIX_COL ? e->e.r.left.vp->col : X e->e.r.left.vp->col+Cdelta; X ret->e.r.left.vp = lookat (newrow, newcol); X ret->e.r.left.vf = e->e.r.left.vf; X newrow=e->e.r.right.vf & FIX_ROW ? e->e.r.right.vp->row : X e->e.r.right.vp->row+Rdelta; X newcol=e->e.r.right.vf & FIX_COL ? e->e.r.right.vp->col : X e->e.r.right.vp->col+Cdelta; X ret->e.r.right.vp = lookat (newrow, newcol); X ret->e.r.right.vf = e->e.r.right.vf; X } else { X ret = (struct enode *) xmalloc ((unsigned) sizeof (struct enode)); X ret->op = e->op; X switch (ret->op) { X case 'v': X { X int newrow, newcol; X newrow=e->e.v.vf & FIX_ROW ? e->e.v.vp->row : X e->e.v.vp->row+Rdelta; X newcol=e->e.v.vf & FIX_COL ? e->e.v.vp->col : X e->e.v.vp->col+Cdelta; X ret->e.v.vp = lookat (newrow, newcol); X ret->e.v.vf = e->e.v.vf; X break; X } X case 'k': X ret->e.k = e->e.k; X break; X case 'f': X ret->e.o.right = copye (e->e.o.right,0,0); X ret->e.o.left = (struct enode *)0; X break; X case '$': X ret->e.s = xmalloc((unsigned) strlen(e->e.s)+1); X (void) strcpy(ret->e.s, e->e.s); X break; X default: X ret->e.o.right = copye (e->e.o.right,Rdelta,Cdelta); X ret->e.o.left = copye (e->e.o.left,Rdelta,Cdelta); X break; X } X } X return ret; X} X X/* X * sync_refs and syncref are used to remove references to X * deleted struct ents. Note that the deleted structure must still X * be hanging around before the call, but not referenced by an entry X * in tbl. Thus the free_ent, fix_ent calls in sc.c X */ Xvoid Xsync_refs () X{ X register i,j; X register struct ent *p; X sync_ranges(); X for (i=0; i<=maxrow; i++) X for (j=0; j<=maxcol; j++) X if ((p = *ATBL(tbl, i, j)) && p->expr) X syncref(p->expr); X} X Xvoid Xsyncref(e) Xregister struct enode *e; X{ X if (e == (struct enode *)0) X return; X else if (e->op & REDUCE) { X e->e.r.right.vp = lookat(e->e.r.right.vp->row, e->e.r.right.vp->col); X e->e.r.left.vp = lookat(e->e.r.left.vp->row, e->e.r.left.vp->col); X } else { X switch (e->op) { X case 'v': X e->e.v.vp = lookat(e->e.v.vp->row, e->e.v.vp->col); X break; X case 'k': X break; X case '$': X break; X default: X syncref(e->e.o.right); X syncref(e->e.o.left); X break; X } X } X} X Xvoid Xhiderow(arg) Xint arg; X{ X register int r1; X register int r2; X X r1 = currow; X r2 = r1 + arg - 1; X if (r1 < 0 || r1 > r2) { X error ("Invalid range"); X return; X } X if (r2 >= maxrows-1) X { if (!growtbl(GROWROW, arg+1, 0)) X { error("You can't hide the last row"); X return; X } X } X FullUpdate++; X modflg++; X while (r1 <= r2) X row_hidden[r1++] = 1; X} X Xvoid Xhidecol(arg) Xint arg; X{ X register int c1; X register int c2; X X c1 = curcol; X c2 = c1 + arg - 1; X if (c1 < 0 || c1 > c2) { X error ("Invalid range"); X return; X } X if (c2 >= maxcols-1) X { if ((arg >= ABSMAXCOLS-1) || !growtbl(GROWCOL, 0, arg+1)) X { error("You can't hide the last col"); X return; X } X } X FullUpdate++; X modflg++; X while (c1 <= c2) X col_hidden[c1++] = 1; X} X Xvoid Xshowrow(r1, r2) Xint r1, r2; X{ X if (r1 < 0 || r1 > r2) { X error ("Invalid range"); X return; X } X if (r2 > maxrows-1) { X r2 = maxrows-1; X } X FullUpdate++; X modflg++; X while (r1 <= r2) X row_hidden[r1++] = 0; X} X Xvoid Xshowcol(c1, c2) Xint c1, c2; X{ X if (c1 < 0 || c1 > c2) { X error ("Invalid range"); X return; X } X if (c2 > maxcols-1) { X c2 = maxcols-1; X } X FullUpdate++; X modflg++; X while (c1 <= c2) X col_hidden[c1++] = 0; X} X X/* Open the output file, setting up a pipe if needed */ X XFILE * Xopenout(fname, rpid) Xchar *fname; Xint *rpid; X{ X int pipefd[2]; X int pid; X FILE *f; X char *efname; X X while (*fname && (*fname == ' ')) /* Skip leading blanks */ X fname++; X X if (*fname != '|') { /* Open file if not pipe */ X *rpid = 0; X X efname = findhome(fname); X#ifdef DOBACKUPS X if (!backup_file(efname) && X (yn_ask("Could not create backup copy, Save anyhow?: (y,n)") != 1)) X return(0); X#endif X return(fopen(efname, "w")); X } X X fname++; /* Skip | */ X if ( pipe (pipefd) < 0) { X error("Can't make pipe to child"); X *rpid = 0; X return(0); X } X X deraw(); X#ifdef VMS X fprintf(stderr, "No son tasks available yet under VMS--sorry\n"); X#else /* VMS */ X X if ((pid=fork()) == 0) /* if child */ X { X (void) close (0); /* close stdin */ X (void) close (pipefd[1]); X (void) dup (pipefd[0]); /* connect to pipe input */ X (void) signal (SIGINT, SIG_DFL); /* reset */ X (void) execl ("/bin/sh", "sh", "-c", fname, 0); X exit (-127); X } X else /* else parent */ X { X *rpid = pid; X if ((f = fdopen (pipefd[1], "w")) == (FILE *)0) X { X (void) kill (pid, -9); X error ("Can't fdopen output"); X (void) close (pipefd[1]); X *rpid = 0; X return(0); X } X } X#endif /* VMS */ X return(f); X} X Xvoid Xcloseout(f, pid) XFILE *f; Xint pid; X{ X int temp; X X (void) fclose (f); X if (pid) { X while (pid != wait(&temp)) /**/; X (void) printf("Press RETURN to continue "); X (void) fflush(stdout); X (void) nmgetch(); X goraw(); X } X} X Xvoid Xcopyent(n,p,dr,dc) X register struct ent *n, *p; X int dr, dc; X{ X if(!n||!p){error("internal error");return;} X n -> v = p -> v; X n -> flags = p -> flags; X n -> expr = copye (p -> expr, dr, dc); X n -> label = (char *)0; X if (p -> label) { X n -> label = (char *) X xmalloc ((unsigned) (strlen (p -> label) + 1)); X (void) strcpy (n -> label, p -> label); X } X} X Xvoid Xwrite_fd (f, r0, c0, rn, cn) Xregister FILE *f; Xint r0, c0, rn, cn; X{ X register struct ent **pp; X register r, c; X X (void) fprintf (f, "# This data file was generated by the Spreadsheet "); X (void) fprintf (f, "Calculator.\n"); X (void) fprintf (f, "# You almost certainly shouldn't edit it.\n\n"); X print_options(f); X for (c=0; c<maxcols; c++) X if (fwidth[c] != DEFWIDTH || precision[c] != DEFPREC) X (void) fprintf (f, "format %s %d %d\n",coltoa(c),fwidth[c],precision[c]); X for (c=c0; c<cn; c++) { X if (col_hidden[c]) { X (void) fprintf(f, "hide %s\n", coltoa(c)); X } X } X for (r=r0; r<=rn; r++) { X if (row_hidden[r]) { X (void) fprintf(f, "hide %d\n", r); X } X } X X write_range(f); X X if (mdir) X (void) fprintf(f, "mdir \"%s\"\n", mdir); X for (r=r0; r<=rn; r++) { X pp = ATBL(tbl, r, c0); X for (c=c0; c<=cn; c++, pp++) X if (*pp) { X if ((*pp)->label) { X edits(r,c); X (void) fprintf(f, "%s\n",line); X } X if ((*pp)->flags&is_valid) { X editv (r, c); X (void) fprintf (f, "%s\n",line); X } X } X } X} X Xint Xwritefile (fname, r0, c0, rn, cn) Xchar *fname; Xint r0, c0, rn, cn; X{ X register FILE *f; X char save[PATHLEN]; X int pid; X X#ifndef VMS X if (Crypt) { X return (cwritefile(fname, r0, c0, rn, cn)); X } X#endif /* VMS */ X X if (*fname == '\0') fname = curfile; X X (void) strcpy(save,fname); X X if ((f= openout(fname, &pid)) == (FILE *)0) X { error ("Can't create file \"%s\"", fname); X return (-1); X } X X write_fd(f, r0, c0, rn, cn); X X closeout(f, pid); X X if (!pid) { X (void) strcpy(curfile, save); X modflg = 0; X error("File \"%s\" written.",curfile); X } X X return (0); X} X Xvoid Xreadfile (fname,eraseflg) Xchar *fname; Xint eraseflg; X{ X register FILE *f; X char save[PATHLEN]; X X if (*fname == '*' && mdir) { X (void) strcpy(save, mdir); X *fname = '/'; X (void) strcat(save, fname); X } else { X if (*fname == '\0') X fname = curfile; X (void) strcpy(save,fname); X } X X#ifndef VMS X if (Crypt) { X creadfile(save, eraseflg); X return; X } X#endif /* VMS */ X X if (eraseflg && strcmp(fname,curfile) && modcheck(" first")) return; X X if ((f = fopen(findhome(save), "r")) == (FILE *)0) X { error ("Can't read file \"%s\"", save); X return; X } X X if (eraseflg) erasedb (); X X loading++; X while (fgets(line,sizeof line,f)) { X linelim = 0; X if (line[0] != '#') (void) yyparse (); X } X --loading; X (void) fclose (f); X linelim = -1; X modflg++; X if (eraseflg) { X (void) strcpy(curfile,save); X modflg = 0; X } X EvalAll(); X} X Xvoid Xerasedb () X{ X register r, c; X for (c = 0; c<=maxcol; c++) { X fwidth[c] = DEFWIDTH; X precision[c] = DEFPREC; X } X X for (r = 0; r<=maxrow; r++) { X register struct ent **pp = ATBL(tbl, r, 0); X for (c=0; c++<=maxcol; pp++) X if (*pp) { X if ((*pp)->expr) efree (*pp, (*pp) -> expr); X if ((*pp)->label) xfree ((char *)((*pp) -> label)); X xfree ((char *)(*pp)); X *pp = (struct ent *)0; X } X } X maxrow = 0; X maxcol = 0; X clean_range(); X FullUpdate++; X} X Xvoid Xbackcol(arg) X int arg; X{ X while (--arg>=0) { X if (curcol) X curcol--; X else X {error ("At column A"); break;} X while(col_hidden[curcol] && curcol) X curcol--; X } X} X Xvoid Xforwcol(arg) X int arg; X{ X while (--arg>=0) { X if (curcol < maxcols - 1) X curcol++; X else X if (!growtbl(GROWCOL, 0, arg)) /* get as much as needed */ X break; X while(col_hidden[curcol]&&(curcol<maxcols-1)) X curcol++; X } X} X Xvoid Xforwrow(arg) X int arg; X{ X while (--arg>=0) { X if (currow < maxrows - 1) X currow++; X else X if (!growtbl(GROWROW, arg, 0)) /* get as much as needed */ X break; X while (row_hidden[currow]&&(currow<maxrows-1)) X currow++; X } X} X Xvoid Xbackrow(arg) X int arg; X{ X while (--arg>=0) { X if (currow) X currow--; X else X {error ("At row zero"); break;} X while (row_hidden[currow] && currow) X currow--; X } X} X X X/* X * Show a cell's label string or expression value. May overwrite value if X * there is one already displayed in the cell. Created from old code in X * update(), copied with minimal changes. X */ X Xvoid Xshowstring (string, leftflush, hasvalue, row, col, nextcolp, mxcol, fieldlenp, r, c) X char *string; /* to display */ X int leftflush; /* or rightflush */ X int hasvalue; /* is there a numeric value? */ X int row, col; /* spreadsheet location */ X int *nextcolp; /* value returned through it */ X int mxcol; /* last column displayed? */ X int *fieldlenp; /* value returned through it */ X int r, c; /* screen row and column */ X{ X register int nextcol = *nextcolp; X register int fieldlen = *fieldlenp; X X char field[FBUFLEN]; X int slen; X char *start, *last; X register char *fp; X struct ent *nc; X X /* This figures out if the label is allowed to X slop over into the next blank field */ X X slen = strlen (string); X while ((slen > fieldlen) && (nextcol <= mxcol) && X !((nc = lookat (row, nextcol)) -> flags & is_valid) && X !(nc->label)) { X X if (! col_hidden [nextcol]) X fieldlen += fwidth [nextcol]; X X nextcol++; X } X if (slen > fieldlen) X slen = fieldlen; X X /* Now justify and print */ X start = leftflush ? field : field + fieldlen - slen; X last = field+fieldlen; X fp = field; X while (fp < start) X *fp++ = ' '; X while (slen--) X *fp++ = *string++; X if ((! hasvalue) || fieldlen != fwidth[col]) X while (fp < last) X *fp++ = ' '; X *fp = '\0'; X#ifdef VMS X mvaddstr(r, c, field); /* this is a macro */ X#else X (void) mvaddstr(r, c, field); X#endif X X *nextcolp = nextcol; X *fieldlenp = fieldlen; X} X Xint Xetype(e) Xregister struct enode *e; X{ X if (e == (struct enode *)0) X return NUM; X switch (e->op) { X case O_SCONST: case '#': case DATE: case FMT: case STINDEX: X case EXT: case SVAL: case SUBSTR: X return (STR); X X case '?': X case IF: X return(etype(e->e.o.right->e.o.left)); X X case 'f': X return(etype(e->e.o.right)); X X case O_VAR: { X register struct ent *p; X p = e->e.v.vp; X if (p->expr) X return(p->flags & is_strexpr ? STR : NUM); X else if (p->label) X return(STR); X else X return(NUM); X } X X default: X return(NUM); X } X} X X/* return 1 if yes given, 0 otherwise */ Xint Xyn_ask(msg) Xchar *msg; X{ char ch; X X (void) move (0, 0); X (void) clrtoeol (); X (void) addstr (msg); X (void) refresh(); X ch = nmgetch(); X if ( ch != 'y' && ch != 'Y' && ch != 'n' && ch != 'N' ) { X if (ch == ctl('g') || ch == ESC) X return(-1); X error("y or n response required"); X return (-1); X } X if (ch == 'y' || ch == 'Y') X return(1); X else X return(0); X} X X#include <pwd.h> Xchar * Xfindhome(path) Xchar *path; X{ X static char *HomeDir = NULL; X extern char *getenv(); X X if (*path == '~') X { char *pathptr; X char tmppath[PATHLEN]; X X if (HomeDir == NULL) X { HomeDir = getenv("HOME"); X if (HomeDir == NULL) X HomeDir = "/"; X } X pathptr = path + 1; X if ((*pathptr == '/') || (*pathptr == '\0')) X { strcpy(tmppath, HomeDir); X } X else X { struct passwd *pwent; X extern struct passwd *getpwnam(); X char *namep; X char name[50]; X X namep = name; X while ((*pathptr != '\0') && (*pathptr != '/')) X *(namep++) = *(pathptr++); X *namep = '\0'; X if ((pwent = getpwnam(name)) == NULL) X { sprintf(path, "Can't find user %s", name); X return(NULL); X } X strcpy(tmppath, pwent->pw_dir); X } X X strcat(tmppath, pathptr); X strcpy(path, tmppath); X } X return(path); X} X X#ifdef DOBACKUPS X#include <sys/types.h> X#include <sys/stat.h> X X/* X * make a backup copy of a file, use the same mode and name in the format X * [path/]#file~ X * return 1 if we were successful, 0 otherwise X */ Xint Xbackup_file(path) Xchar *path; X{ X struct stat statbuf; X char fname[PATHLEN]; X char tpath[PATHLEN]; X#ifdef sequent X char *buf; X#else X char buf[BUFSIZ]; X#endif X char *tpp; X int infd, outfd; X int count; X X /* tpath will be the [path/]file ---> [path/]#file~ */ X strcpy(tpath, path); X if ((tpp = strrchr(tpath, '/')) == NULL) X tpp = tpath; X else X tpp++; X strcpy(fname, tpp); X sprintf(tpp, "#%s~", fname); X X if (stat(path, &statbuf) == 0) X { X#ifdef sequent X if ((buf = xmalloc(statbuf.st_blksize)) == (char *)0) X return(0); X#endif X X if ((infd = open(path, O_RDONLY, 0)) < 0) X { X#ifdef sequent X xfree(buf); X#endif X return(0); X } X if ((outfd = open(tpath, O_TRUNC|O_WRONLY|O_CREAT, X statbuf.st_mode)) < 0) X { X#ifdef sequent X xfree(buf); X#endif X return(0); X } X#ifdef sequent X while((count = read(infd, buf, statbuf.st_blksize)) > 0) X#else X while((count = read(infd, buf, sizeof(buf))) > 0) X#endif X { if (write(outfd, buf, count) != count) X { count = -1; X break; X } X } X close(infd); X close(outfd); X#ifdef sequent X xfree(buf); X#endif X return((count < 0) ? 0 : 1); X } X else X if (errno == ENOENT) X return(1); X return(0); X} X#endif END_OF_FILE if test 30867 -ne `wc -c <'cmds.c'`; then echo shar: \"'cmds.c'\" unpacked with wrong size! fi # end of 'cmds.c' fi if test -f 'lex.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'lex.c'\" else echo shar: Extracting \"'lex.c'\" \(13128 characters\) sed "s/^X//" >'lex.c' <<'END_OF_FILE' X/* SC A Spreadsheet Calculator 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 X#if defined(BSD42) || defined(BSD43) X#include <sys/ioctl.h> X#endif X X#ifdef IEEE_MATH X#include <ieeefp.h> X#endif /* IEEE_MATH */ X X#include <curses.h> X#include <signal.h> X#include <setjmp.h> X#include "sc.h" X#include <ctype.h> X X#ifdef BSD42 X#include <strings.h> X#else X#ifndef SYSIII X#include <string.h> X#endif X#endif X X#ifdef VMS X#include "gram_tab.h" Xtypedef union { X int ival; X double fval; X struct ent *ent; X struct enode *enode; X char *sval; X struct range_s rval; X} YYSTYPE; Xextern YYSTYPE yylval; Xextern int VMS_read_raw; /*sigh*/ X#else /* VMS */ X#include "y.tab.h" X#endif /* VMS */ X Xchar *strtof(); X Xjmp_buf wakeup; Xjmp_buf fpe_buf; X Xstruct key { X char *key; X int val; X}; X Xstruct key experres[] = { X#include "experres.h" X 0, 0}; X Xstruct key statres[] = { X#include "statres.h" X 0, 0}; X Xyylex () X{ 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 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 Xint Xatocol (string, len) X char *string; X int len; X{ 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 X X#ifdef SIMPLE X Xinitkbd() X{} X Xkbd_again() X{} X Xresetkbd() X{} X X#ifndef VMS X Xnmgetch() X{ X return (toascii(getchar())); X} X X#else /* VMS */ X Xnmgetch() X/* 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*/ X{ X short c; X static int key_id=0; X int status; X#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 X XVMS_MSG (status) Xint status; X/* X Routine to put out the VMS operating system error (if one occurs). X*/ X{ X#include <descrip.h> X char errstr[81], buf[120]; X $DESCRIPTOR(errdesc, errstr); X short int length; X#define err_out(msg) fprintf (stderr,msg) X 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 } X} X#endif /* VMS */ X X#else /*SIMPLE*/ X X#if defined(BSD42) || defined (SYSIII) || defined(BSD43) X X#define N_KEY 4 X Xstruct key_map { X char *k_str; X char k_val; X char k_index; X}; X Xstruct key_map km[N_KEY]; X Xchar keyarea[N_KEY*30]; X Xchar *tgetstr(); Xchar *getenv(); Xchar *ks; Xchar ks_buf[20]; Xchar *ke; Xchar ke_buf[20]; X X#ifdef TIOCSLTC Xstruct ltchars old_chars, new_chars; X#endif X Xchar 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}; X Xcharout(c) Xint c; X{ X (void)putchar(c); X} X Xinitkbd() X{ 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 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); X#endif X} X Xvoid Xkbd_again() X{ X if (ks) X tputs(ks, 1, charout); X X#ifdef TIOCSLTC X (void)ioctl(fileno(stdin), TIOCSLTC, (char *)&new_chars); X#endif X} X Xvoid Xresetkbd() X{ X if (ke) X tputs(ke, 1, charout); X X#ifdef TIOCSLTC X (void)ioctl(fileno(stdin), TIOCSLTC, (char *)&old_chars); X#endif X} X Xnmgetch() X{ 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 X#ifdef SIGVOID X void time_out(); X#else X int time_out(); X#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} X X#endif X X#if defined(SYSV2) || defined(SYSV3) X Xinitkbd() X{ X keypad(stdscr, TRUE); X} X Xvoid Xkbd_again() X{ X keypad(stdscr, TRUE); X} X Xvoid Xresetkbd() X{ X keypad(stdscr, FALSE); X} X Xnmgetch() X{ 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#ifdef KEY_C1 X/* This stuff works for a wyse wy75 in ANSI mode under 5.3. Good luck. */ X/* 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; X#endif X default: c = toascii(c); X break; X } X return (c); X} X X#endif /* SYSV2 || SYSV3 */ X X#endif /* SIMPLE */ X X#ifdef SIGVOID Xvoid X#endif Xtime_out(signo) Xint signo; X{ X#ifdef IEEE_MATH X (void)fpsetsticky((fp_except)0); /* Clear exception */ X#endif /* IEEE_MATH */ X longjmp(wakeup, -1); X} X X#ifdef SIGVOID Xvoid X#endif Xfpe_trap(signo) Xint signo; X{ X longjmp(fpe_buf, 1); X} X 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 Xchar * Xstrtof(p, res) Xregister char *p; Xdouble *res; X{ X double acc; X int sign; X double fpos; X int exp; X int exps; X#ifdef SIGVOID X void (*sig_save)(); X#else X int (*sig_save)(); X#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); X} END_OF_FILE if test 13128 -ne `wc -c <'lex.c'`; then echo shar: \"'lex.c'\" unpacked with wrong size! fi # end of 'lex.c' fi if test -f 'psc.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'psc.c'\" else echo shar: Extracting \"'psc.c'\" \(5741 characters\) sed "s/^X//" >'psc.c' <<'END_OF_FILE' X/* 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 X#include <ctype.h> X#include <stdio.h> X#include "sc.h" X X#define END 0 X#define NUM 1 X#define ALPHA 2 X#define SPACE 3 X#define EOL 4 X Xextern char *optarg; Xextern int optind; Xchar *coltoa(); Xchar *progname; X X#ifdef SYSV3 Xextern void exit(); X#else Xextern int exit(); X#endif X Xint colfirst = 0; Xint r0 = 0; Xint c0 = 0; Xint rinc = 1; Xint cinc = 1; Xint leftadj = 0; Xint len = 20000; Xchar delim1 = ' '; Xchar delim2 = '\t'; Xint strip_delim = 1; Xint drop_format = 0; Xint *fwidth; Xint *precision; Xint maxcols; X Xchar token[1000]; X Xmain(argc, argv) Xint argc; Xchar **argv; X{ 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} X Xscan() X{ 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} X Xgetcol(p) Xchar *p; X{ 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} X Xgetrow(p) Xchar *p; X{ 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} X Xchar * Xcoltoa(col) Xint col; X{ 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} X END_OF_FILE if test 5741 -ne `wc -c <'psc.c'`; then echo shar: \"'psc.c'\" unpacked with wrong size! fi # end of 'psc.c' fi if test -f 'xmalloc.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xmalloc.c'\" else echo shar: Extracting \"'xmalloc.c'\" \(686 characters\) sed "s/^X//" >'xmalloc.c' <<'END_OF_FILE' X/* X * A safer saner malloc, for careless programmers X * $Revision: 6.8 $ X */ X X#include <stdio.h> X#include <curses.h> X#include "sc.h" X Xextern char *malloc(); X X#ifdef SYSV3 Xextern void free(); Xextern void exit(); X#endif X Xchar * Xxmalloc(n) Xunsigned n; X{ Xregister char *ptr; X Xif ((ptr = malloc(n + sizeof(double))) == NULL) X fatal("xmalloc: no memory"); X*((int *) ptr) = 12345; /* magic number */ Xreturn(ptr + sizeof(double)); X} X Xxfree(p) Xchar *p; X{ Xif (p == NULL) X fatal("xfree: NULL"); Xp -= sizeof(double); Xif (*((int *) p) != 12345) X fatal("xfree: storage not malloc'ed"); Xfree(p); X} X Xfatal(str) Xchar *str; X{ X deraw(); X (void) fprintf(stderr,"%s\n", str); X exit(1); X} END_OF_FILE if test 686 -ne `wc -c <'xmalloc.c'`; then echo shar: \"'xmalloc.c'\" unpacked with wrong size! fi # end of 'xmalloc.c' fi echo shar: End of archive 4 \(of 6\). cp /dev/null ark4isdone MISSING="" for I in 1 2 3 4 5 6 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 6 archives. rm -f ark[1-9]isdone else echo You still must unpack the following archives: echo " " ${MISSING} fi exit 0 exit 0 # Just in case... -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net. Use a domain-based address or give alternate paths, or you may lose out.