[net.sources] GNUPLOT 1.1: part 2 of 6

williams@vu-vlsi.UUCP (01/28/87)

GNUPLOT 1.1: part 2 of 6

--------------------------------CUT HERE----------------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	command.c
#	eval.c
#	graphics.c
#	internal.c
#	misc.c
#	parse.c
# This archive created: Tue Jan 27 13:21:33 1987
export PATH; PATH=/bin:$PATH
echo shar: extracting "'command.c'" '(21346 characters)'
if test -f 'command.c'
then
	echo shar: will not over-write existing file "'command.c'"
else
cat << \SHAR_EOF > 'command.c'
/*
 *
 *    G N U P L O T  --  command.c
 *
 *  Copyright (C) 1986, 1987  Thomas Williams, Colin Kelley
 *
 *  You may use this code as you wish if credit is given and this message
 *  is retained.
 *
 *  Please e-mail any useful additions to vu-vlsi!plot so they may be
 *  included in later releases.
 *
 *  This file should be edited with 4-column tabs!  (:set ts=4 sw=4 in vi)
 */

#include <stdio.h>
#include <math.h>

#ifdef MSDOS
#include <process.h>
#endif

#include "plot.h"

#ifndef STDOUT
#define STDOUT 1
#endif

/*
 * global variables to hold status of 'set' options
 *
 */
BOOLEAN			autoscale	= TRUE;
char			dummy_var[MAX_ID_LEN+1] = "x";
enum PLOT_STYLE data_style	= POINTS,
				func_style	= LINES;
BOOLEAN			log_x		= FALSE,
				log_y		= FALSE;
FILE*			outfile;
char			outstr[MAX_ID_LEN+1] = "STDOUT";
int				samples		= SAMPLES;
int				term		= 0;				/* unknown term is 0 */
double			xmin		= -10.0,
				xmax		= 10.0,
				ymin		= -10.0,
				ymax		= 10.0;
double			zero = ZERO;			/* zero threshold, not 0! */


BOOLEAN screen_ok;
BOOLEAN term_init;
BOOLEAN undefined;

/*
 * instead of <strings.h>
 */

char *gets(),*getenv();
char *strcpy(),*strncpy(),*strcat();

char *malloc();

double magnitude(),angle(),real(),imag();
struct value *const_express(), *pop(), *complex();
struct at_type *temp_at(), *perm_at();
struct udft_entry *add_udf();
struct udvt_entry *add_udv();

extern struct termentry term_tbl[];

struct lexical_unit token[MAX_TOKENS];
char input_line[MAX_LINE_LEN+1] = "set term ";
char c_dummy_var[MAX_ID_LEN+1]; 		/* current dummy var */
int num_tokens, c_token;

struct curve_points *first_plot = NULL;
struct udft_entry plot_func, *dummy_func;

static char replot_line[MAX_LINE_LEN+1];
static int plot_token;					/* start of 'plot' command */
static char help[MAX_LINE_LEN] = HELP;

com_line()
{
	read_line();

	screen_ok = TRUE; /* so we can flag any new output */

	do_line();
}


do_line()	  /* also used in load_file */
{
	if (is_comment(input_line[0]))
		return;
	if (is_system(input_line[0])) {
		do_system();
		fputs("!\n",stderr);
		return;
	}
	num_tokens = scanner(input_line);
	c_token = 0;
	while(c_token < num_tokens) {
		command();
		if (c_token < num_tokens)	/* something after command */
			if (equals(c_token,";"))
				c_token++;
			else
					int_error("';' expected",c_token);
	}
}



command()
{
static char sv_file[MAX_LINE_LEN+1];
			/* string holding name of save or load file */

	c_dummy_var[0] = '\0';		/* no dummy variable */

	if (is_definition(c_token))
		define();
	else if (equals(c_token,"help") || equals(c_token,"?")) {
		register int len;
		register char *help_ptr;

		c_token++;
		if ((help_ptr = getenv("GNUHELP")))	/* initial command */
			(void) strncpy(help,help_ptr,sizeof(help) - 1);
		else
			(void) strncpy(help,HELP,sizeof(help) - 1);

		while (!(END_OF_COMMAND)) {
			len = strlen(help);
			help[len] = ' ';   /* put blank between help segments */
			copy_str(help+len+1,c_token++);
		}
		do_help();
		screen_ok = FALSE;
		c_token++;
	}
	else if (almost_equals(c_token,"pr$int")) {
		struct value a;

		c_token++;
		(void) const_express(&a);
		(void) putc('\t',stderr);
		disp_value(stderr,&a);
		(void) putc('\n',stderr);
		screen_ok = FALSE;
	}
	else if (almost_equals(c_token,"p$lot")) {
		plot_token = c_token++;
		plotrequest();
	}
	else if (almost_equals(c_token,"rep$lot")) {
		if (replot_line[0] == '\0') 
			int_error("no previous plot",c_token);
		(void) strcpy(input_line,replot_line);
		screen_ok = FALSE;
		num_tokens = scanner(input_line);
		c_token = 1;					/* skip the 'plot' part */
		plotrequest();
	}
	else if (almost_equals(c_token,"se$t"))
		set_stuff();
	else if (almost_equals(c_token,"sh$ow"))
		show_stuff();
	else if (almost_equals(c_token,"cl$ear")) {
		if (!term_init) {
			(*term_tbl[term].init)();
			term_init = TRUE;
		}
		(*term_tbl[term].graphics)();
		(*term_tbl[term].text)();
		(void) fflush(outfile);
		screen_ok = FALSE;
		c_token++;
	}
	else if (almost_equals(c_token,"she$ll")) {
		do_shell();
		screen_ok = FALSE;
		c_token++;
	}
	else if (almost_equals(c_token,"sa$ve")) {
		if (almost_equals(++c_token,"f$unctions")) {
			if (!isstring(++c_token))
				int_error("expecting filename",c_token);
			else {
				quote_str(sv_file,c_token);
				save_functions(fopen(sv_file,"w"));
			}
		}
		else if (almost_equals(c_token,"v$ariables")) {
			if (!isstring(++c_token))
				int_error("expecting filename",c_token);
			else {
				quote_str(sv_file,c_token);
				save_variables(fopen(sv_file,"w"));
			}
		}
		else if (isstring(c_token)) {
			quote_str(sv_file,c_token);
			save_all(fopen(sv_file,"w"));
		}
		else {
			int_error(
		"filename or keyword 'functions' or 'variables' expected",c_token);
		}
		c_token++;
	}
	else if (almost_equals(c_token,"l$oad")) {
		if (!isstring(++c_token))
			int_error("expecting filename",c_token);
		else {
			quote_str(sv_file,c_token);
			load_file(fopen(sv_file,"r"));	
		/* input_line[] and token[] now destroyed! */
			c_token = num_tokens = 0;
		}
	}
	else if (almost_equals(c_token,"ex$it") ||
			almost_equals(c_token,"q$uit")) {
		done(IO_SUCCESS);
	}
	else if (!equals(c_token,";")) {		/* null statement */
		int_error("invalid command",c_token);
	}
}


enum PLOT_STYLE
get_style()
{
register enum PLOT_STYLE ps;

	c_token++;
	if (almost_equals(c_token,"l$ines"))
		ps = LINES;
	else if (almost_equals(c_token,"i$mpulses"))
		ps = IMPULSES;
	else if (almost_equals(c_token,"p$oints"))
		ps = POINTS;
	else
		int_error("expecting 'lines', 'points', or 'impulses'",c_token);
	c_token++;
	return(ps);
}


set_stuff()
{
static char testfile[MAX_LINE_LEN+1];

	if (almost_equals(++c_token,"a$utoscale")) {
		autoscale = TRUE;
		c_token++;
	}
	else if (almost_equals(c_token,"noa$utoscale")) {
		autoscale = FALSE;
		c_token++;
	}
	else if (almost_equals(c_token,"d$ata")) {
		c_token++;
		if (!almost_equals(c_token,"s$tyle"))
			int_error("expecting keyword 'style'",c_token);
		data_style = get_style();
	}
	else if (almost_equals(c_token,"d$ummy")) {
		c_token++;
		copy_str(dummy_var,c_token++);
	}
	else if (almost_equals(c_token,"f$unction")) {
		c_token++;
		if (!almost_equals(c_token,"s$tyle"))
			int_error("expecting keyword 'style'",c_token);
		func_style = get_style();
	}
	else if (almost_equals(c_token,"l$ogscale")) {
		c_token++;
		if (equals(c_token,"x")) {
			log_y = FALSE;
			log_x = TRUE;
			c_token++;
		}
		else if (equals(c_token,"y")) {
			log_x = FALSE;
			log_y = TRUE;
			c_token++;
		}
		else if (equals(c_token,"xy") || equals(c_token,"yx")) {
			log_x = log_y = TRUE;
			c_token++;
		}
		else
			int_error("expecting 'x', 'y', or 'xy'",c_token);
	}
	else if (almost_equals(c_token,"nol$ogscale")) {
		log_x = log_y = FALSE;
		c_token++;
	}
	else if (almost_equals(c_token,"o$utput")) {
		register FILE *f;

		c_token++;
		if (END_OF_COMMAND) {	/* no file specified */
			(void) fclose(outfile);
			outfile = fdopen(dup(STDOUT), "w");
			term_init = FALSE;
			(void) strcpy(outstr,"STDOUT");
		} else if (!isstring(c_token))
			int_error("expecting filename",c_token);
		else {
			quote_str(testfile,c_token);
			if (!(f = fopen(testfile,"w"))) {
			  os_error("cannot open file; output not changed",c_token);
			}
			(void) fclose(outfile);
			outfile = f;
			term_init = FALSE;
			outstr[0] = '\'';
			(void) strcat(strcpy(outstr+1,testfile),"'");
		}
		c_token++;
	}
	else if (almost_equals(c_token,"sa$mples")) {
		register int tsamp;
		struct value a;

		c_token++;
		tsamp = (int)magnitude(const_express(&a));
		if (tsamp < 1)
			int_error("sampling rate must be > 0; sampling unchanged",
				c_token);
		else {
			register struct curve_points *f_p = first_plot;

			first_plot = NULL;
			cp_free(f_p);
			samples = tsamp;
		}
	}
	else if (almost_equals(c_token,"t$erminal")) {
		c_token++;
		if (END_OF_COMMAND) {
			list_terms();
			screen_ok = FALSE;
		}
		else
			term = set_term(c_token);
		c_token++;
	}
	else if (almost_equals(c_token,"x$range")) {
		c_token++;
		if (!equals(c_token,"["))
			int_error("expecting '['",c_token);
		c_token++;
		load_range(&xmin,&xmax);
		if (!equals(c_token,"]"))
			int_error("expecting ']'",c_token);
		c_token++;
	}
	else if (almost_equals(c_token,"y$range")) {
		c_token++;
		if (!equals(c_token,"["))
			int_error("expecting '['",c_token);
		c_token++;
		load_range(&ymin,&ymax);
		autoscale = FALSE;
		if (!equals(c_token,"]"))
			int_error("expecting ']'",c_token);
		c_token++;
	}
	else if (almost_equals(c_token,"z$ero")) {
		struct value a;
		c_token++;
		zero = magnitude(const_express(&a));
	}
	else
		int_error(
	"valid set options:  '[no]autoscale', 'data', 'dummy', 'function',\n\
'[no]logscale', 'output', 'samples', 'terminal', 'xrange', 'yrange', 'zero'",
	c_token);
}


