|
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: 39193 (0x9919) Types: TextFile Names: »dm.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki └─⟦this⟧ »EUUGD11/stat-5.3/eu/stat/src/dm.c«
# line 2 "dm.y" /* Copyright 1980 Gary Perlman */ #include "stat.h" PGM(dm,Data Manipulation,5.8,10/14/86) #define DM_VERSION "5.8 10/14/86" #ifndef MSDOS # ifndef PTREE # define PTREE # endif PTREE #endif MSDOS /* 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 FLOATPTR 0 /* codes for parse tree node types */ #define OPERATOR 1 #define STRINGOP 2 #define STRINGPTR 3 #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 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 */ 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 */ int Seed; /* random seed sent to initrand */ Boole 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 */ # line 99 "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 SQRT 273 # define SIN 274 # define COS 275 # define TAN 276 # define ATAN 277 # define ACOS 278 # define ASIN 279 # define NTYPE 280 #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 409 "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. */ yylex () { extern YYSTYPE yylval; char *strsave (); int column; while (isspace (*Expra) || *Expra == '_') Expra++; if (isdigit (*Expra) || *Expra == '.') { if (Nconst == MAXCONST) ERRMSG1 (Maximum number of constants is %d, MAXCONST) Const[Nconst] = atof (Expra); yylval.num = &Const[Nconst++]; Expra += skipnumber (Expra, 1); return (NUMBER); } switch (*Expra) { case '"': case '\'': yylval.str = strsave (); return (STRING); case 'a': if (begins ("atan", Expra)) {Expra += 4; return (ATAN);} if (begins ("asin", Expra)) {Expra += 4; return (ASIN);} if (begins ("acos", Expra)) {Expra += 4; return (ACOS);} if (begins ("abs", Expra)) {Expra += 3; return ('a');} if (begins ("and", Expra)) {Expra += 3; return ('&');} break; case 'A': if (begins ("AND", Expra)) { Expra += 3; return ('&'); } break; case 'c': if (begins ("cos", Expra)) {Expra += 3; return (COS);} if (begins ("ceil", Expra)) {Expra += 4; return ('c');} break; case 'f': if (begins ("floor", Expra)) {Expra += 5; return ('f');} break; case 'G': if (begins ("GE", Expra)) { Expra += 2; return (GE); } if (begins ("GT", Expra)) { Expra += 2; return (GT); } break; case 'e': if (begins ("else", Expra)) {Expra += 4; return (ELSE);} else if (begins ("exp", Expra)) {Expra += 3; return ('e');} break; case 'E': if (begins ("EQ", Expra)) { Expra += 2; return (EQ); } if (begins ("ELSE", Expra)) { Expra += 4; return (ELSE); } if (begins ("EXIT", Expra)) Expra += 4; else Expra++; yylval.num = &Exitflag; return (NUMBER); case 'i': if (begins ("if", Expra)) {Expra += 2; return (IF);} break; case 'I': if (begins ("IF", Expra)) { Expra += 2; return (IF); } if (begins ("INLINE", Expra)) { Expra += 6; yylval.num = &INLINE; return (NUMBER); } if (begins ("INPUT", Expra)) Expra += 5; else Expra++; yylval.str = Inputline; return (STRING); case 'K': if (begins ("KILL", Expra)) Expra += 4; else Expra++; yylval.num = &Suppress; return (NUMBER); case 'l': if (begins ("log", Expra)) {Expra += 3; return ('l');} if (begins ("len", Expra)) {Expra += 3; return ('#');} break; case 'L': if (begins ("LE", Expra)) { Expra += 2; return (LE); } if (begins ("LT", Expra)) { Expra += 2; return (LT); } if (begins ("Log", Expra)) {Expra += 3; return ('L');} break; case 'n': if (begins ("not", Expra)) { Expra += 3; return ('!'); } if (begins ("number", Expra)) { Expra += 6; return (NTYPE); } break; case 'N': if (begins ("NOT", Expra)) { Expra += 3; return ('!'); } if (begins ("NE", Expra) && !begins ("NEXT", Expra)) { Expra += 2; return (NE); } if (begins ("NIL", Expra)) { Expra += 3; yylval.num = &Nil; } else if (begins ("NEXT", Expra)) { Expra += 4; yylval.num = &Suppress; } else { Expra++; yylval.num = &N; } return (NUMBER); case 'o': if (begins ("or", Expra)) { Expra += 2; return ('|'); } break; case 'O': if (begins ("OR", Expra)) { Expra += 2; return ('|'); } if (begins ("OUTLINE", Expra)) { Expra += 7; yylval.num = &OUTLINE; return (NUMBER); } break; case 'R': if (begins ("RAND", Expra)) Expra += 4; else Expra++; Userand = TRUE; if (isdigit (*Expra)) { Seed = atoi (Expra); while (isdigit (*Expra)) Expra++; } yylval.num = &Randu; return (NUMBER); case 's': if (begins ("sqrt", Expra)) { Expra += 4; return (SQRT); } if (begins ("sin", Expra)) { Expra += 3; return (SIN); } column = atoi (++Expra); Expra += skipnumber (Expra, 0); yylval.str = Str[column]; return (STRING); case 'S': if (begins ("SKIP", Expra)) { Expra += 4; yylval.num = &Suppress; } else { if (begins ("SUM", Expra)) Expra += 3; else Expra++; yylval.num = ∑ } return (NUMBER); case 't': if (begins ("tan", Expra)) {Expra += 3; return (TAN);} if (begins ("then", Expra)) {Expra += 4; return (THEN);} break; case 'T': if (begins ("THEN", Expra)) {Expra += 4; return (THEN);} break; case 'x': if (Expra[1] == '[') { Expra++; return ('x'); } column = atoi (++Expra); Expra += skipnumber (Expra, 0); yylval.num = &Input[column]; return (NUMBER); case 'y': if (Expra[1] == '[') { Expra++; return ('y'); } column = atoi (++Expra); Expra += skipnumber (Expra, 0); yylval.num = &Output[column]; return (NUMBER); 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; } return ((int) *Expra++); } yyerror (msg) char *msg; { if (msg && *msg) fprintf (stderr, "\007dm: %s\n", msg); fprintf (stderr, "\007dm: Failure occurred 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 quotechar = *Expra++; while (*Expra && *Expra != quotechar) *bptr++ = *Expra++; if (*Expra == quotechar) Expra++; *bptr = '\0'; return (strdup (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 = myalloc (ENODE, 1); 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; { Boole interactive = FALSE; /* if true, input in interactive mode */ Boole 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 (); if (argc == 0) { interactive = TRUE; printf ("dm: version %s (Copyright 1980 Gary Perlman)\n", DM_VERSION); 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 && !feof (stdin)) 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 (Seed); } /* loop runs the process on the input to produce the output */ loop () { double eval (); Boole 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 printnum (Outfile, 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; int randval; if (getline (Inputline, BUFSIZ, Infile) == EOF) return (EOF); if (Userand) { while ((randval = rand ()) < 0); Randu = randval/Maxrand; } Sum = 0.0; INLINE += 1.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 Input[col] = 0.0; N = ncols; return (ncols); } /* eval is a recursive function that takes a parse tree of an expression, and returns its value. The major kludge 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; int 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 NTYPE: return ((double) number (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) return (Input[sindex]); 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 SQRT: if (tmp2 < 0.0) ERRMSG3 (sqrt undefined for %f Input line %.0f expr[%d], tmp2, INLINE, Exprno) return (sqrt (tmp2)); case SIN: return (sin (tmp2)); case COS: return (cos (tmp2)); case TAN: return (tan (tmp2)); case ATAN: return (atan (tmp2)); case ACOS: return (acos (tmp2)); case ASIN: return (asin (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: ERRMSG3 (Unknown operator '%c' %d \\%3o, operator, operator, 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 ("KILL"); else if (nptr == &Exitflag) printf ("EXIT"); else if (nptr == &Nil) printf ("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 ("INLINE"); else if (dptr > Output && dptr <= &Output[MAXCOL]) printf ("y%d", dptr - Output); else if (dptr == &OUTLINE) printf ("OUTLINE"); else if (dptr == &N) printf ("N"); else if (dptr == &Sum) printf ("SUM"); else if (dptr == &Randu) printf ("RAND"); else printnum (stdout, *dptr); } else if (tree->etype == STRINGPTR) { char *sptr = tree->contents.str; if (sptr == Inputline) printf ("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 NTYPE: printf ("number "); break; case '#': printf ("len "); break; case 'l': printf ("log "); break; case 'L': printf ("Log "); break; case 'e': printf ("exp "); break; case SQRT: printf ("sqrt "); break; case SIN: printf ("sin "); break; case COS: printf ("cos "); break; case TAN: printf ("tan "); break; case ATAN: printf ("atan "); break; case ACOS: printf ("acos "); break; case ASIN: printf ("asin "); break; case 'c': printf ("ceil "); break; case 'f': printf ("floor "); break; case 'a': printf ("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); } printnum (ioptr, value) FILE *ioptr; double value; { char *format = "%g"; if (value >= 0.0 && (fzero (floor (value) - value))) format = "%.0f"; fprintf (ioptr, format, value); } short yyexca[] ={ -1, 1, 0, -1, -2, 0, -1, 84, 265, 0, 266, 0, 267, 0, 268, 0, 269, 0, 270, 0, -2, 15, -1, 85, 265, 0, 266, 0, 267, 0, 268, 0, 269, 0, 270, 0, -2, 16, -1, 86, 265, 0, 266, 0, 267, 0, 268, 0, 269, 0, 270, 0, -2, 19, -1, 87, 265, 0, 266, 0, 267, 0, 268, 0, 269, 0, 270, 0, -2, 20, -1, 88, 265, 0, 266, 0, 267, 0, 268, 0, 269, 0, 270, 0, -2, 23, -1, 89, 265, 0, 266, 0, 267, 0, 268, 0, 269, 0, 270, 0, -2, 24, }; # define YYNPROD 54 # define YYLAST 476 short yyact[]={ 9, 52, 24, 31, 40, 116, 33, 7, 30, 28, 75, 29, 8, 32, 31, 55, 54, 110, 1, 30, 107, 0, 31, 40, 32, 51, 0, 30, 28, 44, 29, 0, 32, 0, 0, 0, 31, 40, 2, 0, 0, 30, 28, 11, 29, 0, 32, 31, 44, 0, 0, 0, 30, 28, 0, 29, 0, 32, 0, 113, 33, 0, 44, 107, 20, 0, 22, 0, 19, 21, 0, 33, 0, 0, 0, 10, 31, 40, 112, 33, 0, 30, 28, 94, 29, 0, 32, 5, 6, 52, 42, 0, 111, 33, 0, 31, 40, 0, 0, 106, 30, 28, 44, 29, 33, 32, 0, 0, 0, 42, 31, 40, 0, 51, 0, 30, 28, 0, 29, 0, 32, 44, 0, 42, 31, 40, 0, 0, 0, 30, 28, 0, 29, 33, 32, 31, 44, 0, 0, 0, 30, 28, 0, 29, 0, 32, 0, 0, 114, 115, 0, 0, 33, 0, 0, 117, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 42, 0, 45, 46, 48, 47, 50, 49, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 27, 0, 25, 27, 43, 41, 34, 35, 37, 36, 39, 38, 0, 0, 0, 12, 13, 14, 15, 16, 17, 18, 23, 43, 41, 34, 35, 37, 36, 39, 38, 0, 0, 0, 0, 0, 0, 43, 41, 34, 35, 37, 36, 39, 38, 0, 0, 0, 0, 0, 34, 35, 37, 36, 39, 38, 0, 0, 0, 0, 0, 0, 45, 46, 48, 47, 50, 49, 53, 0, 0, 0, 0, 0, 0, 109, 0, 43, 41, 34, 35, 37, 36, 39, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 41, 34, 35, 37, 36, 39, 38, 0, 0, 0, 0, 0, 0, 0, 43, 41, 34, 35, 37, 36, 39, 38, 0, 0, 0, 0, 0, 0, 0, 41, 34, 35, 37, 36, 39, 38, 59, 4, 0, 0, 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 95, 96, 97, 98, 99, 100, 3, 102, 103, 0, 0, 0, 0, 0, 56, 58, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 108, 0, 77, 0, 0, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 0, 0, 0, 0, 0, 0, 0, 101, 0, 0, 104, 105, 0, 4, 4, 0, 0, 0, 0, 0, 4 }; short yypact[]={ -33,-1000,-1000, 73, -66, -75, -76, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -30, -30, -33,-1000,-1000, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -33, -30, -30, -30, -30, -30, -30, -33, -30, -30, -33, -33, 58, 22,-1000, -66, 10,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000, -1000,-1000,-1000,-1000,-1000, -30,-1000, 39, -23, -23, -88, -88, -88, -88, 98, 98, 98, 98, 98, 98, 10, 10, 87, 87, -41,-1000,-1000,-1000,-1000,-1000, -1000, -1,-1000,-1000, -15, -34,-1000,-1000, -21, -33, -33,-1000,-1000,-1000,-257,-1000, -33,-1000 }; short yypgo[]={ 0, 410, 358, 38, 18 }; 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, 1, 1, 1, 1, 1, 1, 1, 1, 2, 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, 2, 2, 2, 2, 2, 2, 2, 2, 4, 3, 3, 5, 6, 1, 3, 1 }; short yychk[]={ -1000, -4, -3, -1, -2, 120, 121, 40, 45, 33, 108, 76, 273, 274, 275, 276, 277, 278, 279, 101, 97, 102, 99, 280, 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, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, 40, -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, 41, -2, 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, 0, 0, 0, 0, 0, 0, 0, 0, 51, 53, 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, 0, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 0, 45, 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, 47, 48, 0, 0, 6, 52, 0, 0, 0, 46, 4, 5, 0, 49, 0, 50 }; #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 125 "dm.y" { Expr[Exprno] = yypvt[-0].ex; } break; case 2: # line 130 "dm.y" { yyval.ex = yypvt[-0].ex; } break; case 3: # line 134 "dm.y" { yyval.ex = yypvt[-0].ex; } break; case 4: # line 139 "dm.y" { Tmp1.opr = 'x'; yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-1].ex); } break; case 5: # line 144 "dm.y" { Tmp1.opr = 'y'; yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-1].ex); } break; case 6: # line 149 "dm.y" { yyval.ex = yypvt[-1].ex; } break; case 7: # line 153 "dm.y" { Tmp1.opr = '+'; yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex); } break; case 8: # line 158 "dm.y" { Tmp1.opr = '-'; yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex); } break; case 9: # line 163 "dm.y" { Tmp1.opr = '*'; yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex); } break; case 10: # line 168 "dm.y" { Tmp1.opr = '%'; yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex); } break; case 11: # line 173 "dm.y" { Tmp1.opr = '/'; yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex); } break; case 12: # line 178 "dm.y" { Tmp1.opr = '^'; yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex); } break; case 13: # line 183 "dm.y" { Tmp1.opr = '='; yyval.ex = node (&Tmp1, STRINGOP, yypvt[-2].ex, yypvt[-0].ex); } break; case 14: # line 188 "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 195 "dm.y" { Tmp1.opr = '='; yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex); } break; case 16: # line 200 "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 207 "dm.y" { Tmp1.opr = '>'; yyval.ex = node (&Tmp1, STRINGOP, yypvt[-2].ex, yypvt[-0].ex); } break; case 18: # line 212 "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 219 "dm.y" { Tmp1.opr = '>'; yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex); } break; case 20: # line 224 "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 231 "dm.y" { Tmp1.opr = '<'; yyval.ex = node (&Tmp1, STRINGOP, yypvt[-2].ex, yypvt[-0].ex); } break; case 22: # line 236 "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 243 "dm.y" { Tmp1.opr = '<'; yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex); } break; case 24: # line 248 "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 255 "dm.y" { Tmp1.opr = '&'; yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex); } break; case 26: # line 260 "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 267 "dm.y" { Tmp1.opr = '|'; yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex); } break; case 28: # line 272 "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 279 "dm.y" { Tmp1.opr = '_'; yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex); } break; case 30: # line 284 "dm.y" { Tmp1.opr = '!'; yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex); } break; case 31: # line 289 "dm.y" { Tmp1.opr = 'l'; yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex); } break; case 32: # line 294 "dm.y" { Tmp1.opr = 'L'; yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex); } break; case 33: # line 299 "dm.y" { Tmp1.opr = SQRT; yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex); } break; case 34: # line 304 "dm.y" { Tmp1.opr = SIN; yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex); } break; case 35: # line 309 "dm.y" { Tmp1.opr = COS; yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex); } break; case 36: # line 314 "dm.y" { Tmp1.opr = TAN; yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex); } break; case 37: # line 319 "dm.y" { Tmp1.opr = ATAN; yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex); } break; case 38: # line 324 "dm.y" { Tmp1.opr = ACOS; yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex); } break; case 39: # line 329 "dm.y" { Tmp1.opr = ASIN; yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex); } break; case 40: # line 334 "dm.y" { Tmp1.opr = 'e'; yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex); } break; case 41: # line 339 "dm.y" { Tmp1.opr = 'a'; yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex); } break; case 42: # line 344 "dm.y" { Tmp1.opr = 'f'; yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex); } break; case 43: # line 349 "dm.y" { Tmp1.opr = 'c'; yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex); } break; case 44: # line 354 "dm.y" { Tmp1.opr = NTYPE; yyval.ex = node (&Tmp1, STRINGOP, ENULL, yypvt[-0].ex); } break; case 45: # line 359 "dm.y" { Tmp1.opr = '#'; yyval.ex = node (&Tmp1, STRINGOP, ENULL, yypvt[-0].ex); } break; case 46: # line 364 "dm.y" { Tmp1.opr = '['; yyval.ex = node (&Tmp1, STRINGOP, yypvt[-3].ex, yypvt[-1].ex); } break; case 47: # line 369 "dm.y" { Tmp1.opr = 'C'; yyval.ex = node (&Tmp1, STRINGOP, yypvt[-2].ex, yypvt[-0].ex); } break; case 48: # line 374 "dm.y" { Tmp1.opr = '!'; Tmp2.opr = 'C'; yyval.ex = node (&Tmp1, OPERATOR, ENULL, node (&Tmp2, STRINGOP, yypvt[-2].ex, yypvt[-0].ex)); } break; case 49: # line 381 "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 50: # line 388 "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 51: # line 395 "dm.y" { Tmp1.num = yypvt[-0].num; yyval.ex = node (&Tmp1, FLOATPTR, ENULL, ENULL); } break; case 52: # line 401 "dm.y" { yyval.ex = yypvt[-1].ex; } break; case 53: # line 405 "dm.y" { Tmp1.str = yypvt[-0].str; yyval.ex = node (&Tmp1, STRINGPTR, ENULL, ENULL); } break; } goto yystack; /* stack new state and value */ }