%{ #include "hexcalc.h" %} %union /* stack type */ { BASE_TYPE val; /* actual value */ Symbol *sym; /* symbol table pointer */ } %token NUMBER %token CONST VAR BLTIN UNDEF QUIT HELP CHRADIX %type expr asgn %right '=' %left '|' %left '^' %left '&' %left LSH RSH %left '+' '-' %left '*' '/' '%' %left UNARYMINUS '~' %right POW /* exponentiation */ %% list: /* nothing */ | list '\n' | list asgn '\n' | list expr '\n' { if (radix == 16) printf ("\t%lx\n", $2); else if (radix == 10) printf ("\t%lu\n", $2); else printf ("\t%lo\n", $2); } | list HELP '\n' { puthelp(); } | list QUIT '\n' { longjmp (prog_end, 1); } | list CHRADIX '\n' { if (*($2->name) == 'h') radix = 16; else if (*($2->name) == 'd') radix = 10; else radix = 8; } | list error '\n' { yyerrok; } ; asgn: VAR '=' expr { $$ = $1->u.val = $3; $1->type = VAR; } ; expr: NUMBER { $$ = $1; } | CONST { $$ = $1->u.val; } | VAR { if ($1->type == UNDEF) execerror ("undefined variable", $1->name); $$ = $1->u.val; } | asgn | BLTIN '(' expr ')' { $$ = (*($1->u.ptr))($3); } | expr LSH expr { $$ = $1 << $3; } | expr RSH expr { $$ = $1 >> $3; } | expr '|' expr { $$ = $1 | $3; } | expr '^' expr { $$ = $1 ^ $3; } | expr '&' expr { $$ = $1 & $3; } | expr '+' expr { $$ = $1 + $3; } | expr '-' expr { $$ = $1 - $3; } | expr '*' expr { $$ = $1 * $3; } | expr '/' expr { if ($3 == 0) execerror ("division by zero", (char *)0); $$ = $1 / $3; } | expr '%' expr { if ($3 == 0) execerror ("modulo zero", (char *)0); $$ = $1 % $3; } | expr POW expr { $$ = ulpow ($1, $3); } | '(' expr ')' { $$ = $2; } | '-' expr %prec UNARYMINUS { $$ = -$2; } | '~' expr { $$ = ~ $2; } ; %% #include #include char *progname; /* for error messages */ int lineno = 1; int radix = 16; STATIC char *credit = "hexcalc 1.1 by Richard Hargrove, 25 June 1988; based on hoc3 from Kernighan and Pike"; jmp_buf prog_begin, prog_end; /******************************************************************************/ void puthelp() { static char *help_text[] = { "Type in an expression or command. Expressions other than assignment", "cause the evaluated result to be output. All values are 32-bit integers.", "Expressions are made up of the following operands and operators:", "", "Operands: numeric literals (must begin with a digit), variables", "(31 chars max, initialized with assignment), and built-in functions.", "Built-ins: DEC(expr) output decimal value of expr", " OCT(expr) output octal value of expr", " HEX(expr) output hex value of expr", "Operators: ( ) grouping", " ** exponentiation", " - ~ unary minus, bitwise not", " * / % multiplication, division, modulus", " + - addition, subtraction", " << >> left-shift, right-shift", " & bitwise and", " ^ bitwise exclusive-or", " | bitwise or", " = assignment", "", "Commands: help HELP print this message", " quit exit terminate execution", " hex dec oct set the default radix", (char *)0 }; int i = 0; while (help_text[i] != (char *)0) { puts(help_text[i++]); } } /******************************************************************************/ void warning (s, t) /* print warning message */ char *s, *t; { fprintf (stderr, "%s : %s", progname, s); if (t != (char *)0) { fprintf (stderr, " %s", t); } fprintf (stderr, " near line %d\n", lineno); } /******************************************************************************/ void yyerror (s) /* called for yacc syntax error */ char *s; { warning (s, (char *)0); } /******************************************************************************/ void execerror (s, t) char *s, *t; { warning (s, t); longjmp (prog_begin, 1); } /******************************************************************************/ main (argc, argv) int argc; char *argv []; { progname = argv [0]; init (); if (setjmp (prog_end) == 0) { (void)setjmp (prog_begin); yyparse (); } return 0; }