]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - bin/expr/expr.y
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.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 char            **av;
44 int             nonposix;
45 struct val      *result;
46
47 void            assert_to_integer(struct val *);
48 void            assert_div(intmax_t, intmax_t);
49 void            assert_minus(intmax_t, intmax_t, intmax_t);
50 void            assert_plus(intmax_t, intmax_t, intmax_t);
51 void            assert_times(intmax_t, intmax_t, intmax_t);
52 int             compare_vals(struct val *, struct val *);
53 void            free_value(struct val *);
54 int             is_integer(const char *);
55 int             is_string(struct val *);
56 int             is_zero_or_null(struct val *);
57 struct val      *make_integer(intmax_t);
58 struct val      *make_str(const char *);
59 struct val      *op_and(struct val *, struct val *);
60 struct val      *op_colon(struct val *, struct val *);
61 struct val      *op_div(struct val *, struct val *);
62 struct val      *op_eq(struct val *, struct val *);
63 struct val      *op_ge(struct val *, struct val *);
64 struct val      *op_gt(struct val *, struct val *);
65 struct val      *op_le(struct val *, struct val *);
66 struct val      *op_lt(struct val *, struct val *);
67 struct val      *op_minus(struct val *, struct val *);
68 struct val      *op_ne(struct val *, struct val *);
69 struct val      *op_or(struct val *, struct val *);
70 struct val      *op_plus(struct val *, struct val *);
71 struct val      *op_rem(struct val *, struct val *);
72 struct val      *op_times(struct val *, struct val *);
73 int             to_integer(struct val *);
74 void            to_string(struct val *);
75 int             yyerror(const char *);
76 int             yylex(void);
77 int             yyparse(void);
78
79 %}
80
81 %union
82 {
83         struct val *val;
84 }
85
86 %left <val> '|'
87 %left <val> '&'
88 %left <val> '=' '>' '<' GE LE NE
89 %left <val> '+' '-'
90 %left <val> '*' '/' '%'
91 %left <val> ':'
92
93 %token <val> TOKEN
94 %type <val> start expr
95
96 %%
97
98 start: expr { result = $$; }
99
100 expr:   TOKEN
101         | '(' expr ')' { $$ = $2; }
102         | expr '|' expr { $$ = op_or($1, $3); }
103         | expr '&' expr { $$ = op_and($1, $3); }
104         | expr '=' expr { $$ = op_eq($1, $3); }
105         | expr '>' expr { $$ = op_gt($1, $3); }
106         | expr '<' expr { $$ = op_lt($1, $3); }
107         | expr GE expr  { $$ = op_ge($1, $3); }
108         | expr LE expr  { $$ = op_le($1, $3); }
109         | expr NE expr  { $$ = op_ne($1, $3); }
110         | expr '+' expr { $$ = op_plus($1, $3); }
111         | expr '-' expr { $$ = op_minus($1, $3); }
112         | expr '*' expr { $$ = op_times($1, $3); }
113         | expr '/' expr { $$ = op_div($1, $3); }
114         | expr '%' expr { $$ = op_rem($1, $3); }
115         | expr ':' expr { $$ = op_colon($1, $3); }
116         ;
117
118 %%
119
120 struct val *
121 make_integer(intmax_t i)
122 {
123         struct val *vp;
124
125         vp = (struct val *)malloc(sizeof(*vp));
126         if (vp == NULL)
127                 errx(ERR_EXIT, "malloc() failed");
128
129         vp->type = integer;
130         vp->u.i  = i;
131         return (vp);
132 }
133
134 struct val *
135 make_str(const char *s)
136 {
137         struct val *vp;
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         if (is_integer(s))
144                 vp->type = numeric_string;
145         else
146                 vp->type = string;
147
148         return (vp);
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 int
159 to_integer(struct val *vp)
160 {
161         intmax_t i;
162
163         /* we can only convert numeric_string to integer, here */
164         if (vp->type == numeric_string) {
165                 errno = 0;
166                 i  = strtoimax(vp->u.s, (char **)NULL, 10);
167                 /* just keep as numeric_string, if the conversion fails */
168                 if (errno != ERANGE) {
169                         free(vp->u.s);
170                         vp->u.i = i;
171                         vp->type = integer;
172                 }
173         }
174         return (vp->type == integer);
175 }
176
177 void
178 assert_to_integer(struct val *vp)
179 {
180         if (vp->type == string)
181                 errx(ERR_EXIT, "not a decimal number: '%s'", vp->u.s);
182         if (!to_integer(vp))
183                 errx(ERR_EXIT, "operand too large: '%s'", vp->u.s);
184 }
185
186 void
187 to_string(struct val *vp)
188 {
189         char *tmp;
190
191         if (vp->type == string || vp->type == numeric_string)
192                 return;
193
194         /*
195          * log_10(x) ~= 0.3 * log_2(x).  Rounding up gives the number
196          * of digits; add one each for the sign and terminating null
197          * character, respectively.
198          */
199 #define NDIGITS(x) (3 * (sizeof(x) * CHAR_BIT) / 10 + 1 + 1 + 1)
200         tmp = malloc(NDIGITS(vp->u.i));
201         if (tmp == NULL)
202                 errx(ERR_EXIT, "malloc() failed");
203
204         sprintf(tmp, "%jd", vp->u.i);
205         vp->type = string;
206         vp->u.s  = tmp;
207 }
208
209 int
210 is_integer(const char *s)
211 {
212         if (nonposix) {
213                 if (*s == '\0')
214                         return (1);
215                 while (isspace((unsigned char)*s))
216                         s++;
217         }
218         if (*s == '-' || (nonposix && *s == '+'))
219                 s++;
220         if (*s == '\0')
221                 return (0);
222         while (isdigit((unsigned char)*s))
223                 s++;
224         return (*s == '\0');
225 }
226
227 int
228 is_string(struct val *vp)
229 {
230         /* only TRUE if this string is not a valid integer */
231         return (vp->type == string);
232 }
233
234 int
235 yylex(void)
236 {
237         char *p;
238
239         if (*av == NULL)
240                 return (0);
241
242         p = *av++;
243
244         if (strlen(p) == 1) {
245                 if (strchr("|&=<>+-*/%:()", *p))
246                         return (*p);
247         } else if (strlen(p) == 2 && p[1] == '=') {
248                 switch (*p) {
249                 case '>': return (GE);
250                 case '<': return (LE);
251                 case '!': return (NE);
252                 }
253         }
254
255         yylval.val = make_str(p);
256         return (TOKEN);
257 }
258
259 int
260 is_zero_or_null(struct val *vp)
261 {
262         if (vp->type == integer)
263                 return (vp->u.i == 0);
264
265         return (*vp->u.s == 0 || (to_integer(vp) && vp->u.i == 0));
266 }
267
268 int
269 main(int argc, char *argv[])
270 {
271         int c;
272
273         setlocale(LC_ALL, "");
274         if (getenv("EXPR_COMPAT") != NULL
275             || check_utility_compat("expr")) {
276                 av = argv + 1;
277                 nonposix = 1;
278         } else {
279                 while ((c = getopt(argc, argv, "e")) != -1) {
280                         switch (c) {
281                         case 'e':
282                                 nonposix = 1;
283                                 break;
284                         default:
285                                 errx(ERR_EXIT,
286                                     "usage: expr [-e] expression\n");
287                         }
288                 }
289                 av = argv + optind;
290         }
291
292         yyparse();
293
294         if (result->type == integer)
295                 printf("%jd\n", result->u.i);
296         else
297                 printf("%s\n", result->u.s);
298
299         return (is_zero_or_null(result));
300 }
301
302 int
303 yyerror(const char *s __unused)
304 {
305         errx(ERR_EXIT, "syntax error");
306 }
307
308 struct val *
309 op_or(struct val *a, struct val *b)
310 {
311         if (!is_zero_or_null(a)) {
312                 free_value(b);
313                 return (a);
314         }
315         free_value(a);
316         if (!is_zero_or_null(b))
317                 return (b);
318         free_value(b);
319         return (make_integer((intmax_t)0));
320 }
321
322 struct val *
323 op_and(struct val *a, struct val *b)
324 {
325         if (is_zero_or_null(a) || is_zero_or_null(b)) {
326                 free_value(a);
327                 free_value(b);
328                 return (make_integer((intmax_t)0));
329         } else {
330                 free_value(b);
331                 return (a);
332         }
333 }
334
335 int
336 compare_vals(struct val *a, struct val *b)
337 {
338         int r;
339
340         if (is_string(a) || is_string(b)) {
341                 to_string(a);
342                 to_string(b);
343                 r = strcoll(a->u.s, b->u.s);
344         } else {
345                 assert_to_integer(a);
346                 assert_to_integer(b);
347                 if (a->u.i > b->u.i)
348                         r = 1;
349                 else if (a->u.i < b->u.i)
350                         r = -1;
351                 else
352                         r = 0;
353         }
354
355         free_value(a);
356         free_value(b);
357         return (r);
358 }
359
360 struct val *
361 op_eq(struct val *a, struct val *b)
362 {
363         return (make_integer((intmax_t)(compare_vals(a, b) == 0)));
364 }
365
366 struct val *
367 op_gt(struct val *a, struct val *b)
368 {
369         return (make_integer((intmax_t)(compare_vals(a, b) > 0)));
370 }
371
372 struct val *
373 op_lt(struct val *a, struct val *b)
374 {
375         return (make_integer((intmax_t)(compare_vals(a, b) < 0)));
376 }
377
378 struct val *
379 op_ge(struct val *a, struct val *b)
380 {
381         return (make_integer((intmax_t)(compare_vals(a, b) >= 0)));
382 }
383
384 struct val *
385 op_le(struct val *a, struct val *b)
386 {
387         return (make_integer((intmax_t)(compare_vals(a, b) <= 0)));
388 }
389
390 struct val *
391 op_ne(struct val *a, struct val *b)
392 {
393         return (make_integer((intmax_t)(compare_vals(a, b) != 0)));
394 }
395
396 void
397 assert_plus(intmax_t a, intmax_t b, intmax_t r)
398 {
399         /*
400          * sum of two positive numbers must be positive,
401          * sum of two negative numbers must be negative
402          */
403         if ((a > 0 && b > 0 && r <= 0) ||
404             (a < 0 && b < 0 && r >= 0))
405                 errx(ERR_EXIT, "overflow");
406 }
407
408 struct val *
409 op_plus(struct val *a, struct val *b)
410 {
411         struct val *r;
412
413         assert_to_integer(a);
414         assert_to_integer(b);
415         r = make_integer(a->u.i + b->u.i);
416         assert_plus(a->u.i, b->u.i, r->u.i);
417
418         free_value(a);
419         free_value(b);
420         return (r);
421 }
422
423 void
424 assert_minus(intmax_t a, intmax_t b, intmax_t r)
425 {
426         /* special case subtraction of INTMAX_MIN */
427         if (b == INTMAX_MIN && a < 0)
428                 errx(ERR_EXIT, "overflow");
429         /* check addition of negative subtrahend */
430         assert_plus(a, -b, r);
431 }
432
433 struct val *
434 op_minus(struct val *a, struct val *b)
435 {
436         struct val *r;
437
438         assert_to_integer(a);
439         assert_to_integer(b);
440         r = make_integer(a->u.i - b->u.i);
441         assert_minus(a->u.i, b->u.i, r->u.i);
442
443         free_value(a);
444         free_value(b);
445         return (r);
446 }
447
448 void
449 assert_times(intmax_t a, intmax_t b, intmax_t r)
450 {
451         /*
452          * if first operand is 0, no overflow is possible,
453          * else result of division test must match second operand
454          */
455         if (a != 0 && r / a != b)
456                 errx(ERR_EXIT, "overflow");
457 }
458
459 struct val *
460 op_times(struct val *a, struct val *b)
461 {
462         struct val *r;
463
464         assert_to_integer(a);
465         assert_to_integer(b);
466         r = make_integer(a->u.i * b->u.i);
467         assert_times(a->u.i, b->u.i, r->u.i);
468
469         free_value(a);
470         free_value(b);
471         return (r);
472 }
473
474 void
475 assert_div(intmax_t a, intmax_t b)
476 {
477         if (b == 0)
478                 errx(ERR_EXIT, "division by zero");
479         /* only INTMAX_MIN / -1 causes overflow */
480         if (a == INTMAX_MIN && b == -1)
481                 errx(ERR_EXIT, "overflow");
482 }
483
484 struct val *
485 op_div(struct val *a, struct val *b)
486 {
487         struct val *r;
488
489         assert_to_integer(a);
490         assert_to_integer(b);
491         /* assert based on operands only, not on result */
492         assert_div(a->u.i, b->u.i);
493         r = make_integer(a->u.i / b->u.i);
494
495         free_value(a);
496         free_value(b);
497         return (r);
498 }
499
500 struct val *
501 op_rem(struct val *a, struct val *b)
502 {
503         struct val *r;
504
505         assert_to_integer(a);
506         assert_to_integer(b);
507         /* pass a=1 to only check for div by zero */
508         assert_div(1, b->u.i);
509         r = make_integer(a->u.i % b->u.i);
510
511         free_value(a);
512         free_value(b);
513         return (r);
514 }
515
516 struct val *
517 op_colon(struct val *a, struct val *b)
518 {
519         regex_t rp;
520         regmatch_t rm[2];
521         char errbuf[256];
522         int eval;
523         struct val *v;
524
525         /* coerce both arguments to strings */
526         to_string(a);
527         to_string(b);
528
529         /* compile regular expression */
530         if ((eval = regcomp(&rp, b->u.s, 0)) != 0) {
531                 regerror(eval, &rp, errbuf, sizeof(errbuf));
532                 errx(ERR_EXIT, "%s", errbuf);
533         }
534
535         /* compare string against pattern */
536         /* remember that patterns are anchored to the beginning of the line */
537         if (regexec(&rp, a->u.s, (size_t)2, rm, 0) == 0 && rm[0].rm_so == 0)
538                 if (rm[1].rm_so >= 0) {
539                         *(a->u.s + rm[1].rm_eo) = '\0';
540                         v = make_str(a->u.s + rm[1].rm_so);
541
542                 } else
543                         v = make_integer((intmax_t)(rm[0].rm_eo - rm[0].rm_so));
544         else
545                 if (rp.re_nsub == 0)
546                         v = make_integer((intmax_t)0);
547                 else
548                         v = make_str("");
549
550         /* free arguments and pattern buffer */
551         free_value(a);
552         free_value(b);
553         regfree(&rp);
554
555         return (v);
556 }