DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ T c

⟦2f6a0949a⟧ TextFile

    Length: 24479 (0x5f9f)
    Types: TextFile
    Names: »calc.c«

Derivation

└─⟦87ddcff64⟧ Bits:30001253 CPHDIST85 Tape, 1985 Autumn Conference Copenhagen
    └─ ⟦this⟧ »cph85dist/stat/src/calc.c« 

TextFile


# line 2 "calc.y"
/* Copyright (c) 1982 Gary Perlman (see Copyright file) */
static	char	sccsid[] = "@(#) calc.y 5.0 (unix|stat) 2/26/85";
/* PGM(calc, Algebraic Modeling Calculator) */
#include <stdio.h>
#include <math.h>
#include <ctype.h>
#include <signal.h>

#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 = 0;
char	*Varname[MAXVAR];
char	*Exprptr;
int 	Printequation = 1;
char	*Prompt = "CALC: ";
int 	Interactive = 0;
typedef struct	exprnode
	{
	int 	nodetype;          /* NUMBER, OPERATOR, or VARIABLE */
	int 	operator;          /* index of var if a variable, else +/-* */
	double	*value;
	struct	exprnode *left;
	struct	exprnode *right;
	} ENODE;
ENODE	*Expression, *Variable[MAXVAR];
double	eval (), answer;
double	*constant;
char	*malloc ();
char	*getline ();
FILE	*outfile = stdout;
# 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
#ifndef YYSTYPE
#define YYSTYPE int
#endif
YYSTYPE yylval, yyval;
# define YYERRCODE 256

# line 108 "calc.y"


yylex ()
	{
	extern	int yylval;
	char	tmpvarname[BUFSIZ];
	int 	i;
	while (isspace (*Exprptr)) Exprptr++;
	if (begins ("acos", Exprptr)) {Exprptr += 4; return (ACOS);}
	if (begins ("asin", Exprptr)) {Exprptr += 4; return (ASIN);}
	if (begins ("atan", Exprptr)) {Exprptr += 4; return (ATAN);}
	if (begins ("cos", Exprptr)) {Exprptr += 3; return (COS);}
	if (begins ("sin", Exprptr)) {Exprptr += 3; return (SIN);}
	if (begins ("tan", Exprptr)) {Exprptr += 3; return (TAN);}
	if (begins ("log", Exprptr)) {Exprptr += 3; return (LOG);}
	if (begins ("sqrt", Exprptr)) {Exprptr += 4; return (SQRT);}
	if (begins ("exp", Exprptr)) {Exprptr += 3; return (EXP);}
	if (begins ("abs", Exprptr)) {Exprptr += 3; return (ABS);}
	if (begins ("if", Exprptr)) {Exprptr += 2; return (IF);}
	if (begins ("then", Exprptr)) {Exprptr += 4; return (THEN);}
	if (begins ("else", Exprptr)) {Exprptr += 4; return (ELSE);}
	if (isdigit (*Exprptr) || *Exprptr == '.')
		{
		constant = (double *) malloc (sizeof (double));
		if (constant == NULL)
			errorexit ("Out of storage space");
		*constant = atof (Exprptr);
		yylval = (int) constant;
		/* now skip over the number */
		while (isdigit (*Exprptr)) Exprptr++;
		if (*Exprptr == '.') Exprptr++;
		while (isdigit (*Exprptr)) Exprptr++;
		if (*Exprptr == 'E' || *Exprptr == 'e')
			{
			Exprptr++;
			if (*Exprptr == '+' || *Exprptr == '-') Exprptr++;
			while (isdigit (*Exprptr)) Exprptr++;
			}
		return (NUMBER);
		}
	if (isvarchar (*Exprptr))
		{
		for (i = 0; isvarchar (Exprptr[i]); i++)
			tmpvarname[i] = Exprptr[i];
		tmpvarname[i] = NULL;
		Exprptr += i;
		i = 0;
		while (i < Nvar && strcmp (tmpvarname, Varname[i])) i++;
		if (i == Nvar)
			{
			Varname[i] = malloc (strlen (tmpvarname) + 1);
			if (Varname[i] == NULL)
				errorexit ("Out of storage space");
			strcpy (Varname[i], tmpvarname);
			if (++Nvar == MAXVAR)
				errorexit ("Too many variables");
			}
		yylval = i;
		return (VARIABLE);
		}
	if (begins ("!=", Exprptr)) { Exprptr += 2; return (NE); }
	if (begins (">=", Exprptr)) { Exprptr += 2; return (GE); }
	if (begins ("<=", Exprptr)) { Exprptr += 2; return (LE); }
	if (begins ("==", Exprptr)) { Exprptr += 2; return (EQ); }
	if (begins ("**", Exprptr)) { Exprptr += 2; return ('^'); }
	return (*Exprptr++);
	}

yyerror (msg)
char	*msg;
	{
	fprintf (outfile, "%s:\n", msg);
	fprintf (outfile, "Parsing error.  ");
	fprintf (outfile, "This is left in input: [%s]\n", Exprptr-1);
	}

