|
|
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 c
Length: 26663 (0x6827)
Types: TextFile
Names: »calc.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦this⟧ »EUUGD11/stat-5.3/eu/stat/src/calc.c«
# line 2 "calc.y"
/* Copyright 1981 Gary Perlman */
#ifdef MSDOS /* increase stack size on MSODS */
int _stack = 32000;
#endif
#ifndef lint
static char sccsid[] = "@(#) calc.y 5.2 (|stat) 11/2/85";
#endif
#define CALC_VERSION "5.2 11/2/85"
/* PGM(calc, Algebraic Modeling Calculator) */
#include <stdio.h>
#include <math.h>
#include <ctype.h>
#ifdef MSDOS
typedef int void;
#else
# include <signal.h>
#endif
#define FZERO (10e-10)
#define fzero(x) (fabs (x) < FZERO)
#define isvarchar(c) (isalnum (c) || (c) == '_')
#ifndef iscntrl
#define iscntrl(a) ((a)>0&&(a)<26)
#endif
#define OPERATOR 1
#define PARSERROR 1
#define MAXVAR 1000
#define UNDEFINED -99999999999.987654321
int Nvar;
char *Varname[MAXVAR];
char *Eptr;
int Printequation = 1;
char *Prompt = "CALC: ";
int Interactive = 0;
char Format[100] = "%.10g"; /* default print format for numbers */
typedef union
{
int opr; /* if OPERATOR */
double *num; /* if NUMBER */
int var; /* if VARIABLE */
} 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 *left;
struct enode *right;
} ENODE;
#define ENULL ((ENODE *) NULL)
ENODE *Expression, *Variable[MAXVAR];
double eval (), Answer;
double *Constant;
char *malloc ();
char *getline ();
FILE *Outfile = stdout;
# line 68 "calc.y"
typedef union
{
int opr; /* an operator */
int var; /* an index into the variable table */
double *num; /* a pointer to a numerical constant */
ENODE *ex; /* an expression in the parse tree */
} YYSTYPE;
# define NUMBER 257
# define VARIABLE 258
# define IF 259
# define THEN 260
# define ELSE 261
# define EQ 262
# define NE 263
# define GE 264
# define LE 265
# define UMINUS 266
# define ABS 267
# define EXP 268
# define LOG 269
# define SQRT 270
# define COS 271
# define TAN 272
# define SIN 273
# define ACOS 274
# define ASIN 275
# define ATAN 276
#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 272 "calc.y"
yylex ()
{
extern YYSTYPE yylval;
char tmpvarname[BUFSIZ];
int i;
while (isspace (*Eptr)) Eptr++;
if (begins ("acos", Eptr)) {Eptr += 4; return (ACOS);}
if (begins ("asin", Eptr)) {Eptr += 4; return (ASIN);}
if (begins ("atan", Eptr)) {Eptr += 4; return (ATAN);}
if (begins ("cos", Eptr)) {Eptr += 3; return (COS);}
if (begins ("sin", Eptr)) {Eptr += 3; return (SIN);}
if (begins ("tan", Eptr)) {Eptr += 3; return (TAN);}
if (begins ("log", Eptr)) {Eptr += 3; return (LOG);}
if (begins ("sqrt", Eptr)) {Eptr += 4; return (SQRT);}
if (begins ("exp", Eptr)) {Eptr += 3; return (EXP);}
if (begins ("abs", Eptr)) {Eptr += 3; return (ABS);}
if (begins ("if", Eptr)) {Eptr += 2; return (IF);}
if (begins ("then", Eptr)) {Eptr += 4; return (THEN);}
if (begins ("else", Eptr)) {Eptr += 4; return (ELSE);}
if (*Eptr == '$')
{
Eptr++;
yylval.num = &Answer;
return (NUMBER);
}
if (isdigit (*Eptr) || *Eptr == '.')
{
Constant = (double *) malloc (sizeof (double));
if (Constant == NULL)
errorexit ("Out of storage space");
*Constant = atof (Eptr);
yylval.num = Constant;
Eptr += skipnumber (Eptr, 1);
return (NUMBER);
}
if (isvarchar (*Eptr))
{
for (i = 0; isvarchar (Eptr[i]); i++)
tmpvarname[i] = Eptr[i];
tmpvarname[i] = NULL;
Eptr += i;
i = 0;
while (i < Nvar && strcmp (tmpvarname, Varname[i])) i++;
if (i == Nvar)
{
Varname[i] = malloc ((unsigned) (strlen(tmpvarname)+1));
if (Varname[i] == NULL)
errorexit ("Out of storage space");
(void) strcpy (Varname[i], tmpvarname);
if (++Nvar == MAXVAR)
errorexit ("Too many variables");
}
yylval.var = i;
return (VARIABLE);
}
if (begins ("!=", Eptr)) { Eptr += 2; return (NE); }
if (begins (">=", Eptr)) { Eptr += 2; return (GE); }
if (begins ("<=", Eptr)) { Eptr += 2; return (LE); }
if (begins ("==", Eptr)) { Eptr += 2; return (EQ); }
if (begins ("**", Eptr)) { Eptr += 2; return ('^'); }
if (begins ("&&", Eptr)) { Eptr += 2; return ('&'); }
if (begins ("||", Eptr)) { Eptr += 2; return ('|'); }
return ((int) *Eptr++);
}
yyerror (msg)
char *msg;
{
fprintf (Outfile, "%s:\n", msg);
fprintf (Outfile, "Parsing error. ");
fprintf (Outfile, "This is left in input: [%s]\n", Eptr-1);
}
ENODE *
node (datum, datatype, lson, rson)
STUFF *datum; /* pointer to a number or an operator */
int datatype; /* NUMBER or VARIABLE or OPERATOR */
ENODE *lson; /* left part of tree */
ENODE *rson; /* right part of tree */
{
ENODE *newnode;
newnode = (ENODE *) malloc (sizeof (ENODE));
if (newnode == ENULL)
errorexit ("Out of storage space");
newnode->etype = datatype;
if (datatype == OPERATOR)
newnode->contents.opr = datum->opr;
else if (datatype == VARIABLE)
newnode->contents.var = datum->var;
else /* (datatype == NUMBER) */
newnode->contents.num = datum->num;
newnode->left = lson;
newnode->right = rson;
return (newnode);
}
main (argc, argv) int argc; char *argv[];
{
int i;
#ifndef MSDOS
signal (SIGINT, SIG_IGN);
#endif
if (isatty (fileno (stdin)))
{
Interactive = 1;
printf ("calc: version %s (Copyright 1981 Gary Perlman)\n", CALC_VERSION);
printf ("Enter expressions after the prompt '%s'\n", Prompt);
#ifdef MSDOS
printf ("Quit with ^Z, get help with ?\n");
#else
printf ("Quit with ^D, get help with ?\n");
#endif
}
for (i = 1; i < argc; i++)
process (argv[i]);
process ("-");
if (Interactive) /* wipe out prompt */
printf ("\015 \015");
exit (0);
}
process (filename) char *filename;
{
char exprline[BUFSIZ];
FILE *ioptr;
if (filename == NULL || !strcmp (filename, "-"))
{
ioptr = stdin;
filename = NULL;
}
else if ((ioptr = fopen (filename, "r")) == NULL)
{
fprintf (stderr, "Can't open %s\n", filename);
return;
}
if (filename)
fprintf (Outfile, "Reading from %s\n", filename);
for (;;)
{
if (ioptr == stdin && Interactive)
fprintf (Outfile, Prompt);
if (!getline (exprline, ioptr)) break;
Eptr = exprline;
while (isspace (*Eptr))
Eptr++;
if (*Eptr == '\0' || *Eptr == '?')
{
if (filename == NULL && Interactive)
printmenu ();
continue;
}
if (iscntrl (*Eptr))
{
control (Eptr);
continue;
}
if (yyparse() == PARSERROR)
continue;
if (Printequation || ioptr != stdin)
ptree (Outfile, Expression);
if (fzero (Answer = eval (Expression)))
Answer = 0.0;
if (Printequation)
printf (" =");
if (Answer == UNDEFINED)
fprintf (Outfile, "\tUNDEFINED\n");
else
{
putc ('\t', Outfile);
fprintf (Outfile, Format, Answer);
putc ('\n', Outfile);
}
}
if (ioptr != stdin)
(void) fclose (ioptr);
}
printmenu ()
{
puts ("Expressions are in standard C syntax (like algebra).");
puts ("The following CTRL characters have special functions:");
puts ("(You may have to precede the character with a ^V)");
#ifdef MSDOS
puts ("^Z end of input to CALC");
#else
puts ("^D end of input to CALC");
#endif
puts ("^P toggles the printing of equations");
puts ("^Rfile reads the expressions from the named file");
puts ("^Wfile writes all expressions to the named file");
puts (" If no file is supplied, then print to the screen");
}
#define CTRL_PRINT 16
#define CTRL_READ 18
#define CTRL_WRITE 23
#define CTRL_VAR 22
#define CTRL_FMT 6
control (key) char *key;
{
int var;
FILE *saveoutfile;
switch (*key)
{
case CTRL_FMT:
if (key[1] == '\0' || isspace (key[1]))
fprintf (Outfile, "Current_Format = '%s'\n", Format);
else
strcpy (Format+1, key+1);
return;
case CTRL_PRINT:
Printequation = !Printequation;
return;
case CTRL_READ:
while (iscntrl (*key) || isspace (*key))
key++;
process (key);
return;
case CTRL_WRITE:
case CTRL_VAR:
while (*key && (iscntrl (*key) || isspace (*key)))
key++;
if (*key)
{
fprintf (Outfile, "Writing to %s\n", key);
saveoutfile = Outfile;
if ((Outfile = fopen (key, "a")) == NULL)
{
fprintf (stderr, "Can't open %s\n", key);
Outfile = saveoutfile;
}
}
for (var = 0; var < Nvar; var++)
{
fprintf (Outfile, "%-10s = ", Varname[var]);
if (Outfile == stdout)
{
if (fzero (Answer = eval (Variable[var])))
Answer = 0.0;
if (Answer == UNDEFINED)
fprintf (Outfile, " UNDEFINED = ");
else
{
fprintf (Outfile, Format, Answer);
fprintf (Outfile, " = ");
}
}
ptree (Outfile, Variable[var]);
fprintf (Outfile, "\n");
}
if (*key)
{
(void) fclose (Outfile);
Outfile = saveoutfile;
}
return;
default:
fprintf (stderr, "Unknown control character.\n");
}
}
double
eval (expression)
ENODE *expression;
{
double tmp1, tmp2;
if (expression == ENULL)
return (UNDEFINED);
if (expression->etype == NUMBER)
return (*expression->contents.num);
if (expression->etype == VARIABLE)
{
if (Variable[expression->contents.var])
return (eval (Variable[expression->contents.var]));
else
return (UNDEFINED);
}
if ((tmp2 = eval (expression->right)) == UNDEFINED)
return (UNDEFINED);
switch (expression->contents.opr)
{
case '_': return (-tmp2);
case '!': return (fzero (tmp2) ? 1.0 : 0.0);
case LOG: if (tmp2 <= FZERO) return (UNDEFINED);
else return (log (tmp2));
case COS: return (cos (tmp2));
case SIN: return (sin (tmp2));
case TAN: return (tan (tmp2));
case ACOS: return (acos (tmp2));
case ASIN: return (asin (tmp2));
case ATAN: return (atan (tmp2));
case EXP: return (exp (tmp2));
case ABS: return (fabs (tmp2));
case SQRT: if (tmp2 < 0.0) return (UNDEFINED);
else return (sqrt (tmp2));
}
if ((tmp1 = eval (expression->left)) == UNDEFINED)
return (UNDEFINED);
switch (expression->contents.opr)
{
case '+': return (tmp1 + tmp2);
case '-': return (tmp1 - tmp2);
case '*': return (tmp1 * tmp2);
case '%': if ((int) tmp2 == 0) return (tmp1);
else return ((double) (((int) tmp1) % ((int) tmp2)));
case '/': if (fzero (tmp2)) return (UNDEFINED);
else return (tmp1/tmp2);
case '^': return (pow (tmp1, tmp2));
case '&': return ((!fzero (tmp1) && !fzero (tmp2)) ? 1.0 : 0.0);
case '|': return ((!fzero (tmp1) || !fzero (tmp2)) ? 1.0 : 0.0);
case '>': return (tmp1 > tmp2 ? 1.0 : 0.0);
case '<': return (tmp1 < tmp2 ? 1.0 : 0.0);
case EQ : return (fzero (tmp1 - tmp2) ? 1.0 : 0.0);
case NE : return (!fzero (tmp1 - tmp2) ? 1.0 : 0.0);
case LE : return (tmp1 <= tmp2 ? 1.0 : 0.0);
case GE : return (tmp1 >= tmp2 ? 1.0 : 0.0);
case ':': return (0.0); /* dummy return for ? */
case '?':
if (expression->right->contents.opr == ':')
return (!fzero (tmp1)
? eval (expression->right->left)
: eval (expression->right->right));
else if (!fzero (tmp1)) return (eval (expression->right));
else return (UNDEFINED);
default: fprintf (stderr, "calc: Unknown operator '%c' = %d\n",
expression->contents.opr, expression->contents.opr);
return (UNDEFINED);
}
}
ptree (ioptr, expression) ENODE *expression; FILE *ioptr;
{
if (expression == ENULL)
return;
if (expression->etype == VARIABLE)
{
fprintf (ioptr, "%s", Varname[expression->contents.var]);
return;
}
else if (expression->etype == NUMBER)
{
if (*expression->contents.num == UNDEFINED)
fprintf (ioptr, "UNDEFINED");
else
fprintf (ioptr, Format, *expression->contents.num);
return;
}
switch (expression->contents.opr)
{
case LOG: fprintf (ioptr, "log("); break;
case ABS: fprintf (ioptr, "abs("); break;
case EXP: fprintf (ioptr, "exp("); break;
case SQRT: fprintf (ioptr, "sqrt("); break;
case ATAN: fprintf (ioptr, "atan("); break;
case ASIN: fprintf (ioptr, "asin("); break;
case ACOS: fprintf (ioptr, "acos("); break;
case TAN: fprintf (ioptr, "tan("); break;
case SIN: fprintf (ioptr, "sin("); break;
case COS: fprintf (ioptr, "cos("); break;
case '_' : putc ('-', ioptr);
ptree (ioptr, expression->right); return;
case '?':
fprintf (ioptr, "(if ");
ptree (ioptr, expression->left);
fprintf (ioptr, " then ");
if (expression->right->contents.opr == ':')
{
ptree (ioptr, expression->right->left);
fprintf (ioptr, " else ");
ptree (ioptr, expression->right->right);
}
else ptree (ioptr, expression->right);
putc (')', ioptr);
return;
default: putc ('(', ioptr);
ptree (ioptr, expression->left);
switch (expression->contents.opr)
{
case EQ: fprintf (ioptr, " == "); break;
case NE: fprintf (ioptr, " != "); break;
case GE: fprintf (ioptr, " >= "); break;
case LE: fprintf (ioptr, " <= "); break;
default: fprintf (ioptr, " %c ",expression->contents.opr);
}
}
ptree (ioptr, expression->right);
putc (')', ioptr);
}
/* Suzanne Shouman fixed a bug here. Thanks */
begins (s1, s2) char *s1, *s2;
{
int alphlag = isvarchar (*s1);
while (*s1)
if (*s1++ != *s2++) return (0);
return (alphlag ? !isvarchar(*s2) : 1);
}
checkrecursion (varno, expr)
int varno; /* look for recursion involving this variable */
ENODE *expr; /* look for recursion of varno in this expr */
{
if (expr == ENULL || expr->etype == NUMBER)
return (0);
if (expr->etype == VARIABLE)
{
if (expr->contents.var == varno)
return (1);
if (checkrecursion (varno, Variable[expr->contents.var]))
return (1);
}
return
(
checkrecursion (varno, expr->left)
||
checkrecursion (varno, expr->right)
);
}
char *
getline (line, ioptr) char *line; FILE *ioptr;
{
register int C;
register char *lptr = line;
while ((C = getc (ioptr)) != '\n' && C != ';' && C != EOF)
*lptr++ = C;
if (C == EOF) return (NULL);
while (C != '\n' && C != EOF) C = getc (ioptr);
*lptr = '\0';
return (line);
}
errorexit (string) char *string;
{
fprintf (stderr, "calc: %s\n", string);
control ("\027calc.save");
fprintf (stderr, "Current state saved in calc.save\n");
exit (1);
}
short yyexca[] ={
-1, 1,
0, -1,
-2, 0,
-1, 58,
262, 0,
263, 0,
264, 0,
265, 0,
60, 0,
62, 0,
-2, 12,
-1, 59,
262, 0,
263, 0,
264, 0,
265, 0,
60, 0,
62, 0,
-2, 13,
-1, 60,
262, 0,
263, 0,
264, 0,
265, 0,
60, 0,
62, 0,
-2, 14,
-1, 61,
262, 0,
263, 0,
264, 0,
265, 0,
60, 0,
62, 0,
-2, 15,
-1, 62,
262, 0,
263, 0,
264, 0,
265, 0,
60, 0,
62, 0,
-2, 16,
-1, 63,
262, 0,
263, 0,
264, 0,
265, 0,
60, 0,
62, 0,
-2, 17,
};
# define YYNPROD 36
# define YYLAST 456
short yyact[]={
7, 25, 5, 23, 32, 37, 1, 3, 22, 20,
0, 21, 6, 24, 0, 23, 0, 0, 0, 0,
22, 20, 23, 21, 71, 24, 29, 22, 31, 34,
23, 32, 24, 0, 0, 22, 20, 0, 21, 0,
24, 23, 32, 0, 0, 68, 22, 20, 0, 21,
0, 24, 0, 29, 0, 31, 34, 0, 0, 0,
25, 0, 0, 0, 29, 0, 31, 34, 23, 32,
0, 0, 25, 22, 20, 0, 21, 0, 24, 25,
0, 0, 0, 0, 0, 0, 0, 25, 0, 0,
33, 29, 0, 31, 34, 23, 32, 0, 25, 0,
22, 20, 0, 21, 0, 24, 23, 32, 0, 0,
0, 22, 20, 0, 21, 0, 24, 33, 29, 0,
31, 0, 0, 0, 0, 25, 0, 0, 33, 29,
0, 31, 0, 23, 32, 0, 0, 0, 22, 20,
0, 21, 0, 24, 0, 0, 0, 0, 0, 0,
0, 0, 25, 0, 23, 33, 29, 0, 31, 22,
20, 0, 21, 25, 24, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 29, 0, 31,
0, 0, 33, 0, 0, 0, 0, 0, 0, 0,
25, 0, 0, 33, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 25, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 19, 4, 8, 35, 26, 27,
30, 28, 0, 0, 17, 16, 15, 18, 12, 14,
13, 9, 10, 11, 0, 0, 0, 0, 0, 0,
0, 0, 0, 70, 35, 26, 27, 30, 28, 0,
0, 0, 0, 0, 0, 35, 26, 27, 30, 28,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 35, 26, 27, 30, 28, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 35,
26, 27, 30, 28, 0, 0, 0, 0, 0, 0,
0, 26, 27, 30, 28, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 26, 27,
30, 28, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 26,
27, 30, 28, 2, 0, 0, 0, 36, 0, 38,
39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 0, 52, 53, 54, 55, 56, 57,
58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
0, 69, 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, 0, 0, 72, 73 };
short yypact[]={
-33,-1000, 31, -33, -56, -33, -33, -33, -33, -33,
-33, -33, -33, -33, -33, -33, -33, -33, -33,-1000,
-33, -33, -33, -33, -33, -33, -33, -33, -33, -33,
-33, -33, -33, -33, -33, -33, 4, -33, 31,-1000,
117, -7,-1000,-1000,-1000,-1000,-1000,-1000,-1000,-1000,
-1000,-1000, -15, -15, -93, -93, -93, -93, -22, -22,
-22, -22, -22, -22, 117, 96, -34, 69,-1000, 31,
-33, -33, 58, 69 };
short yypgo[]={
0, 383, 6 };
short yyr1[]={
0, 2, 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 };
short yyr2[]={
0, 1, 3, 3, 2, 3, 3, 3, 3, 3,
3, 2, 3, 3, 3, 3, 3, 3, 3, 3,
2, 5, 4, 3, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 1, 1 };
short yychk[]={
-1000, -2, -1, 40, 258, 35, 45, 33, 259, 274,
275, 276, 271, 273, 272, 269, 268, 267, 270, 257,
43, 45, 42, 37, 47, 94, 262, 263, 265, 60,
264, 62, 38, 124, 63, 261, -1, 61, -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, 41, -1,
260, 58, -1, -1 };
short yydef[]={
0, -2, 1, 0, 34, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 35,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 4, 11,
20, 0, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 5, 6, 7, 8, 9, 10, -2, -2,
-2, -2, -2, -2, 18, 19, 0, 23, 2, 3,
0, 0, 22, 21 };
#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 94 "calc.y"
{ Expression = yypvt[-0].ex;} break;
case 2:
# line 96 "calc.y"
{ yyval.ex = yypvt[-1].ex; } break;
case 3:
# line 97 "calc.y"
{
if (checkrecursion (yypvt[-2].var, yypvt[-0].ex))
{
fprintf (stderr, "calc: Can't have recursive definitions\n");
Variable[yypvt[-2].var] = NULL;
}
else Variable[yypvt[-2].var] = yypvt[-0].ex;
yyval.ex = yypvt[-0].ex;
} break;
case 4:
# line 107 "calc.y"
{
Constant = (double *) malloc (sizeof (double));
if (Constant == NULL)
errorexit ("Out of storage space");
*Constant = eval (yypvt[-0].ex);
Tmp1.num = Constant;
yyval.ex = node (&Tmp1, NUMBER, ENULL, ENULL);
} break;
case 5:
# line 116 "calc.y"
{
Tmp1.opr = '+';
yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex);
} break;
case 6:
# line 121 "calc.y"
{
Tmp1.opr = '-';
yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex);
} break;
case 7:
# line 126 "calc.y"
{
Tmp1.opr = '*';
yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex);
} break;
case 8:
# line 131 "calc.y"
{
Tmp1.opr = '%';
yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex);
} break;
case 9:
# line 136 "calc.y"
{
Tmp1.opr = '/';
yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex);
} break;
case 10:
# line 141 "calc.y"
{
Tmp1.opr = '^';
yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex);
} break;
case 11:
# line 146 "calc.y"
{
Tmp1.opr = '_';
yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex);
} break;
case 12:
# line 151 "calc.y"
{
Tmp1.opr = EQ;
yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex);
} break;
case 13:
# line 156 "calc.y"
{
Tmp1.opr = NE;
yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex);
} break;
case 14:
# line 161 "calc.y"
{
Tmp1.opr = LE;
yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex);
} break;
case 15:
# line 166 "calc.y"
{
Tmp1.opr = '<';
yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex);
} break;
case 16:
# line 171 "calc.y"
{
Tmp1.opr = GE;
yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex);
} break;
case 17:
# line 176 "calc.y"
{
Tmp1.opr = '>';
yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex);
} break;
case 18:
# line 181 "calc.y"
{
Tmp1.opr = '&';
yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex);
} break;
case 19:
# line 186 "calc.y"
{
Tmp1.opr = '|';
yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex);
} break;
case 20:
# line 191 "calc.y"
{
Tmp1.opr = '!';
yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex);
} break;
case 21:
# line 196 "calc.y"
{
Tmp1.opr = '?';
Tmp2.opr = ':';
yyval.ex = node (&Tmp1, OPERATOR, yypvt[-4].ex, node (&Tmp2, OPERATOR, yypvt[-2].ex, yypvt[-0].ex));
} break;
case 22:
# line 202 "calc.y"
{
Tmp1.opr = '?';
yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex);
} break;
case 23:
# line 207 "calc.y"
{
Tmp1.opr = ':';
yyval.ex = node (&Tmp1, OPERATOR, yypvt[-2].ex, yypvt[-0].ex);
} break;
case 24:
# line 212 "calc.y"
{
Tmp1.opr = ACOS;
yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex);
} break;
case 25:
# line 217 "calc.y"
{
Tmp1.opr = ASIN;
yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex);
} break;
case 26:
# line 222 "calc.y"
{
Tmp1.opr = ATAN;
yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex);
} break;
case 27:
# line 227 "calc.y"
{
Tmp1.opr = COS;
yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex);
} break;
case 28:
# line 232 "calc.y"
{
Tmp1.opr = SIN;
yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex);
} break;
case 29:
# line 237 "calc.y"
{
Tmp1.opr = TAN;
yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex);
} break;
case 30:
# line 242 "calc.y"
{
Tmp1.opr = LOG;
yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex);
} break;
case 31:
# line 247 "calc.y"
{
Tmp1.opr = EXP;
yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex);
} break;
case 32:
# line 252 "calc.y"
{
Tmp1.opr = ABS;
yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex);
} break;
case 33:
# line 257 "calc.y"
{
Tmp1.opr = SQRT;
yyval.ex = node (&Tmp1, OPERATOR, ENULL, yypvt[-0].ex);
} break;
case 34:
# line 262 "calc.y"
{
Tmp1.var = yypvt[-0].var;
yyval.ex = node (&Tmp1, VARIABLE, ENULL, ENULL);
} break;
case 35:
# line 267 "calc.y"
{
Tmp1.num = yypvt[-0].num;
yyval.ex = node (&Tmp1, NUMBER, ENULL, ENULL);
} break;
}
goto yystack; /* stack new state and value */
}