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