|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T d
Length: 35723 (0x8b8b)
Types: TextFile
Names: »dm.c«
└─⟦87ddcff64⟧ Bits:30001253 CPHDIST85 Tape, 1985 Autumn Conference Copenhagen
└─⟦this⟧ »cph85dist/stat/src/dm.c«
# line 2 "dm.y"
#include "unixstat.h"
PGM(dm,Data Manipulation,5.0,3/2/85)
/* Copyright (c) 1982 Gary Perlman (see Copyright file) */
/*
MSDOS note: in dm.c (the output from yacc on dm.y),
you must change the line:
yyval = yypv[1];
to:
yyval.ex = yypv[1].ex;
The reason is that the Lattice C compiler cannot do union assignments.
*/
/*
dm is a data manipulator designed to manipulate files of columns of number and
strings. The major components of this program are:
(1) a parser, built by yacc, called yyparse.
(2) a scanner, yylex, called by yyparse.
(3) a parse tree node function, called by yyparse.
(4) a function, eval, that evaluates the parse trees.
(5) a main that calls I/O routines and the control loop.
The following section is a bunch of global declarations that will be put
literally into the program, y.tab.c by yacc.
*/
#define MAXEXPR 100 /* maximum number of expressions */
#define MAXSTRING 32 /* maximum length of input string */
#define MAXCOL 100 /* maximum number of input columns */
#define MAXCONST 100 /* maximum number of constants */
#define LOGe10 2.302585092994 /* used for L function */
#define FLOATPTR 0 /* codes for parse tree node types */
#define OPERATOR 1
#define STRINGOP 2
#define STRINGPTR 3
typedef int lgl; /* no lgl type in C */
#define FALSE 0
#define TRUE 1
#define PARSERROR 1 /* returned by yyparse on error */
/*
The following few numbers are reserved by dm to signal special conditions by
being returned by various routines. They are hopefully numbers that no
expressions would ever evaluate to.
*/
#define LARGE 9999999999999.0 /* a large number */
#define SUPPRESS -1125899906842624. /* suppress output */
#define STRINGFLAG -8888888888888777.0 /* returned by eval */
#define NIL -998888677484837274. /* cause nil output */
#define EXITFLAG -99999999999999.9 /* cause exit */
char *N_KILL = "KILL";
char *N_EXIT = "EXIT";
char *N_NIL = "NIL";
char *N_INLINE = "INLINE";
char *N_OUTLINE = "OUTLINE";
char *N_INPUT = "INPUT";
char *N_N = "N";
char *N_SUM = "SUM";
char *N_RAND = "RAND";
char *N_ABS = "abs";
char *N_FLOOR = "floor";
char *N_CEIL = "ceil";
char *N_EXP = "exp";
char *N_LOG = "log";
char *N_LOG10 = "Log";
char Outpipe = 0; /* true if output is piped */
FILE *Infile; /* data read from here */
char Inputline[BUFSIZ]; /* INPUT read into here */
FILE *Outfile; /* output from dm */
char *Evalstr[MAXCOL+1]; /* ptrs to strings from eval */
char Str[MAXCOL+1][MAXSTRING]; /* columns from each dataline */
char *Expra; /* ptr to each expression */
typedef union
{
int opr; /* if operator or stringop */
double *num; /* if FLOATPTR */
char *str; /* if STRINGOP */
} STUFF;
STUFF Tmp1, Tmp2; /* used in the parser to cast operators */
typedef struct enode /* expression node in tree */
{
int etype; /* type of node */
STUFF contents;
struct enode *lchild;
struct enode *rchild;
} ENODE;
#define ENULL ((ENODE *) NULL)
ENODE *Expr[MAXEXPR+1]; /* ptr to each parse tree */
double Input[MAXCOL+1]; /* input numbers */
#define INLINE (Input[0]) /* input line number stored here */
lgl Usenumber[MAXCOL+1]; /* true is Input[i] is used */
int Usecols; /* maximum col number accessed */
double Output[MAXEXPR+1]; /* output numbers */
#define OUTLINE (Output[0]) /* output line number stored here */
double Const[MAXCONST]; /* constants stored here */
int Nconst; /* number of constants */
double Nil = NIL; /* flagged by NIL */
double Suppress = SUPPRESS; /* flagged by KILL */
double Stringflag = STRINGFLAG; /* eval returns string */
double Exitflag = EXITFLAG; /* flagged by EXIT */
double Randu; /* uniform rand num */
extern double Maxrand; /* set by initrand */
lgl Userand; /* true if Randu is used */
double N; /* number of input cols */
double Sum; /* sum of input cols */
int Should_output[MAXEXPR+1]; /* used with X */
int Exprno; /* expression number */
int Nexpr; /* number of expressions */
char *malloc (), *strcpy ();
# line 122 "dm.y"
typedef union { /* union of the data types the parser will deal with */
int opr;
char *str;
double *num;
ENODE *ex;
} YYSTYPE;
# define NUMBER 257
# define STRING 258
# define STRINDEX 259
# define IF 260
# define THEN 261
# define ELSE 262
# define NOR 263
# define NAND 264
# define EQ 265
# define NE 266
# define GE 267
# define GT 268
# define LE 269
# define LT 270
# define NOTIN 271
# define C 67
# define UMINUS 272
# define l 108
# define L 76
# define e 101
# define a 97
# define f 102
# define c 99
#define yyclearin yychar = -1
#define yyerrok yyerrflag = 0
extern int yychar;
extern short yyerrflag;
#ifndef YYMAXDEPTH
#define YYMAXDEPTH 150
#endif
YYSTYPE yylval, yyval;
# define YYERRCODE 256
# line 386 "dm.y"
/*
Next is the scanner that will be repeatedly called by yyparse, yylex.
This simple program reads from a global char *Expra, set by main. Variables
are handled by returning NUMBER or STRING, tokens defined in above grammar.
*/
#define CONST (*Expra=='.'||(*Expra>='0'&&*Expra<='9'))
yylex ()
{
extern YYSTYPE yylval;
char *strsave ();
int column;
while (isspace (*Expra)) Expra++;
if (CONST)
{
if (Nconst == MAXCONST)
ERRMSG1 (Maximum number of constants is %d, MAXCONST)
Const[Nconst] = atof (Expra);
yylval.num = &Const[Nconst++];
while (CONST) Expra++;
return (NUMBER);
}
switch (*Expra)
{
case '"':
case '\'':
yylval.str = strsave ();
return (STRING);
case 's':
column = atoi (++Expra);
if (column > Usecols) Usecols = column;
yylval.str = Str[column];
while (CONST) Expra++;
return (STRING);
case 'x':
if (Expra[1] == '[')
{
Expra++;
return ('x');
}
column = atoi (++Expra);
if (column > Usecols) Usecols = column;
Usenumber[column] = TRUE;
yylval.num = &Input[column];
while (CONST) Expra++;
return (NUMBER);
case 'y':
if (Expra[1] == '[')
{
Expra++;
return ('y');
}
column = atoi (++Expra);
if (column > Usecols) Usecols = column;
yylval.num = &Output[column];
while (CONST) Expra++;
return (NUMBER);
case 'K':
if (begins (N_KILL, Expra))
Expra += strlen (N_KILL);
else Expra++;
yylval.num = &Suppress;
return (NUMBER);
case 'E':
if (begins (N_EXIT, Expra))
Expra += strlen (N_EXIT);
else Expra++;
yylval.num = &Exitflag;
return (NUMBER);
case 'N':
if (begins (N_NIL, Expra))
{
Expra += strlen (N_NIL);
yylval.num = &Nil;
}
else if (begins ("NEXT", Expra))
{
Expra += 4;
yylval.num = &Suppress;
}
else
{
Expra++;
yylval.num = &N;
}
return (NUMBER);
case 'S':
if (begins ("SKIP", Expra))
{
Expra += 4;
yylval.num = &Suppress;
}
else
{
if (begins (N_SUM, Expra))
Expra += strlen (N_SUM);
else Expra++;
yylval.num = ∑
}
return (NUMBER);
case 'R':
if (begins (N_RAND, Expra)) Expra += strlen (N_RAND); else Expra++;
Userand = TRUE;
yylval.num = &Randu;
return (NUMBER);
case 'I':
if (begins (N_INLINE, Expra))
{
Expra += strlen (N_INLINE);
yylval.num = &INLINE;
return (NUMBER);
}
if (begins (N_INPUT, Expra))
Expra += strlen (N_INPUT);
else Expra++;
yylval.str = Inputline;
return (STRING);
case 'O':
if (begins (N_OUTLINE, Expra))
{
Expra += strlen (N_OUTLINE);
yylval.num = &OUTLINE;
return (NUMBER);
}
break;
case '=': if (Expra[1] == '=') Expra += 2;
else Expra++;
return (EQ);
case '<': if (Expra[1] == '=')
{
Expra += 2;
return (LE);
}
Expra++;
return (LT);
case '>': if (Expra[1] == '=')
{
Expra += 2;
return (GE);
}
Expra++;
return (GT);
case '!': switch (Expra[1])
{
case '=': Expra += 2; return (NE);
case 'C': Expra += 2; return (NOTIN);
case '&': Expra += 2; return (NAND);
case '|': Expra += 2; return (NOR);
default: Expra++; return ('!');
}
case '&': if (Expra[1] == '&') Expra++; break;
case '|': if (Expra[1] == '|') Expra++; break;
case 'i': if (begins ("if", Expra))
{Expra += 2; return (IF);} break;
case 't': if (begins ("then", Expra))
{Expra += 4; return (THEN);} break;
case 'e': if (begins ("else", Expra))
{Expra += 4; return (ELSE);}
else if (begins (N_EXP, Expra))
{Expra += strlen (N_EXP); return ('e');}
break;
case 'a': if (begins (N_ABS, Expra))
{Expra += strlen (N_ABS); return ('a');}
break;
case 'f': if (begins (N_FLOOR, Expra))
{Expra += strlen (N_FLOOR); return ('f');}
break;
case 'c': if (begins (N_CEIL, Expra))
{Expra += strlen (N_CEIL); return ('c');}
break;
case 'l': if (begins (N_LOG, Expra))
{Expra += strlen (N_LOG); return ('l');}
break;
case 'L': if (begins (N_LOG10, Expra))
{Expra += strlen (N_LOG10); return ('L');}
break;
}
return ((int) *Expra++);
}
yyerror (msg)
char *msg;
{
if (msg && *msg) fprintf (stderr, "\007dm: %s\n", msg);
fprintf (stderr,
"\007dm: Failure occured with this left in input: (%s)\n", Expra-1);
#ifdef PTREE
ptree (Expr[Exprno]);
putchar ('\n');
#endif
}
char *
strsave ()
{
char buf[BUFSIZ], *bptr = buf;
char *p;
char quotechar = *Expra++;
while (*Expra && *Expra != quotechar)
*bptr++ = *Expra++;
if (*Expra == quotechar) Expra++;
*bptr = '\0';
if ((p = malloc ((unsigned) strlen (buf) + 1) ) == NULL)
ERRSPACE (saving strings)
return (strcpy (p, buf));
}
ENODE *
node (datum, dtype, lson, rson)
STUFF *datum; /* string, number, or operator */
int dtype; /* STRINGPTR, FLOATPTR, OPERATOR, STRINGOP */
ENODE *lson;
ENODE *rson;
{
ENODE *newnode;
newnode = (ENODE *) malloc (sizeof (ENODE));
if (newnode == NULL)
ERRSPACE(expressions)
newnode->etype = dtype;
switch (dtype)
{
case FLOATPTR: newnode->contents.num = datum->num; break;
case STRINGPTR: newnode->contents.str = datum->str; break;
case STRINGOP:
case OPERATOR: newnode->contents.opr = datum->opr; break;
default: fprintf (stderr, "\007dm/enode: unknown data type.\n");
}
newnode->lchild = lson;
newnode->rchild = rson;
return (newnode);
}
main (argc, argv) int argc; char *argv[];
{
ARGV0;
initial (argc, argv);
loop ();
exit (0);
}
/*
initial does the following:
1) inits the random number generator
2) reads in expressions from file, user, or argv[i].
3) parses expressions.
4) opens input and output files.
*/
initial (argc, argv) int argc; char **argv;
{
lgl interactive = FALSE; /* if true, input in interactive mode */
lgl input_by_hand = FALSE; /* true if expressions input by hand */
char exprline[BUFSIZ]; /* expressions read into here */
FILE *exprfile; /* expressions read from here */
FILE *getfile (); /* gets a file open */
argc--;
if (argc) checkstdin (Argv0);
if (argc == 0)
{
interactive = TRUE;
exprfile = getfile ("Expression file? ", "r");
if (exprfile == NULL)
{
input_by_hand = TRUE;
exprfile = stdin;
printf ("Enter ONE expression per line.\n");
printf ("End with an empty line.\n");
}
}
else if (argv[1][0] == 'E') /*Expra file flag */
{
if ((exprfile = fopen (&argv[1][1], "r")) == NULL)
ERROPEN (&argv[1][1])
}
else exprfile = NULL;
for (;;) /* PARSE expressions until done */
{
readexpr:
if (exprfile == NULL) /*read expras from argv[i] */
{
if (++Exprno > argc) break;
Expra = argv[Exprno];
}
else /*read Expras from exprfile */
{
++Exprno;
if (input_by_hand) printf ("expression[%d]: ", Exprno);
if (getline (exprline, BUFSIZ, exprfile) <= 0) break;
Expra = exprline;
}
while (isspace (*Expra)) Expra++;
if (*Expra == 'X')
{
Should_output[Exprno] = FALSE;
Expra++;
}
else Should_output[Exprno] = TRUE;
if (yyparse() == PARSERROR) /* call parser */
{
fprintf (stderr, "\007dm: error in parsing expr[%d].\n",
Exprno--);
if (input_by_hand) goto readexpr; else exit (1);
}
#ifdef PTREE
if (interactive)
{
printf ("e%d: ", Exprno);
ptree (Expr[Exprno]);
putchar ('\n');
}
#endif
}
Nexpr = Exprno - 1;
if (Nexpr == 0)
{
Exprno = 0;
fprintf (stderr, "dm: \007No expressions were read in\n");
if (input_by_hand) goto readexpr;
else exit (1);
}
/* OPEN I/O files */
if (interactive)
{
if ((Infile = getfile ("Input file? ", "r")) == NULL)
Infile = stdin;
if ((Outfile = getfile ("Output file or pipe? ", "w")) == NULL)
Outfile = stdout;
}
else
{
Infile = stdin;
Outfile = stdout;
}
if (Userand) initrand ();
}
/* loop runs the process on the input to produce the output */
loop ()
{
double eval ();
lgl skip = FALSE;
while (getinput () != EOF)
{
skip = FALSE;
for (Exprno = 1; Exprno <= Nexpr; Exprno++)
if ((Output[Exprno] = eval(Expr[Exprno])) == Suppress)
{skip = TRUE; break;}
else if (Output[Exprno] == Exitflag) exit (0);
if (skip == TRUE) continue;
OUTLINE += 1.0;
for (Exprno = 1; Exprno <= Nexpr; Exprno++)
if (Should_output[Exprno])
{
if (Output[Exprno] == Stringflag)
fprintf (Outfile, "%s",Evalstr[Exprno]);
else if (Output[Exprno] == Nil) continue;
else fprintf (Outfile,"%.6g",Output[Exprno]);
if (Exprno < Nexpr) putc ('\t', Outfile);
}
putc ('\n', Outfile);
/* fflush (Outfile); why was this needed? */
}
#ifndef MSDOS /* no popen on MSDOS */
if (Outpipe) VOID pclose (Outfile);
#endif
}
int
getinput ()
{
int ncols;
register int col;
if (getline (Inputline, BUFSIZ, Infile) == EOF) return (EOF);
if (Userand) Randu = rand()/Maxrand;
Sum = 0.0;
INLINE += 1.0;
for (col = 1; col <= Usecols; col++)
Str[col][0] = '\0';
ncols = sstrings (Inputline, Str[1], MAXCOL, MAXSTRING);
for (col = 1; col <= ncols; col++)
if (number (Str[col]))
Sum += Input[col] = atof(Str[col]);
else
if (Usenumber[col])
ERRMSG2 (number expected in column %d on line %.0f, col, INLINE)
N = ncols;
return (ncols);
}
/*
eval is a recursive function that takes a parse tree of an expression,
and returns its value. The major kluge in this program is how it handles
strings. Since it wants to return a double, it cannot return a string, so
the use of strings is somewhat restricted. When eval evals to a string, it
returns STRINGFLAG after setting a global char *Evalstr[Exprno] to the str
MAIN will look for this flag and switch its output to Evalstr[Exprno] rather
than Output[Exprno].
*/
double
eval (expression) ENODE *expression;
{
int comp; /*for string comparisons*/
int sindex, character; /*for STRINDEX function */
char *string_2b_indexed; /*for STRINDEX function */
double tmp1, tmp2;
char operator;
if (expression == NULL) return (0.0);
if (expression->etype == FLOATPTR)
return (*expression->contents.num);
if (expression->etype == STRINGPTR)
{
Evalstr[Exprno] = expression->contents.str;
return (Stringflag);
}
if (expression->etype == STRINGOP)
{
switch (expression->contents.opr)
{
case '=': /*string compare*/
comp = strcmp (expression->lchild->contents.str,
expression->rchild->contents.str);
return (comp ? 0.0 : 1.0);
case '>': /*string compare*/
comp = strcmp (expression->lchild->contents.str,
expression->rchild->contents.str);
return (comp > 0 ? 1.0 : 0.0);
case '<': /*string compare*/
comp = strcmp (expression->lchild->contents.str,
expression->rchild->contents.str);
return (comp < 0 ? 1.0 : 0.0);
case 'C': /*true is s1 is in s2 */
comp = substr (expression->lchild->contents.str,
expression->rchild->contents.str);
return (comp ? 1.0 : 0.0);
case '#':
return ((double) strlen (expression->rchild->contents.str));
case '[': /* string index */
sindex = eval (expression->rchild);
string_2b_indexed = expression->lchild->contents.str;
character = string_2b_indexed[sindex-1];
return (1.0 * character);
}
}
operator = expression->contents.opr;
if (operator == ':') return (0.0); /*dummy for conditional */
tmp1 = eval (expression->lchild);
tmp2 = eval (expression->rchild);
switch (operator)
{
case 'x':
sindex = (int) tmp2;
if (sindex < 0 || sindex > N)
ERRMSG1 (computed index for x (%d) is out of range, sindex)
if (Usenumber[sindex]) return (Input[sindex]);
if (number (Str[sindex])) return (atof (Str[sindex]));
ERRMSG2 (number expected in column %d of line %.0f, sindex, INLINE)
case 'y':
sindex = (int) tmp2;
if (sindex >= 0 && sindex <= Nexpr)
return (Output[sindex]);
ERRMSG1 (computed index for y (%d) is out of range, sindex)
case '_': return (-tmp2);
case '!': return (fzero (tmp2) ? 1.0 : 0.0);
case 'l': if (tmp2 <= 0.0)
ERRMSG3 (log undefined for %f on line %.0f expr[%d], tmp2, INLINE,Exprno)
return (log (tmp2));
case 'L': if (tmp2 <= 0.0)
ERRMSG3(Log undefined for %f Input line %.0f expr[%d], tmp2,INLINE,Exprno)
return (log (tmp2) / LOGe10);
case 'e': return (exp (tmp2));
case 'a': return (fabs (tmp2));
case 'c': return (ceil (tmp2));
case 'f': return (floor (tmp2));
case '+': return (tmp1 + tmp2);
case '-': return (tmp1 - tmp2);
case '*': return (tmp1 * tmp2);
case '%': if (fzero (tmp2))
ERRMSG2 (division by zero. input line %.0f expr[%d], INLINE,Exprno)
return ((double) (((int) tmp1) % ((int) tmp2)));
case '/': if (fzero (tmp2))
ERRMSG2 (division by zero. input line %.0f expr[%d], INLINE,Exprno)
return (tmp1/tmp2);
case '^':
if (tmp1 < 0.0 && (floor (tmp2) != tmp2))
ERRMSG1 (power failure at line %.0f, INLINE)
return (pow (tmp1, tmp2));
case '>': return (tmp1 > tmp2 ? 1.0 : 0.0);
case '<': return (tmp1 < tmp2 ? 1.0 : 0.0);
case '=': return (fzero (tmp1 - tmp2) ? 1.0 : 0.0);
case '&': return ((!fzero (tmp1) && !fzero (tmp2)) ? 1.0 : 0.0);
case '|': return ((!fzero (tmp1) || !fzero (tmp2)) ? 1.0 : 0.0);
case '?': if (!fzero (tmp1))
return (eval (expression->rchild->lchild));
return (eval (expression->rchild->rchild));
default:
ERRMSG1 (Unknown operator '%c', operator)
}
return (Exitflag);
}
#ifdef PTREE
ptree (tree) ENODE *tree;
{
if (tree == NULL) return;
if (tree->etype == FLOATPTR)
if (*tree->contents.num < -LARGE)
{
double *nptr = tree->contents.num;
if (nptr == &Suppress)
printf (N_KILL);
else if (nptr == &Exitflag)
printf (N_EXIT);
else if (nptr == &Nil)
printf (N_NIL);
else printf ("CONTROL");
}
else /* regular number */
{
double *dptr = tree->contents.num;
if (dptr > Input && dptr <= &Input[MAXCOL])
printf ("x%d", dptr - Input);
else if (dptr == &INLINE)
printf (N_INLINE);
else if (dptr > Output && dptr <= &Output[MAXCOL])
printf ("y%d", dptr - Output);
else if (dptr == &OUTLINE)
printf (N_OUTLINE);
else if (dptr == &N)
printf (N_N);
else if (dptr == &Sum)
printf (N_SUM);
else if (dptr == &Randu)
printf (N_RAND);
else printf ("%g", *dptr);
}
else if (tree->etype == STRINGPTR)
{
char *sptr = tree->contents.str;
if (sptr == Inputline)
printf (N_INPUT);
else if (sptr >= Str[0] && sptr < Str[MAXCOL])
printf ("s%d", (sptr - Str[0])/MAXSTRING);
else printf ("'%s'", sptr);
}
else if (tree->etype == OPERATOR || tree->etype == STRINGOP)
{
int op = tree->contents.opr;
printf ("(");
ptree (tree->lchild);
switch (op)
{
case 'l': printf ("%s ", N_LOG); break;
case 'L': printf ("%s ", N_LOG10); break;
case 'e': printf ("%s ", N_EXP); break;
case 'c': printf ("%s ", N_CEIL); break;
case 'f': printf ("%s ", N_FLOOR); break;
case 'a': printf ("%s ", N_ABS); break;
default:
printf (" %c ", op);
}
ptree (tree->rchild);
printf (")");
}
else printf ("(bad node type %d)", tree->etype);
}
#endif
FILE *
getfile (prompt, mode) char *prompt, *mode;
{
#ifndef MSDOS /* no popen on MSDOS */
FILE *popen ();
#endif
FILE *fopen (), *ioptr;
char filename[BUFSIZ];
char *ptr = filename;
newfile:
printf ("%s", prompt);
if (getline (filename, MAXSTRING, stdin) <= 0) return (NULL);
while (isspace (*ptr)) ptr++;
if (*ptr == NULL) return (NULL);
if (*mode == 'w')
if (*ptr == '|') Outpipe = 1;
else if (!canwrite (filename)) goto newfile;
if (Outpipe)
{
#ifndef MSDOS /* no popen on MSDOS */
if ((ioptr = popen (ptr+1, "w")) == NULL)
#endif
{
fprintf (stderr, "Cannot create pipe.\n");
Outpipe = 0;
goto newfile;
}
}
else if ((ioptr = fopen (filename, mode)) == NULL)
{
printf ("Cannot open '%s'.\n", filename);
goto newfile;
}
return (ioptr);
}
int
getline (string, maxlen, ioptr)
char *string;
int maxlen;
FILE *ioptr;
{
register int inchar;
register int len = 0;
while ((inchar = getc (ioptr)) != EOF)
{
if (inchar == '\n') break;
else if (inchar == '\\')
if ((inchar = getc (ioptr)) == EOF) inchar = '\\';
string[len] = inchar;
if (++len == maxlen) break;
}
string[len] = '\0';
if (len == 0 && feof (ioptr)) return (EOF);
return (len);
}
begins (s1, s2) char *s1, *s2;
{
while (*s1)
if (*s1++ != *s2++) return (0);
return (1);
/* return (isalpha (*s2) ? 0 : 1); can't be used because of s1 C s2 */
}
substr (s1, s2) char *s1, *s2;
{
while (*s2)
if (begins (s1, s2)) return (1);
else s2++;
return (0);
}
short yyexca[] ={
-1, 1,
0, -1,
-2, 0,
-1, 66,
265, 0,
266, 0,
267, 0,
268, 0,
269, 0,
270, 0,
-2, 15,
-1, 67,
265, 0,
266, 0,
267, 0,
268, 0,
269, 0,
270, 0,
-2, 16,
-1, 68,
265, 0,
266, 0,
267, 0,
268, 0,
269, 0,
270, 0,
-2, 19,
-1, 69,
265, 0,
266, 0,
267, 0,
268, 0,
269, 0,
270, 0,
-2, 20,
-1, 70,
265, 0,
266, 0,
267, 0,
268, 0,
269, 0,
270, 0,
-2, 23,
-1, 71,
265, 0,
266, 0,
267, 0,
268, 0,
269, 0,
270, 0,
-2, 24,
};
# define YYNPROD 45
# define YYLAST 396
short yyact[]={
23, 32, 96, 19, 23, 22, 20, 44, 21, 22,
24, 23, 32, 25, 24, 47, 22, 20, 46, 21,
90, 24, 23, 32, 1, 0, 36, 22, 20, 0,
21, 43, 24, 23, 32, 0, 0, 36, 22, 20,
2, 21, 0, 24, 0, 23, 32, 0, 36, 88,
22, 20, 0, 21, 0, 24, 93, 25, 0, 36,
0, 25, 0, 0, 23, 32, 0, 92, 25, 22,
20, 36, 21, 0, 24, 0, 23, 76, 91, 25,
0, 22, 20, 0, 21, 0, 24, 34, 0, 0,
25, 23, 32, 0, 0, 0, 22, 20, 34, 21,
0, 24, 25, 0, 9, 0, 16, 0, 0, 34,
0, 7, 0, 0, 0, 0, 8, 36, 23, 0,
34, 25, 0, 22, 20, 0, 21, 0, 24, 0,
94, 95, 34, 25, 0, 0, 0, 97, 0, 0,
0, 0, 0, 0, 0, 0, 0, 11, 25, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 13, 0,
15, 0, 12, 14, 0, 25, 0, 0, 34, 10,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 5, 6, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 37, 38, 40, 39, 42,
41, 45, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 35, 33, 26, 27,
29, 28, 31, 30, 0, 0, 0, 35, 33, 26,
27, 29, 28, 31, 30, 0, 0, 0, 35, 33,
26, 27, 29, 28, 31, 30, 0, 89, 0, 35,
33, 26, 27, 29, 28, 31, 30, 0, 0, 0,
0, 35, 33, 26, 27, 29, 28, 31, 30, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 33, 26, 27, 29, 28, 31, 30, 49, 4,
0, 0, 0, 0, 26, 27, 29, 28, 31, 30,
0, 0, 0, 0, 0, 58, 0, 35, 33, 26,
27, 29, 28, 31, 30, 0, 0, 0, 18, 19,
0, 17, 0, 0, 0, 4, 77, 78, 79, 80,
81, 82, 0, 84, 85, 0, 3, 0, 0, 0,
0, 0, 0, 0, 48, 50, 51, 52, 53, 54,
55, 56, 57, 0, 59, 0, 0, 60, 61, 62,
63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
73, 74, 75, 0, 0, 0, 0, 0, 4, 4,
83, 0, 0, 86, 87, 4 };
short yypact[]={
71,-1000,-1000, 54, -60, -73, -76, 71, 71, 71,
71, 71, 71, 71, 71, 71,-255, 71,-1000,-1000,
71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
71, 71, 71, 71, 71, 71, 71,-255,-255,-255,
-255,-255,-255, 71,-255,-255, 71, 71, 8, -60,
-1000, 39,-1000,-1000,-1000,-1000,-1000,-1000,-1000, -4,
-33, -33, -81, -81, -81, -81, 81, 81, 81, 81,
81, 81, 39, 39, 27, 27, -38,-1000,-1000,-1000,
-1000,-1000,-1000, -15,-1000,-1000, -26, -37,-1000, 71,
71,-1000,-1000,-1000,-260,-1000, 71,-1000 };
short yypgo[]={
0, 346, 298, 40, 24 };
short yyr1[]={
0, 4, 3, 3, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 2 };
short yyr2[]={
0, 1, 1, 1, 4, 4, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 2,
2, 2, 2, 2, 2, 2, 2, 2, 4, 3,
3, 5, 6, 1, 1 };
short yychk[]={
-1000, -4, -3, -1, -2, 120, 121, 40, 45, 33,
108, 76, 101, 97, 102, 99, 35, 260, 257, 258,
43, 45, 42, 37, 47, 94, 265, 266, 268, 267,
270, 269, 38, 264, 124, 263, 63, 265, 266, 268,
267, 270, 269, 91, 67, 271, 91, 91, -1, -2,
-1, -1, -1, -1, -1, -1, -1, -1, -2, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -3, -2, -2, -2,
-2, -2, -2, -1, -2, -2, -1, -1, 41, 261,
58, 93, 93, 93, -3, -3, 262, -3 };
short yydef[]={
0, -2, 1, 2, 3, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 43, 44,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
29, 30, 31, 32, 33, 34, 35, 36, 37, 0,
7, 8, 9, 10, 11, 12, -2, -2, -2, -2,
-2, -2, 25, 26, 27, 28, 0, 13, 14, 17,
18, 21, 22, 0, 39, 40, 0, 0, 6, 0,
0, 38, 4, 5, 0, 41, 0, 42 };
#ifndef lint
static char yaccpar_sccsid[] = "@(#)yaccpar 4.1 (Berkeley) 2/11/83";
#endif not lint
#
# define YYFLAG -1000
# define YYERROR goto yyerrlab
# define YYACCEPT return(0)
# define YYABORT return(1)
/* parser for yacc output */
#ifdef YYDEBUG
int yydebug = 0; /* 1 for debugging */
#endif
YYSTYPE yyv[YYMAXDEPTH]; /* where the values are stored */
int yychar = -1; /* current input token number */
int yynerrs = 0; /* number of errors */
short yyerrflag = 0; /* error recovery flag */
yyparse() {
short yys[YYMAXDEPTH];
short yyj, yym;
register YYSTYPE *yypvt;
register short yystate, *yyps, yyn;
register YYSTYPE *yypv;
register short *yyxi;
yystate = 0;
yychar = -1;
yynerrs = 0;
yyerrflag = 0;
yyps= &yys[-1];
yypv= &yyv[-1];
yystack: /* put a state and value onto the stack */
#ifdef YYDEBUG
if( yydebug ) printf( "state %d, char 0%o\n", yystate, yychar );
#endif
if( ++yyps> &yys[YYMAXDEPTH] ) { yyerror( "yacc stack overflow" ); return(1); }
*yyps = yystate;
++yypv;
*yypv = yyval;
yynewstate:
yyn = yypact[yystate];
if( yyn<= YYFLAG ) goto yydefault; /* simple state */
if( yychar<0 ) if( (yychar=yylex())<0 ) yychar=0;
if( (yyn += yychar)<0 || yyn >= YYLAST ) goto yydefault;
if( yychk[ yyn=yyact[ yyn ] ] == yychar ){ /* valid shift */
yychar = -1;
yyval = yylval;
yystate = yyn;
if( yyerrflag > 0 ) --yyerrflag;
goto yystack;
}
yydefault:
/* default state action */
if( (yyn=yydef[yystate]) == -2 ) {
if( yychar<0 ) if( (yychar=yylex())<0 ) yychar = 0;
/* look through exception table */
for( yyxi=yyexca; (*yyxi!= (-1)) || (yyxi[1]!=yystate) ; yyxi += 2 ) ; /* VOID */
while( *(yyxi+=2) >= 0 ){
if( *yyxi == yychar ) break;
}
if( (yyn = yyxi[1]) < 0 ) return(0); /* accept */
}
if( yyn == 0 ){ /* error */
/* error ... attempt to resume parsing */
switch( yyerrflag ){
case 0: /* brand new error */
yyerror( "syntax error" );
yyerrlab:
++yynerrs;
case 1:
case 2: /* incompletely recovered error ... try again */
yyerrflag = 3;
/* find a state where "error" is a legal shift action */
while ( yyps >= yys ) {
yyn = yypact[*yyps] + YYERRCODE;
if( yyn>= 0 && yyn < YYLAST && yychk[yyact[yyn]] == YYERRCODE ){
yystate = yyact[yyn]; /* simulate a shift of "error" */
goto yystack;
}
yyn = yypact[*yyps];
/* the current yyps has no shift onn "error", pop stack */
#ifdef YYDEBUG
if( yydebug ) printf( "error recovery pops state %d, uncovers %d\n", *yyps, yyps[-1] );
#endif
--yyps;
--yypv;
}
/* there is no state on the stack with an error shift ... abort */
yyabort:
return(1);
case 3: /* no shift yet; clobber input char */
#ifdef YYDEBUG
if( yydebug ) printf( "error recovery discards char %d\n", yychar );
#endif
if( yychar == 0 ) goto yyabort; /* don't discard EOF, quit */
yychar = -1;
goto yynewstate; /* try again in the same state */
}
}
/* reduction by production yyn */
#ifdef YYDEBUG
if( yydebug ) printf("reduce %d\n",yyn);
#endif
yyps -= yyr2[yyn];
yypvt = yypv;
yypv -= yyr2[yyn];
yyval = yypv[1];
yym=yyn;
/* consult goto table to find next state */
yyn = yyr1[yyn];
yyj = yypgo[yyn] + *yyps + 1;
if( yyj>=YYLAST || yychk[ yystate = yyact[yyj] ] != -yyn ) yystate = yyact[yypgo[yyn]];
switch(yym){
case 1:
# line 146 "dm.y"
{
Expr[Exprno] = yypvt[-0].ex;
} break;
case 2:
# line 151 "dm.y"
{
yyval.ex = yypvt[-0].ex;
} break;
case 3:
# line 155 "dm.y"
{
yyval.ex = yypvt[-0].ex;
} break;
case 4:
# line 160 "dm.y"
{
Tmp1.opr = 'x';
yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-1].ex);
} break;
case 5:
# line 165 "dm.y"
{
Tmp1.opr = 'y';
yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-1].ex);
} break;
case 6:
# line 170 "dm.y"
{
yyval.ex = yypvt[-1].ex;
} break;
case 7:
# line 174 "dm.y"
{
Tmp1.opr = '+';
yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex);
} break;
case 8:
# line 179 "dm.y"
{
Tmp1.opr = '-';
yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex);
} break;
case 9:
# line 184 "dm.y"
{
Tmp1.opr = '*';
yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex);
} break;
case 10:
# line 189 "dm.y"
{
Tmp1.opr = '%';
yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex);
} break;
case 11:
# line 194 "dm.y"
{
Tmp1.opr = '/';
yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex);
} break;
case 12:
# line 199 "dm.y"
{
Tmp1.opr = '^';
yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex);
} break;
case 13:
# line 204 "dm.y"
{
Tmp1.opr = '=';
yyval.ex = node (&Tmp1, STRINGOP, yypvt[-2].ex, yypvt[-0].ex);
} break;
case 14:
# line 209 "dm.y"
{
Tmp1.opr = '!';
Tmp2.opr = '=';
yyval.ex = node (&Tmp1, OPERATOR, ENULL,
node (&Tmp2, STRINGOP, yypvt[-2].ex, yypvt[-0].ex));
} break;
case 15:
# line 216 "dm.y"
{
Tmp1.opr = '=';
yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex);
} break;
case 16:
# line 221 "dm.y"
{
Tmp1.opr = '!';
Tmp2.opr = '=';
yyval.ex = node (&Tmp1, OPERATOR, ENULL,
node (&Tmp2, OPERATOR, yypvt[-2].ex, yypvt[-0].ex));
} break;
case 17:
# line 228 "dm.y"
{
Tmp1.opr = '>';
yyval.ex = node (&Tmp1, STRINGOP, yypvt[-2].ex, yypvt[-0].ex);
} break;
case 18:
# line 233 "dm.y"
{
Tmp1.opr = '!';
Tmp2.opr = '<';
yyval.ex = node (&Tmp1, OPERATOR, ENULL,
node (&Tmp2, STRINGOP, yypvt[-2].ex, yypvt[-0].ex));
} break;
case 19:
# line 240 "dm.y"
{
Tmp1.opr = '>';
yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex);
} break;
case 20:
# line 245 "dm.y"
{
Tmp1.opr = '!';
Tmp2.opr = '<';
yyval.ex = node (&Tmp1, OPERATOR, ENULL,
node (&Tmp2, OPERATOR, yypvt[-2].ex, yypvt[-0].ex));
} break;
case 21:
# line 252 "dm.y"
{
Tmp1.opr = '<';
yyval.ex = node (&Tmp1, STRINGOP, yypvt[-2].ex, yypvt[-0].ex);
} break;
case 22:
# line 257 "dm.y"
{
Tmp1.opr = '!';
Tmp2.opr = '>';
yyval.ex = node (&Tmp1, OPERATOR, ENULL,
node (&Tmp2, STRINGOP, yypvt[-2].ex, yypvt[-0].ex));
} break;
case 23:
# line 264 "dm.y"
{
Tmp1.opr = '<';
yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex);
} break;
case 24:
# line 269 "dm.y"
{
Tmp1.opr = '!';
Tmp2.opr = '>';
yyval.ex = node (&Tmp1, OPERATOR, ENULL,
node (&Tmp2, OPERATOR, yypvt[-2].ex, yypvt[-0].ex));
} break;
case 25:
# line 276 "dm.y"
{
Tmp1.opr = '&';
yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex);
} break;
case 26:
# line 281 "dm.y"
{
Tmp1.opr = '!';
Tmp2.opr = '&';
yyval.ex = node (&Tmp1, OPERATOR, ENULL,
node (&Tmp2, OPERATOR, yypvt[-2].ex, yypvt[-0].ex));
} break;
case 27:
# line 288 "dm.y"
{
Tmp1.opr = '|';
yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex);
} break;
case 28:
# line 293 "dm.y"
{
Tmp1.opr = '!';
Tmp2.opr = '|';
yyval.ex = node (&Tmp1, OPERATOR, ENULL,
node (&Tmp2, OPERATOR, yypvt[-2].ex, yypvt[-0].ex));
} break;
case 29:
# line 300 "dm.y"
{
Tmp1.opr = '_';
yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex);
} break;
case 30:
# line 305 "dm.y"
{
Tmp1.opr = '!';
yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex);
} break;
case 31:
# line 310 "dm.y"
{
Tmp1.opr = 'l';
yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex);
} break;
case 32:
# line 315 "dm.y"
{
Tmp1.opr = 'L';
yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex);
} break;
case 33:
# line 320 "dm.y"
{
Tmp1.opr = 'e';
yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex);
} break;
case 34:
# line 325 "dm.y"
{
Tmp1.opr = 'a';
yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex);
} break;
case 35:
# line 330 "dm.y"
{
Tmp1.opr = 'f';
yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex);
} break;
case 36:
# line 335 "dm.y"
{
Tmp1.opr = 'c';
yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex);
} break;
case 37:
# line 340 "dm.y"
{
Tmp1.opr = '#';
yyval.ex = node (&Tmp1, STRINGOP, ENULL, yypvt[-0].ex);
} break;
case 38:
# line 345 "dm.y"
{
Tmp1.opr = '[';
yyval.ex = node (&Tmp1, STRINGOP, yypvt[-3].ex, yypvt[-1].ex);
} break;
case 39:
# line 350 "dm.y"
{
Tmp1.opr = 'C';
yyval.ex = node (&Tmp1, STRINGOP, yypvt[-2].ex, yypvt[-0].ex);
} break;
case 40:
# line 355 "dm.y"
{
Tmp1.opr = '!';
Tmp2.opr = 'C';
yyval.ex = node (&Tmp1, OPERATOR, ENULL,
node (&Tmp2, STRINGOP, yypvt[-2].ex, yypvt[-0].ex));
} break;
case 41:
# line 362 "dm.y"
{
Tmp1.opr = '?';
Tmp2.opr = ':';
yyval.ex = node (&Tmp1, OPERATOR, yypvt[-4].ex,
node (&Tmp2, OPERATOR, yypvt[-2].ex, yypvt[-0].ex));
} break;
case 42:
# line 369 "dm.y"
{
Tmp1.opr = '?';
Tmp2.opr = ':';
yyval.ex = node (&Tmp1, OPERATOR, yypvt[-4].ex,
node (&Tmp2, OPERATOR, yypvt[-2].ex, yypvt[-0].ex));
} break;
case 43:
# line 376 "dm.y"
{
Tmp1.num = yypvt[-0].num;
yyval.ex = node (&Tmp1, FLOATPTR, ENULL, ENULL);
} break;
case 44:
# line 382 "dm.y"
{
Tmp1.str = yypvt[-0].str;
yyval.ex = node (&Tmp1, STRINGPTR, ENULL, ENULL);
} break;
}
goto yystack; /* stack new state and value */
}