show_stuff()
{
	if (almost_equals(++c_token,"ac$tion_table") ||
			 equals(c_token,"at") ) {
		c_token++;
		show_at();
		c_token++;
	}
	else if (almost_equals(c_token,"au$toscale")) {
		(void) putc('\n',stderr);
		show_autoscale();
		c_token++;
	}
	else if (almost_equals(c_token,"d$ata")) {
		c_token++;
		if (!almost_equals(c_token,"s$tyle"))
			int_error("expecting keyword 'style'",c_token);
		(void) putc('\n',stderr);
		show_style("data",data_style);
		c_token++;
	}
	else if (almost_equals(c_token,"d$ummy")) {
		fprintf(stderr,"\n\tdummy variable is %s\n",dummy_var);
		c_token++;
	}
	else if (almost_equals(c_token,"f$unctions")) {
		c_token++;
		if (almost_equals(c_token,"s$tyle"))  {
			(void) putc('\n',stderr);
			show_style("functions",func_style);
			c_token++;
		}
		else
			show_functions();
	}
	else if (almost_equals(c_token,"l$ogscale")) {
		(void) putc('\n',stderr);
		show_logscale();
		c_token++;
	}
	else if (almost_equals(c_token,"o$utput")) {
		(void) putc('\n',stderr);
		show_output();
		c_token++;
	}
	else if (almost_equals(c_token,"sa$mples")) {
		(void) putc('\n',stderr);
		show_samples();
		c_token++;
	}
	else if (almost_equals(c_token,"t$erminal")) {
		(void) putc('\n',stderr);
		show_term();
		c_token++;
	}
	else if (almost_equals(c_token,"v$ariables")) {
		show_variables();
		c_token++;
	}
	else if (almost_equals(c_token,"ve$rsion")) {
		show_version();
		c_token++;
	}
	else if (almost_equals(c_token,"x$range")) {
		(void) putc('\n',stderr);
		show_range('x',xmin,xmax);
		c_token++;
	}
	else if (almost_equals(c_token,"y$range")) {
		(void) putc('\n',stderr);
		show_range('y',ymin,ymax);
		c_token++;
	}
	else if (almost_equals(c_token,"z$ero")) {
		(void) putc('\n',stderr);
		show_zero();
		c_token++;
	}
	else if (almost_equals(c_token,"a$ll")) {
		c_token++;
		show_version();
		fprintf(stderr,"\tdummy variable is %s\n",dummy_var);
		show_style("data",data_style);
		show_style("functions",func_style);
		show_output();
		show_term();
		show_samples();
		show_logscale();
		show_autoscale();
		show_zero();
		show_range('x',xmin,xmax);
		show_range('y',ymin,ymax);
		show_variables();
		show_functions();
		c_token++;
	}
	else
		int_error(
	"valid show options:  'action_table', 'all', 'autoscale', 'data',\n\
'dummy', 'function', 'logscale', 'output', 'samples', 'terminal',\n\
'variables', 'version', 'xrange', 'yrange', 'zero'", c_token);
	screen_ok = FALSE;
	(void) putc('\n',stderr);
}


load_range(a,b)
double *a,*b;
{
struct value t;

	if (equals(c_token,"]"))
		return;
	if (END_OF_COMMAND) {
	    int_error("starting range value or ':' expected",c_token);
	} else if (!equals(c_token,"to") && !equals(c_token,":"))  {
		*a = real(const_express(&t));
	}	
	if (!equals(c_token,"to") && !equals(c_token,":"))
		int_error("':' expected",c_token);
	c_token++;
	if (!equals(c_token,"]"))
		*b = real(const_express(&t));
}


plotrequest()
{
	
	if (!term)					/* unknown */
		int_error("use 'set term' to set terminal type first",c_token);

	if (equals(c_token,"[")) {
		c_token++;
		if (isletter(c_token)) {
			copy_str(c_dummy_var,c_token++);
			if (equals(c_token,"="))
				c_token++;
			else
				int_error("'=' expected",c_token);
		}
		load_range(&xmin,&xmax);
		if (!equals(c_token,"]"))
			int_error("']' expected",c_token);
		c_token++;
	}

	if (equals(c_token,"[")) { /* set optional y ranges */
		c_token++;
		load_range(&ymin,&ymax);
		autoscale = FALSE;
		if (!equals(c_token,"]"))
			int_error("']' expected",c_token);
		c_token++;
	}

	eval_plots();
}


define()
{
register int start_token;  /* the 1st token in the function definition */
register struct udvt_entry *udv;
register struct udft_entry *udf;

	if (equals(c_token+1,"(")) {
		/* function ! */
		start_token = c_token;
		copy_str(c_dummy_var, c_token + 2);
		c_token += 5; /* skip (, dummy, ) and = */
		if (END_OF_COMMAND)
			int_error("function definition expected",c_token);
		udf = dummy_func = add_udf(start_token);
		if (udf->at)				/* already a dynamic a.t. there */
			free((char *)udf->at);	/* so free it first */
		if (!(udf->at = perm_at()))
			int_error("not enough memory for function",start_token);
		m_capture(&(udf->definition),start_token,c_token-1);
	}
	else {
		/* variable ! */
		start_token = c_token;
		c_token +=2;
		udv = add_udv(start_token);
		(void) const_express(&(udv->udv_value));
		udv->udv_undef = FALSE;
	}
}


get_data(this_plot)
struct curve_points *this_plot;
{
static char data_file[MAX_LINE_LEN+1], line[MAX_LINE_LEN+1];
register int i, overflow, l_num;
register FILE *fp;
float x, y;

	quote_str(data_file, c_token);
	this_plot->plot_type = DATA;
	if (!(fp = fopen(data_file, "r")))
		os_error("can't open data file", c_token);

	l_num = 0;

	overflow = i = 0;

	while (fgets(line, MAX_LINE_LEN, fp)) {
		l_num++;
		if (is_comment(line[0]) || ! line[1])	/* line[0] will be '\n' */
			continue;		/* ignore comments  and blank lines */

		if (i == samples+1) {
			overflow = i;	/* keep track for error message later */
			i--;			/* so we don't fall off end of points[i] */
		}
		switch (sscanf(line, "%f %f", &x, &y)) {
			case 1:			/* only one number on the line */
				y = x;		/* so use it as the y value, */
				x = i;		/* and use the index as the x */
			/* no break; !!! */
			case 2:
				this_plot->points[i].undefined = TRUE;
				if (x >= xmin && x <= xmax && (autoscale ||
					(y >= ymin && y <= ymax))) {
					if (log_x) {
						if (x <= 0.0)
							break;
						this_plot->points[i].x = log10(x);
					} else
						this_plot->points[i].x = x;
					if (log_y) {
						if (y <= 0.0)
							break;
						this_plot->points[i].y = log10(y);
					} else
						this_plot->points[i].y = y;
					if (autoscale) {
						if (y < ymin) ymin = y;
						if (y > ymax) ymax = y;
					}

					this_plot->points[i].undefined = FALSE;
				}
				if (overflow)
					overflow++;
				else
					i++;
				break;

			default:
				(void) sprintf(line, "bad data on line %d", l_num);
				int_error(line,c_token);
		}
	}
	if (overflow) {
		(void) sprintf(line,
	"%d data points found--samples must be set at least this high",overflow);
				/* actually, samples can be one less! */
		int_error(line,c_token);
	}
	this_plot->p_count = i;
	(void) fclose(fp);
}


