expr.y revision 62926
14Srgrimes%{
24Srgrimes/* Written by Pace Willisson (pace@blitz.com)
3295Sjtc * and placed in the public domain.
44Srgrimes *
5295Sjtc * Largely rewritten by J.T. Conklin (jtc@wimsey.com)
6295Sjtc *
750471Speter * $FreeBSD: head/bin/expr/expr.y 62926 2000-07-10 21:30:55Z se $
84Srgrimes */
9468Sjtc
1062926Sse#include <sys/types.h>
114Srgrimes#include <stdio.h>
124Srgrimes#include <stdlib.h>
134Srgrimes#include <string.h>
14468Sjtc#include <locale.h>
154Srgrimes#include <ctype.h>
16295Sjtc#include <err.h>
1762926Sse#include <regex.h>
1831Salm
194Srgrimesenum valtype {
2012378Sjoerg	integer, numeric_string, string
214Srgrimes} ;
2231Salm
234Srgrimesstruct val {
244Srgrimes	enum valtype type;
254Srgrimes	union {
264Srgrimes		char *s;
2762926Sse		quad_t i;
284Srgrimes	} u;
2931Salm} ;
304Srgrimes
314Srgrimesstruct val *result;
324Srgrimesstruct val *op_or ();
334Srgrimesstruct val *op_and ();
344Srgrimesstruct val *op_eq ();
354Srgrimesstruct val *op_gt ();
364Srgrimesstruct val *op_lt ();
374Srgrimesstruct val *op_ge ();
384Srgrimesstruct val *op_le ();
394Srgrimesstruct val *op_ne ();
404Srgrimesstruct val *op_plus ();
414Srgrimesstruct val *op_minus ();
424Srgrimesstruct val *op_times ();
434Srgrimesstruct val *op_div ();
444Srgrimesstruct val *op_rem ();
454Srgrimesstruct val *op_colon ();
464Srgrimes
474Srgrimeschar **av;
484Srgrimes%}
494Srgrimes
504Srgrimes%union
514Srgrimes{
524Srgrimes	struct val *val;
534Srgrimes}
544Srgrimes
554Srgrimes%left <val> '|'
564Srgrimes%left <val> '&'
574Srgrimes%left <val> '=' '>' '<' GE LE NE
584Srgrimes%left <val> '+' '-'
594Srgrimes%left <val> '*' '/' '%'
604Srgrimes%left <val> ':'
614Srgrimes
624Srgrimes%token <val> TOKEN
634Srgrimes%type <val> start expr
644Srgrimes
654Srgrimes%%
664Srgrimes
674Srgrimesstart: expr { result = $$; }
684Srgrimes
694Srgrimesexpr:	TOKEN
704Srgrimes	| '(' expr ')' { $$ = $2; }
714Srgrimes	| expr '|' expr { $$ = op_or ($1, $3); }
724Srgrimes	| expr '&' expr { $$ = op_and ($1, $3); }
734Srgrimes	| expr '=' expr { $$ = op_eq ($1, $3); }
744Srgrimes	| expr '>' expr { $$ = op_gt ($1, $3); }
754Srgrimes	| expr '<' expr { $$ = op_lt ($1, $3); }
764Srgrimes	| expr GE expr  { $$ = op_ge ($1, $3); }
774Srgrimes	| expr LE expr  { $$ = op_le ($1, $3); }
784Srgrimes	| expr NE expr  { $$ = op_ne ($1, $3); }
794Srgrimes	| expr '+' expr { $$ = op_plus ($1, $3); }
804Srgrimes	| expr '-' expr { $$ = op_minus ($1, $3); }
814Srgrimes	| expr '*' expr { $$ = op_times ($1, $3); }
824Srgrimes	| expr '/' expr { $$ = op_div ($1, $3); }
834Srgrimes	| expr '%' expr { $$ = op_rem ($1, $3); }
844Srgrimes	| expr ':' expr { $$ = op_colon ($1, $3); }
854Srgrimes	;
864Srgrimes
874Srgrimes
884Srgrimes%%
894Srgrimes
904Srgrimesstruct val *
914Srgrimesmake_integer (i)
9262926Ssequad_t i;
934Srgrimes{
944Srgrimes	struct val *vp;
954Srgrimes
964Srgrimes	vp = (struct val *) malloc (sizeof (*vp));
974Srgrimes	if (vp == NULL) {
9812378Sjoerg		errx (2, "malloc() failed");
994Srgrimes	}
1004Srgrimes
1014Srgrimes	vp->type = integer;
1024Srgrimes	vp->u.i  = i;
1034Srgrimes	return vp;
1044Srgrimes}
1054Srgrimes
1064Srgrimesstruct val *
1074Srgrimesmake_str (s)
1084Srgrimeschar *s;
1094Srgrimes{
1104Srgrimes	struct val *vp;
1119909Sjoerg	int i, isint;
1124Srgrimes
1134Srgrimes	vp = (struct val *) malloc (sizeof (*vp));
1144Srgrimes	if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) {
11512378Sjoerg		errx (2, "malloc() failed");
1164Srgrimes	}
1174Srgrimes
1189909Sjoerg	for(i = 1, isint = isdigit(s[0]) || s[0] == '-';
1199909Sjoerg	    isint && i < strlen(s);
1209909Sjoerg	    i++)
1219909Sjoerg	{
1229909Sjoerg		if(!isdigit(s[i]))
1239909Sjoerg			 isint = 0;
1249909Sjoerg	}
1259909Sjoerg
12612378Sjoerg	if (isint)
12712378Sjoerg		vp->type = numeric_string;
12812378Sjoerg	else
12912378Sjoerg		vp->type = string;
1309909Sjoerg
1314Srgrimes	return vp;
1324Srgrimes}
1334Srgrimes
1344Srgrimes
1354Srgrimesvoid
1364Srgrimesfree_value (vp)
1374Srgrimesstruct val *vp;
1384Srgrimes{
13912378Sjoerg	if (vp->type == string || vp->type == numeric_string)
1404Srgrimes		free (vp->u.s);
1414Srgrimes}
1424Srgrimes
1434Srgrimes
14462926Ssequad_t
1454Srgrimesto_integer (vp)
1464Srgrimesstruct val *vp;
1474Srgrimes{
14862926Sse	quad_t i;
1494Srgrimes
1504Srgrimes	if (vp->type == integer)
1514Srgrimes		return 1;
1524Srgrimes
15312378Sjoerg	if (vp->type == string)
15412378Sjoerg		return 0;
1554Srgrimes
15612378Sjoerg	/* vp->type == numeric_string, make it numeric */
15762926Sse	i  = strtoq(vp->u.s, (char**)NULL, 10);
1584Srgrimes	free (vp->u.s);
15912378Sjoerg	vp->u.i = i;
1604Srgrimes	vp->type = integer;
1614Srgrimes	return 1;
1624Srgrimes}
1634Srgrimes
1644Srgrimesvoid
1654Srgrimesto_string (vp)
1664Srgrimesstruct val *vp;
1674Srgrimes{
1684Srgrimes	char *tmp;
1694Srgrimes
17012378Sjoerg	if (vp->type == string || vp->type == numeric_string)
1714Srgrimes		return;
1724Srgrimes
1734Srgrimes	tmp = malloc (25);
1744Srgrimes	if (tmp == NULL) {
17512378Sjoerg		errx (2, "malloc() failed");
1764Srgrimes	}
1774Srgrimes
17862926Sse	sprintf (tmp, "%qd", vp->u.i);
1794Srgrimes	vp->type = string;
1804Srgrimes	vp->u.s  = tmp;
1814Srgrimes}
1824Srgrimes
1834Srgrimes
1844Srgrimesint
1854Srgrimesisstring (vp)
1864Srgrimesstruct val *vp;
1874Srgrimes{
18812378Sjoerg	/* only TRUE if this string is not a valid integer */
1894Srgrimes	return (vp->type == string);
1904Srgrimes}
1914Srgrimes
1924Srgrimes
1934Srgrimesint
1944Srgrimesyylex ()
1954Srgrimes{
1964Srgrimes	char *p;
1974Srgrimes
1984Srgrimes	if (*av == NULL)
1994Srgrimes		return (0);
2004Srgrimes
2014Srgrimes	p = *av++;
2024Srgrimes
2034Srgrimes	if (strlen (p) == 1) {
2044Srgrimes		if (strchr ("|&=<>+-*/%:()", *p))
2054Srgrimes			return (*p);
2064Srgrimes	} else if (strlen (p) == 2 && p[1] == '=') {
2074Srgrimes		switch (*p) {
2084Srgrimes		case '>': return (GE);
2094Srgrimes		case '<': return (LE);
2104Srgrimes		case '!': return (NE);
2114Srgrimes		}
2124Srgrimes	}
2134Srgrimes
2144Srgrimes	yylval.val = make_str (p);
2154Srgrimes	return (TOKEN);
2164Srgrimes}
2174Srgrimes
2184Srgrimesint
2194Srgrimesis_zero_or_null (vp)
2204Srgrimesstruct val *vp;
2214Srgrimes{
2224Srgrimes	if (vp->type == integer) {
2234Srgrimes		return (vp->u.i == 0);
2244Srgrimes	} else {
225181Sconklin		return (*vp->u.s == 0 || (to_integer (vp) && vp->u.i == 0));
2264Srgrimes	}
2274Srgrimes	/* NOTREACHED */
2284Srgrimes}
2294Srgrimes
2307165Sjoergint yyparse ();
2317165Sjoerg
23212378Sjoergint
2334Srgrimesmain (argc, argv)
2344Srgrimesint argc;
2354Srgrimeschar **argv;
2364Srgrimes{
237468Sjtc	setlocale (LC_ALL, "");
238468Sjtc
2394Srgrimes	av = argv + 1;
2404Srgrimes
2414Srgrimes	yyparse ();
2424Srgrimes
2434Srgrimes	if (result->type == integer)
24462926Sse		printf ("%qd\n", result->u.i);
2454Srgrimes	else
2464Srgrimes		printf ("%s\n", result->u.s);
2474Srgrimes
24812378Sjoerg	return (is_zero_or_null (result));
2494Srgrimes}
2504Srgrimes
2514Srgrimesint
2524Srgrimesyyerror (s)
2534Srgrimeschar *s;
2544Srgrimes{
255295Sjtc	errx (2, "syntax error");
2564Srgrimes}
2574Srgrimes
2584Srgrimes
2594Srgrimesstruct val *
2604Srgrimesop_or (a, b)
2614Srgrimesstruct val *a, *b;
2624Srgrimes{
2634Srgrimes	if (is_zero_or_null (a)) {
2644Srgrimes		free_value (a);
2654Srgrimes		return (b);
2664Srgrimes	} else {
2674Srgrimes		free_value (b);
2684Srgrimes		return (a);
2694Srgrimes	}
2704Srgrimes}
2714Srgrimes
2724Srgrimesstruct val *
2734Srgrimesop_and (a, b)
2744Srgrimesstruct val *a, *b;
2754Srgrimes{
2764Srgrimes	if (is_zero_or_null (a) || is_zero_or_null (b)) {
2774Srgrimes		free_value (a);
2784Srgrimes		free_value (b);
27962926Sse		return (make_integer ((quad_t)0));
2804Srgrimes	} else {
2814Srgrimes		free_value (b);
2824Srgrimes		return (a);
2834Srgrimes	}
2844Srgrimes}
2854Srgrimes
2864Srgrimesstruct val *
2874Srgrimesop_eq (a, b)
2884Srgrimesstruct val *a, *b;
2894Srgrimes{
2904Srgrimes	struct val *r;
2914Srgrimes
2924Srgrimes	if (isstring (a) || isstring (b)) {
2934Srgrimes		to_string (a);
2944Srgrimes		to_string (b);
29562926Sse		r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) == 0));
2964Srgrimes	} else {
29712378Sjoerg		(void)to_integer(a);
29812378Sjoerg		(void)to_integer(b);
29962926Sse		r = make_integer ((quad_t)(a->u.i == b->u.i));
3004Srgrimes	}
3014Srgrimes
3024Srgrimes	free_value (a);
3034Srgrimes	free_value (b);
3044Srgrimes	return r;
3054Srgrimes}
3064Srgrimes
3074Srgrimesstruct val *
3084Srgrimesop_gt (a, b)
3094Srgrimesstruct val *a, *b;
3104Srgrimes{
3114Srgrimes	struct val *r;
3124Srgrimes
3134Srgrimes	if (isstring (a) || isstring (b)) {
3144Srgrimes		to_string (a);
3154Srgrimes		to_string (b);
31662926Sse		r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) > 0));
3174Srgrimes	} else {
31812378Sjoerg		(void)to_integer(a);
31912378Sjoerg		(void)to_integer(b);
32062926Sse		r = make_integer ((quad_t)(a->u.i > b->u.i));
3214Srgrimes	}
3224Srgrimes
3234Srgrimes	free_value (a);
3244Srgrimes	free_value (b);
3254Srgrimes	return r;
3264Srgrimes}
3274Srgrimes
3284Srgrimesstruct val *
3294Srgrimesop_lt (a, b)
3304Srgrimesstruct val *a, *b;
3314Srgrimes{
3324Srgrimes	struct val *r;
3334Srgrimes
3344Srgrimes	if (isstring (a) || isstring (b)) {
3354Srgrimes		to_string (a);
3364Srgrimes		to_string (b);
33762926Sse		r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) < 0));
3384Srgrimes	} else {
33912378Sjoerg		(void)to_integer(a);
34012378Sjoerg		(void)to_integer(b);
34162926Sse		r = make_integer ((quad_t)(a->u.i < b->u.i));
3424Srgrimes	}
3434Srgrimes
3444Srgrimes	free_value (a);
3454Srgrimes	free_value (b);
3464Srgrimes	return r;
3474Srgrimes}
3484Srgrimes
3494Srgrimesstruct val *
3504Srgrimesop_ge (a, b)
3514Srgrimesstruct val *a, *b;
3524Srgrimes{
3534Srgrimes	struct val *r;
3544Srgrimes
3554Srgrimes	if (isstring (a) || isstring (b)) {
3564Srgrimes		to_string (a);
3574Srgrimes		to_string (b);
35862926Sse		r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) >= 0));
3594Srgrimes	} else {
36012378Sjoerg		(void)to_integer(a);
36112378Sjoerg		(void)to_integer(b);
36262926Sse		r = make_integer ((quad_t)(a->u.i >= b->u.i));
3634Srgrimes	}
3644Srgrimes
3654Srgrimes	free_value (a);
3664Srgrimes	free_value (b);
3674Srgrimes	return r;
3684Srgrimes}
3694Srgrimes
3704Srgrimesstruct val *
3714Srgrimesop_le (a, b)
3724Srgrimesstruct val *a, *b;
3734Srgrimes{
3744Srgrimes	struct val *r;
3754Srgrimes
3764Srgrimes	if (isstring (a) || isstring (b)) {
3774Srgrimes		to_string (a);
3784Srgrimes		to_string (b);
37962926Sse		r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) <= 0));
3804Srgrimes	} else {
38112378Sjoerg		(void)to_integer(a);
38212378Sjoerg		(void)to_integer(b);
38362926Sse		r = make_integer ((quad_t)(a->u.i <= b->u.i));
3844Srgrimes	}
3854Srgrimes
3864Srgrimes	free_value (a);
3874Srgrimes	free_value (b);
3884Srgrimes	return r;
3894Srgrimes}
3904Srgrimes
3914Srgrimesstruct val *
3924Srgrimesop_ne (a, b)
3934Srgrimesstruct val *a, *b;
3944Srgrimes{
3954Srgrimes	struct val *r;
3964Srgrimes
3974Srgrimes	if (isstring (a) || isstring (b)) {
3984Srgrimes		to_string (a);
3994Srgrimes		to_string (b);
40062926Sse		r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) != 0));
4014Srgrimes	} else {
40212378Sjoerg		(void)to_integer(a);
40312378Sjoerg		(void)to_integer(b);
40462926Sse		r = make_integer ((quad_t)(a->u.i != b->u.i));
4054Srgrimes	}
4064Srgrimes
4074Srgrimes	free_value (a);
4084Srgrimes	free_value (b);
4094Srgrimes	return r;
4104Srgrimes}
4114Srgrimes
4124Srgrimesstruct val *
4134Srgrimesop_plus (a, b)
4144Srgrimesstruct val *a, *b;
4154Srgrimes{
4164Srgrimes	struct val *r;
4174Srgrimes
4184Srgrimes	if (!to_integer (a) || !to_integer (b)) {
419295Sjtc		errx (2, "non-numeric argument");
4204Srgrimes	}
4214Srgrimes
42262926Sse	r = make_integer (/*(quad_t)*/(a->u.i + b->u.i));
4234Srgrimes	free_value (a);
4244Srgrimes	free_value (b);
4254Srgrimes	return r;
4264Srgrimes}
4274Srgrimes
4284Srgrimesstruct val *
4294Srgrimesop_minus (a, b)
4304Srgrimesstruct val *a, *b;
4314Srgrimes{
4324Srgrimes	struct val *r;
4334Srgrimes
4344Srgrimes	if (!to_integer (a) || !to_integer (b)) {
435295Sjtc		errx (2, "non-numeric argument");
4364Srgrimes	}
4374Srgrimes
43862926Sse	r = make_integer (/*(quad_t)*/(a->u.i - b->u.i));
4394Srgrimes	free_value (a);
4404Srgrimes	free_value (b);
4414Srgrimes	return r;
4424Srgrimes}
4434Srgrimes
4444Srgrimesstruct val *
4454Srgrimesop_times (a, b)
4464Srgrimesstruct val *a, *b;
4474Srgrimes{
4484Srgrimes	struct val *r;
4494Srgrimes
4504Srgrimes	if (!to_integer (a) || !to_integer (b)) {
451295Sjtc		errx (2, "non-numeric argument");
4524Srgrimes	}
4534Srgrimes
45462926Sse	r = make_integer (/*(quad_t)*/(a->u.i * b->u.i));
4554Srgrimes	free_value (a);
4564Srgrimes	free_value (b);
4574Srgrimes	return (r);
4584Srgrimes}
4594Srgrimes
4604Srgrimesstruct val *
4614Srgrimesop_div (a, b)
4624Srgrimesstruct val *a, *b;
4634Srgrimes{
4644Srgrimes	struct val *r;
4654Srgrimes
4664Srgrimes	if (!to_integer (a) || !to_integer (b)) {
467295Sjtc		errx (2, "non-numeric argument");
4684Srgrimes	}
4694Srgrimes
4704Srgrimes	if (b->u.i == 0) {
471295Sjtc		errx (2, "division by zero");
4724Srgrimes	}
4734Srgrimes
47462926Sse	r = make_integer (/*(quad_t)*/(a->u.i / b->u.i));
4754Srgrimes	free_value (a);
4764Srgrimes	free_value (b);
4774Srgrimes	return r;
4784Srgrimes}
4794Srgrimes
4804Srgrimesstruct val *
4814Srgrimesop_rem (a, b)
4824Srgrimesstruct val *a, *b;
4834Srgrimes{
4844Srgrimes	struct val *r;
4854Srgrimes
4864Srgrimes	if (!to_integer (a) || !to_integer (b)) {
487295Sjtc		errx (2, "non-numeric argument");
4884Srgrimes	}
4894Srgrimes
4904Srgrimes	if (b->u.i == 0) {
491295Sjtc		errx (2, "division by zero");
4924Srgrimes	}
4934Srgrimes
49462926Sse	r = make_integer (/*(quad_t)*/(a->u.i % b->u.i));
4954Srgrimes	free_value (a);
4964Srgrimes	free_value (b);
4974Srgrimes	return r;
4984Srgrimes}
4994Srgrimes
5004Srgrimesstruct val *
5014Srgrimesop_colon (a, b)
5024Srgrimesstruct val *a, *b;
5034Srgrimes{
50431Salm	regex_t rp;
505468Sjtc	regmatch_t rm[2];
50631Salm	char errbuf[256];
50731Salm	int eval;
508181Sconklin	struct val *v;
5094Srgrimes
510181Sconklin	/* coerce to both arguments to strings */
511181Sconklin	to_string(a);
512181Sconklin	to_string(b);
513181Sconklin
51431Salm	/* compile regular expression */
515539Sjtc	if ((eval = regcomp (&rp, b->u.s, 0)) != 0) {
51631Salm		regerror (eval, &rp, errbuf, sizeof(errbuf));
517295Sjtc		errx (2, "%s", errbuf);
5184Srgrimes	}
5194Srgrimes
52031Salm	/* compare string against pattern */
521539Sjtc	/* remember that patterns are anchored to the beginning of the line */
522539Sjtc	if (regexec(&rp, a->u.s, 2, rm, 0) == 0 && rm[0].rm_so == 0) {
52331Salm		if (rm[1].rm_so >= 0) {
524295Sjtc			*(a->u.s + rm[1].rm_eo) = '\0';
52531Salm			v = make_str (a->u.s + rm[1].rm_so);
52631Salm
5274Srgrimes		} else {
52862926Sse			v = make_integer ((quad_t)(rm[0].rm_eo - rm[0].rm_so));
5294Srgrimes		}
5304Srgrimes	} else {
531295Sjtc		if (rp.re_nsub == 0) {
53262926Sse			v = make_integer ((quad_t)0);
533295Sjtc		} else {
534295Sjtc			v = make_str ("");
535295Sjtc		}
5364Srgrimes	}
5374Srgrimes
53831Salm	/* free arguments and pattern buffer */
53931Salm	free_value (a);
54031Salm	free_value (b);
54131Salm	regfree (&rp);
54231Salm
54331Salm	return v;
5444Srgrimes}
545