expr.y revision 90109
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 90109 2002-02-02 06:36:49Z imp $
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>
1763755Sse#include <errno.h>
1862926Sse#include <regex.h>
1963755Sse#include <limits.h>
2031Salm
214Srgrimesenum valtype {
2212378Sjoerg	integer, numeric_string, string
234Srgrimes} ;
2431Salm
254Srgrimesstruct val {
264Srgrimes	enum valtype type;
274Srgrimes	union {
284Srgrimes		char *s;
2962926Sse		quad_t i;
304Srgrimes	} u;
3131Salm} ;
324Srgrimes
334Srgrimesstruct val *result;
344Srgrimes
3590109Simpint		chk_div(quad_t, quad_t);
3690109Simpint		chk_minus(quad_t, quad_t, quad_t);
3790109Simpint		chk_plus(quad_t, quad_t, quad_t);
3890109Simpint		chk_times(quad_t, quad_t, quad_t);
3990109Simpvoid		free_value(struct val *);
4090109Simpint		is_zero_or_null(struct val *);
4190109Simpint		isstring(struct val *);
4290109Simpstruct val	*make_integer(quad_t);
4390109Simpstruct val	*make_str(const char *);
4490109Simpstruct val	*op_and(struct val *, struct val *);
4590109Simpstruct val	*op_colon(struct val *, struct val *);
4690109Simpstruct val	*op_div(struct val *, struct val *);
4790109Simpstruct val	*op_eq(struct val *, struct val *);
4890109Simpstruct val	*op_ge(struct val *, struct val *);
4990109Simpstruct val	*op_gt(struct val *, struct val *);
5090109Simpstruct val	*op_le(struct val *, struct val *);
5190109Simpstruct val	*op_lt(struct val *, struct val *);
5290109Simpstruct val	*op_minus(struct val *, struct val *);
5390109Simpstruct val	*op_ne(struct val *, struct val *);
5490109Simpstruct val	*op_or(struct val *, struct val *);
5590109Simpstruct val	*op_plus(struct val *, struct val *);
5690109Simpstruct val	*op_rem(struct val *, struct val *);
5790109Simpstruct val	*op_times(struct val *, struct val *);
5890109Simpquad_t		to_integer(struct val *);
5990109Simpvoid		to_string(struct val *);
6090109Simpint		yyerror(const char *);
6190109Simpint		yylex(void);
6290109Simpint		yyparse(void);
6377244Skris
644Srgrimeschar **av;
654Srgrimes%}
664Srgrimes
674Srgrimes%union
684Srgrimes{
694Srgrimes	struct val *val;
704Srgrimes}
714Srgrimes
724Srgrimes%left <val> '|'
734Srgrimes%left <val> '&'
744Srgrimes%left <val> '=' '>' '<' GE LE NE
754Srgrimes%left <val> '+' '-'
764Srgrimes%left <val> '*' '/' '%'
774Srgrimes%left <val> ':'
784Srgrimes
794Srgrimes%token <val> TOKEN
804Srgrimes%type <val> start expr
814Srgrimes
824Srgrimes%%
834Srgrimes
844Srgrimesstart: expr { result = $$; }
854Srgrimes
864Srgrimesexpr:	TOKEN
874Srgrimes	| '(' expr ')' { $$ = $2; }
884Srgrimes	| expr '|' expr { $$ = op_or ($1, $3); }
894Srgrimes	| expr '&' expr { $$ = op_and ($1, $3); }
904Srgrimes	| expr '=' expr { $$ = op_eq ($1, $3); }
914Srgrimes	| expr '>' expr { $$ = op_gt ($1, $3); }
924Srgrimes	| expr '<' expr { $$ = op_lt ($1, $3); }
934Srgrimes	| expr GE expr  { $$ = op_ge ($1, $3); }
944Srgrimes	| expr LE expr  { $$ = op_le ($1, $3); }
954Srgrimes	| expr NE expr  { $$ = op_ne ($1, $3); }
964Srgrimes	| expr '+' expr { $$ = op_plus ($1, $3); }
974Srgrimes	| expr '-' expr { $$ = op_minus ($1, $3); }
984Srgrimes	| expr '*' expr { $$ = op_times ($1, $3); }
994Srgrimes	| expr '/' expr { $$ = op_div ($1, $3); }
1004Srgrimes	| expr '%' expr { $$ = op_rem ($1, $3); }
1014Srgrimes	| expr ':' expr { $$ = op_colon ($1, $3); }
1024Srgrimes	;
1034Srgrimes
1044Srgrimes
1054Srgrimes%%
1064Srgrimes
1074Srgrimesstruct val *
10890109Simpmake_integer(quad_t i)
1094Srgrimes{
1104Srgrimes	struct val *vp;
1114Srgrimes
1124Srgrimes	vp = (struct val *) malloc (sizeof (*vp));
1134Srgrimes	if (vp == NULL) {
11412378Sjoerg		errx (2, "malloc() failed");
1154Srgrimes	}
1164Srgrimes
1174Srgrimes	vp->type = integer;
1184Srgrimes	vp->u.i  = i;
1194Srgrimes	return vp;
1204Srgrimes}
1214Srgrimes
1224Srgrimesstruct val *
12390109Simpmake_str(const char *s)
1244Srgrimes{
1254Srgrimes	struct val *vp;
12677244Skris	size_t i;
12777244Skris	int isint;
1284Srgrimes
1294Srgrimes	vp = (struct val *) malloc (sizeof (*vp));
1304Srgrimes	if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) {
13112378Sjoerg		errx (2, "malloc() failed");
1324Srgrimes	}
1334Srgrimes
1349909Sjoerg	for(i = 1, isint = isdigit(s[0]) || s[0] == '-';
1359909Sjoerg	    isint && i < strlen(s);
1369909Sjoerg	    i++)
1379909Sjoerg	{
1389909Sjoerg		if(!isdigit(s[i]))
1399909Sjoerg			 isint = 0;
1409909Sjoerg	}
1419909Sjoerg
14212378Sjoerg	if (isint)
14312378Sjoerg		vp->type = numeric_string;
14412378Sjoerg	else
14512378Sjoerg		vp->type = string;
1469909Sjoerg
1474Srgrimes	return vp;
1484Srgrimes}
1494Srgrimes
1504Srgrimes
1514Srgrimesvoid
15290109Simpfree_value(struct val *vp)
1534Srgrimes{
15412378Sjoerg	if (vp->type == string || vp->type == numeric_string)
1554Srgrimes		free (vp->u.s);
1564Srgrimes}
1574Srgrimes
1584Srgrimes
15962926Ssequad_t
16090109Simpto_integer(struct val *vp)
1614Srgrimes{
16262926Sse	quad_t i;
1634Srgrimes
1644Srgrimes	if (vp->type == integer)
1654Srgrimes		return 1;
1664Srgrimes
16712378Sjoerg	if (vp->type == string)
16812378Sjoerg		return 0;
1694Srgrimes
17012378Sjoerg	/* vp->type == numeric_string, make it numeric */
17163755Sse	errno = 0;
17262926Sse	i  = strtoq(vp->u.s, (char**)NULL, 10);
17363755Sse	if (errno != 0) {
17463755Sse		errx (2, "overflow");
17563755Sse	}
1764Srgrimes	free (vp->u.s);
17712378Sjoerg	vp->u.i = i;
1784Srgrimes	vp->type = integer;
1794Srgrimes	return 1;
1804Srgrimes}
1814Srgrimes
1824Srgrimesvoid
18390109Simpto_string(struct val *vp)
1844Srgrimes{
1854Srgrimes	char *tmp;
1864Srgrimes
18712378Sjoerg	if (vp->type == string || vp->type == numeric_string)
1884Srgrimes		return;
1894Srgrimes
19077244Skris	tmp = malloc ((size_t)25);
1914Srgrimes	if (tmp == NULL) {
19212378Sjoerg		errx (2, "malloc() failed");
1934Srgrimes	}
1944Srgrimes
19577244Skris	sprintf (tmp, "%lld", (long long)vp->u.i);
1964Srgrimes	vp->type = string;
1974Srgrimes	vp->u.s  = tmp;
1984Srgrimes}
1994Srgrimes
2004Srgrimes
2014Srgrimesint
20290109Simpisstring(struct val *vp)
2034Srgrimes{
20412378Sjoerg	/* only TRUE if this string is not a valid integer */
2054Srgrimes	return (vp->type == string);
2064Srgrimes}
2074Srgrimes
2084Srgrimes
2094Srgrimesint
21090109Simpyylex(void)
2114Srgrimes{
2124Srgrimes	char *p;
2134Srgrimes
2144Srgrimes	if (*av == NULL)
2154Srgrimes		return (0);
2164Srgrimes
2174Srgrimes	p = *av++;
2184Srgrimes
2194Srgrimes	if (strlen (p) == 1) {
2204Srgrimes		if (strchr ("|&=<>+-*/%:()", *p))
2214Srgrimes			return (*p);
2224Srgrimes	} else if (strlen (p) == 2 && p[1] == '=') {
2234Srgrimes		switch (*p) {
2244Srgrimes		case '>': return (GE);
2254Srgrimes		case '<': return (LE);
2264Srgrimes		case '!': return (NE);
2274Srgrimes		}
2284Srgrimes	}
2294Srgrimes
2304Srgrimes	yylval.val = make_str (p);
2314Srgrimes	return (TOKEN);
2324Srgrimes}
2334Srgrimes
2344Srgrimesint
23590109Simpis_zero_or_null(struct val *vp)
2364Srgrimes{
2374Srgrimes	if (vp->type == integer) {
2384Srgrimes		return (vp->u.i == 0);
2394Srgrimes	} else {
240181Sconklin		return (*vp->u.s == 0 || (to_integer (vp) && vp->u.i == 0));
2414Srgrimes	}
2424Srgrimes	/* NOTREACHED */
2434Srgrimes}
2444Srgrimes
24512378Sjoergint
24690109Simpmain(int argc __unused, char *argv[])
2474Srgrimes{
248468Sjtc	setlocale (LC_ALL, "");
249468Sjtc
2504Srgrimes	av = argv + 1;
2514Srgrimes
2524Srgrimes	yyparse ();
2534Srgrimes
2544Srgrimes	if (result->type == integer)
25577244Skris		printf ("%lld\n", (long long)result->u.i);
2564Srgrimes	else
2574Srgrimes		printf ("%s\n", result->u.s);
2584Srgrimes
25912378Sjoerg	return (is_zero_or_null (result));
2604Srgrimes}
2614Srgrimes
2624Srgrimesint
26390109Simpyyerror(const char *s __unused)
2644Srgrimes{
265295Sjtc	errx (2, "syntax error");
2664Srgrimes}
2674Srgrimes
2684Srgrimes
2694Srgrimesstruct val *
27090109Simpop_or(struct val *a, struct val *b)
2714Srgrimes{
2724Srgrimes	if (is_zero_or_null (a)) {
2734Srgrimes		free_value (a);
2744Srgrimes		return (b);
2754Srgrimes	} else {
2764Srgrimes		free_value (b);
2774Srgrimes		return (a);
2784Srgrimes	}
2794Srgrimes}
2804Srgrimes
2814Srgrimesstruct val *
28290109Simpop_and(struct val *a, struct val *b)
2834Srgrimes{
2844Srgrimes	if (is_zero_or_null (a) || is_zero_or_null (b)) {
2854Srgrimes		free_value (a);
2864Srgrimes		free_value (b);
28762926Sse		return (make_integer ((quad_t)0));
2884Srgrimes	} else {
2894Srgrimes		free_value (b);
2904Srgrimes		return (a);
2914Srgrimes	}
2924Srgrimes}
2934Srgrimes
2944Srgrimesstruct val *
29590109Simpop_eq(struct val *a, struct val *b)
2964Srgrimes{
2974Srgrimes	struct val *r;
2984Srgrimes
2994Srgrimes	if (isstring (a) || isstring (b)) {
3004Srgrimes		to_string (a);
3014Srgrimes		to_string (b);
30262926Sse		r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) == 0));
3034Srgrimes	} else {
30412378Sjoerg		(void)to_integer(a);
30512378Sjoerg		(void)to_integer(b);
30662926Sse		r = make_integer ((quad_t)(a->u.i == b->u.i));
3074Srgrimes	}
3084Srgrimes
3094Srgrimes	free_value (a);
3104Srgrimes	free_value (b);
3114Srgrimes	return r;
3124Srgrimes}
3134Srgrimes
3144Srgrimesstruct val *
31590109Simpop_gt(struct val *a, struct val *b)
3164Srgrimes{
3174Srgrimes	struct val *r;
3184Srgrimes
3194Srgrimes	if (isstring (a) || isstring (b)) {
3204Srgrimes		to_string (a);
3214Srgrimes		to_string (b);
32262926Sse		r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) > 0));
3234Srgrimes	} else {
32412378Sjoerg		(void)to_integer(a);
32512378Sjoerg		(void)to_integer(b);
32662926Sse		r = make_integer ((quad_t)(a->u.i > b->u.i));
3274Srgrimes	}
3284Srgrimes
3294Srgrimes	free_value (a);
3304Srgrimes	free_value (b);
3314Srgrimes	return r;
3324Srgrimes}
3334Srgrimes
3344Srgrimesstruct val *
33590109Simpop_lt(struct val *a, struct val *b)
3364Srgrimes{
3374Srgrimes	struct val *r;
3384Srgrimes
3394Srgrimes	if (isstring (a) || isstring (b)) {
3404Srgrimes		to_string (a);
3414Srgrimes		to_string (b);
34262926Sse		r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) < 0));
3434Srgrimes	} else {
34412378Sjoerg		(void)to_integer(a);
34512378Sjoerg		(void)to_integer(b);
34662926Sse		r = make_integer ((quad_t)(a->u.i < b->u.i));
3474Srgrimes	}
3484Srgrimes
3494Srgrimes	free_value (a);
3504Srgrimes	free_value (b);
3514Srgrimes	return r;
3524Srgrimes}
3534Srgrimes
3544Srgrimesstruct val *
35590109Simpop_ge(struct val *a, struct val *b)
3564Srgrimes{
3574Srgrimes	struct val *r;
3584Srgrimes
3594Srgrimes	if (isstring (a) || isstring (b)) {
3604Srgrimes		to_string (a);
3614Srgrimes		to_string (b);
36262926Sse		r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) >= 0));
3634Srgrimes	} else {
36412378Sjoerg		(void)to_integer(a);
36512378Sjoerg		(void)to_integer(b);
36662926Sse		r = make_integer ((quad_t)(a->u.i >= b->u.i));
3674Srgrimes	}
3684Srgrimes
3694Srgrimes	free_value (a);
3704Srgrimes	free_value (b);
3714Srgrimes	return r;
3724Srgrimes}
3734Srgrimes
3744Srgrimesstruct val *
37590109Simpop_le(struct val *a, struct val *b)
3764Srgrimes{
3774Srgrimes	struct val *r;
3784Srgrimes
3794Srgrimes	if (isstring (a) || isstring (b)) {
3804Srgrimes		to_string (a);
3814Srgrimes		to_string (b);
38262926Sse		r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) <= 0));
3834Srgrimes	} else {
38412378Sjoerg		(void)to_integer(a);
38512378Sjoerg		(void)to_integer(b);
38662926Sse		r = make_integer ((quad_t)(a->u.i <= b->u.i));
3874Srgrimes	}
3884Srgrimes
3894Srgrimes	free_value (a);
3904Srgrimes	free_value (b);
3914Srgrimes	return r;
3924Srgrimes}
3934Srgrimes
3944Srgrimesstruct val *
39590109Simpop_ne(struct val *a, struct val *b)
3964Srgrimes{
3974Srgrimes	struct val *r;
3984Srgrimes
3994Srgrimes	if (isstring (a) || isstring (b)) {
4004Srgrimes		to_string (a);
4014Srgrimes		to_string (b);
40262926Sse		r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) != 0));
4034Srgrimes	} else {
40412378Sjoerg		(void)to_integer(a);
40512378Sjoerg		(void)to_integer(b);
40662926Sse		r = make_integer ((quad_t)(a->u.i != b->u.i));
4074Srgrimes	}
4084Srgrimes
4094Srgrimes	free_value (a);
4104Srgrimes	free_value (b);
4114Srgrimes	return r;
4124Srgrimes}
4134Srgrimes
41463755Sseint
41590109Simpchk_plus(quad_t a, quad_t b, quad_t r)
41663755Sse{
41763755Sse	/* sum of two positive numbers must be positive */
41863755Sse	if (a > 0 && b > 0 && r <= 0)
41963755Sse		return 1;
42063755Sse	/* sum of two negative numbers must be negative */
42163755Sse	if (a < 0 && b < 0 && r >= 0)
42263755Sse		return 1;
42363755Sse	/* all other cases are OK */
42463755Sse	return 0;
42563755Sse}
42663755Sse
4274Srgrimesstruct val *
42890109Simpop_plus(struct val *a, struct val *b)
4294Srgrimes{
4304Srgrimes	struct val *r;
4314Srgrimes
4324Srgrimes	if (!to_integer (a) || !to_integer (b)) {
433295Sjtc		errx (2, "non-numeric argument");
4344Srgrimes	}
4354Srgrimes
43662926Sse	r = make_integer (/*(quad_t)*/(a->u.i + b->u.i));
43763755Sse	if (chk_plus (a->u.i, b->u.i, r->u.i)) {
43863755Sse		errx (2, "overflow");
43963755Sse	}
4404Srgrimes	free_value (a);
4414Srgrimes	free_value (b);
4424Srgrimes	return r;
4434Srgrimes}
44463755Sse
44563755Sseint
44690109Simpchk_minus(quad_t a, quad_t b, quad_t r)
44763755Sse{
44863755Sse	/* special case subtraction of QUAD_MIN */
44963755Sse	if (b == QUAD_MIN) {
45063755Sse		if (a >= 0)
45163755Sse			return 1;
45263755Sse		else
45363755Sse			return 0;
45463755Sse	}
45563755Sse	/* this is allowed for b != QUAD_MIN */
45663755Sse	return chk_plus (a, -b, r);
45763755Sse}
45863755Sse
4594Srgrimesstruct val *
46090109Simpop_minus(struct val *a, struct val *b)
4614Srgrimes{
4624Srgrimes	struct val *r;
4634Srgrimes
4644Srgrimes	if (!to_integer (a) || !to_integer (b)) {
465295Sjtc		errx (2, "non-numeric argument");
4664Srgrimes	}
4674Srgrimes
46862926Sse	r = make_integer (/*(quad_t)*/(a->u.i - b->u.i));
46963755Sse	if (chk_minus (a->u.i, b->u.i, r->u.i)) {
47063755Sse		errx (2, "overflow");
47163755Sse	}
4724Srgrimes	free_value (a);
4734Srgrimes	free_value (b);
4744Srgrimes	return r;
4754Srgrimes}
47663755Sse
47763755Sseint
47890109Simpchk_times(quad_t a, quad_t b, quad_t r)
47963755Sse{
48063755Sse	/* special case: first operand is 0, no overflow possible */
48163755Sse	if (a == 0)
48263755Sse		return 0;
48363755Sse	/* cerify that result of division matches second operand */
48463755Sse	if (r / a != b)
48563755Sse		return 1;
48663755Sse	return 0;
48763755Sse}
48863755Sse
4894Srgrimesstruct val *
49090109Simpop_times(struct val *a, struct val *b)
4914Srgrimes{
4924Srgrimes	struct val *r;
4934Srgrimes
4944Srgrimes	if (!to_integer (a) || !to_integer (b)) {
495295Sjtc		errx (2, "non-numeric argument");
4964Srgrimes	}
4974Srgrimes
49862926Sse	r = make_integer (/*(quad_t)*/(a->u.i * b->u.i));
49963755Sse	if (chk_times (a->u.i, b->u.i, r->u.i)) {
50063755Sse		errx (2, "overflow");
50163755Sse	}
5024Srgrimes	free_value (a);
5034Srgrimes	free_value (b);
5044Srgrimes	return (r);
5054Srgrimes}
50663755Sse
50763755Sseint
50890109Simpchk_div(quad_t a, quad_t b)
50963755Sse{
51063755Sse	/* div by zero has been taken care of before */
51163755Sse	/* only QUAD_MIN / -1 causes overflow */
51263755Sse	if (a == QUAD_MIN && b == -1)
51363755Sse		return 1;
51463755Sse	/* everything else is OK */
51563755Sse	return 0;
51663755Sse}
51763755Sse
5184Srgrimesstruct val *
51990109Simpop_div(struct val *a, struct val *b)
5204Srgrimes{
5214Srgrimes	struct val *r;
5224Srgrimes
5234Srgrimes	if (!to_integer (a) || !to_integer (b)) {
524295Sjtc		errx (2, "non-numeric argument");
5254Srgrimes	}
5264Srgrimes
5274Srgrimes	if (b->u.i == 0) {
528295Sjtc		errx (2, "division by zero");
5294Srgrimes	}
5304Srgrimes
53162926Sse	r = make_integer (/*(quad_t)*/(a->u.i / b->u.i));
53277244Skris	if (chk_div (a->u.i, b->u.i)) {
53363755Sse		errx (2, "overflow");
53463755Sse	}
5354Srgrimes	free_value (a);
5364Srgrimes	free_value (b);
5374Srgrimes	return r;
5384Srgrimes}
5394Srgrimes
5404Srgrimesstruct val *
54190109Simpop_rem(struct val *a, struct val *b)
5424Srgrimes{
5434Srgrimes	struct val *r;
5444Srgrimes
5454Srgrimes	if (!to_integer (a) || !to_integer (b)) {
546295Sjtc		errx (2, "non-numeric argument");
5474Srgrimes	}
5484Srgrimes
5494Srgrimes	if (b->u.i == 0) {
550295Sjtc		errx (2, "division by zero");
5514Srgrimes	}
5524Srgrimes
55362926Sse	r = make_integer (/*(quad_t)*/(a->u.i % b->u.i));
55463755Sse	/* chk_rem necessary ??? */
5554Srgrimes	free_value (a);
5564Srgrimes	free_value (b);
5574Srgrimes	return r;
5584Srgrimes}
5594Srgrimes
5604Srgrimesstruct val *
56190109Simpop_colon(struct val *a, struct val *b)
5624Srgrimes{
56331Salm	regex_t rp;
564468Sjtc	regmatch_t rm[2];
56531Salm	char errbuf[256];
56631Salm	int eval;
567181Sconklin	struct val *v;
5684Srgrimes
569181Sconklin	/* coerce to both arguments to strings */
570181Sconklin	to_string(a);
571181Sconklin	to_string(b);
572181Sconklin
57331Salm	/* compile regular expression */
574539Sjtc	if ((eval = regcomp (&rp, b->u.s, 0)) != 0) {
57531Salm		regerror (eval, &rp, errbuf, sizeof(errbuf));
576295Sjtc		errx (2, "%s", errbuf);
5774Srgrimes	}
5784Srgrimes
57931Salm	/* compare string against pattern */
580539Sjtc	/* remember that patterns are anchored to the beginning of the line */
58177244Skris	if (regexec(&rp, a->u.s, (size_t)2, rm, 0) == 0 && rm[0].rm_so == 0) {
58231Salm		if (rm[1].rm_so >= 0) {
583295Sjtc			*(a->u.s + rm[1].rm_eo) = '\0';
58431Salm			v = make_str (a->u.s + rm[1].rm_so);
58531Salm
5864Srgrimes		} else {
58762926Sse			v = make_integer ((quad_t)(rm[0].rm_eo - rm[0].rm_so));
5884Srgrimes		}
5894Srgrimes	} else {
590295Sjtc		if (rp.re_nsub == 0) {
59162926Sse			v = make_integer ((quad_t)0);
592295Sjtc		} else {
593295Sjtc			v = make_str ("");
594295Sjtc		}
5954Srgrimes	}
5964Srgrimes
59731Salm	/* free arguments and pattern buffer */
59831Salm	free_value (a);
59931Salm	free_value (b);
60031Salm	regfree (&rp);
60131Salm
60231Salm	return v;
6034Srgrimes}
604