eval_plots()
{
register int i;
register struct curve_points *this_plot, **tp_ptr;
register int start_token, mysamples;
register double x_min, x_max, y_min, y_max, x;
register double xdiff, temp;
register int plot_num;
static struct value a;

	/* don't sample higher than output device can handle! */
	mysamples = (samples <= term_tbl[term].xmax) ?samples :term_tbl[term].xmax;

	if (log_x) {
		if (xmin < 0.0 || xmax < 0.0)
			int_error("x range must be above 0 for log scale!",NO_CARET);
		x_min = log10(xmin);
		x_max = log10(xmax);
	} else {
		x_min = xmin;
		x_max = xmax;
	}

	if (autoscale) {
		ymin = HUGE;
		ymax = -HUGE;
	} else if (log_y && (ymin <= 0.0 || ymax <= 0.0))
			int_error("y range must be above 0 for log scale!",
				NO_CARET);

	xdiff = (x_max - x_min) / mysamples;

	tp_ptr = &(first_plot);
	plot_num = 0;

	while (TRUE) {
		if (END_OF_COMMAND)
			int_error("function to plot expected",c_token);

		start_token = c_token;

		if (is_definition(c_token)) {
			define();
		} else {
			plot_num++;
			if (*tp_ptr)
				this_plot = *tp_ptr;
			else {		/* no memory malloc()'d there yet */
				this_plot = (struct curve_points *)
					malloc((unsigned int) (sizeof(struct curve_points) -
					(MAX_POINTS - (samples+1))*sizeof(struct coordinate)));
				if (!this_plot)
					int_error("out of memory",c_token);
				this_plot->next_cp = NULL;
				this_plot->title = NULL;
				*tp_ptr = this_plot;
			}

			if (isstring(c_token)) {			/* data file to plot */
				this_plot->plot_type = DATA;
				this_plot->plot_style = data_style;
				get_data(this_plot);
				c_token++;
			}
			else {							/* function to plot */
				this_plot->plot_type = FUNC;
				this_plot->plot_style = func_style;

				(void) strcpy(c_dummy_var,dummy_var);
				dummy_func = &plot_func;

				plot_func.at = temp_at();

				for (i = 0; i <= mysamples; i++) {
					if (i == samples+1)
						int_error("number of points exceeded samples",
							NO_CARET);
					x = x_min + i*xdiff;
					if (log_x)
						x = pow(10.0,x);
					(void) complex(&plot_func.dummy_value, x, 0.0);
					
					evaluate_at(plot_func.at,&a);

					if (this_plot->points[i].undefined =
						undefined || (fabs(imag(&a)) > zero))
							continue;

					temp = real(&a);

					if (log_y && temp <= 0.0) {
							this_plot->points[i].undefined = TRUE;
							continue;
					}
					if (autoscale) {
						if (temp < ymin) ymin = temp;
						if (temp > ymax) ymax = temp;
					} else if (temp < ymin || temp > ymax) {
						this_plot->points[i].undefined = TRUE;
						continue;
					}

					this_plot->points[i].y = log_y ? log10(temp) : temp;
				}
				this_plot->p_count = i; /* mysamples + 1 */
			}
			m_capture(&(this_plot->title),start_token,c_token-1);
			if (almost_equals(c_token,"w$ith"))
				this_plot->plot_style = get_style();
			tp_ptr = &(this_plot->next_cp);
		}

		if (equals(c_token,","))
			c_token++;
		else
			break;
	}

	if (autoscale && (ymin == ymax))
		ymax += 1.0;	/* kludge to avoid divide-by-zero in do_plot */

	if (log_y) {
		y_min = log10(ymin);
		y_max = log10(ymax);
	} else {
		y_min = ymin;
		y_max = ymax;
	}
	capture(replot_line,plot_token,c_token);	
	do_plot(first_plot,plot_num,x_min,x_max,y_min,y_max);
}



done(status)
int status;
{
	if (term)
		(*term_tbl[term].reset)();
	exit(status);
}


#ifdef vms

#include <descrip.h>
#include <rmsdef.h>
#include <errno.h>

extern lib$get_input(), lib$put_output();

int vms_len;

unsigned int status[2] = {1, 0};

$DESCRIPTOR(prompt_desc,PROMPT);
$DESCRIPTOR(line_desc,input_line);

$DESCRIPTOR(help_desc,help);
$DESCRIPTOR(helpfile_desc,"GNUPLOT$HELP");


read_line()
{
	switch(status[1] = lib$get_input(&line_desc, &prompt_desc, &vms_len)){
		case RMS$_EOF:
			done(IO_SUCCESS);	/* ^Z isn't really an error */
			break;
		case RMS$_TNS:			/* didn't press return in time */
			vms_len--;		/* skip the last character */
			break;			/* and parse anyway */
		case RMS$_BES:			/* Bad Escape Sequence */
		case RMS$_PES:			/* Partial Escape Sequence */
			sys$putmsg(status);
			vms_len = 0;		/* ignore the line */
			break;
		case SS$_NORMAL:
			break;			/* everything's fine */
		default:
			done(status[1]);	/* give the error message */
	}
	input_line[vms_len] = '\0';
}


do_help()
{
	help_desc.dsc$w_length = strlen(help);
	if ((vaxc$errno = lbr$output_help(lib$put_output,0,&help_desc,
		&helpfile_desc,0,lib$get_input)) != SS$_NORMAL)
			os_error("can't open GNUPLOT$HELP");
}


do_shell()
{
	if ((vaxc$errno = lib$spawn()) != SS$_NORMAL) {
		os_error("spawn error",NO_CARET);
	}
}


do_system()
{
	input_line[0] = ' ';	/* an embarrassment, but... */

	if ((vaxc$errno = lib$spawn(&line_desc)) != SS$_NORMAL)
		os_error("spawn error",NO_CARET);

	(void) putc('\n',stderr);
}

#else /* vms */

do_help()
{
	if (system(help))
		os_error("can't spawn help",c_token);
}


do_system()
{
	if (system(input_line + 1))
		os_error("system() failed",NO_CARET);
}

#ifdef MSDOS

read_line()
{
register int i;

	input_line[0] = MAX_LINE_LEN - 1;
	cputs(PROMPT);
	cgets(input_line);			/* console input so CED will work */
	(void) putc('\n',stderr);
	if (input_line[2] == 26) {
		(void) putc('\n',stderr);		/* end-of-file */
		done(IO_SUCCESS);
	}

	i = 0;
	while (input_line[i] = input_line[i+2])
		i++;		/* yuck!  move everything down two characters */
}


do_shell()
{
register char *comspec;
	if (!(comspec = getenv("COMSPEC")))
		comspec = "\command.com";
	if (spawnl(P_WAIT,comspec,NULL) == -1)
		os_error("unable to spawn shell",NO_CARET);
}

#else /* MSDOS */
		/* plain old Unix */

read_line()
{
	fputs(PROMPT,stderr);
	if (!gets(input_line)) {
		(void) putc('\n',stderr);		/* end-of-file */
		done(IO_SUCCESS);
	}
}

#ifdef VFORK

do_shell()
{
register char *shell;
register int p;
static int execstat;
	if (!(shell = getenv("SHELL")))
		shell = SHELL;
	if ((p = vfork()) == 0) {
		execstat = execl(shell,shell,NULL);
		_exit(1);
	} else if (p == -1)
		os_error("vfork failed",c_token);
	else
		while (wait(NULL) != p)
			;
	if (execstat == -1)
		os_error("shell exec failed",c_token);
	(void) putc('\n',stderr);
}
#else /* VFORK */

#define EXEC "exec "
do_shell()
{
static char exec[100] = EXEC;
register char *shell;
	if (!(shell = getenv("SHELL")))
		shell = SHELL;

	if (system(strncpy(&exec[sizeof(EXEC)-1],shell,
		sizeof(exec)-sizeof(EXEC)-1)))
		os_error("system() failed",NO_CARET);

	(void) putc('\n',stderr);
}
#endif /* VFORK */
#endif /* MSDOS */
#endif /* vms */
SHAR_EOF
if test 21346 -ne "`wc -c < 'command.c'`"
then
	echo shar: error transmitting "'command.c'" '(should have been 21346 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'eval.c'" '(3101 characters)'
if test -f 'eval.c'
then
	echo shar: will not over-write existing file "'eval.c'"
else
cat << \SHAR_EOF > 'eval.c'
/*
 *
 *    G N U P L O T  --  eval.c
 *
 *  Copyright (C) 1986, 1987  Colin Kelley, Thomas Williams
 *
 *  You may use this code as you wish if credit is given and this message
 *  is retained.
 *
 *  Please e-mail any useful additions to vu-vlsi!plot so they may be
 *  included in later releases.
 *
 *  This file should be edited with 4-column tabs!  (:set ts=4 sw=4 in vi)
 */

#include <stdio.h>
#include "plot.h"

char *malloc();

extern int c_token;
extern struct ft_entry ft[];
extern struct udvt_entry *first_udv;
extern struct udft_entry *first_udf;
extern struct at_type at;
extern struct lexical_unit token[];

struct value *integer();



struct udvt_entry *
add_udv(t_num)  /* find or add value and return pointer */
int t_num;
{
register struct udvt_entry **udv_ptr = &first_udv;

	/* check if it's already in the table... */

	while (*udv_ptr) {
		if (equals(t_num,(*udv_ptr)->udv_name))
			return(*udv_ptr);
		udv_ptr = &((*udv_ptr)->next_udv);
	}

	if (!(*udv_ptr = (struct udvt_entry *)
		malloc((unsigned int)sizeof(struct udvt_entry))))
			int_error("not enought memory for value",t_num);
	(*udv_ptr)->next_udv = NULL;
	copy_str((*udv_ptr)->udv_name,t_num);
	(*udv_ptr)->udv_value.type = INT;	/* not necessary, but safe! */
	(*udv_ptr)->udv_undef = TRUE;
	return(*udv_ptr);
}