ENODE *
node (datum, datatype, lson, rson)
int 	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 == NULL)
		errorexit ("Out of storage space");
	newnode->nodetype = datatype;
	if (datatype == OPERATOR || datatype == VARIABLE)
		newnode->operator = datum;
	else newnode->value = (double *) datum;
	newnode->left = lson;
	newnode->right = rson;
	return (newnode);
	}

main (argc, argv) int argc; char *argv[];
	{
	int 	i;
	signal (SIGINT, SIG_IGN);
	if (isatty (0))
		{
		Interactive = 1;
		printf ("Enter expressions after the prompt '%s'\n", Prompt);
		printf ("Quit with ^D, get help with ?\n");
		}
	for (i = 1; i < argc; i++) process (argv[i]);
	process ("-");
	if (Interactive) printf ("\015           \015");
	exit (0);
	}

process (filename) char *filename;
	{
	char	exprline[BUFSIZ];
	FILE	*ioptr;
	if (filename == NULL || (filename[0] == '-' && filename[1] == '\0'))
		{
		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;
		Exprptr = exprline;
		while (isspace (*Exprptr)) Exprptr++;
		if (!*Exprptr || *Exprptr == '?')
			{
			if (filename == NULL && Interactive) printmenu ();
			continue;
			}
		if (iscntrl (*Exprptr))
			{
			control (Exprptr);
			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 fprintf (outfile, "\t%g\n", answer);
		}
	if (ioptr != stdin) 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)");
	puts ("^D	end of input to CALC");
	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

control (key) char *key;
	{
	int 	var;
	FILE	*saveoutfile;
	switch (*key)
		{
		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, "%10g = ", answer);
					}
				ptree (outfile, Variable[var]);
				fprintf (outfile, "\n");
				}
			if (*key)
				{
				fclose (outfile);
				outfile = saveoutfile;
				}
			return;
		default: fprintf (stderr, "Unknown control character.\n");
		}
	}

double
eval (expression) ENODE *expression;
	{
	double	tmp1, tmp2;
	if (expression == NULL) return (UNDEFINED);
	if (expression->nodetype == VARIABLE)
		if (Variable[expression->operator])
			return (eval (Variable[expression->operator]));
		else	return (UNDEFINED);
	if (expression->nodetype == NUMBER)
		return (*expression->value);
	if ((tmp2 = eval (expression->right)) == UNDEFINED) return (UNDEFINED);
	switch (expression->operator)
	{
	case '_': return (-tmp2);
	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->operator)
	{
	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));
	case '|': return (!fzero (tmp1) || !fzero (tmp2));
	case '!': return (fzero (tmp1) ? 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->operator == ':')
			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, "Unknown operator '%c' = %d\n",
		expression->operator, expression->operator);
		return (UNDEFINED);
	}
	}

ptree (ioptr, expression) ENODE *expression; FILE *ioptr;
	{
	if (expression == NULL)
		return;
	if (expression->nodetype == VARIABLE)
		{
		fprintf (ioptr, "%s", Varname[expression->operator]);
		return;
		}
	else if (expression->nodetype == NUMBER)
		{
		if (*expression->value == UNDEFINED)
			fprintf (ioptr, "UNDEFINED");
		else	fprintf (ioptr, "%g", *expression->value);
		return;
		}
	switch	(expression->operator)
		{
		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->operator == ':')
				{
				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->operator)
				{
				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->operator);
				}
		}
	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 == NULL) return (0);
	if (expr->nodetype == VARIABLE)
		{
		if (expr->operator == varno) return (1);
		if (checkrecursion (varno, Variable[expr->operator])) 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, "%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,   6, 383 };
short yyr1[]={

   0,   1,   2,   2,   2,   2,   2,   2,   2,   2,
   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
   2,   2,   2,   2,   2,   2,   2,   2,   2,   2,
   2,   2,   2,   2,   2,   2 };
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,  -1,  -2,  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,  -2,  61,  -2,  -2,
  -2,  -2,  -2,  -2,  -2,  -2,  -2,  -2,  -2,  -2,
  -2,  -2,  -2,  -2,  -2,  -2,  -2,  -2,  -2,  -2,
  -2,  -2,  -2,  -2,  -2,  -2,  -2,  -2,  41,  -2,
 260,  58,  -2,  -2 };
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 58 "calc.y"
 { Expression = (ENODE *) yypvt[-0];} break;
case 2:
# line 60 "calc.y"
 { yyval = yypvt[-1]; } break;
case 3:
# line 61 "calc.y"
 {
			if (checkrecursion (yypvt[-2], (ENODE *) yypvt[-0]))
				{
				fprintf (stderr, "Can't have recursive definitions\n");
				Variable[yypvt[-2]] = NULL;
				}
			else Variable[yypvt[-2]] = (ENODE *) yypvt[-0];
			yyval = yypvt[-0];
		} break;
