expr.y revision 1.7 1 1.1 cgd %{
2 1.1 cgd /* Written by Pace Willisson (pace (at) blitz.com)
3 1.1 cgd * and placed in the public domain
4 1.2 cgd *
5 1.7 jtc * $Header: /tank/opengrok/rsync2/NetBSD/src/bin/expr/expr.y,v 1.7 1993/07/20 00:29:41 jtc Exp $
6 1.1 cgd */
7 1.1 cgd #include <stdio.h>
8 1.4 cgd #include <stdlib.h>
9 1.4 cgd #include <string.h>
10 1.1 cgd #include <ctype.h>
11 1.5 cgd
12 1.4 cgd enum valtype {
13 1.4 cgd integer, string
14 1.4 cgd } ;
15 1.5 cgd
16 1.1 cgd struct val {
17 1.4 cgd enum valtype type;
18 1.4 cgd union {
19 1.4 cgd char *s;
20 1.4 cgd int i;
21 1.4 cgd } u;
22 1.5 cgd } ;
23 1.1 cgd
24 1.1 cgd struct val *result;
25 1.1 cgd struct val *op_or ();
26 1.1 cgd struct val *op_and ();
27 1.1 cgd struct val *op_eq ();
28 1.1 cgd struct val *op_gt ();
29 1.1 cgd struct val *op_lt ();
30 1.1 cgd struct val *op_ge ();
31 1.1 cgd struct val *op_le ();
32 1.1 cgd struct val *op_ne ();
33 1.1 cgd struct val *op_plus ();
34 1.1 cgd struct val *op_minus ();
35 1.1 cgd struct val *op_times ();
36 1.1 cgd struct val *op_div ();
37 1.1 cgd struct val *op_rem ();
38 1.1 cgd struct val *op_colon ();
39 1.1 cgd
40 1.1 cgd char **av;
41 1.1 cgd %}
42 1.1 cgd
43 1.1 cgd %union
44 1.1 cgd {
45 1.1 cgd struct val *val;
46 1.1 cgd }
47 1.1 cgd
48 1.1 cgd %left <val> '|'
49 1.1 cgd %left <val> '&'
50 1.1 cgd %left <val> '=' '>' '<' GE LE NE
51 1.1 cgd %left <val> '+' '-'
52 1.1 cgd %left <val> '*' '/' '%'
53 1.1 cgd %left <val> ':'
54 1.1 cgd %left UNARY
55 1.1 cgd
56 1.1 cgd %token <val> TOKEN
57 1.1 cgd %type <val> start expr
58 1.1 cgd
59 1.1 cgd %%
60 1.1 cgd
61 1.1 cgd start: expr { result = $$; }
62 1.1 cgd
63 1.1 cgd expr: TOKEN
64 1.1 cgd | '(' expr ')' { $$ = $2; }
65 1.1 cgd | expr '|' expr { $$ = op_or ($1, $3); }
66 1.1 cgd | expr '&' expr { $$ = op_and ($1, $3); }
67 1.1 cgd | expr '=' expr { $$ = op_eq ($1, $3); }
68 1.1 cgd | expr '>' expr { $$ = op_gt ($1, $3); }
69 1.1 cgd | expr '<' expr { $$ = op_lt ($1, $3); }
70 1.1 cgd | expr GE expr { $$ = op_ge ($1, $3); }
71 1.1 cgd | expr LE expr { $$ = op_le ($1, $3); }
72 1.1 cgd | expr NE expr { $$ = op_ne ($1, $3); }
73 1.1 cgd | expr '+' expr { $$ = op_plus ($1, $3); }
74 1.1 cgd | expr '-' expr { $$ = op_minus ($1, $3); }
75 1.1 cgd | expr '*' expr { $$ = op_times ($1, $3); }
76 1.1 cgd | expr '/' expr { $$ = op_div ($1, $3); }
77 1.1 cgd | expr '%' expr { $$ = op_rem ($1, $3); }
78 1.1 cgd | expr ':' expr { $$ = op_colon ($1, $3); }
79 1.1 cgd | '-' expr %prec UNARY { $$ = op_minus (NULL, $2); }
80 1.1 cgd ;
81 1.1 cgd
82 1.1 cgd
83 1.1 cgd %%
84 1.1 cgd
85 1.1 cgd struct val *
86 1.4 cgd make_integer (i)
87 1.4 cgd int i;
88 1.4 cgd {
89 1.4 cgd struct val *vp;
90 1.4 cgd
91 1.5 cgd vp = (struct val *) malloc (sizeof (*vp));
92 1.4 cgd if (vp == NULL) {
93 1.4 cgd fprintf (stderr, "expr: out of memory\n");
94 1.4 cgd exit (2);
95 1.4 cgd }
96 1.4 cgd
97 1.4 cgd vp->type = integer;
98 1.4 cgd vp->u.i = i;
99 1.4 cgd return vp;
100 1.4 cgd }
101 1.4 cgd
102 1.4 cgd struct val *
103 1.4 cgd make_str (s)
104 1.4 cgd char *s;
105 1.1 cgd {
106 1.1 cgd struct val *vp;
107 1.1 cgd
108 1.5 cgd vp = (struct val *) malloc (sizeof (*vp));
109 1.4 cgd if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) {
110 1.4 cgd fprintf (stderr, "expr: out of memory\n");
111 1.1 cgd exit (2);
112 1.1 cgd }
113 1.1 cgd
114 1.4 cgd vp->type = string;
115 1.4 cgd return vp;
116 1.4 cgd }
117 1.4 cgd
118 1.4 cgd
119 1.4 cgd void
120 1.4 cgd free_value (vp)
121 1.4 cgd struct val *vp;
122 1.4 cgd {
123 1.4 cgd if (vp->type == string)
124 1.4 cgd free (vp->u.s);
125 1.4 cgd }
126 1.4 cgd
127 1.1 cgd
128 1.4 cgd int
129 1.4 cgd to_integer (vp)
130 1.4 cgd struct val *vp;
131 1.4 cgd {
132 1.4 cgd char *s;
133 1.4 cgd int neg;
134 1.4 cgd int i;
135 1.4 cgd
136 1.4 cgd if (vp->type == integer)
137 1.4 cgd return 1;
138 1.4 cgd
139 1.4 cgd s = vp->u.s;
140 1.4 cgd i = 0;
141 1.4 cgd
142 1.4 cgd neg = (*s == '-');
143 1.4 cgd if (neg)
144 1.4 cgd s++;
145 1.4 cgd
146 1.4 cgd for (;*s; s++) {
147 1.4 cgd if (!isdigit (*s))
148 1.4 cgd return 0;
149 1.4 cgd
150 1.4 cgd i *= 10;
151 1.4 cgd i += *s - '0';
152 1.1 cgd }
153 1.1 cgd
154 1.4 cgd free (vp->u.s);
155 1.4 cgd if (neg)
156 1.4 cgd i *= -1;
157 1.4 cgd
158 1.4 cgd vp->type = integer;
159 1.4 cgd vp->u.i = i;
160 1.4 cgd return 1;
161 1.1 cgd }
162 1.1 cgd
163 1.4 cgd void
164 1.4 cgd to_string (vp)
165 1.4 cgd struct val *vp;
166 1.1 cgd {
167 1.4 cgd char *tmp;
168 1.4 cgd
169 1.4 cgd if (vp->type == string)
170 1.4 cgd return;
171 1.4 cgd
172 1.4 cgd tmp = malloc (25);
173 1.4 cgd if (tmp == NULL) {
174 1.4 cgd fprintf (stderr, "expr: out of memory\n");
175 1.4 cgd exit (2);
176 1.4 cgd }
177 1.4 cgd
178 1.4 cgd sprintf (tmp, "%d", vp->u.i);
179 1.4 cgd vp->type = string;
180 1.4 cgd vp->u.s = tmp;
181 1.4 cgd }
182 1.4 cgd
183 1.1 cgd
184 1.4 cgd int
185 1.4 cgd isstring (vp)
186 1.4 cgd struct val *vp;
187 1.4 cgd {
188 1.4 cgd return (vp->type == string);
189 1.1 cgd }
190 1.1 cgd
191 1.4 cgd
192 1.1 cgd int
193 1.1 cgd yylex ()
194 1.1 cgd {
195 1.1 cgd struct val *vp;
196 1.1 cgd char *p;
197 1.1 cgd
198 1.1 cgd if (*av == NULL)
199 1.1 cgd return (0);
200 1.1 cgd
201 1.1 cgd p = *av++;
202 1.1 cgd
203 1.1 cgd if (strlen (p) == 1) {
204 1.4 cgd if (strchr ("|&=<>+-*/%:()", *p))
205 1.1 cgd return (*p);
206 1.1 cgd } else if (strlen (p) == 2 && p[1] == '=') {
207 1.1 cgd switch (*p) {
208 1.1 cgd case '>': return (GE);
209 1.1 cgd case '<': return (LE);
210 1.1 cgd case '!': return (NE);
211 1.1 cgd }
212 1.1 cgd }
213 1.1 cgd
214 1.4 cgd yylval.val = make_str (p);
215 1.1 cgd return (TOKEN);
216 1.1 cgd }
217 1.1 cgd
218 1.1 cgd int
219 1.1 cgd is_zero_or_null (vp)
220 1.1 cgd struct val *vp;
221 1.1 cgd {
222 1.5 cgd /* Like most other versions of expr, this version will return
223 1.5 cgd false for a string value of multiple zeros.*/
224 1.5 cgd
225 1.4 cgd if (vp->type == integer) {
226 1.5 cgd return (vp->u.i == 0);
227 1.4 cgd } else {
228 1.5 cgd return (*vp->u.s == 0 || strcmp (vp->u.s, "0") == 0);
229 1.4 cgd }
230 1.5 cgd /* NOTREACHED */
231 1.1 cgd }
232 1.1 cgd
233 1.1 cgd void
234 1.1 cgd main (argc, argv)
235 1.1 cgd int argc;
236 1.1 cgd char **argv;
237 1.1 cgd {
238 1.1 cgd av = argv + 1;
239 1.1 cgd
240 1.1 cgd yyparse ();
241 1.1 cgd
242 1.4 cgd if (result->type == integer)
243 1.4 cgd printf ("%d\n", result->u.i);
244 1.1 cgd else
245 1.4 cgd printf ("%s\n", result->u.s);
246 1.1 cgd
247 1.1 cgd if (is_zero_or_null (result))
248 1.1 cgd exit (1);
249 1.1 cgd else
250 1.1 cgd exit (0);
251 1.1 cgd }
252 1.1 cgd
253 1.1 cgd int
254 1.1 cgd yyerror (s)
255 1.1 cgd char *s;
256 1.1 cgd {
257 1.4 cgd fprintf (stderr, "expr: syntax error\n");
258 1.1 cgd exit (2);
259 1.1 cgd }
260 1.1 cgd
261 1.1 cgd
262 1.1 cgd struct val *
263 1.1 cgd op_or (a, b)
264 1.1 cgd struct val *a, *b;
265 1.1 cgd {
266 1.4 cgd if (is_zero_or_null (a)) {
267 1.4 cgd free_value (a);
268 1.1 cgd return (b);
269 1.4 cgd } else {
270 1.4 cgd free_value (b);
271 1.1 cgd return (a);
272 1.4 cgd }
273 1.1 cgd }
274 1.1 cgd
275 1.1 cgd struct val *
276 1.1 cgd op_and (a, b)
277 1.1 cgd struct val *a, *b;
278 1.1 cgd {
279 1.4 cgd if (is_zero_or_null (a) || is_zero_or_null (b)) {
280 1.4 cgd free_value (a);
281 1.4 cgd free_value (b);
282 1.1 cgd return (make_integer (0));
283 1.4 cgd } else {
284 1.4 cgd free_value (b);
285 1.1 cgd return (a);
286 1.4 cgd }
287 1.1 cgd }
288 1.1 cgd
289 1.1 cgd struct val *
290 1.1 cgd op_eq (a, b)
291 1.1 cgd struct val *a, *b;
292 1.1 cgd {
293 1.4 cgd struct val *r;
294 1.4 cgd
295 1.4 cgd /* attempt to coerce both arguments to integers */
296 1.4 cgd (void) to_integer (a);
297 1.4 cgd (void) to_integer (b);
298 1.4 cgd
299 1.4 cgd /* But if either one of them really is a string, do
300 1.4 cgd a string comparison */
301 1.4 cgd if (isstring (a) || isstring (b)) {
302 1.4 cgd to_string (a);
303 1.4 cgd to_string (b);
304 1.4 cgd r = make_integer (strcmp (a->u.s, b->u.s) == 0);
305 1.4 cgd } else {
306 1.4 cgd r = make_integer (a->u.i == b->u.i);
307 1.4 cgd }
308 1.4 cgd
309 1.4 cgd free_value (a);
310 1.4 cgd free_value (b);
311 1.4 cgd return r;
312 1.1 cgd }
313 1.1 cgd
314 1.1 cgd struct val *
315 1.1 cgd op_gt (a, b)
316 1.1 cgd struct val *a, *b;
317 1.1 cgd {
318 1.4 cgd struct val *r;
319 1.4 cgd
320 1.4 cgd /* attempt to coerce both arguments to integers */
321 1.4 cgd (void) to_integer (a);
322 1.4 cgd (void) to_integer (b);
323 1.4 cgd
324 1.4 cgd /* But if either one of them really is a string, do
325 1.4 cgd a string comparison */
326 1.4 cgd if (isstring (a) || isstring (b)) {
327 1.4 cgd to_string (a);
328 1.4 cgd to_string (b);
329 1.4 cgd r = make_integer (strcmp (a->u.s, b->u.s) > 0);
330 1.4 cgd } else {
331 1.4 cgd r= make_integer (a->u.i > b->u.i);
332 1.4 cgd }
333 1.4 cgd
334 1.4 cgd free_value (a);
335 1.4 cgd free_value (b);
336 1.4 cgd return r;
337 1.1 cgd }
338 1.1 cgd
339 1.1 cgd struct val *
340 1.1 cgd op_lt (a, b)
341 1.1 cgd struct val *a, *b;
342 1.1 cgd {
343 1.4 cgd struct val *r;
344 1.4 cgd
345 1.4 cgd /* attempt to coerce both arguments to integers */
346 1.4 cgd (void) to_integer (a);
347 1.4 cgd (void) to_integer (b);
348 1.4 cgd
349 1.4 cgd /* But if either one of them really is a string, do
350 1.4 cgd a string comparison */
351 1.4 cgd if (isstring (a) || isstring (b)) {
352 1.4 cgd to_string (a);
353 1.4 cgd to_string (b);
354 1.4 cgd r = make_integer (strcmp (a->u.s, b->u.s) < 0);
355 1.4 cgd } else {
356 1.4 cgd r = make_integer (a->u.i < b->u.i);
357 1.4 cgd }
358 1.4 cgd
359 1.4 cgd free_value (a);
360 1.4 cgd free_value (b);
361 1.4 cgd return r;
362 1.1 cgd }
363 1.1 cgd
364 1.1 cgd struct val *
365 1.1 cgd op_ge (a, b)
366 1.1 cgd struct val *a, *b;
367 1.1 cgd {
368 1.4 cgd struct val *r;
369 1.4 cgd
370 1.4 cgd /* attempt to coerce both arguments to integers */
371 1.4 cgd (void) to_integer (a);
372 1.4 cgd (void) to_integer (b);
373 1.4 cgd
374 1.4 cgd /* But if either one of them really is a string, do
375 1.4 cgd a string comparison */
376 1.4 cgd if (isstring (a) || isstring (b)) {
377 1.4 cgd to_string (a);
378 1.4 cgd to_string (b);
379 1.4 cgd r = make_integer (strcmp (a->u.s, b->u.s) >= 0);
380 1.4 cgd } else {
381 1.4 cgd r = make_integer (a->u.i >= b->u.i);
382 1.4 cgd }
383 1.4 cgd
384 1.4 cgd free_value (a);
385 1.4 cgd free_value (b);
386 1.4 cgd return r;
387 1.1 cgd }
388 1.1 cgd
389 1.1 cgd struct val *
390 1.1 cgd op_le (a, b)
391 1.1 cgd struct val *a, *b;
392 1.1 cgd {
393 1.4 cgd struct val *r;
394 1.4 cgd
395 1.4 cgd /* attempt to coerce both arguments to integers */
396 1.4 cgd (void) to_integer (a);
397 1.4 cgd (void) to_integer (b);
398 1.4 cgd
399 1.4 cgd /* But if either one of them really is a string, do
400 1.4 cgd a string comparison */
401 1.4 cgd if (isstring (a) || isstring (b)) {
402 1.4 cgd to_string (a);
403 1.4 cgd to_string (b);
404 1.4 cgd r = make_integer (strcmp (a->u.s, b->u.s) <= 0);
405 1.4 cgd } else {
406 1.4 cgd r = make_integer (a->u.i <= b->u.i);
407 1.4 cgd }
408 1.4 cgd
409 1.4 cgd free_value (a);
410 1.4 cgd free_value (b);
411 1.4 cgd return r;
412 1.1 cgd }
413 1.1 cgd
414 1.1 cgd struct val *
415 1.1 cgd op_ne (a, b)
416 1.1 cgd struct val *a, *b;
417 1.1 cgd {
418 1.4 cgd struct val *r;
419 1.4 cgd
420 1.4 cgd /* attempt to coerce both arguments to integers */
421 1.4 cgd (void) to_integer (a);
422 1.4 cgd (void) to_integer (b);
423 1.4 cgd
424 1.4 cgd /* But if either one of them really is a string, do
425 1.4 cgd a string comparison */
426 1.4 cgd if (isstring (a) || isstring (b)) {
427 1.4 cgd to_string (a);
428 1.4 cgd to_string (b);
429 1.4 cgd r = make_integer (strcmp (a->u.s, b->u.s) != 0);
430 1.4 cgd } else {
431 1.4 cgd r = make_integer (a->u.i != b->u.i);
432 1.4 cgd }
433 1.4 cgd
434 1.4 cgd free_value (a);
435 1.4 cgd free_value (b);
436 1.4 cgd return r;
437 1.1 cgd }
438 1.1 cgd
439 1.1 cgd struct val *
440 1.1 cgd op_plus (a, b)
441 1.1 cgd struct val *a, *b;
442 1.1 cgd {
443 1.4 cgd struct val *r;
444 1.4 cgd
445 1.4 cgd if (!to_integer (a) || !to_integer (b)) {
446 1.4 cgd fprintf (stderr, "expr: non-numeric argument\n");
447 1.4 cgd exit (2);
448 1.4 cgd }
449 1.1 cgd
450 1.4 cgd r = make_integer (a->u.i + b->u.i);
451 1.4 cgd free_value (a);
452 1.4 cgd free_value (b);
453 1.4 cgd return r;
454 1.1 cgd }
455 1.1 cgd
456 1.1 cgd struct val *
457 1.1 cgd op_minus (a, b)
458 1.1 cgd struct val *a, *b;
459 1.1 cgd {
460 1.4 cgd struct val *r;
461 1.4 cgd
462 1.4 cgd if (!to_integer (a) || !to_integer (b)) {
463 1.4 cgd fprintf (stderr, "expr: non-numeric argument\n");
464 1.4 cgd exit (2);
465 1.4 cgd }
466 1.1 cgd
467 1.4 cgd r = make_integer (a->u.i - b->u.i);
468 1.4 cgd free_value (a);
469 1.4 cgd free_value (b);
470 1.4 cgd return r;
471 1.1 cgd }
472 1.1 cgd
473 1.1 cgd struct val *
474 1.1 cgd op_times (a, b)
475 1.1 cgd struct val *a, *b;
476 1.1 cgd {
477 1.4 cgd struct val *r;
478 1.1 cgd
479 1.4 cgd if (!to_integer (a) || !to_integer (b)) {
480 1.4 cgd fprintf (stderr, "expr: non-numeric argument\n");
481 1.4 cgd exit (2);
482 1.4 cgd }
483 1.4 cgd
484 1.4 cgd r = make_integer (a->u.i * b->u.i);
485 1.4 cgd free_value (a);
486 1.4 cgd free_value (b);
487 1.4 cgd return (r);
488 1.1 cgd }
489 1.1 cgd
490 1.1 cgd struct val *
491 1.1 cgd op_div (a, b)
492 1.1 cgd struct val *a, *b;
493 1.1 cgd {
494 1.4 cgd struct val *r;
495 1.4 cgd
496 1.4 cgd if (!to_integer (a) || !to_integer (b)) {
497 1.4 cgd fprintf (stderr, "expr: non-numeric argument\n");
498 1.4 cgd exit (2);
499 1.4 cgd }
500 1.4 cgd
501 1.4 cgd if (b->u.i == 0) {
502 1.4 cgd fprintf (stderr, "expr: division by zero\n");
503 1.4 cgd exit (2);
504 1.4 cgd }
505 1.1 cgd
506 1.4 cgd r = make_integer (a->u.i / b->u.i);
507 1.4 cgd free_value (a);
508 1.4 cgd free_value (b);
509 1.4 cgd return r;
510 1.1 cgd }
511 1.1 cgd
512 1.1 cgd struct val *
513 1.1 cgd op_rem (a, b)
514 1.1 cgd struct val *a, *b;
515 1.1 cgd {
516 1.4 cgd struct val *r;
517 1.4 cgd
518 1.4 cgd if (!to_integer (a) || !to_integer (b)) {
519 1.4 cgd fprintf (stderr, "expr: non-numeric argument\n");
520 1.4 cgd exit (2);
521 1.4 cgd }
522 1.4 cgd
523 1.4 cgd if (b->u.i == 0) {
524 1.4 cgd fprintf (stderr, "expr: division by zero\n");
525 1.4 cgd exit (2);
526 1.4 cgd }
527 1.1 cgd
528 1.4 cgd r = make_integer (a->u.i % b->u.i);
529 1.4 cgd free_value (a);
530 1.4 cgd free_value (b);
531 1.4 cgd return r;
532 1.1 cgd }
533 1.1 cgd
534 1.6 jtc #include <regex.h>
535 1.6 jtc #define SE_MAX 30
536 1.1 cgd
537 1.1 cgd struct val *
538 1.1 cgd op_colon (a, b)
539 1.1 cgd struct val *a, *b;
540 1.1 cgd {
541 1.6 jtc regex_t rp;
542 1.6 jtc regmatch_t rm[SE_MAX];
543 1.6 jtc char errbuf[256];
544 1.6 jtc int eval;
545 1.6 jtc struct val *v;
546 1.6 jtc
547 1.7 jtc /* coerce to both arguments to strings */
548 1.7 jtc to_string(a);
549 1.7 jtc to_string(b);
550 1.6 jtc
551 1.6 jtc /* compile regular expression */
552 1.7 jtc if ((eval = regcomp (&rp, b->u.s, 0)) != 0) {
553 1.6 jtc regerror (eval, &rp, errbuf, sizeof(errbuf));
554 1.6 jtc fprintf (stderr, "expr: %s\n", errbuf);
555 1.6 jtc exit (2);
556 1.6 jtc }
557 1.6 jtc free (newpat);
558 1.6 jtc
559 1.6 jtc /* compare string against pattern */
560 1.6 jtc if (regexec(&rp, a->u.s, SE_MAX, rm, 0) == 0) {
561 1.6 jtc if (rm[1].rm_so >= 0) {
562 1.6 jtc *(a->u.s + rm[1].rm_eo) = 0;
563 1.6 jtc v = make_str (a->u.s + rm[1].rm_so);
564 1.1 cgd
565 1.1 cgd } else {
566 1.6 jtc v = make_integer (rm[0].rm_eo - rm[0].rm_so);
567 1.1 cgd }
568 1.1 cgd } else {
569 1.6 jtc v = make_integer (0);
570 1.1 cgd }
571 1.6 jtc
572 1.6 jtc /* free arguments and pattern buffer */
573 1.6 jtc free_value (a);
574 1.6 jtc free_value (b);
575 1.6 jtc regfree (&rp);
576 1.5 cgd
577 1.6 jtc return v;
578 1.1 cgd }
579