struct udft_entry *
add_udf(t_num)  /* find or add function and return pointer */
int t_num; /* index to token[] */
{
register struct udft_entry **udf_ptr = &first_udf;

	while (*udf_ptr) {
		if (equals(t_num,(*udf_ptr)->udf_name))
			return(*udf_ptr);
		udf_ptr = &((*udf_ptr)->next_udf);
	}
	if (!(*udf_ptr = (struct udft_entry *)
		malloc((unsigned int)sizeof(struct udft_entry))))
			int_error("not enought memory for function",t_num);
	(*udf_ptr)->next_udf = (struct udft_entry *) NULL;
	(*udf_ptr)->definition = NULL;
	(*udf_ptr)->at = NULL;
	copy_str((*udf_ptr)->udf_name,t_num);
	(void) integer(&((*udf_ptr)->dummy_value), 0);
	return(*udf_ptr);
}


union argument *
add_action(sf_index)
enum operators sf_index;		/* index of p-code function */
{
	if (at.a_count >= MAX_AT_LEN)
		int_error("action table overflow",NO_CARET);
	at.actions[at.a_count].index = sf_index;
	return(&(at.actions[at.a_count++].arg));
}


int standard(t_num)  /* return standard function index or 0 */
{
register int i;
	for (i = (int)SF_START; ft[i].f_name != NULL; i++) {
		if (equals(t_num,ft[i].f_name))
			return(i);
	}
	return(0);
}

 

execute_at(at_ptr)
struct at_type *at_ptr;
{
register int i,index,count,offset;

	count = at_ptr->a_count;
	for (i = 0; i < count;) {
		index = (int)at_ptr->actions[i].index;
		offset = (*ft[index].func)(&(at_ptr->actions[i].arg));
		if (is_jump(index))
			i += offset;
		else
			i++;
	}
}

/*

 'ft' is a table containing C functions within this program. 

 An 'action_table' contains pointers to these functions and arguments to be
 passed to them. 

 at_ptr is a pointer to the action table which must be executed (evaluated)

 so the iterated line exectues the function indexed by the at_ptr and 
 passes the address of the argument which is pointed to by the arg_ptr 

*/
SHAR_EOF
if test 3101 -ne "`wc -c < 'eval.c'`"
then
	echo shar: error transmitting "'eval.c'" '(should have been 3101 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'graphics.c'" '(7287 characters)'
if test -f 'graphics.c'
then
	echo shar: will not over-write existing file "'graphics.c'"
else
cat << \SHAR_EOF > 'graphics.c'
/*
 *
 *    G N U P L O T  --  graphics.c
 *
 *  Copyright (C) 1986, 1987  Thomas Williams, Colin Kelley
 *
 *  You may use this code as you wish if credit is given and this message
 *  is retained.
 *
 *  Please e-mail any useful additions to vu-vlsi!plot so they may be
 *  included in later releases.
 *
 *  This file should be edited with 4-column tabs!  (:set ts=4 sw=4 in vi)
 */

#include <stdio.h>
#include <math.h>
#include "plot.h"

char *strcpy(),*strncpy(),*strcat();

extern BOOLEAN autoscale;
extern FILE *outfile;
extern BOOLEAN log_x, log_y;
extern int term;

extern BOOLEAN screen_ok;
extern BOOLEAN term_init;

extern struct termentry term_tbl[];


#ifndef max		/* Lattice C has max() in math.h, but shouldn't! */
#define max(a,b) ((a > b) ? a : b)
#endif

#define map_x(x) (int)((x-xmin)*xscale) /* maps floating point x to screen */ 
#define map_y(y) (int)((y-ymin)*yscale)	/* same for y */


double raise(x,y)
double x;
int y;
{
register int i;
double val;

	val = 1.0;
	for (i=0; i < abs(y); i++)
		val *= x;
	if (y < 0 ) return (1.0/val);
	return(val);
}


double make_tics(tmin,tmax,logscale)
double tmin,tmax;
BOOLEAN logscale;
{
register double xr,xnorm,tics,tic,l10;

	xr = fabs(tmin-tmax);
	
	l10 = log10(xr);
	if (logscale) {
		tic = raise(10.0,(l10 >= 0.0 ) ? (int)l10 : ((int)l10-1));
		if (tic < 1.0)
			tic = 1.0;
	} else {
		xnorm = pow(10.0,l10-(double)((l10 >= 0.0 ) ? (int)l10 : ((int)l10-1)));
		if (xnorm <= 2)
			tics = 0.2;
		else if (xnorm <= 5)
			tics = 0.5;
		else tics = 1.0;	
		tic = tics * raise(10.0,(l10 >= 0.0 ) ? (int)l10 : ((int)l10-1));
	}
	return(tic);
}

char *idx(a,b)
char *a,b;
{
	do {
		if (*a == b)
			return(a);
	} while (*a++);
	return(0);
}

 
num2str(num,str)
double num;
char str[];
{
static char temp[80];
register double d;
register char *a,*b;

 	if ((d = fabs(num)) > 9999.0 || d < 0.001 && d != 0.0) 
		(void) sprintf(temp,"%-.3e",num);	
	else
		(void) sprintf(temp,"%-.3g",num);
	if (b = idx(temp,'e')) {
		a = b;
		while ( *(--a) == '0') /* trailing zeros */
			;	
		if ( *a == '.') 
			a--;
		(void) strncpy(str,temp,(int)(a-temp)+1);
		str[(int)(a-temp)+1] = '\0';
		a = b+1;	/* point to 1 after 'e' */
		(void) strcat(str,"e");
		if ( *a == '-') 
			(void) strcat(str,"-");
		a++;						 /* advance a past '+' or '-' */
		while ( *a == '0' && *(a+1) != '\0') /* leading zeroes */
			a++;
		(void) strcat(str,a); /* copy rest of string */
	}
	else
		(void) strcpy(str,temp);	
}


do_plot(plots, pcount, xmin, xmax, ymin, ymax)
struct curve_points *plots;
int pcount;			/* count of plots in linked list */
double xmin, xmax;
double ymin, ymax;
{
register int i, x;
register struct termentry *t = &term_tbl[term];
register BOOLEAN prev_undef;
register int curve, xaxis_y, yaxis_x, dpcount;
register struct curve_points *this_plot;
register enum PLOT_TYPE p_type;
register double xscale, yscale;
register double ytic, xtic, least, most, ticplace;
register int mms,mts;
			/* only a Pyramid would have this many registers! */
static char xns[20],xms[20],yns[20],yms[20],xts[20],yts[20];
static char label[80];

	if (ymin == HUGE || ymax == -HUGE)
		int_error("all points undefined!", NO_CARET);

	ytic = make_tics(ymin,ymax,log_y);
	xtic = make_tics(xmin,xmax,log_x);
	dpcount = 0;
	
	if (ymin < ymax ) {
		ymin = ytic * floor(ymin/ytic);	
		ymax = ytic * ceil(ymax/ytic);
	}
	else {
		ymin = ytic * ceil(ymin/ytic);
		ymax = ytic * floor(ymax/ytic);
	}

	if (xmin == xmax)
		int_error("xmin should not equal xmax!",NO_CARET);
	if (ymin == ymax)
		int_error("ymin should not equal ymax!",NO_CARET);
	
	yscale = (t->ymax - 2)/(ymax - ymin);
	xscale = (t->xmax - 2)/(xmax - xmin);
	
	if (!term_init) {
		(*t->init)();
		term_init = TRUE;
	}
	screen_ok = FALSE;
	(*t->graphics)();
	(*t->linetype)(-2); /* border linetype */

	/* draw plot border */
	(*t->move)(0,0);	
	(*t->vector)(t->xmax-1,0);	
	(*t->vector)(t->xmax-1,t->ymax-1);	
	(*t->vector)(0,t->ymax-1);	
	(*t->vector)(0,0);

	least = (ymin < ymax) ? ymin : ymax;
	most = (ymin < ymax) ? ymax : ymin;

	for (ticplace = ytic + least; ticplace < most ; ticplace += ytic) { 
		(*t->move)(0,map_y(ticplace));
		(*t->vector)(t->h_tic,map_y(ticplace));
		(*t->move)(t->xmax-1,map_y(ticplace));
       	        (*t->vector)(t->xmax-1-t->h_tic,map_y(ticplace));
	}

	if (xmin < xmax ) {
		least = xtic * floor(xmin/xtic);	
		most = xtic * ceil(xmax/xtic);
	}
	else {
		least = xtic * ceil(xmin/xtic);
		most = xtic * floor(xmax/xtic);
	}

	for (ticplace = xtic + least; ticplace < most ; ticplace += xtic) { 
		(*t->move)(map_x(ticplace),0);
		(*t->vector)(map_x(ticplace),t->v_tic);
		(*t->move)(map_x(ticplace),t->ymax-1);
       	        (*t->vector)(map_x(ticplace),t->ymax-1-t->v_tic);
	}

	if (log_x) {
		num2str(pow(10.0,xmin),xns);
		num2str(pow(10.0,xmax),xms);
		num2str(pow(10.0,xtic),xts);
	}
	else {
		num2str(xmin,xns);
		num2str(xmax,xms);
		num2str(xtic,xts);
	}
	if (log_y) {
		num2str(pow(10.0,ymin),yns);
		num2str(pow(10.0,ymax),yms);
		num2str(pow(10.0,ytic),yts);
	} else {
		num2str(ymin,yns);
		num2str(ymax,yms);
		num2str(ytic,yts);
	}
	mms = max(strlen(xms),strlen(yms));
	mts = max(strlen(xts),strlen(yts));

	(void) sprintf(label,"%s < y < %-*s  inc = %-*s",yns,mms,yms,mts,yts);
	(*t->lrput_text)(0, label);
	(void) sprintf(label,"%s < x < %-*s  inc = %-*s",xns,mms,xms,mts,xts);
	(*t->lrput_text)(1, label);


/* DRAW AXES */
	(*t->linetype)(-1);	/* axis line type */
	xaxis_y = map_y(0.0);
	yaxis_x = map_x(0.0); 

	if (xaxis_y < 0)
		xaxis_y = 0;				/* save for impulse plotting */
	else if (xaxis_y >= t->ymax)
		xaxis_y = t->ymax - 1;
	else if (!log_y) {
		(*t->move)(0,xaxis_y);
		(*t->vector)((t->xmax-1),xaxis_y);
	}

	if (!log_x && yaxis_x >= 0 && yaxis_x < t->xmax) {
		(*t->move)(yaxis_x,0);
		(*t->vector)(yaxis_x,(t->ymax-1));
	}

/* DRAW CURVES */
	this_plot = plots;
	for (curve = 0; curve < pcount; this_plot = this_plot->next_cp, curve++) {
		(*t->linetype)(curve);
		(*t->ulput_text)(curve, this_plot->title);
		(*t->linetype)(curve);

		p_type = this_plot->plot_type;
		switch(this_plot->plot_style) {
			case IMPULSES:
				for (i = 0; i < this_plot->p_count; i++) {
					if (!this_plot->points[i].undefined) {
						if (p_type == DATA)
							x = map_x(this_plot->points[i].x);
						else
							x = (long)(t->xmax-1)*i/(this_plot->p_count-1);
						(*t->move)(x,xaxis_y);
						(*t->vector)(x,map_y(this_plot->points[i].y));
					}
				}
				break;
			case LINES:
				prev_undef = TRUE;
				for (i = 0; i < this_plot->p_count; i++) {
					if (!this_plot->points[i].undefined) {
						if (p_type == DATA)
							x = map_x(this_plot->points[i].x);
						else
							x = (long)(t->xmax-1)*i/(this_plot->p_count-1);
						if (prev_undef)
							(*t->move)(x,
							map_y(this_plot->points[i].y));
						(*t->vector)(x,
							map_y(this_plot->points[i].y));
					}
					prev_undef = this_plot->points[i].undefined;
				}
				break;
			case POINTS:
				for (i = 0; i < this_plot->p_count; i++) {
					if (!this_plot->points[i].undefined) {
						if (p_type == DATA)
							x = map_x(this_plot->points[i].x);
						else
							x = (long)(t->xmax-1)*i/(this_plot->p_count-1);
						(*t->point)(x,map_y(this_plot->points[i].y),dpcount);
					}
				}
				dpcount++;
				break;

		}
	}
	(*t->text)();
	(void) fflush(outfile);
}
SHAR_EOF
if test 7287 -ne "`wc -c < 'graphics.c'`"
then
	echo shar: error transmitting "'graphics.c'" '(should have been 7287 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'internal.c'" '(13595 characters)'
