home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume3
/
hexcalc1.1
< prev
next >
Wrap
Internet Message Format
|
1989-02-03
|
45KB
Path: xanth!mcnc!uvaarpa!umd5!ames!necntc!ncoast!allbery
From: richardh@killer.UUCP (Richard Hargrove)
Newsgroups: comp.sources.misc
Subject: v03i063: hexcalc 1.1
Keywords: hex calculator utility
Message-ID: <4622@killer.UUCP>
Date: 28 Jun 88 01:35:22 GMT
Sender: allbery@ncoast.UUCP
Reply-To: richardh@killer.UUCP (Richard Hargrove)
Organization: The Unix(R) Connection, Dallas, Texas
Lines: 1875
Approved: allbery@ncoast.UUCP
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
--------------------------------------------