expr.y revision 1.11 1 %{
2 /* Written by Pace Willisson (pace (at) blitz.com)
3 * and placed in the public domain.
4 *
5 * Largely rewritten by J.T. Conklin (jtc (at) wimsey.com)
6 *
7 * $Header: /tank/opengrok/rsync2/NetBSD/src/bin/expr/expr.y,v 1.11 1993/08/17 16:01:23 jtc Exp $
8 */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <ctype.h>
13 #include <err.h>
14
15 enum valtype {
16 integer, string
17 } ;
18
19 struct val {
20 enum valtype type;
21 union {
22 char *s;
23 int i;
24 } u;
25 } ;
26
27 struct val *result;
28 struct val *op_or ();
29 struct val *op_and ();
30 struct val *op_eq ();
31 struct val *op_gt ();
32 struct val *op_lt ();
33 struct val *op_ge ();
34 struct val *op_le ();
35 struct val *op_ne ();
36 struct val *op_plus ();
37 struct val *op_minus ();
38 struct val *op_times ();
39 struct val *op_div ();
40 struct val *op_rem ();
41 struct val *op_colon ();
42
43 char **av;
44 %}
45
46 %union
47 {
48 struct val *val;
49 }
50
51 %left <val> '|'
52 %left <val> '&'
53 %left <val> '=' '>' '<' GE LE NE
54 %left <val> '+' '-'
55 %left <val> '*' '/' '%'
56 %left <val> ':'
57 %left UNARY
58
59 %token <val> TOKEN
60 %type <val> start expr
61
62 %%
63
64 start: expr { result = $$; }
65
66 expr: TOKEN
67 | '(' expr ')' { $$ = $2; }
68 | expr '|' expr { $$ = op_or ($1, $3); }
69 | expr '&' expr { $$ = op_and ($1, $3); }
70 | expr '=' expr { $$ = op_eq ($1, $3); }
71 | expr '>' expr { $$ = op_gt ($1, $3); }
72 | expr '<' expr { $$ = op_lt ($1, $3); }
73 | expr GE expr { $$ = op_ge ($1, $3); }
74 | expr LE expr { $$ = op_le ($1, $3); }
75 | expr NE expr { $$ = op_ne ($1, $3); }
76 | expr '+' expr { $$ = op_plus ($1, $3); }
77 | expr '-' expr { $$ = op_minus ($1, $3); }
78 | expr '*' expr { $$ = op_times ($1, $3); }
79 | expr '/' expr { $$ = op_div ($1, $3); }
80 | expr '%' expr { $$ = op_rem ($1, $3); }
81 | expr ':' expr { $$ = op_colon ($1, $3); }
82 | '-' expr %prec UNARY { $$ = op_minus (NULL, $2); }
83 ;
84
85
86 %%
87
88 struct val *
89 make_integer (i)
90 int i;
91 {
92 struct val *vp;
93
94 vp = (struct val *) malloc (sizeof (*vp));
95 if (vp == NULL) {
96 err (2, NULL);
97 }
98
99 vp->type = integer;
100 vp->u.i = i;
101 return vp;
102 }
103
104 struct val *
105 make_str (s)
106 char *s;
107 {
108 struct val *vp;
109
110 vp = (struct val *) malloc (sizeof (*vp));
111 if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) {
112 err (2, NULL);
113 }
114
115 vp->type = string;
116 return vp;
117 }
118
119
120 void
121 free_value (vp)
122 struct val *vp;
123 {
124 if (vp->type == string)
125 free (vp->u.s);
126 }
127
128
129 int
130 to_integer (vp)
131 struct val *vp;
132 {
133 char *s;
134 int neg;
135 int i;
136
137 if (vp->type == integer)
138 return 1;
139
140 s = vp->u.s;
141 i = 0;
142
143 neg = (*s == '-');
144 if (neg)
145 s++;
146
147 for (;*s; s++) {
148 if (!isdigit (*s))
149 return 0;
150
151 i *= 10;
152 i += *s - '0';
153 }
154
155 free (vp->u.s);
156 if (neg)
157 i *= -1;
158
159 vp->type = integer;
160 vp->u.i = i;
161 return 1;
162 }
163
164 void
165 to_string (vp)
166 struct val *vp;
167 {
168 char *tmp;
169
170 if (vp->type == string)
171 return;
172
173 tmp = malloc (25);
174 if (tmp == NULL) {
175 err (2, NULL);
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 if (vp->type == integer) {
223 return (vp->u.i == 0);
224 } else {
225 return (*vp->u.s == 0 || (to_integer (vp) && vp->u.i == 0));
226 }
227 /* NOTREACHED */
228 }
229
230 void
231 main (argc, argv)
232 int argc;
233 char **argv;
234 {
235 av = argv + 1;
236
237 yyparse ();
238
239 if (result->type == integer)
240 printf ("%d\n", result->u.i);
241 else
242 printf ("%s\n", result->u.s);
243
244 if (is_zero_or_null (result))
245 exit (1);
246 else
247 exit (0);
248 }
249
250 int
251 yyerror (s)
252 char *s;
253 {
254 errx (2, "syntax error");
255 }
256
257
258 struct val *
259 op_or (a, b)
260 struct val *a, *b;
261 {
262 if (is_zero_or_null (a)) {
263 free_value (a);
264 return (b);
265 } else {
266 free_value (b);
267 return (a);
268 }
269 }
270
271 struct val *
272 op_and (a, b)
273 struct val *a, *b;
274 {
275 if (is_zero_or_null (a) || is_zero_or_null (b)) {
276 free_value (a);
277 free_value (b);
278 return (make_integer (0));
279 } else {
280 free_value (b);
281 return (a);
282 }
283 }
284
285 struct val *
286 op_eq (a, b)
287 struct val *a, *b;
288 {
289 struct val *r;
290
291 if (isstring (a) || isstring (b)) {
292 to_string (a);
293 to_string (b);
294 r = make_integer (strcoll (a->u.s, b->u.s) == 0);
295 } else {
296 r = make_integer (a->u.i == b->u.i);
297 }
298
299 free_value (a);
300 free_value (b);
301 return r;
302 }
303
304 struct val *
305 op_gt (a, b)
306 struct val *a, *b;
307 {
308 struct val *r;
309
310 if (isstring (a) || isstring (b)) {
311 to_string (a);
312 to_string (b);
313 r = make_integer (strcoll (a->u.s, b->u.s) > 0);
314 } else {
315 r= make_integer (a->u.i > b->u.i);
316 }
317
318 free_value (a);
319 free_value (b);
320 return r;
321 }
322
323 struct val *
324 op_lt (a, b)
325 struct 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
342 struct val *
343 op_ge (a, b)
344 struct 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
361 struct val *
362 op_le (a, b)
363 struct 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
380 struct val *
381 op_ne (a, b)
382 struct 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
399 struct val *
400 op_plus (a, b)
401 struct 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
415 struct val *
416 op_minus (a, b)
417 struct 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
431 struct val *
432 op_times (a, b)
433 struct 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
447 struct val *
448 op_div (a, b)
449 struct 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
467 struct val *
468 op_rem (a, b)
469 struct 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 #define SE_MAX 30
489
490 struct val *
491 op_colon (a, b)
492 struct val *a, *b;
493 {
494 regex_t rp;
495 regmatch_t rm[SE_MAX];
496 char errbuf[256];
497 int eval;
498 struct val *v;
499 char *newpat;
500
501 /* coerce to both arguments to strings */
502 to_string(a);
503 to_string(b);
504
505 /* patterns are anchored to the beginning of the line */
506 newpat = malloc (strlen (b->u.s) + 2);
507 strcpy (newpat, "^");
508 strcat (newpat, b->u.s);
509
510 /* compile regular expression */
511 if ((eval = regcomp (&rp, newpat, 0)) != 0) {
512 regerror (eval, &rp, errbuf, sizeof(errbuf));
513 errx (2, "%s", errbuf);
514 }
515 free (newpat);
516
517 /* compare string against pattern */
518 if (regexec(&rp, a->u.s, SE_MAX, rm, 0) == 0) {
519 if (rm[1].rm_so >= 0) {
520 *(a->u.s + rm[1].rm_eo) = '\0';
521 v = make_str (a->u.s + rm[1].rm_so);
522
523 } else {
524 v = make_integer (rm[0].rm_eo - rm[0].rm_so);
525 }
526 } else {
527 if (rp.re_nsub == 0) {
528 v = make_integer (0);
529 } else {
530 v = make_str ("");
531 }
532 }
533
534 /* free arguments and pattern buffer */
535 free_value (a);
536 free_value (b);
537 regfree (&rp);
538
539 return v;
540 }
541