if test -f 'internal.c'
then
	echo shar: will not over-write existing file "'internal.c'"
else
cat << \SHAR_EOF > 'internal.c'
/*
 *
 *    G N U P L O T  --  internal.c
 *
 *  Copyright (C) 1986, 1987  Colin Kelley, Thomas Williams
 *
 *  You may use this code as you wish if credit is given and this message
 *  is retained.
 *
 *  Please e-mail any useful additions to vu-vlsi!plot so they may be
 *  included in later releases.
 *
 *  This file should be edited with 4-column tabs!  (:set ts=4 sw=4 in vi)
 */

#include <math.h>
#include <stdio.h>
#include "plot.h"

extern BOOLEAN undefined;

char *strcpy();

struct value *pop(), *complex(), *integer();
double magnitude(), angle(), real();

struct value stack[STACK_DEPTH];

int s_p = -1;   /* stack pointer */


/*
 * System V and MSC 4.0 call this when they wants to print an error message.
 * Don't!
 */
matherr()
{
	return (undefined = TRUE);		/* don't print error message */
}


reset_stack()
{
	s_p = -1;
}


check_stack()	/* make sure stack's empty */
{
	if (s_p != -1)
		fprintf(stderr,"\nwarning:  internal error--stack not empty!\n");
}


struct value *pop(x)
struct value *x;
{
	if (s_p  < 0 )
		int_error("stack underflow",NO_CARET);
	*x = stack[s_p--];
	return(x);
}


push(x)
struct value *x;
{
	if (s_p == STACK_DEPTH - 1)
		int_error("stack overflow",NO_CARET);
	stack[++s_p] = *x;
}


#define ERR_VAR "undefined variable: "

f_push(x)
union argument *x;		/* contains pointer to value to push; */
{
static char err_str[sizeof(ERR_VAR) + MAX_ID_LEN] = ERR_VAR;
struct udvt_entry *udv;

	udv = x->udv_arg;
	if (udv->udv_undef) {	 /* undefined */
		(void) strcpy(&err_str[sizeof(ERR_VAR) - 1], udv->udv_name);
		int_error(err_str,NO_CARET);
	}
	push(&(udv->udv_value));
}


f_pushc(x)
union argument *x;
{
	push(&(x->v_arg));
}


f_pushd(x)
union argument *x;
{
	push(&(x->udf_arg->dummy_value));
}


#define ERR_FUN "undefined function: "

f_call(x)  /* execute a udf */
union argument *x;
{
static char err_str[sizeof(ERR_FUN) + MAX_ID_LEN] = ERR_FUN;
register struct udft_entry *udf;

	udf = x->udf_arg;
	if (!udf->at) { /* undefined */
		(void) strcpy(&err_str[sizeof(ERR_FUN) - 1],
				udf->udf_name);
		int_error(err_str,NO_CARET);
	}
	(void) pop(&(udf->dummy_value));

	execute_at(udf->at);
}


static int_check(v)
struct value *v;
{
	if (v->type != INT)
		int_error("non-integer passed to boolean operator",NO_CARET);
}


f_lnot()
{
struct value a;
	int_check(pop(&a));
	push(integer(&a,!a.v.int_val) );
}


f_bnot()
{
struct value a;
	int_check(pop(&a));
	push( integer(&a,~a.v.int_val) );
}


f_bool()
{			/* converts top-of-stack to boolean */
	int_check(&top_of_stack);
	top_of_stack.v.int_val = !!top_of_stack.v.int_val;
}


f_lor()
{
struct value a,b;
	int_check(pop(&b));
	int_check(pop(&a));
	push( integer(&a,a.v.int_val || b.v.int_val) );
}

f_land()
{
struct value a,b;
	int_check(pop(&b));
	int_check(pop(&a));
	push( integer(&a,a.v.int_val && b.v.int_val) );
}


f_bor()
{
struct value a,b;
	int_check(pop(&b));
	int_check(pop(&a));
	push( integer(&a,a.v.int_val | b.v.int_val) );
}


f_xor()
{
struct value a,b;
	int_check(pop(&b));
	int_check(pop(&a));
	push( integer(&a,a.v.int_val ^ b.v.int_val) );
}


f_band()
{
struct value a,b;
	int_check(pop(&b));
	int_check(pop(&a));
	push( integer(&a,a.v.int_val & b.v.int_val) );
}


f_uminus()
{
struct value a;
	(void) pop(&a);
	switch(a.type) {
		case INT:
			a.v.int_val = -a.v.int_val;
			break;
		case CMPLX:
			a.v.cmplx_val.real =
				-a.v.cmplx_val.real;
			a.v.cmplx_val.imag =
				-a.v.cmplx_val.imag;
	}
	push(&a);
}


f_eq() /* note: floating point equality is rare because of roundoff error! */
{
struct value a, b;
	register int result;
	(void) pop(&b);
	(void) pop(&a);
	switch(a.type) {
		case INT:
			switch (b.type) {
				case INT:
					result = (a.v.int_val ==
						b.v.int_val);
					break;
				case CMPLX:
					result = (a.v.int_val ==
						b.v.cmplx_val.real &&
					   b.v.cmplx_val.imag == 0.0);
			}
			break;
		case CMPLX:
			switch (b.type) {
				case INT:
					result = (b.v.int_val == a.v.cmplx_val.real &&
					   a.v.cmplx_val.imag == 0.0);
					break;
				case CMPLX:
					result = (a.v.cmplx_val.real==
						b.v.cmplx_val.real &&
						a.v.cmplx_val.imag==
						b.v.cmplx_val.imag);
			}
	}
	push(integer(&a,result));
}


f_ne()
{
struct value a, b;
	register int result;
	(void) pop(&b);
	(void) pop(&a);
	switch(a.type) {
		case INT:
			switch (b.type) {
				case INT:
					result = (a.v.int_val !=
						b.v.int_val);
					break;
				case CMPLX:
					result = (a.v.int_val !=
						b.v.cmplx_val.real ||
					   b.v.cmplx_val.imag != 0.0);
			}
			break;
		case CMPLX:
			switch (b.type) {
				case INT:
					result = (b.v.int_val !=
						a.v.cmplx_val.real ||
					   a.v.cmplx_val.imag != 0.0);
					break;
				case CMPLX:
					result = (a.v.cmplx_val.real !=
						b.v.cmplx_val.real ||
						a.v.cmplx_val.imag !=
						b.v.cmplx_val.imag);
			}
	}
	push(integer(&a,result));
}


