]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - bin/expr/expr.y
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / bin / expr / expr.y
1 %{
2 /*-
3  * Written by Pace Willisson (pace@blitz.com) 
4  * and placed in the public domain.
5  *
6  * Largely rewritten by J.T. Conklin (jtc@wimsey.com)
7  *
8  * $FreeBSD$
9  */
10
11 #include <sys/types.h>
12
13 #include <ctype.h>
14 #include <err.h>
15 #include <errno.h>
16 #include <inttypes.h>
17 #include <limits.h>
18 #include <locale.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <regex.h>
23 #include <unistd.h>
24   
25 /*
26  * POSIX specifies a specific error code for syntax errors.  We exit
27  * with this code for all errors.
28  */
29 #define ERR_EXIT        2
30
31 enum valtype {
32         integer, numeric_string, string
33 } ;
34
35 struct val {
36         enum valtype type;
37         union {
38                 char *s;
39                 intmax_t i;
40         } u;
41 } ;
42
43 struct val *result;
44
45 int             chk_div(intmax_t, intmax_t);
46 int             chk_minus(intmax_t, intmax_t, intmax_t);
47 int             chk_plus(intmax_t, intmax_t, intmax_t);
48 int             chk_times(intmax_t, intmax_t, intmax_t);
49 void            free_value(struct val *);
50 int             is_zero_or_null(struct val *);
51 int             isstring(struct val *);
52 struct val      *make_integer(intmax_t);
53 struct val      *make_str(const char *);
54 struct val      *op_and(struct val *, struct val *);
55 struct val      *op_colon(struct val *, struct val *);
56 struct val      *op_div(struct val *, struct val *);
57 struct val      *op_eq(struct val *, struct val *);
58 struct val      *op_ge(struct val *, struct val *);
59 struct val      *op_gt(struct val *, struct val *);
60 struct val      *op_le(struct val *, struct val *);
61 struct val      *op_lt(struct val *, struct val *);
62 struct val      *op_minus(struct val *, struct val *);
63 struct val      *op_ne(struct val *, struct val *);
64 struct val      *op_or(struct val *, struct val *);
65 struct val      *op_plus(struct val *, struct val *);
66 struct val      *op_rem(struct val *, struct val *);
67 struct val      *op_times(struct val *, struct val *);
68 intmax_t        to_integer(struct val *);
69 void            to_string(struct val *);
70 int             yyerror(const char *);
71 int             yylex(void);
72 int             yyparse(void);
73
74 static int      eflag;
75 char **av;
76 %}
77
78 %union
79 {
80         struct val *val;
81 }
82
83 %left <val> '|'
84 %left <val> '&'
85 %left <val> '=' '>' '<' GE LE NE
86 %left <val> '+' '-'
87 %left <val> '*' '/' '%'
88 %left <val> ':'
89
90 %token <val> TOKEN
91 %type <val> start expr
92
93 %%
94
95 start: expr { result = $$; }
96
97 expr:   TOKEN
98         | '(' expr ')' { $$ = $2; }
99         | expr '|' expr { $$ = op_or ($1, $3); }
100         | expr '&' expr { $$ = op_and ($1, $3); }
101         | expr '=' expr { $$ = op_eq ($1, $3); }
102         | expr '>' expr { $$ = op_gt ($1, $3); }
103         | expr '<' expr { $$ = op_lt ($1, $3); }
104         | expr GE expr  { $$ = op_ge ($1, $3); }
105         | expr LE expr  { $$ = op_le ($1, $3); }
106         | expr NE expr  { $$ = op_ne ($1, $3); }
107         | expr '+' expr { $$ = op_plus ($1, $3); }
108         | expr '-' expr { $$ = op_minus ($1, $3); }
109         | expr '*' expr { $$ = op_times ($1, $3); }
110         | expr '/' expr { $$ = op_div ($1, $3); }
111         | expr '%' expr { $$ = op_rem ($1, $3); }
112         | expr ':' expr { $$ = op_colon ($1, $3); }
113         ;
114
115
116 %%
117
118 struct val *
119 make_integer(intmax_t i)
120 {
121         struct val *vp;
122
123         vp = (struct val *) malloc (sizeof (*vp));
124         if (vp == NULL) {
125                 errx(ERR_EXIT, "malloc() failed");
126         }
127
128         vp->type = integer;
129         vp->u.i  = i;
130         return vp; 
131 }
132
133 struct val *
134 make_str(const char *s)
135 {
136         struct val *vp;
137         char *ep;
138
139         vp = (struct val *) malloc (sizeof (*vp));
140         if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) {
141                 errx(ERR_EXIT, "malloc() failed");
142         }
143
144         /*
145          * Previously we tried to scan the string to see if it ``looked like''
146          * an integer (erroneously, as it happened).  Let strtoimax() do the
147          * dirty work.  We could cache the value, except that we are using
148          * a union and need to preserve the original string form until we
149          * are certain that it is not needed.
150          *
151          * IEEE Std.1003.1-2001 says:
152          * /integer/ An argument consisting only of an (optional) unary minus  
153          *           followed by digits.          
154          *
155          * This means that arguments which consist of digits followed by
156          * non-digits MUST NOT be considered integers.  strtoimax() will
157          * figure this out for us.
158          */
159         if (eflag)
160                 (void)strtoimax(s, &ep, 10);
161         else
162                 (void)strtol(s, &ep, 10);
163
164         if (*ep != '\0')
165                 vp->type = string;
166         else    
167                 vp->type = numeric_string;
168
169         return vp;
170 }
171
172
173 void
174 free_value(struct val *vp)
175 {
176         if (vp->type == string || vp->type == numeric_string)
177                 free (vp->u.s); 
178 }
179
180
181 intmax_t
182 to_integer(struct val *vp)
183 {
184         intmax_t i;
185
186         if (vp->type == integer)
187                 return 1;
188
189         if (vp->type == string)
190                 return 0;
191
192         /* vp->type == numeric_string, make it numeric */
193         errno = 0;
194         if (eflag) {
195                 i  = strtoimax(vp->u.s, (char **)NULL, 10);
196                 if (errno == ERANGE)
197                         err(ERR_EXIT, NULL);
198         } else {
199                 i = strtol(vp->u.s, (char **)NULL, 10);
200         }
201
202         free (vp->u.s);
203         vp->u.i = i;
204         vp->type = integer;
205         return 1;
206 }
207
208 void
209 to_string(struct val *vp)
210 {
211         char *tmp;
212
213         if (vp->type == string || vp->type == numeric_string)
214                 return;
215
216         /*
217          * log_10(x) ~= 0.3 * log_2(x).  Rounding up gives the number
218          * of digits; add one each for the sign and terminating null
219          * character, respectively.
220          */
221 #define NDIGITS(x) (3 * (sizeof(x) * CHAR_BIT) / 10 + 1 + 1 + 1)
222         tmp = malloc(NDIGITS(vp->u.i));
223         if (tmp == NULL)
224                 errx(ERR_EXIT, "malloc() failed");
225
226         sprintf(tmp, "%jd", vp->u.i);
227         vp->type = string;
228         vp->u.s  = tmp;
229 }
230
231
232 int
233 isstring(struct val *vp)
234 {
235         /* only TRUE if this string is not a valid integer */
236         return (vp->type == string);
237 }
238
239
240 int
241 yylex(void)
242 {
243         char *p;
244
245         if (*av == NULL)
246                 return (0);
247
248         p = *av++;
249
250         if (strlen (p) == 1) {
251                 if (strchr ("|&=<>+-*/%:()", *p))
252                         return (*p);
253         } else if (strlen (p) == 2 && p[1] == '=') {
254                 switch (*p) {
255                 case '>': return (GE);
256                 case '<': return (LE);
257                 case '!': return (NE);
258                 }
259         }
260
261         yylval.val = make_str (p);
262         return (TOKEN);
263 }
264
265 int
266 is_zero_or_null(struct val *vp)
267 {
268         if (vp->type == integer) {
269                 return (vp->u.i == 0);
270         } else {
271                 return (*vp->u.s == 0 || (to_integer (vp) && vp->u.i == 0));
272         }
273         /* NOTREACHED */
274 }
275
276 int
277 main(int argc, char *argv[])
278 {
279         int c;
280
281         setlocale (LC_ALL, "");
282         if (getenv("EXPR_COMPAT") != NULL
283             || check_utility_compat("expr")) {
284                 av = argv + 1;
285                 eflag = 1;
286         } else {
287                 while ((c = getopt(argc, argv, "e")) != -1)
288                         switch (c) {
289                         case 'e':
290                                 eflag = 1;
291                                 break;
292
293                         default:
294                                 fprintf(stderr,
295                                     "usage: expr [-e] expression\n");
296                                 exit(ERR_EXIT);
297                         }
298                 av = argv + optind;
299         }
300
301         yyparse();
302
303         if (result->type == integer)
304                 printf("%jd\n", result->u.i);
305         else
306                 printf("%s\n", result->u.s);
307
308         return (is_zero_or_null(result));
309 }
310
311 int
312 yyerror(const char *s __unused)
313 {
314         errx(ERR_EXIT, "syntax error");
315 }
316
317
318 struct val *
319 op_or(struct val *a, struct val *b)
320 {
321         if (is_zero_or_null (a)) {
322                 free_value (a);
323                 return (b);
324         } else {
325                 free_value (b);
326                 return (a);
327         }
328 }
329                 
330 struct val *
331 op_and(struct val *a, struct val *b)
332 {
333         if (is_zero_or_null (a) || is_zero_or_null (b)) {
334                 free_value (a);
335                 free_value (b);
336                 return (make_integer ((intmax_t)0));
337         } else {
338                 free_value (b);
339                 return (a);
340         }
341 }
342
343 struct val *
344 op_eq(struct val *a, struct val *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 ((intmax_t)(strcoll (a->u.s, b->u.s) == 0));
352         } else {
353                 (void)to_integer(a);
354                 (void)to_integer(b);
355                 r = make_integer ((intmax_t)(a->u.i == b->u.i));
356         }
357
358         free_value (a);
359         free_value (b);
360         return r;
361 }
362
363 struct val *
364 op_gt(struct val *a, struct val *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 ((intmax_t)(strcoll (a->u.s, b->u.s) > 0));
372         } else {
373                 (void)to_integer(a);
374                 (void)to_integer(b);
375                 r = make_integer ((intmax_t)(a->u.i > b->u.i));
376         }
377
378         free_value (a);
379         free_value (b);
380         return r;
381 }
382
383 struct val *
384 op_lt(struct val *a, struct val *b)
385 {
386         struct val *r;
387
388         if (isstring (a) || isstring (b)) {
389                 to_string (a);
390                 to_string (b);
391                 r = make_integer ((intmax_t)(strcoll (a->u.s, b->u.s) < 0));
392         } else {
393                 (void)to_integer(a);
394                 (void)to_integer(b);
395                 r = make_integer ((intmax_t)(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_ge(struct val *a, struct val *b)
405 {
406         struct val *r;
407
408         if (isstring (a) || isstring (b)) {
409                 to_string (a);
410                 to_string (b);
411                 r = make_integer ((intmax_t)(strcoll (a->u.s, b->u.s) >= 0));
412         } else {
413                 (void)to_integer(a);
414                 (void)to_integer(b);
415                 r = make_integer ((intmax_t)(a->u.i >= b->u.i));
416         }
417
418         free_value (a);
419         free_value (b);
420         return r;
421 }
422
423 struct val *
424 op_le(struct val *a, struct val *b)
425 {
426         struct val *r;
427
428         if (isstring (a) || isstring (b)) {
429                 to_string (a);
430                 to_string (b);
431                 r = make_integer ((intmax_t)(strcoll (a->u.s, b->u.s) <= 0));
432         } else {
433                 (void)to_integer(a);
434                 (void)to_integer(b);
435                 r = make_integer ((intmax_t)(a->u.i <= b->u.i));
436         }
437
438         free_value (a);
439         free_value (b);
440         return r;
441 }
442
443 struct val *
444 op_ne(struct val *a, struct val *b)
445 {
446         struct val *r;
447
448         if (isstring (a) || isstring (b)) {
449                 to_string (a);
450                 to_string (b);
451                 r = make_integer ((intmax_t)(strcoll (a->u.s, b->u.s) != 0));
452         } else {
453                 (void)to_integer(a);
454                 (void)to_integer(b);
455                 r = make_integer ((intmax_t)(a->u.i != b->u.i));
456         }
457
458         free_value (a);
459         free_value (b);
460         return r;
461 }
462
463 int
464 chk_plus(intmax_t a, intmax_t b, intmax_t r)
465 {
466
467         /* sum of two positive numbers must be positive */
468         if (a > 0 && b > 0 && r <= 0)
469                 return 1;
470         /* sum of two negative numbers must be negative */
471         if (a < 0 && b < 0 && r >= 0)
472                 return 1;
473         /* all other cases are OK */
474         return 0;
475 }
476
477 struct val *
478 op_plus(struct val *a, struct val *b)
479 {
480         struct val *r;
481
482         if (!to_integer(a) || !to_integer(b)) {
483                 errx(ERR_EXIT, "non-numeric argument");
484         }
485
486         if (eflag) {
487                 r = make_integer(a->u.i + b->u.i);
488                 if (chk_plus(a->u.i, b->u.i, r->u.i)) {
489                         errx(ERR_EXIT, "overflow");
490                 }
491         } else
492                 r = make_integer((long)a->u.i + (long)b->u.i);
493
494         free_value (a);
495         free_value (b);
496         return r;
497 }
498
499 int
500 chk_minus(intmax_t a, intmax_t b, intmax_t r)
501 {
502
503         /* special case subtraction of INTMAX_MIN */
504         if (b == INTMAX_MIN) {
505                 if (a >= 0)
506                         return 1;
507                 else
508                         return 0;
509         }
510         /* this is allowed for b != INTMAX_MIN */
511         return chk_plus (a, -b, r);
512 }
513
514 struct val *
515 op_minus(struct val *a, struct val *b)
516 {
517         struct val *r;
518
519         if (!to_integer(a) || !to_integer(b)) {
520                 errx(ERR_EXIT, "non-numeric argument");
521         }
522
523         if (eflag) {
524                 r = make_integer(a->u.i - b->u.i);
525                 if (chk_minus(a->u.i, b->u.i, r->u.i)) {
526                         errx(ERR_EXIT, "overflow");
527                 }
528         } else
529                 r = make_integer((long)a->u.i - (long)b->u.i);
530
531         free_value (a);
532         free_value (b);
533         return r;
534 }
535
536 int
537 chk_times(intmax_t a, intmax_t b, intmax_t r)
538 {
539         /* special case: first operand is 0, no overflow possible */
540         if (a == 0)
541                 return 0;
542         /* verify that result of division matches second operand */
543         if (r / a != b)
544                 return 1;
545         return 0;
546 }
547
548 struct val *
549 op_times(struct val *a, struct val *b)
550 {
551         struct val *r;
552
553         if (!to_integer(a) || !to_integer(b)) {
554                 errx(ERR_EXIT, "non-numeric argument");
555         }
556
557         if (eflag) {
558                 r = make_integer(a->u.i * b->u.i);
559                 if (chk_times(a->u.i, b->u.i, r->u.i)) {
560                         errx(ERR_EXIT, "overflow");
561                 }
562         } else
563                 r = make_integer((long)a->u.i * (long)b->u.i);
564
565         free_value (a);
566         free_value (b);
567         return (r);
568 }
569
570 int
571 chk_div(intmax_t a, intmax_t b)
572 {
573         /* div by zero has been taken care of before */
574         /* only INTMAX_MIN / -1 causes overflow */
575         if (a == INTMAX_MIN && b == -1)
576                 return 1;
577         /* everything else is OK */
578         return 0;
579 }
580
581 struct val *
582 op_div(struct val *a, struct val *b)
583 {
584         struct val *r;
585
586         if (!to_integer(a) || !to_integer(b)) {
587                 errx(ERR_EXIT, "non-numeric argument");
588         }
589
590         if (b->u.i == 0) {
591                 errx(ERR_EXIT, "division by zero");
592         }
593
594         if (eflag) {
595                 r = make_integer(a->u.i / b->u.i);
596                 if (chk_div(a->u.i, b->u.i)) {
597                         errx(ERR_EXIT, "overflow");
598                 }
599         } else
600                 r = make_integer((long)a->u.i / (long)b->u.i);
601
602         free_value (a);
603         free_value (b);
604         return r;
605 }
606         
607 struct val *
608 op_rem(struct val *a, struct val *b)
609 {
610         struct val *r;
611
612         if (!to_integer(a) || !to_integer(b)) {
613                 errx(ERR_EXIT, "non-numeric argument");
614         }
615
616         if (b->u.i == 0) {
617                 errx(ERR_EXIT, "division by zero");
618         }
619
620         if (eflag)
621                 r = make_integer(a->u.i % b->u.i);
622                 /* chk_rem necessary ??? */
623         else
624                 r = make_integer((long)a->u.i % (long)b->u.i);
625
626         free_value (a);
627         free_value (b);
628         return r;
629 }
630         
631 struct val *
632 op_colon(struct val *a, struct val *b)
633 {
634         regex_t rp;
635         regmatch_t rm[2];
636         char errbuf[256];
637         int eval;
638         struct val *v;
639
640         /* coerce both arguments to strings */
641         to_string(a);
642         to_string(b);
643
644         /* compile regular expression */
645         if ((eval = regcomp (&rp, b->u.s, 0)) != 0) {
646                 regerror (eval, &rp, errbuf, sizeof(errbuf));
647                 errx(ERR_EXIT, "%s", errbuf);
648         }
649
650         /* compare string against pattern */
651         /* remember that patterns are anchored to the beginning of the line */
652         if (regexec(&rp, a->u.s, (size_t)2, rm, 0) == 0 && rm[0].rm_so == 0) {
653                 if (rm[1].rm_so >= 0) {
654                         *(a->u.s + rm[1].rm_eo) = '\0';
655                         v = make_str (a->u.s + rm[1].rm_so);
656
657                 } else {
658                         v = make_integer ((intmax_t)(rm[0].rm_eo - rm[0].rm_so));
659                 }
660         } else {
661                 if (rp.re_nsub == 0) {
662                         v = make_integer ((intmax_t)0);
663                 } else {
664                         v = make_str ("");
665                 }
666         }
667
668         /* free arguments and pattern buffer */
669         free_value (a);
670         free_value (b);
671         regfree (&rp);
672
673         return v;
674 }