autofs: Sync autofs(5) with FreeBSD
[dragonfly.git] / bin / expr / expr.y
1 %{
2 /* Written by Pace Willisson (pace@blitz.com) 
3  * and placed in the public domain.
4  *
5  * Largely rewritten by J.T. Conklin (jtc@wimsey.com)
6  *
7  * $FreeBSD: src/bin/expr/expr.y,v 1.14.2.3 2001/08/01 02:37:46 obrien Exp $
8  */
9
10 #include <sys/types.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <locale.h>
15 #include <ctype.h>
16 #include <err.h>
17 #include <errno.h>
18 #include <regex.h>
19 #include <limits.h>
20   
21 enum valtype {
22         integer, numeric_string, string
23 } ;
24
25 struct val {
26         enum valtype type;
27         union {
28                 char *s;
29                 quad_t i;
30         } u;
31 } ;
32
33 struct val *result;
34
35 int             chk_div (quad_t, quad_t);
36 int             chk_minus (quad_t, quad_t, quad_t);
37 int             chk_plus (quad_t, quad_t, quad_t);
38 int             chk_times (quad_t, quad_t, quad_t);
39 void            free_value (struct val *);
40 int             is_zero_or_null (struct val *);
41 int             isstring (struct val *);
42 int             main (int, char **);
43 struct val      *make_integer (quad_t);
44 struct val      *make_str (const char *);
45 struct val      *op_and (struct val *, struct val *);
46 struct val      *op_colon (struct val *, struct val *);
47 struct val      *op_div (struct val *, struct val *);
48 struct val      *op_eq (struct val *, struct val *);
49 struct val      *op_ge (struct val *, struct val *);
50 struct val      *op_gt (struct val *, struct val *);
51 struct val      *op_le (struct val *, struct val *);
52 struct val      *op_lt (struct val *, struct val *);
53 struct val      *op_minus (struct val *, struct val *);
54 struct val      *op_ne (struct val *, struct val *);
55 struct val      *op_or (struct val *, struct val *);
56 struct val      *op_plus (struct val *, struct val *);
57 struct val      *op_rem (struct val *, struct val *);
58 struct val      *op_times (struct val *, struct val *);
59 quad_t          to_integer (struct val *);
60 void            to_string (struct val *);
61 int             yyerror (const char *) __dead2;
62 int             yylex (void);
63
64 char **av;
65 %}
66
67 %union
68 {
69         struct val *val;
70 }
71
72 %left <val> '|'
73 %left <val> '&'
74 %left <val> '=' '>' '<' GE LE NE
75 %left <val> '+' '-'
76 %left <val> '*' '/' '%'
77 %left <val> ':'
78
79 %token <val> TOKEN
80 %type <val> start expr
81
82 %%
83
84 start: expr { result = $$; }
85
86 expr:   TOKEN
87         | '(' expr ')' { $$ = $2; }
88         | expr '|' expr { $$ = op_or ($1, $3); }
89         | expr '&' expr { $$ = op_and ($1, $3); }
90         | expr '=' expr { $$ = op_eq ($1, $3); }
91         | expr '>' expr { $$ = op_gt ($1, $3); }
92         | expr '<' expr { $$ = op_lt ($1, $3); }
93         | expr GE expr  { $$ = op_ge ($1, $3); }
94         | expr LE expr  { $$ = op_le ($1, $3); }
95         | expr NE expr  { $$ = op_ne ($1, $3); }
96         | expr '+' expr { $$ = op_plus ($1, $3); }
97         | expr '-' expr { $$ = op_minus ($1, $3); }
98         | expr '*' expr { $$ = op_times ($1, $3); }
99         | expr '/' expr { $$ = op_div ($1, $3); }
100         | expr '%' expr { $$ = op_rem ($1, $3); }
101         | expr ':' expr { $$ = op_colon ($1, $3); }
102         ;
103
104
105 %%
106
107 struct val *
108 make_integer(quad_t i)
109 {
110         struct val *vp;
111
112         vp = (struct val *) malloc (sizeof (*vp));
113         if (vp == NULL) {
114                 errx (2, "malloc() failed");
115         }
116
117         vp->type = integer;
118         vp->u.i  = i;
119         return vp; 
120 }
121
122 struct val *
123 make_str(const char *s)
124 {
125         struct val *vp;
126         size_t i;
127         int isint;
128
129         vp = (struct val *) malloc (sizeof (*vp));
130         if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) {
131                 errx (2, "malloc() failed");
132         }
133
134         for(i = 1, isint = isdigit(s[0]) || s[0] == '-';
135             isint && i < strlen(s);
136             i++)
137         {
138                 if(!isdigit(s[i]))
139                          isint = 0;
140         }
141
142         if (isint)
143                 vp->type = numeric_string;
144         else    
145                 vp->type = string;
146
147         return vp;
148 }
149
150
151 void
152 free_value(struct val *vp)
153 {
154         if (vp->type == string || vp->type == numeric_string)
155                 free (vp->u.s); 
156 }
157
158
159 quad_t
160 to_integer(struct val *vp)
161 {
162         quad_t i;
163
164         if (vp->type == integer)
165                 return 1;
166
167         if (vp->type == string)
168                 return 0;
169
170         /* vp->type == numeric_string, make it numeric */
171         errno = 0;
172         i  = strtoll(vp->u.s, NULL, 10);
173         if (errno != 0) {
174                 errx (2, "overflow");
175         }
176         free (vp->u.s);
177         vp->u.i = i;
178         vp->type = integer;
179         return 1;
180 }
181
182 void
183 to_string(struct val *vp)
184 {
185         char *tmp;
186
187         if (vp->type == string || vp->type == numeric_string)
188                 return;
189
190         tmp = malloc ((size_t)25);
191         if (tmp == NULL) {
192                 errx (2, "malloc() failed");
193         }
194
195         sprintf (tmp, "%lld", (long long)vp->u.i);
196         vp->type = string;
197         vp->u.s  = tmp;
198 }
199
200
201 int
202 isstring(struct val *vp)
203 {
204         /* only TRUE if this string is not a valid integer */
205         return (vp->type == string);
206 }
207
208
209 int
210 yylex(void)
211 {
212         char *p;
213
214         if (*av == NULL)
215                 return (0);
216
217         p = *av++;
218
219         if (strlen (p) == 1) {
220                 if (strchr ("|&=<>+-*/%:()", *p))
221                         return (*p);
222         } else if (strlen (p) == 2 && p[1] == '=') {
223                 switch (*p) {
224                 case '>': return (GE);
225                 case '<': return (LE);
226                 case '!': return (NE);
227                 }
228         }
229
230         yylval.val = make_str (p);
231         return (TOKEN);
232 }
233
234 int
235 is_zero_or_null(struct val *vp)
236 {
237         if (vp->type == integer) {
238                 return (vp->u.i == 0);
239         } else {
240                 return (*vp->u.s == 0 || (to_integer (vp) && vp->u.i == 0));
241         }
242         /* NOTREACHED */
243 }
244
245 static void
246 usage(void)
247 {
248         fprintf(stderr,
249                 "usage: expr expression\n");
250         exit(EXIT_FAILURE);
251 }
252
253 int
254 main (int argc, char **argv)
255 {
256         setlocale (LC_ALL, "");
257
258         if (argc > 1 && strcmp(argv[1], "--"))
259                 av = argv + 1;
260         else if (argc > 2)
261                 av = argv + 2;
262         else
263                 usage();
264
265         yyparse ();
266
267         if (result->type == integer)
268                 printf ("%lld\n", (long long)result->u.i);
269         else
270                 printf ("%s\n", result->u.s);
271
272         return (is_zero_or_null (result));
273 }
274
275 int
276 yyerror(const char *s __unused)
277 {
278         errx (2, "syntax error");
279 }
280
281
282 struct val *
283 op_or(struct val *a, struct val *b)
284 {
285         if (is_zero_or_null (a)) {
286                 free_value (a);
287                 return (b);
288         } else {
289                 free_value (b);
290                 return (a);
291         }
292 }
293                 
294 struct val *
295 op_and(struct val *a, struct val *b)
296 {
297         if (is_zero_or_null (a) || is_zero_or_null (b)) {
298                 free_value (a);
299                 free_value (b);
300                 return (make_integer ((quad_t)0));
301         } else {
302                 free_value (b);
303                 return (a);
304         }
305 }
306
307 struct val *
308 op_eq(struct val *a, struct val *b)
309 {
310         struct val *r; 
311
312         if (isstring (a) || isstring (b)) {
313                 to_string (a);
314                 to_string (b);  
315                 r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) == 0));
316         } else {
317                 to_integer(a);
318                 to_integer(b);
319                 r = make_integer ((quad_t)(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_gt(struct val *a, struct val *b)
329 {
330         struct val *r;
331
332         if (isstring (a) || isstring (b)) {
333                 to_string (a);
334                 to_string (b);
335                 r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) > 0));
336         } else {
337                 to_integer(a);
338                 to_integer(b);
339                 r = make_integer ((quad_t)(a->u.i > b->u.i));
340         }
341
342         free_value (a);
343         free_value (b);
344         return r;
345 }
346
347 struct val *
348 op_lt(struct val *a, struct val *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 ((quad_t)(strcoll (a->u.s, b->u.s) < 0));
356         } else {
357                 to_integer(a);
358                 to_integer(b);
359                 r = make_integer ((quad_t)(a->u.i < b->u.i));
360         }
361
362         free_value (a);
363         free_value (b);
364         return r;
365 }
366
367 struct val *
368 op_ge(struct val *a, struct val *b)
369 {
370         struct val *r;
371
372         if (isstring (a) || isstring (b)) {
373                 to_string (a);
374                 to_string (b);
375                 r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) >= 0));
376         } else {
377                 to_integer(a);
378                 to_integer(b);
379                 r = make_integer ((quad_t)(a->u.i >= b->u.i));
380         }
381
382         free_value (a);
383         free_value (b);
384         return r;
385 }
386
387 struct val *
388 op_le(struct val *a, struct val *b)
389 {
390         struct val *r;
391
392         if (isstring (a) || isstring (b)) {
393                 to_string (a);
394                 to_string (b);
395                 r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) <= 0));
396         } else {
397                 to_integer(a);
398                 to_integer(b);
399                 r = make_integer ((quad_t)(a->u.i <= b->u.i));
400         }
401
402         free_value (a);
403         free_value (b);
404         return r;
405 }
406
407 struct val *
408 op_ne(struct val *a, struct val *b)
409 {
410         struct val *r;
411
412         if (isstring (a) || isstring (b)) {
413                 to_string (a);
414                 to_string (b);
415                 r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) != 0));
416         } else {
417                 to_integer(a);
418                 to_integer(b);
419                 r = make_integer ((quad_t)(a->u.i != b->u.i));
420         }
421
422         free_value (a);
423         free_value (b);
424         return r;
425 }
426
427 int
428 chk_plus(quad_t a, quad_t b, quad_t r)
429 {
430         /* sum of two positive numbers must be positive */
431         if (a > 0 && b > 0 && r <= 0)
432                 return 1;
433         /* sum of two negative numbers must be negative */
434         if (a < 0 && b < 0 && r >= 0)
435                 return 1;
436         /* all other cases are OK */
437         return 0;
438 }
439
440 struct val *
441 op_plus(struct val *a, struct val *b)
442 {
443         struct val *r;
444
445         if (!to_integer (a) || !to_integer (b)) {
446                 errx (2, "non-numeric argument");
447         }
448
449         r = make_integer (/*(quad_t)*/(a->u.i + b->u.i));
450         if (chk_plus (a->u.i, b->u.i, r->u.i)) {
451                 errx (2, "overflow");
452         }
453         free_value (a);
454         free_value (b);
455         return r;
456 }
457
458 int
459 chk_minus(quad_t a, quad_t b, quad_t r)
460 {
461         /* special case subtraction of QUAD_MIN */
462         if (b == QUAD_MIN) {
463                 if (a >= 0)
464                         return 1;
465                 else
466                         return 0;
467         }
468         /* this is allowed for b != QUAD_MIN */
469         return chk_plus (a, -b, r);
470 }
471
472 struct val *
473 op_minus(struct val *a, struct val *b)
474 {
475         struct val *r;
476
477         if (!to_integer (a) || !to_integer (b)) {
478                 errx (2, "non-numeric argument");
479         }
480
481         r = make_integer (/*(quad_t)*/(a->u.i - b->u.i));
482         if (chk_minus (a->u.i, b->u.i, r->u.i)) {
483                 errx (2, "overflow");
484         }
485         free_value (a);
486         free_value (b);
487         return r;
488 }
489
490 int
491 chk_times(quad_t a, quad_t b, quad_t r)
492 {
493         /* special case: first operand is 0, no overflow possible */
494         if (a == 0)
495                 return 0;
496         /* cerify that result of division matches second operand */
497         if (r / a != b)
498                 return 1;
499         return 0;
500 }
501
502 struct val *
503 op_times(struct val *a, struct val *b)
504 {
505         struct val *r;
506
507         if (!to_integer (a) || !to_integer (b)) {
508                 errx (2, "non-numeric argument");
509         }
510
511         r = make_integer (/*(quad_t)*/(a->u.i * b->u.i));
512         if (chk_times (a->u.i, b->u.i, r->u.i)) {
513                 errx (2, "overflow");
514         }
515         free_value (a);
516         free_value (b);
517         return (r);
518 }
519
520 int
521 chk_div(quad_t a, quad_t b)
522 {
523         /* div by zero has been taken care of before */
524         /* only QUAD_MIN / -1 causes overflow */
525         if (a == QUAD_MIN && b == -1)
526                 return 1;
527         /* everything else is OK */
528         return 0;
529 }
530
531 struct val *
532 op_div(struct val *a, struct val *b)
533 {
534         struct val *r;
535
536         if (!to_integer (a) || !to_integer (b)) {
537                 errx (2, "non-numeric argument");
538         }
539
540         if (b->u.i == 0) {
541                 errx (2, "division by zero");
542         }
543
544         r = make_integer (/*(quad_t)*/(a->u.i / b->u.i));
545         if (chk_div (a->u.i, b->u.i)) {
546                 errx (2, "overflow");
547         }
548         free_value (a);
549         free_value (b);
550         return r;
551 }
552         
553 struct val *
554 op_rem(struct val *a, struct val *b)
555 {
556         struct val *r;
557
558         if (!to_integer (a) || !to_integer (b)) {
559                 errx (2, "non-numeric argument");
560         }
561
562         if (b->u.i == 0) {
563                 errx (2, "division by zero");
564         }
565
566         r = make_integer (/*(quad_t)*/(a->u.i % b->u.i));
567         /* chk_rem necessary ??? */
568         free_value (a);
569         free_value (b);
570         return r;
571 }
572         
573 struct val *
574 op_colon(struct val *a, struct val *b)
575 {
576         regex_t rp;
577         regmatch_t rm[2];
578         char errbuf[256];
579         int eval;
580         struct val *v;
581
582         /* coerce to both arguments to strings */
583         to_string(a);
584         to_string(b);
585
586         /* compile regular expression */
587         if ((eval = regcomp (&rp, b->u.s, 0)) != 0) {
588                 regerror (eval, &rp, errbuf, sizeof(errbuf));
589                 errx (2, "%s", errbuf);
590         }
591
592         /* compare string against pattern */
593         /* remember that patterns are anchored to the beginning of the line */
594         if (regexec(&rp, a->u.s, (size_t)2, rm, 0) == 0 && rm[0].rm_so == 0) {
595                 if (rm[1].rm_so >= 0) {
596                         *(a->u.s + rm[1].rm_eo) = '\0';
597                         v = make_str (a->u.s + rm[1].rm_so);
598
599                 } else {
600                         v = make_integer ((quad_t)(rm[0].rm_eo - rm[0].rm_so));
601                 }
602         } else {
603                 if (rp.re_nsub == 0) {
604                         v = make_integer ((quad_t)0);
605                 } else {
606                         v = make_str ("");
607                 }
608         }
609
610         /* free arguments and pattern buffer */
611         free_value (a);
612         free_value (b);
613         regfree (&rp);
614
615         return v;
616 }