f_gt()
{
struct value a, b;
	register int result;
	(void) pop(&b);
	(void) pop(&a);
	switch(a.type) {
		case INT:
			switch (b.type) {
				case INT:
					result = (a.v.int_val >
						b.v.int_val);
					break;
				case CMPLX:
					result = (a.v.int_val >
						b.v.cmplx_val.real);
			}
			break;
		case CMPLX:
			switch (b.type) {
				case INT:
					result = (a.v.cmplx_val.real >
						b.v.int_val);
					break;
				case CMPLX:
					result = (a.v.cmplx_val.real >
						b.v.cmplx_val.real);
			}
	}
	push(integer(&a,result));
}


f_lt()
{
struct value a, b;
	register int result;
	(void) pop(&b);
	(void) pop(&a);
	switch(a.type) {
		case INT:
			switch (b.type) {
				case INT:
					result = (a.v.int_val <
						b.v.int_val);
					break;
				case CMPLX:
					result = (a.v.int_val <
						b.v.cmplx_val.real);
			}
			break;
		case CMPLX:
			switch (b.type) {
				case INT:
					result = (a.v.cmplx_val.real <
						b.v.int_val);
					break;
				case CMPLX:
					result = (a.v.cmplx_val.real <
						b.v.cmplx_val.real);
			}
	}
	push(integer(&a,result));
}


f_ge()
{
struct value a, b;
	register int result;
	(void) pop(&b);
	(void) pop(&a);
	switch(a.type) {
		case INT:
			switch (b.type) {
				case INT:
					result = (a.v.int_val >=
						b.v.int_val);
					break;
				case CMPLX:
					result = (a.v.int_val >=
						b.v.cmplx_val.real);
			}
			break;
		case CMPLX:
			switch (b.type) {
				case INT:
					result = (a.v.cmplx_val.real >=
						b.v.int_val);
					break;
				case CMPLX:
					result = (a.v.cmplx_val.real >=
						b.v.cmplx_val.real);
			}
	}
	push(integer(&a,result));
}


f_le()
{
struct value a, b;
	register int result;
	(void) pop(&b);
	(void) pop(&a);
	switch(a.type) {
		case INT:
			switch (b.type) {
				case INT:
					result = (a.v.int_val <=
						b.v.int_val);
					break;
				case CMPLX:
					result = (a.v.int_val <=
						b.v.cmplx_val.real);
			}
			break;
		case CMPLX:
			switch (b.type) {
				case INT:
					result = (a.v.cmplx_val.real <=
						b.v.int_val);
					break;
				case CMPLX:
					result = (a.v.cmplx_val.real <=
						b.v.cmplx_val.real);
			}
	}
	push(integer(&a,result));
}


f_plus()
{
struct value a, b, result;
	(void) pop(&b);
	(void) pop(&a);
	switch(a.type) {
		case INT:
			switch (b.type) {
				case INT:
					(void) integer(&result,a.v.int_val +
						b.v.int_val);
					break;
				case CMPLX:
					(void) complex(&result,a.v.int_val +
						b.v.cmplx_val.real,
					   b.v.cmplx_val.imag);
			}
			break;
		case CMPLX:
			switch (b.type) {
				case INT:
					(void) complex(&result,b.v.int_val +
						a.v.cmplx_val.real,
					   a.v.cmplx_val.imag);
					break;
				case CMPLX:
					(void) complex(&result,a.v.cmplx_val.real+
						b.v.cmplx_val.real,
						a.v.cmplx_val.imag+
						b.v.cmplx_val.imag);
			}
	}
	push(&result);
}


f_minus()
{
struct value a, b, result;
	(void) pop(&b);
	(void) pop(&a);		/* now do a - b */
	switch(a.type) {
		case INT:
			switch (b.type) {
				case INT:
					(void) integer(&result,a.v.int_val -
						b.v.int_val);
					break;
				case CMPLX:
					(void) complex(&result,a.v.int_val -
						b.v.cmplx_val.real,
					   -b.v.cmplx_val.imag);
			}
			break;
		case CMPLX:
			switch (b.type) {
				case INT:
					(void) complex(&result,a.v.cmplx_val.real -
						b.v.int_val,
					    a.v.cmplx_val.imag);
					break;
				case CMPLX:
					(void) complex(&result,a.v.cmplx_val.real-
						b.v.cmplx_val.real,
						a.v.cmplx_val.imag-
						b.v.cmplx_val.imag);
			}
	}
	push(&result);
}


f_mult()
{
struct value a, b, result;
	(void) pop(&b);
	(void) pop(&a);	/* now do a*b */

	switch(a.type) {
		case INT:
			switch (b.type) {
				case INT:
					(void) integer(&result,a.v.int_val *
						b.v.int_val);
					break;
				case CMPLX:
					(void) complex(&result,a.v.int_val *
						b.v.cmplx_val.real,
						a.v.int_val *
						b.v.cmplx_val.imag);
			}
			break;
		case CMPLX:
			switch (b.type) {
				case INT:
					(void) complex(&result,b.v.int_val *
						a.v.cmplx_val.real,
						b.v.int_val *
						a.v.cmplx_val.imag);
					break;
				case CMPLX:
					(void) complex(&result,a.v.cmplx_val.real*
						b.v.cmplx_val.real-
						a.v.cmplx_val.imag*
						b.v.cmplx_val.imag,
						a.v.cmplx_val.real*
						b.v.cmplx_val.imag+
						a.v.cmplx_val.imag*
						b.v.cmplx_val.real);
			}
	}
	push(&result);
}


f_div()
{
struct value a, b, result;
register double square;
	(void) pop(&b);
	(void) pop(&a);	/* now do a/b */

	switch(a.type) {
		case INT:
			switch (b.type) {
				case INT:
					if (b.v.int_val)
					  (void) integer(&result,a.v.int_val /
						b.v.int_val);
					else {
					  (void) integer(&result,0);
					  undefined = TRUE;
					}
					break;
				case CMPLX:
					square = b.v.cmplx_val.real*
						b.v.cmplx_val.real +
						b.v.cmplx_val.imag*
						b.v.cmplx_val.imag;
					if (square)
						(void) complex(&result,a.v.int_val*
						b.v.cmplx_val.real/square,
						-a.v.int_val*
						b.v.cmplx_val.imag/square);
					else {
						(void) complex(&result,0.0,0.0);
						undefined = TRUE;
					}
			}
			break;
		case CMPLX:
			switch (b.type) {
				case INT:
					if (b.v.int_val)
					  
					  (void) complex(&result,a.v.cmplx_val.real/
						b.v.int_val,
						a.v.cmplx_val.imag/
						b.v.int_val);
					else {
						(void) complex(&result,0.0,0.0);
						undefined = TRUE;
					}
					break;
				case CMPLX:
					square = b.v.cmplx_val.real*
						b.v.cmplx_val.real +
						b.v.cmplx_val.imag*
						b.v.cmplx_val.imag;
					if (square)
					(void) complex(&result,(a.v.cmplx_val.real*
						b.v.cmplx_val.real+
						a.v.cmplx_val.imag*
						b.v.cmplx_val.imag)/square,
						(a.v.cmplx_val.imag*
						b.v.cmplx_val.real-
						a.v.cmplx_val.real*
						b.v.cmplx_val.imag)/
							square);
					else {
						(void) complex(&result,0.0,0.0);
						undefined = TRUE;
					}
			}
	}
	push(&result);
}


f_mod()
{
struct value a, b;
	(void) pop(&b);
	(void) pop(&a);	/* now do a%b */

	if (a.type != INT || b.type != INT)
		int_error("can only mod ints",NO_CARET);
	if (b.v.int_val)
		push(integer(&a,a.v.int_val % b.v.int_val));
	else {
		push(integer(&a,0));
		undefined = TRUE;
	}
}


f_power()
{
struct value a, b, result;
register int i, t, count;
register double mag, ang;
	(void) pop(&b);
	(void) pop(&a);	/* now find a**b */

	switch(a.type) {
		case INT:
			switch (b.type) {
				case INT:
					count = abs(b.v.int_val);
					t = 1;
					for(i = 0; i < count; i++)
						t *= a.v.int_val;
					if (b.v.int_val >= 0)
						(void) integer(&result,t);
					else
						(void) complex(&result,1.0/t,0.0);
					break;
				case CMPLX:
					mag =
					  pow(magnitude(&a),fabs(b.v.cmplx_val.real));
					if (b.v.cmplx_val.real < 0.0)
						mag = 1.0/mag;
					ang = angle(&a)*b.v.cmplx_val.real+
					  b.v.cmplx_val.imag;
					(void) complex(&result,mag*cos(ang),
						mag*sin(ang));
			}
			break;
		case CMPLX:
			switch (b.type) {
				case INT:
					if (a.v.cmplx_val.imag == 0.0) {
						mag = pow(a.v.cmplx_val.real,(double)abs(b.v.int_val));
						if (b.v.int_val < 0)
							mag = 1.0/mag;
						(void) complex(&result,mag,0.0);
					}
					else {
						/* not so good, but...! */
						mag = pow(magnitude(&a),(double)abs(b.v.int_val));
						if (b.v.int_val < 0)
							mag = 1.0/mag;
						ang = angle(&a)*b.v.int_val;
						(void) complex(&result,mag*cos(ang),
							mag*sin(ang));
					}
					break;
				case CMPLX:
					mag = pow(magnitude(&a),fabs(b.v.cmplx_val.real));
					if (b.v.cmplx_val.real < 0.0)
					  mag = 1.0/mag;
					ang = angle(&a)*b.v.cmplx_val.real+ b.v.cmplx_val.imag;
					(void) complex(&result,mag*cos(ang),
						mag*sin(ang));
			}
	}
	push(&result);
}


