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 --------------------------------------------