case 4:
# line 70 "calc.y"
 { constant = (double *) malloc (sizeof (double));
		if (constant == NULL)
			errorexit ("Out of storage space");
		*constant = eval ((ENODE *) yypvt[-0]);
		yyval = (int) node ((int) constant, NUMBER, NULL, NULL); } break;
case 5:
# line 75 "calc.y"
 { yyval = (int) node ('+', OPERATOR, yypvt[-2], yypvt[-0]); } break;
case 6:
# line 76 "calc.y"
 { yyval = (int) node ('-', OPERATOR, yypvt[-2], yypvt[-0]); } break;
case 7:
# line 77 "calc.y"
 { yyval = (int) node ('*', OPERATOR, yypvt[-2], yypvt[-0]); } break;
case 8:
# line 78 "calc.y"
 { yyval = (int) node ('%', OPERATOR, yypvt[-2], yypvt[-0]); } break;
case 9:
# line 79 "calc.y"
 { yyval = (int) node ('/', OPERATOR, yypvt[-2], yypvt[-0]); } break;
case 10:
# line 80 "calc.y"
 { yyval = (int) node ('^', OPERATOR, yypvt[-2], yypvt[-0]); } break;
case 11:
# line 82 "calc.y"
 { yyval = (int) node ('_', OPERATOR, NULL, yypvt[-0]); } break;
case 12:
# line 83 "calc.y"
 { yyval = (int) node (EQ, OPERATOR, yypvt[-2], yypvt[-0]); } break;
case 13:
# line 84 "calc.y"
 { yyval = (int) node (NE, OPERATOR, yypvt[-2], yypvt[-0]); } break;
case 14:
# line 85 "calc.y"
 { yyval = (int) node (LE, OPERATOR, yypvt[-2], yypvt[-0]); } break;
case 15:
# line 86 "calc.y"
 { yyval = (int) node ('<', OPERATOR, yypvt[-2], yypvt[-0]); } break;
case 16:
# line 87 "calc.y"
 { yyval = (int) node (GE, OPERATOR, yypvt[-2], yypvt[-0]); } break;
case 17:
# line 88 "calc.y"
 { yyval = (int) node ('>', OPERATOR, yypvt[-2], yypvt[-0]); } break;
case 18:
# line 89 "calc.y"
 { yyval = (int) node ('&', OPERATOR, yypvt[-2], yypvt[-0]); } break;
case 19:
# line 90 "calc.y"
 { yyval = (int) node ('|', OPERATOR, yypvt[-2], yypvt[-0]); } break;
case 20:
# line 91 "calc.y"
 { yyval = (int) node ('!', OPERATOR, NULL, yypvt[-0]); } break;
case 21:
# line 92 "calc.y"
 { yyval = (int) node ('?', OPERATOR, yypvt[-4],
		(int) node (':', OPERATOR, yypvt[-2], yypvt[-0])); } break;
case 22:
# line 94 "calc.y"
 { yyval = (int) node ('?', OPERATOR, yypvt[-2], yypvt[-0]); } break;
case 23:
# line 95 "calc.y"
 { yyval = (int) node (':', OPERATOR, yypvt[-2], yypvt[-0]); } break;
case 24:
# line 96 "calc.y"
 { yyval = (int) node (ACOS, OPERATOR, NULL, yypvt[-0]); } break;
case 25:
# line 97 "calc.y"
 { yyval = (int) node (ASIN, OPERATOR, NULL, yypvt[-0]); } break;
case 26:
# line 98 "calc.y"
 { yyval = (int) node (ATAN, OPERATOR, NULL, yypvt[-0]); } break;
case 27:
# line 99 "calc.y"
 { yyval = (int) node (COS, OPERATOR, NULL, yypvt[-0]); } break;
case 28:
# line 100 "calc.y"
 { yyval = (int) node (SIN, OPERATOR, NULL, yypvt[-0]); } break;
case 29:
# line 101 "calc.y"
 { yyval = (int) node (TAN, OPERATOR, NULL, yypvt[-0]); } break;
case 30:
# line 102 "calc.y"
 { yyval = (int) node (LOG, OPERATOR, NULL, yypvt[-0]); } break;
case 31:
# line 103 "calc.y"
 { yyval = (int) node (EXP, OPERATOR, NULL, yypvt[-0]); } break;
case 32:
# line 104 "calc.y"
 { yyval = (int) node (ABS, OPERATOR, NULL, yypvt[-0]); } break;
case 33:
# line 105 "calc.y"
 { yyval = (int) node (SQRT, OPERATOR, NULL, yypvt[-0]); } break;
case 34:
# line 106 "calc.y"
 { yyval = (int) node (yypvt[-0], VARIABLE, NULL, NULL); } break;
case 35:
# line 107 "calc.y"
 { yyval = (int) node (yypvt[-0], NUMBER, NULL, NULL); } break; 
		}
		goto yystack;  /* stack new state and value */

	}