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 d

⟦8c82309e2⟧ TextFile

    Length: 39193 (0x9919)
    Types: TextFile
    Names: »dm.c«

Derivation

└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
    └─ ⟦this⟧ »EUUGD11/stat-5.3/eu/stat/src/dm.c« 

TextFile


# 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 */

	}