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