expr.y revision 1.8 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.8 jtc * $Header: /tank/opengrok/rsync2/NetBSD/src/bin/expr/expr.y,v 1.8 1993/07/20 00:52:57 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 if (isstring (a) || isstring (b)) {
296 1.4 cgd to_string (a);
297 1.4 cgd to_string (b);
298 1.4 cgd r = make_integer (strcmp (a->u.s, b->u.s) == 0);
299 1.4 cgd } else {
300 1.4 cgd r = make_integer (a->u.i == b->u.i);
301 1.4 cgd }
302 1.4 cgd
303 1.4 cgd free_value (a);
304 1.4 cgd free_value (b);
305 1.4 cgd return r;
306 1.1 cgd }
307 1.1 cgd
308 1.1 cgd struct val *
309 1.1 cgd op_gt (a, b)
310 1.1 cgd struct val *a, *b;
311 1.1 cgd {
312 1.4 cgd struct val *r;
313 1.4 cgd
314 1.4 cgd if (isstring (a) || isstring (b)) {
315 1.4 cgd to_string (a);
316 1.4 cgd to_string (b);
317 1.4 cgd r = make_integer (strcmp (a->u.s, b->u.s) > 0);
318 1.4 cgd } else {
319 1.4 cgd r= make_integer (a->u.i > b->u.i);
320 1.4 cgd }
321 1.4 cgd
322 1.4 cgd free_value (a);
323 1.4 cgd free_value (b);
324 1.4 cgd return r;
325 1.1 cgd }
326 1.1 cgd
327 1.1 cgd struct val *
328 1.1 cgd op_lt (a, b)
329 1.1 cgd struct val *a, *b;
330 1.1 cgd {
331 1.4 cgd struct val *r;
332 1.4 cgd
333 1.4 cgd if (isstring (a) || isstring (b)) {
334 1.4 cgd to_string (a);
335 1.4 cgd to_string (b);
336 1.4 cgd r = make_integer (strcmp (a->u.s, b->u.s) < 0);
337 1.4 cgd } else {
338 1.4 cgd r = make_integer (a->u.i < b->u.i);
339 1.4 cgd }
340 1.4 cgd
341 1.4 cgd free_value (a);
342 1.4 cgd free_value (b);
343 1.4 cgd return r;
344 1.1 cgd }
345 1.1 cgd
346 1.1 cgd struct val *
347 1.1 cgd op_ge (a, b)
348 1.1 cgd struct val *a, *b;
349 1.1 cgd {
350 1.4 cgd struct val *r;
351 1.4 cgd
352 1.4 cgd if (isstring (a) || isstring (b)) {
353 1.4 cgd to_string (a);
354 1.4 cgd to_string (b);
355 1.4 cgd r = make_integer (strcmp (a->u.s, b->u.s) >= 0);
356 1.4 cgd } else {
357 1.4 cgd r = make_integer (a->u.i >= b->u.i);
358 1.4 cgd }
359 1.4 cgd
360 1.4 cgd free_value (a);
361 1.4 cgd free_value (b);
362 1.4 cgd return r;
363 1.1 cgd }
364 1.1 cgd
365 1.1 cgd struct val *
366 1.1 cgd op_le (a, b)
367 1.1 cgd struct val *a, *b;
368 1.1 cgd {
369 1.4 cgd struct val *r;
370 1.4 cgd
371 1.4 cgd if (isstring (a) || isstring (b)) {
372 1.4 cgd to_string (a);
373 1.4 cgd to_string (b);
374 1.4 cgd r = make_integer (strcmp (a->u.s, b->u.s) <= 0);
375 1.4 cgd } else {
376 1.4 cgd r = make_integer (a->u.i <= b->u.i);
377 1.4 cgd }
378 1.4 cgd
379 1.4 cgd free_value (a);
380 1.4 cgd free_value (b);
381 1.4 cgd return r;
382 1.1 cgd }
383 1.1 cgd
384 1.1 cgd struct val *
385 1.1 cgd op_ne (a, b)
386 1.1 cgd struct val *a, *b;
387 1.1 cgd {
388 1.4 cgd struct val *r;
389 1.4 cgd
390 1.4 cgd if (isstring (a) || isstring (b)) {
391 1.4 cgd to_string (a);
392 1.4 cgd to_string (b);
393 1.4 cgd r = make_integer (strcmp (a->u.s, b->u.s) != 0);
394 1.4 cgd } else {
395 1.4 cgd r = make_integer (a->u.i != b->u.i);
396 1.4 cgd }
397 1.4 cgd
398 1.4 cgd free_value (a);
399 1.4 cgd free_value (b);
400 1.4 cgd return r;
401 1.1 cgd }
402 1.1 cgd
403 1.1 cgd struct val *
404 1.1 cgd op_plus (a, b)
405 1.1 cgd struct val *a, *b;
406 1.1 cgd {
407 1.4 cgd struct val *r;
408 1.4 cgd
409 1.4 cgd if (!to_integer (a) || !to_integer (b)) {
410 1.4 cgd fprintf (stderr, "expr: non-numeric argument\n");
411 1.4 cgd exit (2);
412 1.4 cgd }
413 1.1 cgd
414 1.4 cgd r = make_integer (a->u.i + b->u.i);
415 1.4 cgd free_value (a);
416 1.4 cgd free_value (b);
417 1.4 cgd return r;
418 1.1 cgd }
419 1.1 cgd
420 1.1 cgd struct val *
421 1.1 cgd op_minus (a, b)
422 1.1 cgd struct val *a, *b;
423 1.1 cgd {
424 1.4 cgd struct val *r;
425 1.4 cgd
426 1.4 cgd if (!to_integer (a) || !to_integer (b)) {
427 1.4 cgd fprintf (stderr, "expr: non-numeric argument\n");
428 1.4 cgd exit (2);
429 1.4 cgd }
430 1.1 cgd
431 1.4 cgd r = make_integer (a->u.i - b->u.i);
432 1.4 cgd free_value (a);
433 1.4 cgd free_value (b);
434 1.4 cgd return r;
435 1.1 cgd }
436 1.1 cgd
437 1.1 cgd struct val *
438 1.1 cgd op_times (a, b)
439 1.1 cgd struct val *a, *b;
440 1.1 cgd {
441 1.4 cgd struct val *r;
442 1.1 cgd
443 1.4 cgd if (!to_integer (a) || !to_integer (b)) {
444 1.4 cgd fprintf (stderr, "expr: non-numeric argument\n");
445 1.4 cgd exit (2);
446 1.4 cgd }
447 1.4 cgd
448 1.4 cgd r = make_integer (a->u.i * b->u.i);
449 1.4 cgd free_value (a);
450 1.4 cgd free_value (b);
451 1.4 cgd return (r);
452 1.1 cgd }
453 1.1 cgd
454 1.1 cgd struct val *
455 1.1 cgd op_div (a, b)
456 1.1 cgd struct val *a, *b;
457 1.1 cgd {
458 1.4 cgd struct val *r;
459 1.4 cgd
460 1.4 cgd if (!to_integer (a) || !to_integer (b)) {
461 1.4 cgd fprintf (stderr, "expr: non-numeric argument\n");
462 1.4 cgd exit (2);
463 1.4 cgd }
464 1.4 cgd
465 1.4 cgd if (b->u.i == 0) {
466 1.4 cgd fprintf (stderr, "expr: division by zero\n");
467 1.4 cgd exit (2);
468 1.4 cgd }
469 1.1 cgd
470 1.4 cgd r = make_integer (a->u.i / b->u.i);
471 1.4 cgd free_value (a);
472 1.4 cgd free_value (b);
473 1.4 cgd return r;
474 1.1 cgd }
475 1.1 cgd
476 1.1 cgd struct val *
477 1.1 cgd op_rem (a, b)
478 1.1 cgd struct val *a, *b;
479 1.1 cgd {
480 1.4 cgd struct val *r;
481 1.4 cgd
482 1.4 cgd if (!to_integer (a) || !to_integer (b)) {
483 1.4 cgd fprintf (stderr, "expr: non-numeric argument\n");
484 1.4 cgd exit (2);
485 1.4 cgd }
486 1.4 cgd
487 1.4 cgd if (b->u.i == 0) {
488 1.4 cgd fprintf (stderr, "expr: division by zero\n");
489 1.4 cgd exit (2);
490 1.4 cgd }
491 1.1 cgd
492 1.4 cgd r = make_integer (a->u.i % b->u.i);
493 1.4 cgd free_value (a);
494 1.4 cgd free_value (b);
495 1.4 cgd return r;
496 1.1 cgd }
497 1.1 cgd
498 1.6 jtc #include <regex.h>
499 1.6 jtc #define SE_MAX 30
500 1.1 cgd
501 1.1 cgd struct val *
502 1.1 cgd op_colon (a, b)
503 1.1 cgd struct val *a, *b;
504 1.1 cgd {
505 1.6 jtc regex_t rp;
506 1.6 jtc regmatch_t rm[SE_MAX];
507 1.6 jtc char errbuf[256];
508 1.6 jtc int eval;
509 1.6 jtc struct val *v;
510 1.6 jtc
511 1.7 jtc /* coerce to both arguments to strings */
512 1.7 jtc to_string(a);
513 1.7 jtc to_string(b);
514 1.6 jtc
515 1.6 jtc /* compile regular expression */
516 1.7 jtc if ((eval = regcomp (&rp, b->u.s, 0)) != 0) {
517 1.6 jtc regerror (eval, &rp, errbuf, sizeof(errbuf));
518 1.6 jtc fprintf (stderr, "expr: %s\n", errbuf);
519 1.6 jtc exit (2);
520 1.6 jtc }
521 1.6 jtc
522 1.6 jtc /* compare string against pattern */
523 1.6 jtc if (regexec(&rp, a->u.s, SE_MAX, rm, 0) == 0) {
524 1.6 jtc if (rm[1].rm_so >= 0) {
525 1.6 jtc *(a->u.s + rm[1].rm_eo) = 0;
526 1.6 jtc v = make_str (a->u.s + rm[1].rm_so);
527 1.1 cgd
528 1.1 cgd } else {
529 1.6 jtc v = make_integer (rm[0].rm_eo - rm[0].rm_so);
530 1.1 cgd }
531 1.1 cgd } else {
532 1.6 jtc v = make_integer (0);
533 1.1 cgd }
534 1.6 jtc
535 1.6 jtc /* free arguments and pattern buffer */
536 1.6 jtc free_value (a);
537 1.6 jtc free_value (b);
538 1.6 jtc regfree (&rp);
539 1.5 cgd
540 1.6 jtc return v;
541 1.1 cgd }
542