expr.y revision 1.10 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.10 1993/08/16 23:20:22 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 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 fprintf (stderr, "expr: syntax error\n");
255 exit (2);
256 }
257
258
259 struct val *
260 op_or (a, b)
261 struct val *a, *b;
262 {
263 if (is_zero_or_null (a)) {
264 free_value (a);
265 return (b);
266 } else {
267 free_value (b);
268 return (a);
269 }
270 }
271
272 struct val *
273 op_and (a, b)
274 struct val *a, *b;
275 {
276 if (is_zero_or_null (a) || is_zero_or_null (b)) {
277 free_value (a);
278 free_value (b);
279 return (make_integer (0));
280 } else {
281 free_value (b);
282 return (a);
283 }
284 }
285
286 struct val *
287 op_eq (a, b)
288 struct val *a, *b;
289 {
290 struct val *r;
291
292 if (isstring (a) || isstring (b)) {
293 to_string (a);
294 to_string (b);
295 r = make_integer (strcoll (a->u.s, b->u.s) == 0);
296 } else {
297 r = make_integer (a->u.i == b->u.i);
298 }
299
300 free_value (a);
301 free_value (b);
302 return r;
303 }
304
305 struct val *
306 op_gt (a, b)
307 struct val *a, *b;
308 {
309 struct val *r;
310
311 if (isstring (a) || isstring (b)) {
312 to_string (a);
313 to_string (b);
314 r = make_integer (strcoll (a->u.s, b->u.s) > 0);
315 } else {
316 r= make_integer (a->u.i > b->u.i);
317 }
318
319 free_value (a);
320 free_value (b);
321 return r;
322 }
323
324 struct val *
325 op_lt (a, b)
326 struct val *a, *b;
327 {
328 struct val *r;
329
330 if (isstring (a) || isstring (b)) {
331 to_string (a);
332 to_string (b);
333 r = make_integer (strcoll (a->u.s, b->u.s) < 0);
334 } else {
335 r = make_integer (a->u.i < b->u.i);
336 }
337
338 free_value (a);
339 free_value (b);
340 return r;
341 }
342
343 struct val *
344 op_ge (a, b)
345 struct val *a, *b;
346 {
347 struct val *r;
348
349 if (isstring (a) || isstring (b)) {
350 to_string (a);
351 to_string (b);
352 r = make_integer (strcoll (a->u.s, b->u.s) >= 0);
353 } else {
354 r = make_integer (a->u.i >= b->u.i);
355 }
356
357 free_value (a);
358 free_value (b);
359 return r;
360 }
361
362 struct val *
363 op_le (a, b)
364 struct val *a, *b;
365 {
366 struct val *r;
367
368 if (isstring (a) || isstring (b)) {
369 to_string (a);
370 to_string (b);
371 r = make_integer (strcoll (a->u.s, b->u.s) <= 0);
372 } else {
373 r = make_integer (a->u.i <= b->u.i);
374 }
375
376 free_value (a);
377 free_value (b);
378 return r;
379 }
380
381 struct val *
382 op_ne (a, b)
383 struct val *a, *b;
384 {
385 struct val *r;
386
387 if (isstring (a) || isstring (b)) {
388 to_string (a);
389 to_string (b);
390 r = make_integer (strcoll (a->u.s, b->u.s) != 0);
391 } else {
392 r = make_integer (a->u.i != b->u.i);
393 }
394
395 free_value (a);
396 free_value (b);
397 return r;
398 }
399
400 struct val *
401 op_plus (a, b)
402 struct val *a, *b;
403 {
404 struct val *r;
405
406 if (!to_integer (a) || !to_integer (b)) {
407 fprintf (stderr, "expr: non-numeric argument\n");
408 exit (2);
409 }
410
411 r = make_integer (a->u.i + b->u.i);
412 free_value (a);
413 free_value (b);
414 return r;
415 }
416
417 struct val *
418 op_minus (a, b)
419 struct val *a, *b;
420 {
421 struct val *r;
422
423 if (!to_integer (a) || !to_integer (b)) {
424 fprintf (stderr, "expr: non-numeric argument\n");
425 exit (2);
426 }
427
428 r = make_integer (a->u.i - b->u.i);
429 free_value (a);
430 free_value (b);
431 return r;
432 }
433
434 struct val *
435 op_times (a, b)
436 struct val *a, *b;
437 {
438 struct val *r;
439
440 if (!to_integer (a) || !to_integer (b)) {
441 fprintf (stderr, "expr: non-numeric argument\n");
442 exit (2);
443 }
444
445 r = make_integer (a->u.i * b->u.i);
446 free_value (a);
447 free_value (b);
448 return (r);
449 }
450
451 struct val *
452 op_div (a, b)
453 struct val *a, *b;
454 {
455 struct val *r;
456
457 if (!to_integer (a) || !to_integer (b)) {
458 fprintf (stderr, "expr: non-numeric argument\n");
459 exit (2);
460 }
461
462 if (b->u.i == 0) {
463 fprintf (stderr, "expr: division by zero\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_rem (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 if (b->u.i == 0) {
485 fprintf (stderr, "expr: division by zero\n");
486 exit (2);
487 }
488
489 r = make_integer (a->u.i % b->u.i);
490 free_value (a);
491 free_value (b);
492 return r;
493 }
494
495 #include <regex.h>
496 #define SE_MAX 30
497
498 struct val *
499 op_colon (a, b)
500 struct val *a, *b;
501 {
502 regex_t rp;
503 regmatch_t rm[SE_MAX];
504 char errbuf[256];
505 int eval;
506 struct val *v;
507 char *newpat;
508
509 /* coerce to both arguments to strings */
510 to_string(a);
511 to_string(b);
512
513 /* patterns are anchored to the beginning of the line */
514 newpat = malloc (strlen (b->u.s) + 2);
515 strcpy (newpat, "^");
516 strcat (newpat, b->u.s);
517
518 /* compile regular expression */
519 if ((eval = regcomp (&rp, newpat, 0)) != 0) {
520 regerror (eval, &rp, errbuf, sizeof(errbuf));
521 fprintf (stderr, "expr: %s\n", errbuf);
522 exit (2);
523 }
524 free (newpat);
525
526 /* compare string against pattern */
527 if (regexec(&rp, a->u.s, SE_MAX, rm, 0) == 0) {
528 if (rm[1].rm_so >= 0) {
529 *(a->u.s + rm[1].rm_eo) = 0;
530 v = make_str (a->u.s + rm[1].rm_so);
531
532 } else {
533 v = make_integer (rm[0].rm_eo - rm[0].rm_so);
534 }
535 } else {
536 v = make_integer (0);
537 }
538
539 /* free arguments and pattern buffer */
540 free_value (a);
541 free_value (b);
542 regfree (&rp);
543
544 return v;
545 }
546