f_factorial()
{
struct value a;
register int i;
register double val;

	(void) pop(&a);	/* find a! (factorial) */

	switch (a.type) {
		case INT:
			val = 1.0;
			for (i = a.v.int_val; i > 1; i--)  /*fpe's should catch overflows*/
				val *= i;
			break;
		default:
			int_error("factorial (!) argument must be an integer",
			NO_CARET);
		}

	push(complex(&a,val,0.0));
			
}


int
f_jump(x)
union argument *x;
{
	return(x->j_arg);
}


int
f_jumpz(x)
union argument *x;
{
struct value a;
	int_check(&top_of_stack);
	if (top_of_stack.v.int_val) {	/* non-zero */
		(void) pop(&a);
		return 1;				/* no jump */
	}
	else
		return(x->j_arg);		/* leave the argument on TOS */
}


int
f_jumpnz(x)
union argument *x;
{
struct value a;
	int_check(&top_of_stack);
	if (top_of_stack.v.int_val)	/* non-zero */
		return(x->j_arg);		/* leave the argument on TOS */
	else {
		(void) pop(&a);
		return 1;				/* no jump */
	}
}


int
f_jtern(x)
union argument *x;
{
struct value a;

	int_check(pop(&a));
	if (a.v.int_val)
		return(1);				/* no jump; fall through to TRUE code */
	else
		return(x->j_arg);		/* go jump to FALSE code */
}
SHAR_EOF
if test 13595 -ne "`wc -c < 'internal.c'`"
then
	echo shar: error transmitting "'internal.c'" '(should have been 13595 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'misc.c'" '(5921 characters)'
if test -f 'misc.c'
then
	echo shar: will not over-write existing file "'misc.c'"
else
cat << \SHAR_EOF > 'misc.c'
/*
 *
 *    G N U P L O T  --  misc.c
 *
 *  Copyright (C) 1986, 1987  Thomas Williams, Colin Kelley
 *
 *  You may use this code as you wish if credit is given and this message
 *  is retained.
 *
 *  Please e-mail any useful additions to vu-vlsi!plot so they may be
 *  included in later releases.
 *
 *  This file should be edited with 4-column tabs!  (:set ts=4 sw=4 in vi)
 */

#include <stdio.h>
#include "plot.h"

extern BOOLEAN autoscale;
extern BOOLEAN log_x, log_y;
extern FILE* outfile;
extern char outstr[];
extern int samples;
extern int term;
extern double zero;

extern BOOLEAN screen_ok;

extern int c_token;
extern struct at_type at;
extern struct ft_entry ft[];
extern struct udft_entry *first_udf;
extern struct udvt_entry *first_udv;
extern struct termentry term_tbl[];

char *malloc();

struct at_type *temp_at();


/*
 * cp_free() releases any memory which was previously malloc()'d to hold
 *   curve points.
 */
cp_free(cp)
struct curve_points *cp;
{
	if (cp) {
		cp_free(cp->next_cp);
		if (cp->title)
			free((char *)cp->title);
		free((char *)cp);
	}
}



save_functions(fp)
FILE *fp;
{
register struct udft_entry *udf = first_udf;
	
	if (fp) {
		while (udf) {
			if (udf->definition)
				fprintf(fp,"%s\n",udf->definition);
			udf = udf->next_udf;
		}
		(void) fclose(fp);
	} else
		os_error("Cannot open save file",c_token);			
}


save_variables(fp)
FILE *fp;
{
register struct udvt_entry *udv = first_udv->next_udv;	/* skip pi */

	if (fp) {
		while (udv) {
			if (!udv->udv_undef) {
				fprintf(fp,"%s = ",udv->udv_name);
				disp_value(fp,&(udv->udv_value));
				(void) putc('\n',fp);
			}
			udv = udv->next_udv;
		}
		(void) fclose(fp);
	} else
		os_error("Cannot open save file",c_token);			
}


save_all(fp)
FILE *fp;
{
register struct udft_entry *udf = first_udf;
register struct udvt_entry *udv = first_udv->next_udv;	/* skip pi */

	if (fp) {
		while (udf) {
			if (udf->definition)
				fprintf(fp,"%s\n",udf->definition);
			udf = udf->next_udf;
		}
		while (udv) {
			if (!udv->udv_undef) {
				fprintf(fp,"%s = ",udv->udv_name);
				disp_value(fp,&(udv->udv_value));
				(void) putc('\n',fp);
			}
			udv = udv->next_udv;
		}
		(void) fclose(fp);
	} else
		os_error("Cannot open save file",c_token);			
}


load_file(fp)
FILE *fp;
{
register int len;
extern char input_line[];

	if (fp) {
		while (fgets(input_line,MAX_LINE_LEN,fp)) {
			len = strlen(input_line) - 1;
			if (input_line[len] == '\n')
				input_line[len] = '\0';

			screen_ok = FALSE;	/* make sure command line is
					   echoed on error */
			do_line();
		}
		(void) fclose(fp);
	} else
		os_error("Cannot open load file",c_token);
}


show_style(name,style)
char name[];
enum PLOT_STYLE style;
{
	fprintf(stderr,"\t%s are plotted with ",name);
	switch (style) {
		case LINES: fprintf(stderr,"lines\n"); break;
		case POINTS: fprintf(stderr,"points\n"); break;
		case IMPULSES: fprintf(stderr,"impulses\n"); break;
	}
}

show_range(name,min,max)
char name;
double min,max;
{
	fprintf(stderr,"\t%crange is [%g : %g]\n",name,min,max);
}

show_zero()
{
	fprintf(stderr,"\tzero is %g\n",zero);
}

show_samples()
{
	fprintf(stderr,"\tsampling rate is %d\n",samples);
}

show_output()
{
	fprintf(stderr,"\toutput is sent to %s\n",outstr);
}

show_term()
{
	fprintf(stderr,"\tterminal type is %s\n",term_tbl[term].name);
}

show_autoscale()
{
	fprintf(stderr,"\tautoscaling is %s\n",(autoscale)? "ON" : "OFF");
}

show_logscale()
{
	if (log_x && log_y)
		fprintf(stderr,"\tlogscaling both x and y axes\n");
	else if (log_x)
		fprintf(stderr,"\tlogscaling x axis\n");
	else if (log_y)
		fprintf(stderr,"\tlogscaling y axis\n");
	else
		fprintf(stderr,"\tno logscaling\n");
}

show_variables()
{
register struct udvt_entry *udv = first_udv;

	fprintf(stderr,"\n\tVariables:\n");
	while (udv) {
		fprintf(stderr,"\t%-*s ",MAX_ID_LEN,udv->udv_name);
		if (udv->udv_undef)
			fputs("is undefined\n",stderr);
		else {
			fputs("= ",stderr);
			disp_value(stderr,&(udv->udv_value));
			(void) putc('\n',stderr);
		}
		udv = udv->next_udv;
	}
}


show_functions()
{
register struct udft_entry *udf = first_udf;

	fprintf(stderr,"\n\tUser-Defined Functions:\n");

	while (udf) {
		if (udf->definition)
			fprintf(stderr,"\t%s\n",udf->definition);
		else
			fprintf(stderr,"\t%s is undefined\n",udf->udf_name);
		udf = udf->next_udf;
	}
}


show_at()
{
	(void) putc('\n',stderr);
	disp_at(temp_at(),0);
}


disp_at(curr_at, level)
struct at_type *curr_at;
int level;
{
register int i, j;
register union argument *arg;

	for (i = 0; i < curr_at->a_count; i++) {
		(void) putc('\t',stderr);
		for (j = 0; j < level; j++)
			(void) putc(' ',stderr);	/* indent */

			/* print name of instruction */

		fputs(ft[(int)(curr_at->actions[i].index)].f_name,stderr);
		arg = &(curr_at->actions[i].arg);

			/* now print optional argument */

		switch(curr_at->actions[i].index) {
		  case PUSH:	fprintf(stderr," %s\n", arg->udv_arg->udv_name);
					break;
		  case PUSHC:	(void) putc(' ',stderr);
					disp_value(stderr,&(arg->v_arg));
					(void) putc('\n',stderr);
					break;
		  case PUSHD:	fprintf(stderr," %s dummy\n",
					  arg->udf_arg->udf_name);
					break;
		  case CALL:	fprintf(stderr," %s", arg->udf_arg->udf_name);
					if (arg->udf_arg->at) {
						(void) putc('\n',stderr);
						disp_at(arg->udf_arg->at,level+2); /* recurse! */
					} else
						fputs(" (undefined)\n",stderr);
					break;
		  case JUMP:
		  case JUMPZ:
		  case JUMPNZ:
		  case JTERN:
					fprintf(stderr," +%d\n",arg->j_arg);
					break;
		  default:
					(void) putc('\n',stderr);
		}
	}
}


show_version()
{
extern char version[];
extern char date[];
static char *authors[] = {"Thomas Williams","Colin Kelley"};
int x;
long time();

	x = time((long *)NULL) & 1;
	fprintf(stderr,"\n\t%s\n\t%sversion %s\n\tlast modified %s\n",
		PROGRAM, OS, version, date);
	fprintf(stderr,"\tCopyright (C) 1986, 1987  %s, %s\n\n",
		authors[x],authors[1-x]);
}
SHAR_EOF
if test 5921 -ne "`wc -c < 'misc.c'`"
then
	echo shar: error transmitting "'misc.c'" '(should have been 5921 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'parse.c'" '(7780 characters)'
