expr.y revision 468
1344957Smarcel%{
2344957Smarcel/* Written by Pace Willisson (pace@blitz.com)
3344957Smarcel * and placed in the public domain.
4344957Smarcel *
5344957Smarcel * Largely rewritten by J.T. Conklin (jtc@wimsey.com)
6344957Smarcel *
7344957Smarcel * $Id : /b/source/CVS/src/bin/expr/expr.y,v 1.11 1993/08/17 16:01:23 jtc Exp $
8344957Smarcel */
9344957Smarcel
10344957Smarcel#include <stdio.h>
11344957Smarcel#include <stdlib.h>
12344957Smarcel#include <string.h>
13344957Smarcel#include <locale.h>
14344957Smarcel#include <ctype.h>
15344957Smarcel#include <err.h>
16344957Smarcel
17344957Smarcelenum valtype {
18344957Smarcel	integer, string
19344957Smarcel} ;
20344957Smarcel
21344957Smarcelstruct val {
22344957Smarcel	enum valtype type;
23344957Smarcel	union {
24344957Smarcel		char *s;
25344957Smarcel		int   i;
26344957Smarcel	} u;
27344957Smarcel} ;
28344957Smarcel
29344957Smarcelstruct val *result;
30344957Smarcelstruct val *op_or ();
31344957Smarcelstruct val *op_and ();
32344957Smarcelstruct val *op_eq ();
33344957Smarcelstruct val *op_gt ();
34344957Smarcelstruct val *op_lt ();
35344957Smarcelstruct val *op_ge ();
36344957Smarcelstruct val *op_le ();
37344957Smarcelstruct val *op_ne ();
38344957Smarcelstruct val *op_plus ();
39344957Smarcelstruct val *op_minus ();
40344957Smarcelstruct val *op_times ();
41344957Smarcelstruct val *op_div ();
42344957Smarcelstruct val *op_rem ();
43344957Smarcelstruct val *op_colon ();
44344957Smarcel
45344957Smarcelchar **av;
46344957Smarcel%}
47344957Smarcel
48344957Smarcel%union
49344957Smarcel{
50344957Smarcel	struct val *val;
51344957Smarcel}
52344957Smarcel
53344957Smarcel%left <val> '|'
54344957Smarcel%left <val> '&'
55344957Smarcel%left <val> '=' '>' '<' GE LE NE
56344957Smarcel%left <val> '+' '-'
57344957Smarcel%left <val> '*' '/' '%'
58344957Smarcel%left <val> ':'
59344957Smarcel%left UNARY
60344957Smarcel
61344957Smarcel%token <val> TOKEN
62344957Smarcel%type <val> start expr
63344957Smarcel
64344957Smarcel%%
65344957Smarcel
66344957Smarcelstart: expr { result = $$; }
67344957Smarcel
68344957Smarcelexpr:	TOKEN
69344957Smarcel	| '(' expr ')' { $$ = $2; }
70344957Smarcel	| expr '|' expr { $$ = op_or ($1, $3); }
71344957Smarcel	| expr '&' expr { $$ = op_and ($1, $3); }
72344957Smarcel	| expr '=' expr { $$ = op_eq ($1, $3); }
73344957Smarcel	| expr '>' expr { $$ = op_gt ($1, $3); }
74344957Smarcel	| expr '<' expr { $$ = op_lt ($1, $3); }
75344957Smarcel	| expr GE expr  { $$ = op_ge ($1, $3); }
76344957Smarcel	| expr LE expr  { $$ = op_le ($1, $3); }
77344957Smarcel	| expr NE expr  { $$ = op_ne ($1, $3); }
78344957Smarcel	| expr '+' expr { $$ = op_plus ($1, $3); }
79344957Smarcel	| expr '-' expr { $$ = op_minus ($1, $3); }
80344957Smarcel	| expr '*' expr { $$ = op_times ($1, $3); }
81344957Smarcel	| expr '/' expr { $$ = op_div ($1, $3); }
82344957Smarcel	| expr '%' expr { $$ = op_rem ($1, $3); }
83344957Smarcel	| expr ':' expr { $$ = op_colon ($1, $3); }
84344957Smarcel	;
85344957Smarcel
86344957Smarcel
87344957Smarcel%%
88344957Smarcel
89344957Smarcelstruct val *
90344957Smarcelmake_integer (i)
91344957Smarcelint i;
92344957Smarcel{
93344957Smarcel	struct val *vp;
94344957Smarcel
95344957Smarcel	vp = (struct val *) malloc (sizeof (*vp));
96344957Smarcel	if (vp == NULL) {
97344957Smarcel		err (2, NULL);
98344957Smarcel	}
99344957Smarcel
100344957Smarcel	vp->type = integer;
101344957Smarcel	vp->u.i  = i;
102344957Smarcel	return vp;
103344957Smarcel}
104344957Smarcel
105344957Smarcelstruct val *
106344957Smarcelmake_str (s)
107344957Smarcelchar *s;
108344957Smarcel{
109344957Smarcel	struct val *vp;
110344957Smarcel
111344957Smarcel	vp = (struct val *) malloc (sizeof (*vp));
112344957Smarcel	if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) {
113344957Smarcel		err (2, NULL);
114344957Smarcel	}
115344957Smarcel
116344957Smarcel	vp->type = string;
117344957Smarcel	return vp;
118344957Smarcel}
119344957Smarcel
120344957Smarcel
121344957Smarcelvoid
122344957Smarcelfree_value (vp)
123344957Smarcelstruct val *vp;
124344957Smarcel{
125344957Smarcel	if (vp->type == string)
126344957Smarcel		free (vp->u.s);
127344957Smarcel}
128344957Smarcel
129344957Smarcel
130344957Smarcelint
131344957Smarcelto_integer (vp)
132344957Smarcelstruct val *vp;
133344957Smarcel{
134344957Smarcel	char *s;
135344957Smarcel	int neg;
136344957Smarcel	int i;
137344957Smarcel
138344957Smarcel	if (vp->type == integer)
139344957Smarcel		return 1;
140344957Smarcel
141344957Smarcel	s = vp->u.s;
142344957Smarcel	i = 0;
143344957Smarcel
144344957Smarcel	neg = (*s == '-');
145344957Smarcel	if (neg)
146344957Smarcel		s++;
147344957Smarcel
148344957Smarcel	for (;*s; s++) {
149344957Smarcel		if (!isdigit (*s))
150344957Smarcel			return 0;
151344957Smarcel
152344957Smarcel		i *= 10;
153344957Smarcel		i += *s - '0';
154344957Smarcel	}
155344957Smarcel
156344957Smarcel	free (vp->u.s);
157344957Smarcel	if (neg)
158344957Smarcel		i *= -1;
159344957Smarcel
160344957Smarcel	vp->type = integer;
161344957Smarcel	vp->u.i  = i;
162344957Smarcel	return 1;
163344957Smarcel}
164344957Smarcel
165344957Smarcelvoid
166344957Smarcelto_string (vp)
167344957Smarcelstruct val *vp;
168344957Smarcel{
169344957Smarcel	char *tmp;
170344957Smarcel
171344957Smarcel	if (vp->type == string)
172344957Smarcel		return;
173344957Smarcel
174344957Smarcel	tmp = malloc (25);
175344957Smarcel	if (tmp == NULL) {
176344957Smarcel		err (2, NULL);
177344957Smarcel	}
178344957Smarcel
179344957Smarcel	sprintf (tmp, "%d", vp->u.i);
180344957Smarcel	vp->type = string;
181344957Smarcel	vp->u.s  = tmp;
182344957Smarcel}
183344957Smarcel
184344957Smarcel
185344957Smarcelint
186344957Smarcelisstring (vp)
187344957Smarcelstruct val *vp;
188344957Smarcel{
189344957Smarcel	return (vp->type == string);
190344957Smarcel}
191344957Smarcel
192344957Smarcel
193344957Smarcelint
194344957Smarcelyylex ()
195344957Smarcel{
196344957Smarcel	struct val *vp;
197344957Smarcel	char *p;
198344957Smarcel
199344957Smarcel	if (*av == NULL)
200344957Smarcel		return (0);
201344957Smarcel
202344957Smarcel	p = *av++;
203344957Smarcel
204344957Smarcel	if (strlen (p) == 1) {
205344957Smarcel		if (strchr ("|&=<>+-*/%:()", *p))
206344957Smarcel			return (*p);
207344957Smarcel	} else if (strlen (p) == 2 && p[1] == '=') {
208344957Smarcel		switch (*p) {
209344957Smarcel		case '>': return (GE);
210344957Smarcel		case '<': return (LE);
211344957Smarcel		case '!': return (NE);
212344957Smarcel		}
213344957Smarcel	}
214344957Smarcel
215344957Smarcel	yylval.val = make_str (p);
216344957Smarcel	return (TOKEN);
217344957Smarcel}
218344957Smarcel
219344957Smarcelint
220344957Smarcelis_zero_or_null (vp)
221344957Smarcelstruct val *vp;
222344957Smarcel{
223344957Smarcel	if (vp->type == integer) {
224344957Smarcel		return (vp->u.i == 0);
225344957Smarcel	} else {
226344957Smarcel		return (*vp->u.s == 0 || (to_integer (vp) && vp->u.i == 0));
227344957Smarcel	}
228344957Smarcel	/* NOTREACHED */
229344957Smarcel}
230344957Smarcel
231344957Smarcelvoid
232344957Smarcelmain (argc, argv)
233344957Smarcelint argc;
234344957Smarcelchar **argv;
235344957Smarcel{
236344957Smarcel	setlocale (LC_ALL, "");
237344957Smarcel
238344957Smarcel	av = argv + 1;
239344957Smarcel
240344957Smarcel	yyparse ();
241344957Smarcel
242344957Smarcel	if (result->type == integer)
243344957Smarcel		printf ("%d\n", result->u.i);
244344957Smarcel	else
245344957Smarcel		printf ("%s\n", result->u.s);
246344957Smarcel
247344957Smarcel	exit (is_zero_or_null (result));
248344957Smarcel}
249344957Smarcel
250344957Smarcelint
251344957Smarcelyyerror (s)
252344957Smarcelchar *s;
253344957Smarcel{
254344957Smarcel	errx (2, "syntax error");
255344957Smarcel}
256344957Smarcel
257344957Smarcel
258344957Smarcelstruct val *
259344957Smarcelop_or (a, b)
260344957Smarcelstruct val *a, *b;
261344957Smarcel{
262344957Smarcel	if (is_zero_or_null (a)) {
263344957Smarcel		free_value (a);
264344957Smarcel		return (b);
265344957Smarcel	} else {
266344957Smarcel		free_value (b);
267344957Smarcel		return (a);
268344957Smarcel	}
269344957Smarcel}
270344957Smarcel
271344957Smarcelstruct val *
272344957Smarcelop_and (a, b)
273344957Smarcelstruct val *a, *b;
274344957Smarcel{
275344957Smarcel	if (is_zero_or_null (a) || is_zero_or_null (b)) {
276344957Smarcel		free_value (a);
277344957Smarcel		free_value (b);
278344957Smarcel		return (make_integer (0));
279344957Smarcel	} else {
280344957Smarcel		free_value (b);
281344957Smarcel		return (a);
282344957Smarcel	}
283344957Smarcel}
284344957Smarcel
285344957Smarcelstruct val *
286344957Smarcelop_eq (a, b)
287344957Smarcelstruct val *a, *b;
288344957Smarcel{
289344957Smarcel	struct val *r;
290344957Smarcel
291344957Smarcel	if (isstring (a) || isstring (b)) {
292344957Smarcel		to_string (a);
293344957Smarcel		to_string (b);
294344957Smarcel		r = make_integer (strcoll (a->u.s, b->u.s) == 0);
295344957Smarcel	} else {
296344957Smarcel		r = make_integer (a->u.i == b->u.i);
297344957Smarcel	}
298344957Smarcel
299344957Smarcel	free_value (a);
300344957Smarcel	free_value (b);
301344957Smarcel	return r;
302344957Smarcel}
303344957Smarcel
304344957Smarcelstruct val *
305344957Smarcelop_gt (a, b)
306344957Smarcelstruct val *a, *b;
307344957Smarcel{
308344957Smarcel	struct val *r;
309344957Smarcel
310344957Smarcel	if (isstring (a) || isstring (b)) {
311344957Smarcel		to_string (a);
312344957Smarcel		to_string (b);
313344957Smarcel		r = make_integer (strcoll (a->u.s, b->u.s) > 0);
314344957Smarcel	} else {
315344957Smarcel		r= make_integer (a->u.i > b->u.i);
316	}
317
318	free_value (a);
319	free_value (b);
320	return r;
321}
322
323struct val *
324op_lt (a, b)
325struct val *a, *b;
326{
327	struct val *r;
328
329	if (isstring (a) || isstring (b)) {
330		to_string (a);
331		to_string (b);
332		r = make_integer (strcoll (a->u.s, b->u.s) < 0);
333	} else {
334		r = make_integer (a->u.i < b->u.i);
335	}
336
337	free_value (a);
338	free_value (b);
339	return r;
340}
341
342struct val *
343op_ge (a, b)
344struct val *a, *b;
345{
346	struct val *r;
347
348	if (isstring (a) || isstring (b)) {
349		to_string (a);
350		to_string (b);
351		r = make_integer (strcoll (a->u.s, b->u.s) >= 0);
352	} else {
353		r = make_integer (a->u.i >= b->u.i);
354	}
355
356	free_value (a);
357	free_value (b);
358	return r;
359}
360
361struct val *
362op_le (a, b)
363struct val *a, *b;
364{
365	struct val *r;
366
367	if (isstring (a) || isstring (b)) {
368		to_string (a);
369		to_string (b);
370		r = make_integer (strcoll (a->u.s, b->u.s) <= 0);
371	} else {
372		r = make_integer (a->u.i <= b->u.i);
373	}
374
375	free_value (a);
376	free_value (b);
377	return r;
378}
379
380struct val *
381op_ne (a, b)
382struct val *a, *b;
383{
384	struct val *r;
385
386	if (isstring (a) || isstring (b)) {
387		to_string (a);
388		to_string (b);
389		r = make_integer (strcoll (a->u.s, b->u.s) != 0);
390	} else {
391		r = make_integer (a->u.i != b->u.i);
392	}
393
394	free_value (a);
395	free_value (b);
396	return r;
397}
398
399struct val *
400op_plus (a, b)
401struct val *a, *b;
402{
403	struct val *r;
404
405	if (!to_integer (a) || !to_integer (b)) {
406		errx (2, "non-numeric argument");
407	}
408
409	r = make_integer (a->u.i + b->u.i);
410	free_value (a);
411	free_value (b);
412	return r;
413}
414
415struct val *
416op_minus (a, b)
417struct val *a, *b;
418{
419	struct val *r;
420
421	if (!to_integer (a) || !to_integer (b)) {
422		errx (2, "non-numeric argument");
423	}
424
425	r = make_integer (a->u.i - b->u.i);
426	free_value (a);
427	free_value (b);
428	return r;
429}
430
431struct val *
432op_times (a, b)
433struct val *a, *b;
434{
435	struct val *r;
436
437	if (!to_integer (a) || !to_integer (b)) {
438		errx (2, "non-numeric argument");
439	}
440
441	r = make_integer (a->u.i * b->u.i);
442	free_value (a);
443	free_value (b);
444	return (r);
445}
446
447struct val *
448op_div (a, b)
449struct val *a, *b;
450{
451	struct val *r;
452
453	if (!to_integer (a) || !to_integer (b)) {
454		errx (2, "non-numeric argument");
455	}
456
457	if (b->u.i == 0) {
458		errx (2, "division by zero");
459	}
460
461	r = make_integer (a->u.i / b->u.i);
462	free_value (a);
463	free_value (b);
464	return r;
465}
466
467struct val *
468op_rem (a, b)
469struct val *a, *b;
470{
471	struct val *r;
472
473	if (!to_integer (a) || !to_integer (b)) {
474		errx (2, "non-numeric argument");
475	}
476
477	if (b->u.i == 0) {
478		errx (2, "division by zero");
479	}
480
481	r = make_integer (a->u.i % b->u.i);
482	free_value (a);
483	free_value (b);
484	return r;
485}
486
487#include <regex.h>
488
489struct val *
490op_colon (a, b)
491struct val *a, *b;
492{
493	regex_t rp;
494	regmatch_t rm[2];
495	char errbuf[256];
496	int eval;
497	struct val *v;
498	char *newpat;
499
500	/* coerce to both arguments to strings */
501	to_string(a);
502	to_string(b);
503
504	/* patterns are anchored to the beginning of the line */
505	newpat = malloc (strlen (b->u.s) + 2);
506	strcpy (newpat, "^");
507	strcat (newpat, b->u.s);
508
509	/* compile regular expression */
510	if ((eval = regcomp (&rp, newpat, 0)) != 0) {
511		regerror (eval, &rp, errbuf, sizeof(errbuf));
512		errx (2, "%s", errbuf);
513	}
514	free (newpat);
515
516	/* compare string against pattern */
517	if (regexec(&rp, a->u.s, 2, rm, 0) == 0) {
518		if (rm[1].rm_so >= 0) {
519			*(a->u.s + rm[1].rm_eo) = '\0';
520			v = make_str (a->u.s + rm[1].rm_so);
521
522		} else {
523			v = make_integer (rm[0].rm_eo - rm[0].rm_so);
524		}
525	} else {
526		if (rp.re_nsub == 0) {
527			v = make_integer (0);
528		} else {
529			v = make_str ("");
530		}
531	}
532
533	/* free arguments and pattern buffer */
534	free_value (a);
535	free_value (b);
536	regfree (&rp);
537
538	return v;
539}
540