[comp.sources.misc] v03i063: hexcalc 1.1

richardh@killer.UUCP (Richard Hargrove) (06/28/88)

comp.sources.misc: Volume 3, Issue 63
Submitted-By: "Richard Hargrove" <richardh@killer.UUCP>
Archive-Name: hexcalc1.1

Brandon,

Just what the net needs. Another calculator program! This one is modeled
the TI Programmer II (decimal radix is still integer, though). I won't 
repeat the readme file here. I've tested the makefiles under MS-DOS,
Microport Unix SYS V/AT, ATT SYS V, R3 (on a 3b2), SCO Xenix SYS V, and
Intel Xenix 3.5 (SYS III based). All make without a hitch.

If you think it is a reasonable contribution, post away.

thanks,
richard hargrove

-------- cut here -------- cut here -------- cut here -------- cut here --------
#!/bin/sh
# shar:	Shell Archiver  (v1.22)
#
#	Run the following text with /bin/sh to create:
#	  1st_read.me
#	  bltins.c
#	  hctest01.txt
#	  hctest02.txt
#	  hexcalc.h
#	  hexcalc.man
#	  hexcalc.y
#	  init.c
#	  makefile.dos
#	  makefile.unx
#	  symbol.c
#	  ulpow.c
#	  ytab.c
#	  ytab.h
#	  yylex.c
#
sed 's/^X//' << 'SHAR_EOF' > 1st_read.me &&
X	----------------
X        Here is a yacc toy, a hexadecimal calculator program. It's based on
X        hoc3 for those familiar with chapter 8 in _The Unix Programming
X        Environment_ by Kernighan and Pike. To use it, run it and type help.
X        Or better yet, read the included man pages.
X
X	This package is being distributed in both .ARC archive and shell
X	archive (shar) form and is made up of the following files:
X
X		1st_read.me		this file
X
X		hexcalc.exe		executable (.ARC only)
X
X		hexcalc.h		c source code
X		ytab.h
X		bltins.c
X		symbol.c
X		ulpow.c
X		yylex.c
X		init.c
X		ytab.c
X
X		hexcalc.y		yacc source code
X
X		makefile.dos		miscellaneous files
X		makefile.unx
X		hexcalc.man
X		hctest01.txt
X		hctest02.txt
X
X	Included are two simple test "programs" that when fed to hexcalc via
X	stdin exercise expression evaluation and commands. See the test
X	dependency in the Unix makefile.
X
X        I have included the yacc generated source and header files for those
X        who are developing in a non-Unix environment and don't have
X        immediate access to yacc(1). For the MS-DOS environment, I use the
X        version of yacc distributed with the MKS Toolkit. That was the
X        version used to generate the yacc output files.
X
X	The MS-DOS makefile requires the presence of the MKS Toolkit and
X	Turbo C to be useable. The mv, rm, and tcc command invocations can 
X	be modified as appropriate, but it still requires yacc to generate 
X	new ytab.h and ytab.c files. However, the use of make is not required 
X	to generate the executable. The tcc invocation line
X
X	tcc -ehexcalc.exe  ytab.c init.c symbol.c bltins.c yylex.c ulpow.c
X
X	should do it.
X
X        Needless to say, Unix is a trademark of AT&T, MKS Toolkit is a
X	trademark of Mortice Kern Systems, Turbo C is a trademark of
X	Borland International, and MS-DOS is a trademark of Microsoft.
X
X        Richard Hargrove, 25 June 1988
X	...!{ihnp4 | codas | cbosgd}!killer!richardh
X	--------------------------------------------
SHAR_EOF
chmod 0666 1st_read.me || echo "restore of 1st_read.me fails"
sed 's/^X//' << 'SHAR_EOF' > bltins.c &&
X
X/*	bltins.c	hexcalc built-in functions
X */
X
X#include "hexcalc.h"
X
X/******************************************************************************/
XBASE_TYPE dec(val)
XBASE_TYPE val;
X{
X	printf("\t%lu\n", val);
X	return val;
X}
X
X/******************************************************************************/
X
XBASE_TYPE oct(val)
XBASE_TYPE val;
X{
X	printf("\t%lo\n", val);
X	return val;
X}
X
X/******************************************************************************/
X
XBASE_TYPE hex(val)
XBASE_TYPE val;
X{
X	printf("\t%lx\n", val);
X	return val;
X}
SHAR_EOF
chmod 0666 bltins.c || echo "restore of bltins.c fails"
sed 's/^X//' << 'SHAR_EOF' > hctest01.txt &&
X# simple expression evaluation test
X
X## numeric literals (12345678  fedcba98)
X12345678
X0fedcba98
X
X## assignment: assigning values to a and b (no output)
Xa=0deaddead
Xb=2bad2bad
X
X## a (deaddead)
Xa
X## b (2bad2bad)
Xb
X
X## a << 3 (f56ef568)
Xa << 3
X## a >> 4 (deaddea); note unsigned shift 
Xa >> 4
X
X## a | b (ffadffad)
Xa | b
X
X## a ^ b (f500f500)
Xa ^ b
X
X## a & b (aad0aad)
Xa & b
X
X## reassigning values to a and b
Xa = 0dead
Xb = 2bad
X## a + b (10a5a)
Xa + b
X
X## a - b (b300)
Xa - b
X
X## b - a (ffff4d00)
Xb - a
X
X## a * b (25fd89e9)
Xa * b
X
X## a / b (5)
Xa / b
X
X## a % b (44c)
Xa % b
X
X## b ** 2 (77392e9)
Xb ** 2
X
X## a + b * 345 (8fab4e)
Xa + b * 345
X
X## (a + b) * 345 (366d842)
X(a + b) * 345
X
X## quitting
Xexit
SHAR_EOF
chmod 0666 hctest01.txt || echo "restore of hctest01.txt fails"
sed 's/^X//' << 'SHAR_EOF' > hctest02.txt &&
X# hexcalc test script - test the commands, built-in functions, and both
X# silent and echoing comments
X
Xhelp			## help
XHELP			## HELP
Xa=1000			# init a
Xb=8888			# init b
Xa+b			## hex default: a + b (9888)
XOCT(DEC(a+b))		## 39048 114210  9888
Xdec
Xa+b			## dec default: a + b (39048)
XOCT(HEX(a+b))		## 9888  114210  39048
Xoct
Xa+b			## oct default: a + b (114210)
XDEC(HEX(a+b))		## 9888  39048	114210
Xquit			## quitting
SHAR_EOF
chmod 0666 hctest02.txt || echo "restore of hctest02.txt fails"
sed 's/^X//' << 'SHAR_EOF' > hexcalc.h &&
X
X/*	hexcalc.h	include file supporting the calculator utility hexcalc
X */
X
X#ifdef DEBUG
X#define STATIC
X#else
X#define STATIC static
X#endif
X
Xtypedef unsigned long BASE_TYPE;
X
XBASE_TYPE dec(), oct(), hex();
XBASE_TYPE ulpow();
X
Xtypedef struct Symbol		/* symbol table entry */
X{
X	char *name;
X	short type;		/* VAR, BLTIN, UNDEF */
X	union
X	{
X		BASE_TYPE val;	/* if VAR */
X		BASE_TYPE (*ptr)();	/* if BLTIN */
X	} u;
X	struct Symbol *next;	/* to link to another */
X} Symbol;
X
XSymbol *install(), *lookup();
SHAR_EOF
chmod 0666 hexcalc.h || echo "restore of hexcalc.h fails"
sed 's/^X//' << 'SHAR_EOF' > hexcalc.man &&
X
X
X
X    HEXCALC(1)                                                    HEXCALC(1)
X
X
X
X    NAME
X        hexcalc - interactive hexadecimal calculator
X
X    SYNOPSIS
X        hexcalc
X
X    DESCRIPTION
X        Hexcalc reads standard input for a sequence of expressions and
X        commands. Expressions are evaluated and the result is output in
X        the default radix on standard output. Commands are executed,
X        producing their defined action.
X
X        Expressions are made up of the following operands and operators:
X
X        Operands:       Numeric literals; in the default radix, must begin
X                        with a digit (for example, 0cc01e).
X
X                        Variables; initialized with an assignment operation,
X                        31 significant chars max.
X
X                        Built-in functions:
X                        name            description
X                        ---------       -----------
X                        DEC(expr)       output decimal value of expr
X                        OCT(expr)       output octal value of expr
X                        HEX(expr)       output hex value of expr
X
X        Operators (highest to lowest precedence):
X                        operator        description
X                        --------        -----------
X                        (  )            grouping
X                        **              exponentiation
X                        -  ~            unary minus, bitwise not
X                        *  /  %         multiplication, division, modulus
X                        +  -            addition, subtraction
X                        <<  >>          left-shift, right-shift
X                        &               bitwise and
X                        ^               bitwise exclusive-or
X                        |               bitwise or
X                        =               assignment
X
X        The following commands are supported:
X                        name            description
X                        ----------      -----------
X                        help  HELP      print a help message
X                        quit  exit      terminate execution
X                        hex dec oct     set the default radix
X
X        If assignment is the last operation performed when evaluating an
X        expression, nothing is output.
X
X
X
X
X
X                                     [ 1 ]
X
X
X    HEXCALC(1)                                                    HEXCALC(1)
X
X
X
X        Hexcalc also recognizes and ignores comments. Comments begin with
X        either a '#' character or a '##' character pair and are terminated
X        by a newline. Comments beginning with a single '#' are called non-
X        echoing and are completely ignored. Comments beginning with a '##'
X        pair are called echoing comments and are output to stdout, beginning
X        with the second '#', without modification. While comments make
X        little sense when using hexcalc interactively, they can be used in
X        files that are fed to stdin to good effect.
X
X        The _rationale_ behind the current built-in functions is to allow
X        the capture of intermediate results in the output stream as well as
X        modifying the default radix for the results of expression
X        evaluation. Note that they are functions which return the input
X        value as a result so they can be used as operands in more complex
X        expressions.
X
X        The initial default radix is hexadecimal.
X
X    NOTES
X        Hexcalc is based on hoc3, a calculator program that can be found in
X        _The Unix Programming Environment_ by Brian W. Kernighan and Rob
X        Pike, chapter 8. The entire chapter is an exposition of a method of
X        organizing a software development project which develops six
X        different, and successively more complex, versions of hoc, a
X        calculator program. It also serves as an excellent introduction to
X        and tutorial for yacc(1).
X
X    AUTHOR
X        Richard Hargrove
X        25 June 1988
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X                                     [ 2 ]
SHAR_EOF
chmod 0666 hexcalc.man || echo "restore of hexcalc.man fails"
sed 's/^X//' << 'SHAR_EOF' > hexcalc.y &&
X%{
X#include "hexcalc.h"
X%}
X
X%union			/* stack type */
X{
X  BASE_TYPE val;	/* actual value */
X  Symbol *sym;		/* symbol table pointer */
X}
X
X%token	<val>	NUMBER
X%token	<sym>	CONST VAR BLTIN UNDEF QUIT HELP CHRADIX
X%type	<val>	expr asgn
X%right	'='
X%left	'|'
X%left	'^'
X%left	'&'
X%left	LSH RSH
X%left	'+' '-'
X%left	'*' '/' '%'
X%left	UNARYMINUS '~'
X%right	POW		/* exponentiation */
X
X%%
Xlist:		  /* nothing */
X		| list '\n'
X		| list asgn '\n'
X		| list expr '\n'	{ 
X					  if (radix == 16)
X						printf ("\t%lx\n", $2);
X					  else if (radix == 10)
X						printf ("\t%lu\n", $2);
X					  else
X						printf ("\t%lo\n", $2);
X					}
X		| list HELP '\n'        { puthelp(); }
X		| list QUIT '\n'        { longjmp (prog_end, 1); }
X		| list CHRADIX '\n'	{
X					  if (*($2->name) == 'h')
X						radix = 16; 
X					  else if (*($2->name) == 'd')
X						radix = 10; 
X					  else
X						radix = 8; 
X					}
X		| list error '\n'	{ yyerrok; }
X		;
Xasgn:		  VAR '=' expr		{ $$ = $1->u.val = $3; $1->type = VAR; }
X		;
Xexpr:		  NUMBER		{ $$ = $1; }
X		| CONST			{ $$ = $1->u.val; }
X		| VAR			{ 
X			if ($1->type == UNDEF)
X				execerror ("undefined variable", $1->name);
X			$$ = $1->u.val; }
X		| asgn
X		| BLTIN '(' expr ')'	{ $$ = (*($1->u.ptr))($3); }
X		| expr LSH expr 	{ $$ = $1 << $3; }
X		| expr RSH expr 	{ $$ = $1 >> $3; }
X		| expr '|' expr         { $$ = $1 | $3; }
X		| expr '^' expr         { $$ = $1 ^ $3; }
X		| expr '&' expr         { $$ = $1 & $3; }
X		| expr '+' expr		{ $$ = $1 + $3; }
X		| expr '-' expr		{ $$ = $1 - $3; }
X		| expr '*' expr		{ $$ = $1 * $3; }
X		| expr '/' expr		{	
X			if ($3 == 0)
X				execerror ("division by zero", (char *)0);
X			$$ = $1 / $3; }
X		| expr '%' expr		{	
X			if ($3 == 0)
X				execerror ("modulo zero", (char *)0);
X			$$ = $1 % $3; }
X		| expr POW expr 	{ $$ = ulpow ($1, $3); }
X		| '(' expr ')'		{ $$ = $2; }
X		| '-' expr %prec UNARYMINUS { $$ = -$2; }
X		| '~' expr              { $$ = ~ $2; }
X		;
X%%
X
X#include <stdio.h>
X#include <setjmp.h>
X
Xchar *progname;		/* for error messages */
Xint lineno = 1;
Xint radix = 16;
X
XSTATIC char *credit =
X"hexcalc 1.1 by Richard Hargrove, 25 June 1988; based on hoc3 from Kernighan and Pike";
X
Xjmp_buf prog_begin, prog_end;
X
X/******************************************************************************/
X
Xvoid puthelp()
X{
X	static char *help_text[] = {
X	"Type in an expression or command. Expressions other than assignment",
X	"cause the evaluated result to be output. All values are 32-bit integers.",
X	"Expressions are made up of the following operands and operators:",
X	"",
X	"Operands: numeric literals (must begin with a digit), variables",
X	"(31 chars max, initialized with assignment), and built-in functions.",
X	"Built-ins:	DEC(expr)	output decimal value of expr",
X	"		OCT(expr)	output octal value of expr",
X	"		HEX(expr)	output hex value of expr",
X	"Operators:	(  )		grouping",
X	"		**		exponentiation",
X	"		-  ~		unary minus, bitwise not",
X	"		*  /  %		multiplication, division, modulus",
X	"		+  -		addition, subtraction",
X	"		<<  >>		left-shift, right-shift",
X	"		&		bitwise and",
X	"		^		bitwise exclusive-or",
X	"		|		bitwise or",
X	"		=		assignment",
X	"",
X	"Commands:	help  HELP	print this message",
X	"		quit  exit	terminate execution",
X	"		hex dec oct	set the default radix",
X	(char *)0
X	};
X	int i = 0;
X
X	while (help_text[i] != (char *)0)
X	{
X	  puts(help_text[i++]);
X	}
X}
X
X/******************************************************************************/
X
Xvoid warning (s, t)	/* print warning message */
Xchar *s, *t;
X{
X	fprintf (stderr, "%s : %s", progname, s);
X	if (t != (char *)0)
X	{
X		fprintf (stderr, " %s", t);
X	}
X	fprintf (stderr, " near line %d\n", lineno);
X}
X
X
X/******************************************************************************/
X
Xvoid yyerror (s)	/* called for yacc syntax error */
Xchar *s;
X{
X	warning (s, (char *)0);
X}
X
X/******************************************************************************/
X
Xvoid execerror (s, t)
Xchar *s, *t;
X{
X	warning (s, t);
X	longjmp (prog_begin, 1);
X}
X
X/******************************************************************************/
X
Xmain (argc, argv)
Xint argc;
Xchar *argv [];
X{
X	progname = argv [0];
X	init ();
X	if (setjmp (prog_end) == 0)
X	{
X		(void)setjmp (prog_begin);
X		yyparse ();
X	}
X	return 0;
X}
SHAR_EOF
chmod 0666 hexcalc.y || echo "restore of hexcalc.y fails"
sed 's/^X//' << 'SHAR_EOF' > init.c &&
X
X/*	init.c		hexcalc initilization code
X */
X
X#include "hexcalc.h"
X#ifdef __TURBOC__
X#include "ytab.h"
X#else
X#include "y.tab.h"
X#endif
X
XSTATIC struct		/* constants */
X{
X	char *name;
X	BASE_TYPE cval;
X} consts[] = 
X	{
X		(char *)0,		(BASE_TYPE)0
X	};
X
XSTATIC struct		/* built-ins */
X{
X	char *name;
X	BASE_TYPE (*func)();
X} builtins[] = 
X	{
X		"DEC",		dec,
X		"OCT",		oct,
X		"HEX",		hex,
X		(char *)0,	(BASE_TYPE(*)())0
X	};
X
XSTATIC struct 		/* keywords */
X{
X	char *name;
X	short token;
X} keywords[] =
X	{
X		"oct",		CHRADIX,
X		"HELP",		HELP,
X		"exit",         QUIT,
X		"help",		HELP,
X		"quit",         QUIT,
X		"dec",		CHRADIX,
X		"hex",		CHRADIX,
X		(char *)0,	0
X	};
X
X/******************************************************************************/
X
Xinit()		/* install keywords, constants, and built-ins in table */
X{
X	int i;
X	Symbol *s;
X
X	for (i=0; keywords [i].name != (char *)0; ++i)
X	{
X		install (keywords [i].name, keywords [i].token, (BASE_TYPE)0);
X	}
X	for (i=0; consts [i].name != (char *)0; ++i)
X	{
X		install (consts [i].name, CONST, consts [i].cval);
X	}
X	for (i=0; builtins [i].name != (char *)0; ++i)
X	{
X		s = install (builtins [i].name, BLTIN, (BASE_TYPE)0);
X		s->u.ptr = builtins [i].func;
X	}
X}
SHAR_EOF
chmod 0666 init.c || echo "restore of init.c fails"
sed 's/^X//' << 'SHAR_EOF' > makefile.dos &&
X
X# makefile for hexcalc - works with MKS Toolkit yacc, Turbo C, and Turbo Make.
X# Will work with other Unix make-like MAKEs (such as NDMAKE).
X
X# macros
X
XOBJS=hexcalc.obj init.obj bltins.obj ulpow.obj symbol.obj yylex.obj
XYACC=yacc
XYFLAGS=-d
XCC=tcc
XCFLAGS=
X
X# implicit rules (Turbo Make doesn't have ANY predefined implicit rules)
X
X.c.obj :
X	$(CC) -c $<
X
X# MKS yacc generates inline assembler for small model Turbo C !
X
X.y.obj :
X	$(YACC) $(YFLAGS) $<
X	$(CC) $(CFLAGS) -B -c ytab.c
X	mv ytab.obj $&.obj
X
X# dependencies
X
Xhexcalc.exe : $(OBJS)
X	$(CC) $(CFLAGS) -ehexcalc.exe $(OBJS)
X
Xinit.obj : hexcalc.h ytab.h
X
Xyylex.obj : hexcalc.h ytab.h
X
Xytab.h : hexcalc.y
X
Xsymbol.obj : hexcalc.h
X
Xbltins.obj : hexcalc.h
X
Xulpow.obj : hexcalc.h
X
Xhexcalc.obj : hexcalc.h
X
Xclean :
X	rm -f $(OBJS) *.map ytab.[ch]
SHAR_EOF
chmod 0666 makefile.dos || echo "restore of makefile.dos fails"
sed 's/^X//' << 'SHAR_EOF' > makefile.unx &&
X
X# Unix makefile for hexcalc
X
X# macros
X
XOBJS=hexcalc.o init.o bltins.o ulpow.o symbol.o yylex.o
XCFLAGS=-O
XYFLAGS=-d
X
X# browser utility used to verify test results
X# more(1) or pg(1) are alternatives
XBROWSER=less
X
X# implicit rules
X
X.y.o:				# modify default to keep y.tab.c lying around
X	$(YACC) $(YFLAGS) $<
X	$(CC) $(CFLAGS) -c y.tab.c
X	mv y.tab.o $@
X
X# dependencies
X
Xhexcalc : $(OBJS)
X	$(CC) $(CFLAGS) -o hexcalc $(OBJS)
X
Xinit.o : hexcalc.h y.tab.h
X
Xyylex.o : hexcalc.h y.tab.h
X
Xy.tab.h : hexcalc.y
X
Xsymbol.o : hexcalc.h
X
Xbltins.o : hexcalc.h
X
Xulpow.o : hexcalc.h
X
Xhexcalc.o : hexcalc.h
X
Xtest :
X	hexcalc <hctest01.txt | $(BROWSER)
X	hexcalc <hctest02.txt | $(BROWSER)
X
Xlint :
X	lint y.tab.c init.c bltins.c ulpow.c symbol.c yylex.c
X
Xclean :
X	rm -f $(OBJS) y.tab.[ch]
SHAR_EOF
chmod 0666 makefile.unx || echo "restore of makefile.unx fails"
sed 's/^X//' << 'SHAR_EOF' > symbol.c &&
X
X/*	symbol.c	hexcalc symbol table management routines
X */
X
X#include <string.h>
X#include "hexcalc.h"
X
X/* head ptr for the symbol table linked list */
XSTATIC Symbol *symlist = (Symbol *)0;
X
X/******************************************************************************/
X
XSymbol *lookup (s)
Xchar *s;
X{
X	Symbol *sp;
X
X	for (sp = symlist; sp != (Symbol *)0; sp = sp->next)
X	{
X		if (strcmp (sp->name, s) == 0) return sp;
X	}
X	return (Symbol *)0;
X}
X
X/******************************************************************************/
X
Xchar *emalloc (n)
Xunsigned n;
X{
X	void *p, *malloc();
X
X	if ((p = malloc (n)) == (void *)0)
X	{
X		execerror ("out of memory", (char *)0);
X	}
X	return (char *)p;
X}
X
X/******************************************************************************/
X
XSymbol *install (s, t, l)	/* install s in symbol table */
Xchar *s;
Xint t;
XBASE_TYPE l;
X{
X	Symbol *sp = (Symbol *)emalloc (sizeof(Symbol));
X
X	sp->name = (char *)emalloc (strlen (s) + 1);	/* + 1 for '\0' */
X	strcpy (sp->name, s);
X	sp->type = t;
X	sp->u.val = l;
X	sp->next = symlist;
X	symlist = sp;
X	return sp;
X}
SHAR_EOF
chmod 0666 symbol.c || echo "restore of symbol.c fails"
sed 's/^X//' << 'SHAR_EOF' > ulpow.c &&
X
X/*	ulpow -- BASE_TYPE exponentiation (no overflow detection)
X *
X *	Based on lpow() code distributed by Doug Gwyn
X */
X
X#include "hexcalc.h"			/* contains BASE_TYPE typedef */
X
XBASE_TYPE ulpow(base, exponent)		/* returns base^exponent */
XBASE_TYPE base;
XBASE_TYPE exponent;
X{
X	BASE_TYPE result;		/* result accumulator */
X
X	/* handle simple special cases separately: */
X	if (exponent == 0)
X	{
X		return 1;		/* includes 0^0 */
X	}
X	else if (base == 0)
X	{
X		return 0;		/* exp. < 0 should be EDOM */
X	}
X	else if (base == 1)
X	{
X		return 1;
X	}
X	else if (base == -1)
X	{
X#if 0	/* intended code: */
X		return exponent % 2 == 0 ? 1 : -1;
X#else	/* faster equivalent (suggested by Dan Levy of Teletype): */
X		return (exponent & 1) == 0 ? 1 : -1;
X#endif
X	}
X	else if (exponent < 0)
X	{
X		return 0;
X	}
X
X	/* general case with exponent > 0: */
X	result = 1;
X	for ( ; ; )	/* LOOP INVARIANT: result*base^exponent */
X	{
X#if 0	/* intended code: */
X		if (exponent % 2 != 0)
X#else	/* faster equivalent (suggested by Dan Levy of Teletype): */
X		if ((exponent & 1) != 0)
X#endif
X		{
X			result *= base;
X		}
X#if 0	/* intended code: */
X		if ((exponent /= 2) == 0)
X#else	/* faster equivalent (suggested by Dan Levy of Teletype): */
X		if ((exponent >>= 1) == 0)
X#endif
X		{
X			break;		/* result now stable */
X		}
X		base *= base;
X	}
X
X	return result;
X}
SHAR_EOF
chmod 0666 ulpow.c || echo "restore of ulpow.c fails"
sed 's/^X//' << 'SHAR_EOF' > ytab.c &&
X/* C:/BIN\YACC.EXE -d hexcalc.y */
X#line 1 "hexcalc.y"
X
X#include "hexcalc.h"
Xtypedef union {
X  BASE_TYPE val;	/* actual value */
X  Symbol *sym;		/* symbol table pointer */
X} YYSTYPE;
X#define NUMBER	257
X#define CONST	258
X#define VAR	259
X#define BLTIN	260
X#define UNDEF	261
X#define QUIT	262
X#define HELP	263
X#define CHRADIX	264
X#define LSH	265
X#define RSH	266
X#define UNARYMINUS	267
X#define POW	268
Xextern int yychar, yyerrflag;
Xextern YYSTYPE yyval, yylval;
X#line 81
X#include <stdio.h>
X#include <setjmp.h>
X
Xchar *progname;		/* for error messages */
Xint lineno = 1;
Xint radix = 16;
X
XSTATIC char *credit =
X"hexcalc 1.1 by Richard Hargrove, 25 June 1988; based on hoc3 from Kernighan and Pike";
X
Xjmp_buf prog_begin, prog_end;
X
X/******************************************************************************/
X
Xvoid puthelp()
X{
X	static char *help_text[] = {
X	"Type in an expression or command. Expressions other than assignment",
X	"cause the evaluated result to be output. All values are 32-bit integers.",
X	"Expressions are made up of the following operands and operators:",
X	"",
X	"Operands: numeric literals (must begin with a digit), variables",
X	"(31 chars max, initialized with assignment), and built-in functions.",
X	"Built-ins:	DEC(expr)	output decimal value of expr",
X	"		OCT(expr)	output octal value of expr",
X	"		HEX(expr)	output hex value of expr",
X	"Operators:	(  )		grouping",
X	"		**		exponentiation",
X	"		-  ~		unary minus, bitwise not",
X	"		*  /  %		multiplication, division, modulus",
X	"		+  -		addition, subtraction",
X	"		<<  >>		left-shift, right-shift",
X	"		&		bitwise and",
X	"		^		bitwise exclusive-or",
X	"		|		bitwise or",
X	"		=		assignment",
X	"",
X	"Commands:	help  HELP	print this message",
X	"		quit  exit	terminate execution",
X	"		hex dec oct	set the default radix",
X	(char *)0
X	};
X	int i = 0;
X
X	while (help_text[i] != (char *)0)
X	{
X	  puts(help_text[i++]);
X	}
X}
X
X/******************************************************************************/
X
Xvoid warning (s, t)	/* print warning message */
Xchar *s, *t;
X{
X	fprintf (stderr, "%s : %s", progname, s);
X	if (t != (char *)0)
X	{
X		fprintf (stderr, " %s", t);
X	}
X	fprintf (stderr, " near line %d\n", lineno);
X}
X
X
X/******************************************************************************/
X
Xvoid yyerror (s)	/* called for yacc syntax error */
Xchar *s;
X{
X	warning (s, (char *)0);
X}
X
X/******************************************************************************/
X
Xvoid execerror (s, t)
Xchar *s, *t;
X{
X	warning (s, t);
X	longjmp (prog_begin, 1);
X}
X
X/******************************************************************************/
X
Xmain (argc, argv)
Xint argc;
Xchar *argv [];
X{
X	progname = argv [0];
X	init ();
X	if (setjmp (prog_end) == 0)
X	{
X		(void)setjmp (prog_begin);
X		yyparse ();
X	}
X	return 0;
X}
Xstatic short yydef[] = {
X	  -1,    4,   30,   17,   16,    3,   15,   14,   13,   12, 
X	  11,   10,    9,    8,    7,    6,    5
X};
Xstatic short yyex[] = {
X	   0,    0,   -1,    1
X};
Xstatic short yyact[] = {
X	 -52,  -39,  -40,  -41,  -37,  -45,  -44,   -2,  -38,  -35, 
X	 -34,  -36,  264,  263,  262,  260,  259,  258,  257,  256, 
X	 126,   45,   40,   10,  -39,  -40,  -41,  -45,  -44,   -2, 
X	 -38,  260,  259,  258,  257,  126,   45,   40,  -31,   40, 
X	 -30,   61,  -46,   10,  -47,   10,  -48,   10,  -49,   10, 
X	 -50,  -28,  -23,  -26,  -24,  -25,  -27,  -22,  -21,  -19, 
X	 -20,  -29,  268,  266,  265,  124,   94,   47,   45,   43, 
X	  42,   38,   37,   10,  -53,   10,  -29,  268,  -28,  -23, 
X	 -42,  -26,  -24,  -25,  -27,  -22,  -21,  -19,  -20,  -29, 
X	 268,  266,  265,  124,   94,   47,   45,   43,   42,   41, 
X	  38,   37,  -28,  -23,  -43,  -26,  -24,  -25,  -27,  -22, 
X	 -21,  -19,  -20,  -29,  268,  266,  265,  124,   94,   47, 
X	  45,   43,   42,   41,   38,   37,  -28,  -23,  -26,  -24, 
X	 -25,  -27,  -22,  -21,  -19,  -20,  -29,  268,  266,  265, 
X	 124,   94,   47,   45,   43,   42,   38,   37,  -28,  -26, 
X	 -27,  -29,  268,   47,   42,   37,  -28,  -26,  -24,  -25, 
X	 -27,  -19,  -20,  -29,  268,  266,  265,   47,   45,   43, 
X	  42,   37,  -28,  -23,  -26,  -24,  -25,  -27,  -19,  -20, 
X	 -29,  268,  266,  265,   47,   45,   43,   42,   38,   37, 
X	 -28,  -23,  -26,  -24,  -25,  -27,  -22,  -19,  -20,  -29, 
X	 268,  266,  265,   94,   47,   45,   43,   42,   38,   37, 
X	 -28,  -26,  -24,  -25,  -27,  -29,  268,   47,   45,   43, 
X	  42,   37,   -1
X};
Xstatic short yypact[] = {
X	  12,   41,   75,   77,   77,  137,   77,   77,   77,   77, 
X	 152,  152,  164,  181,  200,  216,  216,  114,   31,   31, 
X	  31,   31,   31,   31,   31,   31,   31,   31,   31,   31, 
X	  31,   90,   62,   49,   47,   45,   43,   39,   31,   31,   31
X};
Xstatic short yygo[] = {
X	 -17,  -16,  -15,  -14,  -13,  -12,  -11,  -10,   -9,   -8, 
X	  -7,   -6,  -18,  -32,   -5,   -4,  -33,   40,   39,   38, 
X	  30,   29,   28,   27,   26,   25,   24,   23,   22,   21, 
X	  20,   19,   18,   -3,  -54,    0,   -1,   -1
X};
Xstatic short yypgo[] = {
X	   0,    0,    0,   34,   16,   16,   16,   16,   16,   16, 
X	  16,   16,   16,   16,   16,   16,   16,   16,   16,   16, 
X	  16,   16,   36,   36,   36,   36,   36,   36,   36,   36, 
X	  16,    0
X};
Xstatic short yyrlen[] = {
X	   0,    0,    0,    3,    1,    3,    3,    3,    3,    3, 
X	   3,    3,    3,    3,    3,    3,    2,    2,    3,    4, 
X	   1,    1,    3,    3,    3,    3,    3,    0,    2,    3, 
X	   1,    2
X};
X#define YYS0	50
X#define YYDELTA	23
X#define YYNPACT	41
X#define YYNDEF	17
X
X#define YYr29	0
X#define YYr30	1
X#define YYr31	2
X#define YYr9	3
X#define YYr12	4
X#define YYr15	5
X#define YYr16	6
X#define YYr17	7
X#define YYr18	8
X#define YYr19	9
X#define YYr20	10
X#define YYr21	11
X#define YYr22	12
X#define YYr23	13
X#define YYr24	14
X#define YYr25	15
X#define YYr27	16
X#define YYr28	17
X#define YYr26	18
X#define YYr14	19
X#define YYr11	20
X#define YYr10	21
X#define YYr8	22
X#define YYr7	23
X#define YYr6	24
X#define YYr5	25
X#define YYr4	26
X#define YYrACCEPT	YYr29
X#define YYrERROR	YYr30
X#define YYrLR2	YYr31
X#line 2 "yacc parser: c:/etc/yyparse.c"
X
X/*
X * Automaton to interpret LALR(1) tables.
X *
X *	Macros:
X *		yyclearin - clear the lookahead token.
X *		yyerrok - forgive a pending error
X *		YYERROR - simulate an error
X *		YYACCEPT - halt and return 0
X *		YYABORT - halt and return 1
X *		YYRETURN(value) - halt and return value.  You should use this
X *			instead of return(value).
X *		YYREAD - ensure yychar contains a lookahead token by reading
X *			one if it does not.  See also YYSYNC.
X *
X *	Preprocessor flags:
X *		YYDEBUG - includes debug code.  The parser will print
X *			 a travelogue of the parse if this is defined
X *			 and yydebug is non-zero.
X *		YYSSIZE - size of state and value stacks (default 150).
X *		YYSTATIC - By default, the state stack is an automatic array.
X *			If this is defined, the stack will be static.
X *			In either case, the value stack is static.
X *		YYALLOC - Dynamically allocate both the state and value stacks
X *			by calling malloc() and free().
X *		YYLR2 - defined if lookahead is needed to resolve R/R or S/R conflicts
X *		YYSYNC - if defined, yacc guarantees to fetch a lookahead token
X *			before any action, even if it doesnt need it for a decision.
X *			If YYSYNC is defined, YYREAD will never be necessary unless
X *			the user explicitly sets yychar = -1
X *
X *	Copyright (c) 1983, by the University of Waterloo
X */
X
X#ifndef YYSSIZE
X# define YYSSIZE	150
X#endif
X#ifndef	YYDEBUG
X#define	YYDEBUG	0
X#endif
X#define YYERROR		goto yyerrlabel
X#define yyerrok		yyerrflag = 0
X#define yyclearin	yychar = -1
X#define YYACCEPT	YYRETURN(0)
X#define YYABORT		YYRETURN(1)
X#ifdef YYALLOC
X# define YYRETURN(val)	{ retval = (val); goto yyReturn; }
X#else
X# define YYRETURN(val)	return(val)
X#endif
X#if YYDEBUG
X/* The if..else makes this macro behave exactly like a statement */
X# define YYREAD	if (yychar < 0) {					\
X			if ((yychar = yylex()) < 0)			\
X				yychar = 0;				\
X			if (yydebug)					\
X				printf("read %s (%d)\n", yyptok(yychar),\
X				yychar);				\
X		} else
X#else
X# define YYREAD	if (yychar < 0) {					\
X			if ((yychar = yylex()) < 0)			\
X				yychar = 0;				\
X		} else
X#endif
X#define YYERRCODE	256		/* value of `error' */
X#if __TURBOC__&&__SMALL__
X#define	YYQYYP	*(int *)((int)yyq + ((int)yyq-(int)yyp))
X#else
X#define	YYQYYP	yyq[yyq-yyp]
X#endif
X
XYYSTYPE	yyval,				/* $$ */
X	*yypvt,				/* $n */
X	yylval;				/* yylex() sets this */
X
Xint	yychar,				/* current token */
X	yyerrflag,			/* error flag */
X	yynerrs;			/* error count */
X
X#if YYDEBUG
Xint yydebug = YYDEBUG-0;		/* debug flag & tables */
Xextern char	*yysvar[], *yystoken[], *yyptok();
Xextern short	yyrmap[], yysmap[];
Xextern int	yynstate, yynvar, yyntoken, yynrule;
X# define yyassert(condition, msg, arg) \
X	if (!(condition)) { printf("\nyacc bug: "); printf(msg, arg); YYABORT; }
X#else /* !YYDEBUG */
X# define yyassert(condition, msg, arg)
X#endif
X
Xyyparse()
X{
X
X	register short		yyi, *yyp;	/* for table lookup */
X	register short		*yyps;		/* top of state stack */
X	register short		yystate;	/* current state */
X	register YYSTYPE	*yypv;		/* top of value stack */
X	register short		*yyq;
X	register int		yyj;
X
X#ifdef YYSTATIC
X	static short	yys[YYSSIZE + 1];
X	static YYSTYPE	yyv[YYSSIZE + 1];
X#else
X#ifdef YYALLOC
X	YYSTYPE *yyv;
X	short	*yys;
X	YYSTYPE save_yylval, save_yyval, *save_yypvt;
X	int save_yychar, save_yyerrflag, save_yynerrs;
X	int retval;
X#if 0	/* defined in <stdlib.h>*/
X	extern char	*malloc();
X#endif 0
X#else
X	short		yys[YYSSIZE + 1];
X	static YYSTYPE	yyv[YYSSIZE + 1];	/* historically static */
X#endif
X#endif
X
X#ifdef YYALLOC
X	yys = (short *) malloc((YYSSIZE + 1) * sizeof(short));
X	yyv = (YYSTYPE *) malloc((YYSSIZE + 1) * sizeof(YYSTYPE));
X	if (yys == (short *)0 || yyv == (YYSTYPE *)0) {
X		yyerror("Not enough space for parser stacks");
X		return 1;
X	}
X	save_yylval = yylval;
X	save_yyval = yyval;
X	save_yypvt = yypvt;
X	save_yychar = yychar;
X	save_yyerrflag = yyerrflag;
X	save_yynerrs = yynerrs;
X#endif
X
X	yynerrs = 0;
X	yyerrflag = 0;
X	yychar = -1;
X	yyps = yys;
X	yypv = yyv;
X	yystate = YYS0;		/* start state */
X
XyyStack:
X	yyassert((unsigned)yystate < yynstate, "state %d\n", yystate);
X	if (++yyps > &yys[YYSSIZE]) {
X		yyerror("Parser stack overflow");
X		YYABORT;
X	}
X	*yyps = yystate;	/* stack current state */
X	*++yypv = yyval;	/* ... and value */
X
X#if YYDEBUG
X	if (yydebug)
X		printf("state %d (%d), char %s (%d)\n", yysmap[yystate],
X			yystate, yyptok(yychar), yychar);
X#endif
X
X	/*
X	 *	Look up next action in action table.
X	 */
XyyEncore:
X#ifdef YYSYNC
X	YYREAD;
X#endif
X	if (yystate >= sizeof yypact/sizeof yypact[0]) 	/* simple state */
X		yyi = yystate - YYDELTA;	/* reduce in any case */
X	else {
X		if(*(yyp = &yyact[yypact[yystate]]) >= 0) {
X			/* Look for a shift on yychar */
X#ifndef YYSYNC
X			YYREAD;
X#endif
X			yyq = yyp;
X			yyi = yychar;
X#if __TURBOC__&&__SMALL__
X			/* yyi is in di, yyp is in si */
X		L01:
X			asm lodsw	/* ax = *yyp++; */
X			asm cmp yyi, ax
X			asm jl L01
X#else
X			while (yyi < *yyp++)
X				;
X#endif
X			if (yyi == yyp[-1]) {
X				yystate = ~YYQYYP;
X#if YYDEBUG
X				if (yydebug)
X					printf("shift %d (%d)\n", yysmap[yystate], yystate);
X#endif
X				yyval = yylval;		/* stack what yylex() set */
X				yychar = -1;		/* clear token */
X				if (yyerrflag)
X					yyerrflag--;	/* successful shift */
X				goto yyStack;
X			}
X		}
X
X		/*
X	 	 *	Fell through - take default action
X	 	 */
X
X		if (yystate >= sizeof yydef /sizeof yydef[0])
X			goto yyError;
X		if ((yyi = yydef[yystate]) < 0)	 { /* default == reduce? */
X											/* Search exception table */
X			yyassert((unsigned)~yyi < sizeof yyex/sizeof yyex[0],
X				"exception %d\n", yystate);
X			yyp = &yyex[~yyi];
X#ifndef YYSYNC
X			YYREAD;
X#endif
X			while((yyi = *yyp) >= 0 && yyi != yychar)
X				yyp += 2;
X			yyi = yyp[1];
X			yyassert(yyi >= 0,"Ex table not reduce %d\n", yyi);
X		}
X	}
X
X#ifdef YYLR2
XyyReduce:	/* reduce yyi */
X#endif
X	yyassert((unsigned)yyi < yynrule, "reduce %d\n", yyi);
X	yyj = yyrlen[yyi];
X#if YYDEBUG
X	if (yydebug) printf("reduce %d (%d), pops %d (%d)\n", yyrmap[yyi],
X		yyi, yysmap[yyps[-yyj]], yyps[-yyj]);
X#endif
X	yyps -= yyj;		/* pop stacks */
X	yypvt = yypv;		/* save top */
X	yypv -= yyj;
X	yyval = yypv[1];	/* default action $$ = $1 */
X	switch (yyi) {		/* perform semantic action */
X		
Xcase YYr4: {	/* list :  list expr '\n' */
X#line 28
X 
X					  if (radix == 16)
X						printf ("\t%lx\n", yypvt[-1].val);
X					  else if (radix == 10)
X						printf ("\t%lu\n", yypvt[-1].val);
X					  else
X						printf ("\t%lo\n", yypvt[-1].val);
X					
X} break;
X
Xcase YYr5: {	/* list :  list HELP '\n' */
X#line 36
X puthelp(); 
X} break;
X
Xcase YYr6: {	/* list :  list QUIT '\n' */
X#line 37
X longjmp (prog_end, 1); 
X} break;
X
Xcase YYr7: {	/* list :  list CHRADIX '\n' */
X#line 38
X
X					  if (*(yypvt[-1].sym->name) == 'h')
X						radix = 16; 
X					  else if (*(yypvt[-1].sym->name) == 'd')
X						radix = 10; 
X					  else
X						radix = 8; 
X					
X} break;
X
Xcase YYr8: {	/* list :  list error '\n' */
X#line 46
X yyerrok; 
X} break;
X
Xcase YYr9: {	/* asgn :  VAR '=' expr */
X#line 48
X yyval.val = yypvt[-2].sym->u.val = yypvt[0].val; yypvt[-2].sym->type = VAR; 
X} break;
X
Xcase YYr10: {	/* expr :  NUMBER */
X#line 50
X yyval.val = yypvt[0].val; 
X} break;
X
Xcase YYr11: {	/* expr :  CONST */
X#line 51
X yyval.val = yypvt[0].sym->u.val; 
X} break;
X
Xcase YYr12: {	/* expr :  VAR */
X#line 52
X 
X			if (yypvt[0].sym->type == UNDEF)
X				execerror ("undefined variable", yypvt[0].sym->name);
X			yyval.val = yypvt[0].sym->u.val; 
X} break;
X
Xcase YYr14: {	/* expr :  BLTIN '(' expr ')' */
X#line 57
X yyval.val = (*(yypvt[-3].sym->u.ptr))(yypvt[-1].val); 
X} break;
X
Xcase YYr15: {	/* expr :  expr LSH expr */
X#line 58
X yyval.val = yypvt[-2].val << yypvt[0].val; 
X} break;
X
Xcase YYr16: {	/* expr :  expr RSH expr */
X#line 59
X yyval.val = yypvt[-2].val >> yypvt[0].val; 
X} break;
X
Xcase YYr17: {	/* expr :  expr '|' expr */
X#line 60
X yyval.val = yypvt[-2].val | yypvt[0].val; 
X} break;
X
Xcase YYr18: {	/* expr :  expr '^' expr */
X#line 61
X yyval.val = yypvt[-2].val ^ yypvt[0].val; 
X} break;
X
Xcase YYr19: {	/* expr :  expr '&' expr */
X#line 62
X yyval.val = yypvt[-2].val & yypvt[0].val; 
X} break;
X
Xcase YYr20: {	/* expr :  expr '+' expr */
X#line 63
X yyval.val = yypvt[-2].val + yypvt[0].val; 
X} break;
X
Xcase YYr21: {	/* expr :  expr '-' expr */
X#line 64
X yyval.val = yypvt[-2].val - yypvt[0].val; 
X} break;
X
Xcase YYr22: {	/* expr :  expr '*' expr */
X#line 65
X yyval.val = yypvt[-2].val * yypvt[0].val; 
X} break;
X
Xcase YYr23: {	/* expr :  expr '/' expr */
X#line 66
X	
X			if (yypvt[0].val == 0)
X				execerror ("division by zero", (char *)0);
X			yyval.val = yypvt[-2].val / yypvt[0].val; 
X} break;
X
Xcase YYr24: {	/* expr :  expr '%' expr */
X#line 70
X	
X			if (yypvt[0].val == 0)
X				execerror ("modulo zero", (char *)0);
X			yyval.val = yypvt[-2].val % yypvt[0].val; 
X} break;
X
Xcase YYr25: {	/* expr :  expr POW expr */
X#line 74
X yyval.val = ulpow (yypvt[-2].val, yypvt[0].val); 
X} break;
X
Xcase YYr26: {	/* expr :  '(' expr ')' */
X#line 75
X yyval.val = yypvt[-1].val; 
X} break;
X
Xcase YYr27: {	/* expr :  '-' expr */
X#line 76
X yyval.val = -yypvt[0].val; 
X} break;
X
Xcase YYr28: {	/* expr :  '~' expr */
X#line 77
X yyval.val = ~ yypvt[0].val; 
X} break;
X#line 237 "yacc parser: c:/etc/yyparse.c"
X	case YYrACCEPT:
X		YYACCEPT;
X	case YYrERROR:
X		goto yyError;
X#ifdef YYLR2
X	case YYrLR2:
X#ifndef YYSYNC
X		YYREAD;
X#endif
X		yyj = 0;
X		while(yylr2[yyj] >= 0) {
X			if(yylr2[yyj] == yystate && yylr2[yyj+1] == yychar
X			&& yylook(yys+1,yyps,yystate,yychar,yy2lex(),yylr2[yyj+2]))
X					break;
X			yyj += 3;
X		}
X		if(yylr2[yyj] < 0)
X			goto yyError;
X		if(yylr2[yyj+2] < 0) {
X			yystate = ~ yylr2[yyj+2];
X			goto yyStack;
X		}
X		yyi = yylr2[yyj+2];
X		goto yyReduce;
X#endif
X	}
X
X	/*
X	 *	Look up next state in goto table.
X	 */
X
X	yyp = &yygo[yypgo[yyi]];
X	yyq = yyp++;
X	yyi = *yyps;
X#if	__TURBOC__ && __SMALL__
X	/* yyi is in di, yyp is in si */
XL02:
X	asm lodsw		/* ax = *yyp++; */
X	asm cmp yyi, ax
X	asm jl L02
X#else
X	while (yyi < *yyp++)
X		;
X#endif
X	yystate = ~(yyi == *--yyp? YYQYYP: *yyq);
X	goto yyStack;
X
Xyyerrlabel:	;		/* come here from YYERROR	*/
X/*
X#pragma used yyerrlabel
X */
X	yyerrflag = 1;
X	yyps--, yypv--;
X	
XyyError:
X	switch (yyerrflag) {
X
X	case 0:		/* new error */
X		yynerrs++;
X		yyi = yychar;
X		yyerror("Syntax error");
X		if (yyi != yychar) {
X			/* user has changed the current token */
X			/* try again */
X			yyerrflag++;	/* avoid loops */
X			goto yyEncore;
X		}
X
X	case 1:		/* partially recovered */
X	case 2:
X		yyerrflag = 3;	/* need 3 valid shifts to recover */
X			
X		/*
X		 *	Pop states, looking for a
X		 *	shift on `error'.
X		 */
X
X		for ( ; yyps > yys; yyps--, yypv--) {
X			if (*yyps >= sizeof yypact/sizeof yypact[0])
X				continue;
X			yyp = &yyact[yypact[*yyps]];
X			yyq = yyp;
X			do
X				;
X			while (YYERRCODE < *yyp++);
X			if (YYERRCODE == yyp[-1]) {
X				yystate = ~YYQYYP;
X				goto yyStack;
X			}
X				
X			/* no shift in this state */
X#if YYDEBUG
X			if (yydebug && yyps > yys+1)
X				printf("Error recovery pops state %d (%d), uncovers %d (%d)\n",
X					yysmap[yyps[0]], yyps[0],
X					yysmap[yyps[-1]], yyps[-1]);
X#endif
X			/* pop stacks; try again */
X		}
X		/* no shift on error - abort */
X		break;
X
X	case 3:
X		/*
X		 *	Erroneous token after
X		 *	an error - discard it.
X		 */
X
X		if (yychar == 0)  /* but not EOF */
X			break;
X#if YYDEBUG
X		if (yydebug)
X			printf("Error recovery discards %s (%d), ",
X				yyptok(yychar), yychar);
X#endif
X		yyclearin;
X		goto yyEncore;	/* try again in same state */
X	}
X	YYABORT;
X
X#ifdef YYALLOC
XyyReturn:
X	yylval = save_yylval;
X	yyval = save_yyval;
X	yypvt = save_yypvt;
X	yychar = save_yychar;
X	yyerrflag = save_yyerrflag;
X	yynerrs = save_yynerrs;
X	free((char *)yys);
X	free((char *)yyv);
X	return(retval);
X#endif
X}
X
X#ifdef YYLR2
Xyylook(s,rsp,state,c1,c2,i)
Xshort *s;		/* stack		*/
Xshort *rsp;		/* real top of stack	*/
Xint state;		/* current state	*/
Xint c1;			/* current char		*/
Xint c2;			/* next char		*/
Xint i;			/* action S < 0, R >= 0	*/
X{
X	int j;
X	short *p,*q;
X	short *sb,*st;
X#if YYDEBUG
X	if(yydebug) {
X		printf("LR2 state %d (%d) char %s (%d) lookahead %s (%d)",
X			yysmap[state],state,yyptok(c1),c1,yyptok(c2),c2);
X		if(i > 0)
X			printf("reduce %d (%d)\n", yyrmap[i], i);
X		else
X			printf("shift %d (%d)\n", yysmap[i], i);
X	}
X#endif
X	st = sb = rsp+1;
X	if(i >= 0)
X		goto reduce;
X  shift:
X	state = ~i;
X	c1 = c2;
X	if(c1 < 0)
X		return 1;
X	c2 = -1;
X
X  stack:
X  	if(++st >= &s[YYSSIZE]) {
X		yyerror("Parser Stack Overflow");
X		return 0;
X	}
X	*st = state;
X	if(state >= sizeof yypact/sizeof yypact[0])
X		i = state- YYDELTA;
X	else {
X		p = &yyact[yypact[state]];
X		q = p;
X		i = c1;
X		while(i < *p++)
X			;
X		if(i == p[-1]) {
X			state = ~q[q-p];
X			c1 = c2;
X			if(c1 < 0)
X				return 1;
X			c2 = -1;
X			goto stack;
X		}
X		if(state >= sizeof yydef/sizeof yydef[0])
X			return 0
X		if((i = yydef[state]) < 0) {
X			p = &yyex[~i];
X			while((i = *p) >= 0 && i != c1)
X				p += 2;
X			i = p[1];
X		}
X	}
X  reduce:
X  	j = yyrlen[i];
X	if(st-sb >= j)
X		st -= j;
X	else {
X		rsp -= j+st-sb;
X		st = sb;
X	}
X	switch(i) {
X	case YYrERROR:
X		return 0;
X	case YYrACCEPT:
X		return 1;
X	case YYrLR2:
X		j = 0;
X		while(yylr2[j] >= 0) {
X			if(yylr2[j] == state && yylr2[j+1] == c1)
X				if((i = yylr2[j+2]) < 0)
X					goto shift;
X				else
X					goto reduce;
X		}
X		return 0;
X	}
X	p = &yygo[yypgo[i]];
X	q = p++;
X	i = st==sb ? *rsp : *st;
X	while(i < *p++);
X	state = ~(i == *--p? q[q-p]: *q);
X	goto stack;
X}
X#endif
X		
X#if YYDEBUG
X	
X/*
X *	Print a token legibly.
X *	This won't work if you roll your own token numbers,
X *	but I've found it useful.
X */
Xchar *
Xyyptok(i)
X{
X	static char	buf[10];
X
X	if (i >= YYERRCODE)
X		return yystoken[i-YYERRCODE];
X	if (i < 0)
X		return "";
X	if (i == 0)
X		return "$end";
X	if (i < ' ')
X		sprintf(buf, "'^%c'", i+'@');
X	else
X		sprintf(buf, "'%c'", i);
X	return buf;
X}
X#endif
X#ifdef YYDEBUG
Xchar * yystoken[] = {
X	"error",
X	"NUMBER",
X	"CONST",
X	"VAR",
X	"BLTIN",
X	"UNDEF",
X	"QUIT",
X	"HELP",
X	"CHRADIX",
X	"LSH",
X	"RSH",
X	"UNARYMINUS",
X	"POW",
X	0
X};
Xchar * yysvar[] = {
X	"$accept",
X	"expr",
X	"asgn",
X	"list",
X	0
X};
Xshort yyrmap[] = {
X	  29,   30,   31,    9,   12,   15,   16,   17,   18,   19, 
X	  20,   21,   22,   23,   24,   25,   27,   28,   26,   14, 
X	  11,   10,    8,    7,    6,    5,    4,    1,    2,    3, 
X	  13,    0
X};
Xshort yysmap[] = {
X	   1,    8,   14,   16,   18,   41,   42,   43,   44,   45, 
X	  46,   47,   48,   49,   50,   51,   52,   40,   36,   35, 
X	  34,   33,   32,   31,   30,   29,   28,   27,   26,   21, 
X	  20,   19,   13,   12,   11,   10,    9,    5,    4,    3, 
X	   2,   39,   53,    6,    7,   22,   23,   24,   25,   37, 
X	   0,   15,   38,   17
X};
Xint yyntoken = 27, yynvar = 4, yynstate = 54, yynrule = 32;
X#endif
SHAR_EOF
chmod 0666 ytab.c || echo "restore of ytab.c fails"
sed 's/^X//' << 'SHAR_EOF' > ytab.h &&
Xtypedef union {
X  BASE_TYPE val;	/* actual value */
X  Symbol *sym;		/* symbol table pointer */
X} YYSTYPE;
X#define NUMBER	257
X#define CONST	258
X#define VAR	259
X#define BLTIN	260
X#define UNDEF	261
X#define QUIT	262
X#define HELP	263
X#define CHRADIX	264
X#define LSH	265
X#define RSH	266
X#define UNARYMINUS	267
X#define POW	268
Xextern YYSTYPE yyval, yylval;
SHAR_EOF
chmod 0666 ytab.h || echo "restore of ytab.h fails"
sed 's/^X//' << 'SHAR_EOF' > yylex.c &&
X
X/*	yylex.c		lexical scanner for the hexcalc utility
X */
X
X#include <stdio.h>
X#include <ctype.h>
X
X#include "hexcalc.h"
X#ifdef __TURBOC__
X#include "ytab.h"
X#else
X#include "y.tab.h"
X#endif
X
Xextern int lineno;
Xextern int radix;
X
X#define MAXCHARS 31	/* number of significant chars in an identifier */
X
X/******************************************************************************/
X
Xint yylex ()
X{
X	int c;
X
X	while ((c = getchar()) == ' ' || c == '\t') /* skip whitespace */;
X	if (c == EOF) return 0;
X
X	if (radix == 8)
X	{
X		if (c >= '0' && c <= '7')
X		{
X			ungetc (c, stdin);
X			scanf ("%lo", &yylval.val);
X			return NUMBER;
X		}
X	}
X	else if (isdigit(c))
X	{
X		ungetc (c, stdin);
X		scanf (radix == 16 ? "%lx" : "%lu", &yylval.val);
X		return NUMBER;
X	}
X	if (isalpha(c))
X	{
X		Symbol *s;
X		char sbuf [MAXCHARS+1], *p = sbuf;
X
X		do 
X		{
X			if (p < sbuf+MAXCHARS) *p++ = c;
X		} 
X		while ((c = getchar()) != EOF && isalnum(c));
X		ungetc (c, stdin);
X		*p = '\0';
X		if ((s = lookup (sbuf)) == (Symbol *)0)
X		{
X			s = install (sbuf, UNDEF, (BASE_TYPE)0);
X		}
X		yylval.sym = s;
X		return s->type == UNDEF ? VAR : s->type;
X	}
X	/* handle multi-char operator tokens */
X	if ((c == '<') || (c == '>'))
X	{
X		int c2 = getchar();
X
X		if ((c == '<') && (c2 == '<'))
X		{
X			return LSH;
X		}
X		else if ((c == '>') && (c2 == '>'))
X		{
X			return RSH;
X		}
X		else
X		{
X			ungetc(c2, stdin);
X		}
X	}
X	if (c == '*')
X	{
X		int c2 = getchar();
X
X		if (c2 == '*')
X		{
X			return POW;
X		}
X		else
X		{
X			ungetc(c2, stdin);
X		}
X	}
X	if (c == '#')		/* handle comments */
X	{
X		int echo = (c = getchar()) == '#';
X
X		if (echo != 0) putchar('\t');
X		while (c != '\n')
X		{
X			if (echo != 0) putchar(c);
X			c = getchar();
X		}
X		if (echo != 0) putchar(c);
X	}
X	if (c == '\n') ++lineno;
X
X	return c;
X}
SHAR_EOF
chmod 0666 yylex.c || echo "restore of yylex.c fails"
exit 0
-------- cut here -------- cut here -------- cut here -------- cut here --------

richard hargrove
...!{ihnp4 | codas | cbosgd}!killer!richardh
--------------------------------------------