diff options
| author | svn2git <svn2git@FreeBSD.org> | 1993-11-01 08:00:00 +0000 |
|---|---|---|
| committer | svn2git <svn2git@FreeBSD.org> | 1993-11-01 08:00:00 +0000 |
| commit | 8503f4f13f77abf7adc8f7e329c6f9c1d52b6a20 (patch) | |
| tree | c5b2ce776438e0a52b492a2ab6ab41360b8ba1f6 /bin/expr/expr.y | |
Release FreeBSD 1.0upstream/1.0.0_cvsrelease/1.0.0_cvs
This commit was manufactured to restore the state of the 1.0-RELEASE image.
Releases prior to 5.3-RELEASE are omitting the secure/ and crypto/ subdirs.
Diffstat (limited to 'bin/expr/expr.y')
| -rw-r--r-- | bin/expr/expr.y | 533 |
1 files changed, 533 insertions, 0 deletions
diff --git a/bin/expr/expr.y b/bin/expr/expr.y new file mode 100644 index 000000000000..57ad5022e496 --- /dev/null +++ b/bin/expr/expr.y @@ -0,0 +1,533 @@ +%{ +/* Written by Pace Willisson (pace@blitz.com) + * and placed in the public domain. + * + * Largely rewritten by J.T. Conklin (jtc@wimsey.com) + * + * $Id : /b/source/CVS/src/bin/expr/expr.y,v 1.11 1993/08/17 16:01:23 jtc Exp $ + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <locale.h> +#include <ctype.h> +#include <err.h> + +enum valtype { + integer, string +} ; + +struct val { + enum valtype type; + union { + char *s; + int i; + } u; +} ; + +struct val *result; +struct val *op_or (); +struct val *op_and (); +struct val *op_eq (); +struct val *op_gt (); +struct val *op_lt (); +struct val *op_ge (); +struct val *op_le (); +struct val *op_ne (); +struct val *op_plus (); +struct val *op_minus (); +struct val *op_times (); +struct val *op_div (); +struct val *op_rem (); +struct val *op_colon (); + +char **av; +%} + +%union +{ + struct val *val; +} + +%left <val> '|' +%left <val> '&' +%left <val> '=' '>' '<' GE LE NE +%left <val> '+' '-' +%left <val> '*' '/' '%' +%left <val> ':' +%left UNARY + +%token <val> TOKEN +%type <val> start expr + +%% + +start: expr { result = $$; } + +expr: TOKEN + | '(' expr ')' { $$ = $2; } + | expr '|' expr { $$ = op_or ($1, $3); } + | expr '&' expr { $$ = op_and ($1, $3); } + | expr '=' expr { $$ = op_eq ($1, $3); } + | expr '>' expr { $$ = op_gt ($1, $3); } + | expr '<' expr { $$ = op_lt ($1, $3); } + | expr GE expr { $$ = op_ge ($1, $3); } + | expr LE expr { $$ = op_le ($1, $3); } + | expr NE expr { $$ = op_ne ($1, $3); } + | expr '+' expr { $$ = op_plus ($1, $3); } + | expr '-' expr { $$ = op_minus ($1, $3); } + | expr '*' expr { $$ = op_times ($1, $3); } + | expr '/' expr { $$ = op_div ($1, $3); } + | expr '%' expr { $$ = op_rem ($1, $3); } + | expr ':' expr { $$ = op_colon ($1, $3); } + ; + + +%% + +struct val * +make_integer (i) +int i; +{ + struct val *vp; + + vp = (struct val *) malloc (sizeof (*vp)); + if (vp == NULL) { + err (2, NULL); + } + + vp->type = integer; + vp->u.i = i; + return vp; +} + +struct val * +make_str (s) +char *s; +{ + struct val *vp; + + vp = (struct val *) malloc (sizeof (*vp)); + if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) { + err (2, NULL); + } + + vp->type = string; + return vp; +} + + +void +free_value (vp) +struct val *vp; +{ + if (vp->type == string) + free (vp->u.s); +} + + +int +to_integer (vp) +struct val *vp; +{ + char *s; + int neg; + int i; + + if (vp->type == integer) + return 1; + + s = vp->u.s; + i = 0; + + neg = (*s == '-'); + if (neg) + s++; + + for (;*s; s++) { + if (!isdigit (*s)) + return 0; + + i *= 10; + i += *s - '0'; + } + + free (vp->u.s); + if (neg) + i *= -1; + + vp->type = integer; + vp->u.i = i; + return 1; +} + +void +to_string (vp) +struct val *vp; +{ + char *tmp; + + if (vp->type == string) + return; + + tmp = malloc (25); + if (tmp == NULL) { + err (2, NULL); + } + + sprintf (tmp, "%d", vp->u.i); + vp->type = string; + vp->u.s = tmp; +} + + +int +isstring (vp) +struct val *vp; +{ + return (vp->type == string); +} + + +int +yylex () +{ + struct val *vp; + char *p; + + if (*av == NULL) + return (0); + + p = *av++; + + if (strlen (p) == 1) { + if (strchr ("|&=<>+-*/%:()", *p)) + return (*p); + } else if (strlen (p) == 2 && p[1] == '=') { + switch (*p) { + case '>': return (GE); + case '<': return (LE); + case '!': return (NE); + } + } + + yylval.val = make_str (p); + return (TOKEN); +} + +int +is_zero_or_null (vp) +struct val *vp; +{ + if (vp->type == integer) { + return (vp->u.i == 0); + } else { + return (*vp->u.s == 0 || (to_integer (vp) && vp->u.i == 0)); + } + /* NOTREACHED */ +} + +void +main (argc, argv) +int argc; +char **argv; +{ + setlocale (LC_ALL, ""); + + av = argv + 1; + + yyparse (); + + if (result->type == integer) + printf ("%d\n", result->u.i); + else + printf ("%s\n", result->u.s); + + exit (is_zero_or_null (result)); +} + +int +yyerror (s) +char *s; +{ + errx (2, "syntax error"); +} + + +struct val * +op_or (a, b) +struct val *a, *b; +{ + if (is_zero_or_null (a)) { + free_value (a); + return (b); + } else { + free_value (b); + return (a); + } +} + +struct val * +op_and (a, b) +struct val *a, *b; +{ + if (is_zero_or_null (a) || is_zero_or_null (b)) { + free_value (a); + free_value (b); + return (make_integer (0)); + } else { + free_value (b); + return (a); + } +} + +struct val * +op_eq (a, b) +struct val *a, *b; +{ + struct val *r; + + if (isstring (a) || isstring (b)) { + to_string (a); + to_string (b); + r = make_integer (strcoll (a->u.s, b->u.s) == 0); + } else { + r = make_integer (a->u.i == b->u.i); + } + + free_value (a); + free_value (b); + return r; +} + +struct val * +op_gt (a, b) +struct val *a, *b; +{ + struct val *r; + + if (isstring (a) || isstring (b)) { + to_string (a); + to_string (b); + r = make_integer (strcoll (a->u.s, b->u.s) > 0); + } else { + r= make_integer (a->u.i > b->u.i); + } + + free_value (a); + free_value (b); + return r; +} + +struct val * +op_lt (a, b) +struct val *a, *b; +{ + struct val *r; + + if (isstring (a) || isstring (b)) { + to_string (a); + to_string (b); + r = make_integer (strcoll (a->u.s, b->u.s) < 0); + } else { + r = make_integer (a->u.i < b->u.i); + } + + free_value (a); + free_value (b); + return r; +} + +struct val * +op_ge (a, b) +struct val *a, *b; +{ + struct val *r; + + if (isstring (a) || isstring (b)) { + to_string (a); + to_string (b); + r = make_integer (strcoll (a->u.s, b->u.s) >= 0); + } else { + r = make_integer (a->u.i >= b->u.i); + } + + free_value (a); + free_value (b); + return r; +} + +struct val * +op_le (a, b) +struct val *a, *b; +{ + struct val *r; + + if (isstring (a) || isstring (b)) { + to_string (a); + to_string (b); + r = make_integer (strcoll (a->u.s, b->u.s) <= 0); + } else { + r = make_integer (a->u.i <= b->u.i); + } + + free_value (a); + free_value (b); + return r; +} + +struct val * +op_ne (a, b) +struct val *a, *b; +{ + struct val *r; + + if (isstring (a) || isstring (b)) { + to_string (a); + to_string (b); + r = make_integer (strcoll (a->u.s, b->u.s) != 0); + } else { + r = make_integer (a->u.i != b->u.i); + } + + free_value (a); + free_value (b); + return r; +} + +struct val * +op_plus (a, b) +struct val *a, *b; +{ + struct val *r; + + if (!to_integer (a) || !to_integer (b)) { + errx (2, "non-numeric argument"); + } + + r = make_integer (a->u.i + b->u.i); + free_value (a); + free_value (b); + return r; +} + +struct val * +op_minus (a, b) +struct val *a, *b; +{ + struct val *r; + + if (!to_integer (a) || !to_integer (b)) { + errx (2, "non-numeric argument"); + } + + r = make_integer (a->u.i - b->u.i); + free_value (a); + free_value (b); + return r; +} + +struct val * +op_times (a, b) +struct val *a, *b; +{ + struct val *r; + + if (!to_integer (a) || !to_integer (b)) { + errx (2, "non-numeric argument"); + } + + r = make_integer (a->u.i * b->u.i); + free_value (a); + free_value (b); + return (r); +} + +struct val * +op_div (a, b) +struct val *a, *b; +{ + struct val *r; + + if (!to_integer (a) || !to_integer (b)) { + errx (2, "non-numeric argument"); + } + + if (b->u.i == 0) { + errx (2, "division by zero"); + } + + r = make_integer (a->u.i / b->u.i); + free_value (a); + free_value (b); + return r; +} + +struct val * +op_rem (a, b) +struct val *a, *b; +{ + struct val *r; + + if (!to_integer (a) || !to_integer (b)) { + errx (2, "non-numeric argument"); + } + + if (b->u.i == 0) { + errx (2, "division by zero"); + } + + r = make_integer (a->u.i % b->u.i); + free_value (a); + free_value (b); + return r; +} + +#include <regex.h> + +struct val * +op_colon (a, b) +struct val *a, *b; +{ + regex_t rp; + regmatch_t rm[2]; + char errbuf[256]; + int eval; + struct val *v; + + /* coerce to both arguments to strings */ + to_string(a); + to_string(b); + + /* compile regular expression */ + if ((eval = regcomp (&rp, b->u.s, 0)) != 0) { + regerror (eval, &rp, errbuf, sizeof(errbuf)); + errx (2, "%s", errbuf); + } + + /* compare string against pattern */ + /* remember that patterns are anchored to the beginning of the line */ + if (regexec(&rp, a->u.s, 2, rm, 0) == 0 && rm[0].rm_so == 0) { + if (rm[1].rm_so >= 0) { + *(a->u.s + rm[1].rm_eo) = '\0'; + v = make_str (a->u.s + rm[1].rm_so); + + } else { + v = make_integer (rm[0].rm_eo - rm[0].rm_so); + } + } else { + if (rp.re_nsub == 0) { + v = make_integer (0); + } else { + v = make_str (""); + } + } + + /* free arguments and pattern buffer */ + free_value (a); + free_value (b); + regfree (&rp); + + return v; +} |