if test -f 'parse.c'
then
	echo shar: will not over-write existing file "'parse.c'"
else
cat << \SHAR_EOF > 'parse.c'
/*
 *
 *    G N U P L O T  --  parse.c
 *
 *  Copyright (C) 1986, 1987  Colin Kelley, Thomas Williams
 *
 *  You may use this code as you wish if credit is given and this message
 *  is retained.
 *
 *  Please e-mail any useful additions to vu-vlsi!plot so they may be
 *  included in later releases.
 *
 *  This file should be edited with 4-column tabs!  (:set ts=4 sw=4 in vi)
 */

#include <stdio.h>
#include <setjmp.h>
#include <signal.h>
#include <errno.h>
#include "plot.h"

extern BOOLEAN undefined;

#ifndef vms
extern int errno;
#endif

extern int num_tokens,c_token;
extern struct lexical_unit token[];
extern char c_dummy_var[];			/* name of current dummy variable */
extern struct udft_entry *dummy_func;	/* pointer to dummy variable's func */

char *malloc();

struct value *pop(),*integer(),*complex();
struct at_type *temp_at(), *perm_at();
struct udft_entry *add_udf();
struct udvt_entry *add_udv();
union argument *add_action();

struct at_type at;
static jmp_buf fpe_env;

#define dummy (struct value *) 0

fpe()
{
#ifdef PC	/* thanks to lotto@wjh12.UUCP for telling us about this  */
	_fpreset();
#endif
	(void) signal(SIGFPE, fpe);
	undefined = TRUE;
	longjmp(fpe_env, TRUE);
}


evaluate_at(at_ptr,val_ptr)
struct at_type *at_ptr;
struct value *val_ptr;
{
	undefined = FALSE;
	errno = 0;
	reset_stack();
	if (setjmp(fpe_env))
		return;				/* just bail out */
	(void) signal(SIGFPE, fpe);	/* catch core dumps on FPEs */

	execute_at(at_ptr);

	(void) signal(SIGFPE, SIG_DFL);

	if (errno == EDOM || errno == ERANGE) {
		undefined = TRUE;
	} else {
		(void) pop(val_ptr);
		check_stack();
	}
}


struct value *
const_express(valptr)
struct value *valptr;
{
register int tkn = c_token;
	if (END_OF_COMMAND)
		int_error("constant expression required",c_token);
	evaluate_at(temp_at(),valptr);	/* run it and send answer back */
	if (undefined) {
		int_error("undefined value",tkn);
	}
	return(valptr);
}


struct at_type *
temp_at()	/* build a static action table and return its pointer */
{
	at.a_count = 0;		/* reset action table !!! */
	express();
	return(&at);
}


/* build an action table, put it in dynamic memory, and return its pointer */

struct at_type *
perm_at()
{
register struct at_type *at_ptr;
register unsigned int len;

	(void) temp_at();
	len = sizeof(struct at_type) -
		(MAX_AT_LEN - at.a_count)*sizeof(struct at_entry);
	if (at_ptr = (struct at_type *) malloc(len))
		(void) memcpy(at_ptr,&at,len);
	return(at_ptr);
}


#ifdef NOCOPY
/*
 * cheap and slow version of memcpy() in case you don't have one
 */
memcpy(dest,src,len)
char *dest,*src;
unsigned int len;
{
	while (len--)
		*dest++ = *src++;
}
#endif /* NOCOPY */


express()  /* full expressions */
{
	xterm();
	xterms();
}

xterm()  /* ? : expressions */
{
	aterm();
	aterms();
}


aterm()
{
	bterm();
	bterms();
}


bterm()
{
	cterm();
	cterms();
}


cterm()
{
	dterm();
	dterms();
}


dterm()
{	
	eterm();
	eterms();
}


eterm()
{
	fterm();
	fterms();
}


fterm()
{
	gterm();
	gterms();
}


gterm()
{
	hterm();
	hterms();
}


hterm()
{
	unary(); /* - things */
	iterms(); /* * / % */
}


factor()
{
register int value;

	if (equals(c_token,"(")) {
		c_token++;
		express();
		if (!equals(c_token,")"))
			int_error("')' expected",c_token);
		c_token++;
	}
	else if (isnumber(c_token)) {
		convert(&(add_action(PUSHC)->v_arg),c_token);
		c_token++;
	}
	else if (isletter(c_token)) {
		if ((c_token+1 < num_tokens)  && equals(c_token+1,"(")) {
			value = standard(c_token);
			if (value) {	/* it's a standard function */
				c_token += 2;
				express();
				if (!equals(c_token,")"))
					int_error("')' expected",c_token);
				c_token++;
				(void) add_action(value);
			}
			else {
				value = c_token;
				c_token += 2;
				express();
				if (!equals(c_token,")"))
					int_error("')' expected",c_token);
				c_token++;
				add_action(CALL)->udf_arg = add_udf(value);
			}
		}
		else {
			if (equals(c_token,c_dummy_var)) {
				c_token++;
				add_action(PUSHD)->udf_arg = dummy_func;
			}
			else {
				add_action(PUSH)->udv_arg = add_udv(c_token);
				c_token++;
			}
		}
	} /* end if letter */
	else
		int_error("invalid expression ",c_token);

	/* add action code for ! (factorial) operator */
	while (equals(c_token,"!")) {
		c_token++;
		(void) add_action(FACTORIAL);
	}
	/* add action code for ** operator */
	if (equals(c_token,"**")) {
			c_token++;
			unary();
			(void) add_action(POWER);
	}

}



xterms()
{  /* create action code for ? : expressions */

	if (equals(c_token,"?")) {
		register int savepc1, savepc2;
		register union argument *argptr1,*argptr2;
		c_token++;
		savepc1 = at.a_count;
		argptr1 = add_action(JTERN);
		express();
		if (!equals(c_token,":"))
			int_error("expecting ':'",c_token);
		c_token++;
		savepc2 = at.a_count;
		argptr2 = add_action(JUMP);
		argptr1->j_arg = at.a_count - savepc1;
		express();
		argptr2->j_arg = at.a_count - savepc2;
	}
}


aterms()
{  /* create action codes for || operator */

	while (equals(c_token,"||")) {
		register int savepc;
		register union argument *argptr;
		c_token++;
		savepc = at.a_count;
		argptr = add_action(JUMPNZ);	/* short-circuit if already TRUE */
		aterm();
		argptr->j_arg = at.a_count - savepc;/* offset for jump */
		(void) add_action(BOOL);
	}
}


bterms()
{ /* create action code for && operator */

	while (equals(c_token,"&&")) {
		register int savepc;
		register union argument *argptr;
		c_token++;
		savepc = at.a_count;
		argptr = add_action(JUMPZ);	/* short-circuit if already FALSE */
		bterm();
		argptr->j_arg = at.a_count - savepc;/* offset for jump */
		(void) add_action(BOOL);
	}
}


cterms()
{ /* create action code for | operator */

	while (equals(c_token,"|")) {
		c_token++;
		cterm();
		(void) add_action(BOR);
	}
}


dterms()
{ /* create action code for ^ operator */

	while (equals(c_token,"^")) {
		c_token++;
		dterm();
		(void) add_action(XOR);
	}
}


eterms()
{ /* create action code for & operator */

	while (equals(c_token,"&")) {
		c_token++;
		eterm();
		(void) add_action(BAND);
	}
}


fterms()
{ /* create action codes for == and != operators */

	while (TRUE) {
		if (equals(c_token,"==")) {
			c_token++;
			fterm();
			(void) add_action(EQ);
		}
		else if (equals(c_token,"!=")) {
			c_token++;
			fterm();
			(void) add_action(NE);
		}
		else break;
	}
}


gterms()
{ /* create action code for < > >= or <= operators */
	
	while (TRUE) {
		/* I hate "else if" statements */
		if (equals(c_token,">")) {
			c_token++;
			gterm();
			(void) add_action(GT);
		}
		else if (equals(c_token,"<")) {
			c_token++;
			gterm();
			(void) add_action(LT);
		}		
		else if (equals(c_token,">=")) {
			c_token++;
			gterm();
			(void) add_action(GE);
		}
		else if (equals(c_token,"<=")) {
			c_token++;
			gterm();
			(void) add_action(LE);
		}
		else break;
	}

}



hterms()
{ /* create action codes for + and - operators */

	while (TRUE) {
			if (equals(c_token,"+")) {
				c_token++;
				hterm();
				(void) add_action(PLUS);
			}
			else if (equals(c_token,"-")) {
				c_token++;
				hterm();
				(void) add_action(MINUS);
			}
			else break;
	}
}


iterms()
{ /* add action code for * / and % operators */

	while (TRUE) {
			if (equals(c_token,"*")) {
				c_token++;
				unary();
				(void) add_action(MULT);
			}
			else if (equals(c_token,"/")) {
				c_token++;
				unary();
				(void) add_action(DIV);
			}
			else if (equals(c_token,"%")) {
				c_token++;
				unary();
				(void) add_action(MOD);
			}
			else break;
	}
}


unary()
{ /* add code for unary operators */
	if (equals(c_token,"!")) {
		c_token++;
		unary();
		(void) add_action(LNOT);
	}
	else if (equals(c_token,"~")) {
		c_token++;
		unary();
		(void) add_action(BNOT);
	}
	else if (equals(c_token,"-")) {
		c_token++;
		unary();
		(void) add_action(UMINUS);
	}
	else
		factor();
}
SHAR_EOF
if test 7780 -ne "`wc -c < 'parse.c'`"
then
	echo shar: error transmitting "'parse.c'" '(should have been 7780 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0