sbin/hammer: Fix whitespace alignment changed by e0d7dd09
[dragonfly.git] / bin / expr / expr.y
blobfb581909e6c19b46511cded9610fb56790d38df4
1 %{
2 /* Written by Pace Willisson (pace@blitz.com)
3 * and placed in the public domain.
5 * Largely rewritten by J.T. Conklin (jtc@wimsey.com)
7 * $FreeBSD: src/bin/expr/expr.y,v 1.14.2.3 2001/08/01 02:37:46 obrien Exp $
8 * $DragonFly: src/bin/expr/expr.y,v 1.6 2005/11/06 11:44:02 swildner Exp $
9 */
11 #include <sys/types.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <locale.h>
16 #include <ctype.h>
17 #include <err.h>
18 #include <errno.h>
19 #include <regex.h>
20 #include <limits.h>
22 enum valtype {
23 integer, numeric_string, string
24 } ;
26 struct val {
27 enum valtype type;
28 union {
29 char *s;
30 quad_t i;
31 } u;
32 } ;
34 struct val *result;
36 int chk_div (quad_t, quad_t);
37 int chk_minus (quad_t, quad_t, quad_t);
38 int chk_plus (quad_t, quad_t, quad_t);
39 int chk_times (quad_t, quad_t, quad_t);
40 void free_value (struct val *);
41 int is_zero_or_null (struct val *);
42 int isstring (struct val *);
43 int main (int, char **);
44 struct val *make_integer (quad_t);
45 struct val *make_str (const char *);
46 struct val *op_and (struct val *, struct val *);
47 struct val *op_colon (struct val *, struct val *);
48 struct val *op_div (struct val *, struct val *);
49 struct val *op_eq (struct val *, struct val *);
50 struct val *op_ge (struct val *, struct val *);
51 struct val *op_gt (struct val *, struct val *);
52 struct val *op_le (struct val *, struct val *);
53 struct val *op_lt (struct val *, struct val *);
54 struct val *op_minus (struct val *, struct val *);
55 struct val *op_ne (struct val *, struct val *);
56 struct val *op_or (struct val *, struct val *);
57 struct val *op_plus (struct val *, struct val *);
58 struct val *op_rem (struct val *, struct val *);
59 struct val *op_times (struct val *, struct val *);
60 quad_t to_integer (struct val *);
61 void to_string (struct val *);
62 int yyerror (const char *);
63 int yylex (void);
65 char **av;
68 %union
70 struct val *val;
73 %left <val> '|'
74 %left <val> '&'
75 %left <val> '=' '>' '<' GE LE NE
76 %left <val> '+' '-'
77 %left <val> '*' '/' '%'
78 %left <val> ':'
80 %token <val> TOKEN
81 %type <val> start expr
85 start: expr { result = $$; }
87 expr: TOKEN
88 | '(' expr ')' { $$ = $2; }
89 | expr '|' expr { $$ = op_or ($1, $3); }
90 | expr '&' expr { $$ = op_and ($1, $3); }
91 | expr '=' expr { $$ = op_eq ($1, $3); }
92 | expr '>' expr { $$ = op_gt ($1, $3); }
93 | expr '<' expr { $$ = op_lt ($1, $3); }
94 | expr GE expr { $$ = op_ge ($1, $3); }
95 | expr LE expr { $$ = op_le ($1, $3); }
96 | expr NE expr { $$ = op_ne ($1, $3); }
97 | expr '+' expr { $$ = op_plus ($1, $3); }
98 | expr '-' expr { $$ = op_minus ($1, $3); }
99 | expr '*' expr { $$ = op_times ($1, $3); }
100 | expr '/' expr { $$ = op_div ($1, $3); }
101 | expr '%' expr { $$ = op_rem ($1, $3); }
102 | expr ':' expr { $$ = op_colon ($1, $3); }
108 struct val *
109 make_integer(quad_t i)
111 struct val *vp;
113 vp = (struct val *) malloc (sizeof (*vp));
114 if (vp == NULL) {
115 errx (2, "malloc() failed");
118 vp->type = integer;
119 vp->u.i = i;
120 return vp;
123 struct val *
124 make_str(const char *s)
126 struct val *vp;
127 size_t i;
128 int isint;
130 vp = (struct val *) malloc (sizeof (*vp));
131 if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) {
132 errx (2, "malloc() failed");
135 for(i = 1, isint = isdigit(s[0]) || s[0] == '-';
136 isint && i < strlen(s);
137 i++)
139 if(!isdigit(s[i]))
140 isint = 0;
143 if (isint)
144 vp->type = numeric_string;
145 else
146 vp->type = string;
148 return vp;
152 void
153 free_value(struct val *vp)
155 if (vp->type == string || vp->type == numeric_string)
156 free (vp->u.s);
160 quad_t
161 to_integer(struct val *vp)
163 quad_t i;
165 if (vp->type == integer)
166 return 1;
168 if (vp->type == string)
169 return 0;
171 /* vp->type == numeric_string, make it numeric */
172 errno = 0;
173 i = strtoll(vp->u.s, NULL, 10);
174 if (errno != 0) {
175 errx (2, "overflow");
177 free (vp->u.s);
178 vp->u.i = i;
179 vp->type = integer;
180 return 1;
183 void
184 to_string(struct val *vp)
186 char *tmp;
188 if (vp->type == string || vp->type == numeric_string)
189 return;
191 tmp = malloc ((size_t)25);
192 if (tmp == NULL) {
193 errx (2, "malloc() failed");
196 sprintf (tmp, "%lld", (long long)vp->u.i);
197 vp->type = string;
198 vp->u.s = tmp;
203 isstring(struct val *vp)
205 /* only TRUE if this string is not a valid integer */
206 return (vp->type == string);
211 yylex(void)
213 char *p;
215 if (*av == NULL)
216 return (0);
218 p = *av++;
220 if (strlen (p) == 1) {
221 if (strchr ("|&=<>+-*/%:()", *p))
222 return (*p);
223 } else if (strlen (p) == 2 && p[1] == '=') {
224 switch (*p) {
225 case '>': return (GE);
226 case '<': return (LE);
227 case '!': return (NE);
231 yylval.val = make_str (p);
232 return (TOKEN);
236 is_zero_or_null(struct val *vp)
238 if (vp->type == integer) {
239 return (vp->u.i == 0);
240 } else {
241 return (*vp->u.s == 0 || (to_integer (vp) && vp->u.i == 0));
243 /* NOTREACHED */
246 static void
247 usage(void)
249 fprintf(stderr,
250 "usage: expr expression\n");
251 exit(EXIT_FAILURE);
255 main (int argc, char **argv)
257 setlocale (LC_ALL, "");
259 if (argc > 1 && strcmp(argv[1], "--"))
260 av = argv + 1;
261 else if (argc > 2)
262 av = argv + 2;
263 else
264 usage();
266 yyparse ();
268 if (result->type == integer)
269 printf ("%lld\n", (long long)result->u.i);
270 else
271 printf ("%s\n", result->u.s);
273 return (is_zero_or_null (result));
277 yyerror(const char *s __unused)
279 errx (2, "syntax error");
283 struct val *
284 op_or(struct val *a, struct val *b)
286 if (is_zero_or_null (a)) {
287 free_value (a);
288 return (b);
289 } else {
290 free_value (b);
291 return (a);
295 struct val *
296 op_and(struct val *a, struct val *b)
298 if (is_zero_or_null (a) || is_zero_or_null (b)) {
299 free_value (a);
300 free_value (b);
301 return (make_integer ((quad_t)0));
302 } else {
303 free_value (b);
304 return (a);
308 struct val *
309 op_eq(struct val *a, struct val *b)
311 struct val *r;
313 if (isstring (a) || isstring (b)) {
314 to_string (a);
315 to_string (b);
316 r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) == 0));
317 } else {
318 to_integer(a);
319 to_integer(b);
320 r = make_integer ((quad_t)(a->u.i == b->u.i));
323 free_value (a);
324 free_value (b);
325 return r;
328 struct val *
329 op_gt(struct val *a, struct val *b)
331 struct val *r;
333 if (isstring (a) || isstring (b)) {
334 to_string (a);
335 to_string (b);
336 r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) > 0));
337 } else {
338 to_integer(a);
339 to_integer(b);
340 r = make_integer ((quad_t)(a->u.i > b->u.i));
343 free_value (a);
344 free_value (b);
345 return r;
348 struct val *
349 op_lt(struct val *a, struct val *b)
351 struct val *r;
353 if (isstring (a) || isstring (b)) {
354 to_string (a);
355 to_string (b);
356 r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) < 0));
357 } else {
358 to_integer(a);
359 to_integer(b);
360 r = make_integer ((quad_t)(a->u.i < b->u.i));
363 free_value (a);
364 free_value (b);
365 return r;
368 struct val *
369 op_ge(struct val *a, struct val *b)
371 struct val *r;
373 if (isstring (a) || isstring (b)) {
374 to_string (a);
375 to_string (b);
376 r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) >= 0));
377 } else {
378 to_integer(a);
379 to_integer(b);
380 r = make_integer ((quad_t)(a->u.i >= b->u.i));
383 free_value (a);
384 free_value (b);
385 return r;
388 struct val *
389 op_le(struct val *a, struct val *b)
391 struct val *r;
393 if (isstring (a) || isstring (b)) {
394 to_string (a);
395 to_string (b);
396 r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) <= 0));
397 } else {
398 to_integer(a);
399 to_integer(b);
400 r = make_integer ((quad_t)(a->u.i <= b->u.i));
403 free_value (a);
404 free_value (b);
405 return r;
408 struct val *
409 op_ne(struct val *a, struct val *b)
411 struct val *r;
413 if (isstring (a) || isstring (b)) {
414 to_string (a);
415 to_string (b);
416 r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) != 0));
417 } else {
418 to_integer(a);
419 to_integer(b);
420 r = make_integer ((quad_t)(a->u.i != b->u.i));
423 free_value (a);
424 free_value (b);
425 return r;
429 chk_plus(quad_t a, quad_t b, quad_t r)
431 /* sum of two positive numbers must be positive */
432 if (a > 0 && b > 0 && r <= 0)
433 return 1;
434 /* sum of two negative numbers must be negative */
435 if (a < 0 && b < 0 && r >= 0)
436 return 1;
437 /* all other cases are OK */
438 return 0;
441 struct val *
442 op_plus(struct val *a, struct val *b)
444 struct val *r;
446 if (!to_integer (a) || !to_integer (b)) {
447 errx (2, "non-numeric argument");
450 r = make_integer (/*(quad_t)*/(a->u.i + b->u.i));
451 if (chk_plus (a->u.i, b->u.i, r->u.i)) {
452 errx (2, "overflow");
454 free_value (a);
455 free_value (b);
456 return r;
460 chk_minus(quad_t a, quad_t b, quad_t r)
462 /* special case subtraction of QUAD_MIN */
463 if (b == QUAD_MIN) {
464 if (a >= 0)
465 return 1;
466 else
467 return 0;
469 /* this is allowed for b != QUAD_MIN */
470 return chk_plus (a, -b, r);
473 struct val *
474 op_minus(struct val *a, struct val *b)
476 struct val *r;
478 if (!to_integer (a) || !to_integer (b)) {
479 errx (2, "non-numeric argument");
482 r = make_integer (/*(quad_t)*/(a->u.i - b->u.i));
483 if (chk_minus (a->u.i, b->u.i, r->u.i)) {
484 errx (2, "overflow");
486 free_value (a);
487 free_value (b);
488 return r;
492 chk_times(quad_t a, quad_t b, quad_t r)
494 /* special case: first operand is 0, no overflow possible */
495 if (a == 0)
496 return 0;
497 /* cerify that result of division matches second operand */
498 if (r / a != b)
499 return 1;
500 return 0;
503 struct val *
504 op_times(struct val *a, struct val *b)
506 struct val *r;
508 if (!to_integer (a) || !to_integer (b)) {
509 errx (2, "non-numeric argument");
512 r = make_integer (/*(quad_t)*/(a->u.i * b->u.i));
513 if (chk_times (a->u.i, b->u.i, r->u.i)) {
514 errx (2, "overflow");
516 free_value (a);
517 free_value (b);
518 return (r);
522 chk_div(quad_t a, quad_t b)
524 /* div by zero has been taken care of before */
525 /* only QUAD_MIN / -1 causes overflow */
526 if (a == QUAD_MIN && b == -1)
527 return 1;
528 /* everything else is OK */
529 return 0;
532 struct val *
533 op_div(struct val *a, struct val *b)
535 struct val *r;
537 if (!to_integer (a) || !to_integer (b)) {
538 errx (2, "non-numeric argument");
541 if (b->u.i == 0) {
542 errx (2, "division by zero");
545 r = make_integer (/*(quad_t)*/(a->u.i / b->u.i));
546 if (chk_div (a->u.i, b->u.i)) {
547 errx (2, "overflow");
549 free_value (a);
550 free_value (b);
551 return r;
554 struct val *
555 op_rem(struct val *a, struct val *b)
557 struct val *r;
559 if (!to_integer (a) || !to_integer (b)) {
560 errx (2, "non-numeric argument");
563 if (b->u.i == 0) {
564 errx (2, "division by zero");
567 r = make_integer (/*(quad_t)*/(a->u.i % b->u.i));
568 /* chk_rem necessary ??? */
569 free_value (a);
570 free_value (b);
571 return r;
574 struct val *
575 op_colon(struct val *a, struct val *b)
577 regex_t rp;
578 regmatch_t rm[2];
579 char errbuf[256];
580 int eval;
581 struct val *v;
583 /* coerce to both arguments to strings */
584 to_string(a);
585 to_string(b);
587 /* compile regular expression */
588 if ((eval = regcomp (&rp, b->u.s, 0)) != 0) {
589 regerror (eval, &rp, errbuf, sizeof(errbuf));
590 errx (2, "%s", errbuf);
593 /* compare string against pattern */
594 /* remember that patterns are anchored to the beginning of the line */
595 if (regexec(&rp, a->u.s, (size_t)2, rm, 0) == 0 && rm[0].rm_so == 0) {
596 if (rm[1].rm_so >= 0) {
597 *(a->u.s + rm[1].rm_eo) = '\0';
598 v = make_str (a->u.s + rm[1].rm_so);
600 } else {
601 v = make_integer ((quad_t)(rm[0].rm_eo - rm[0].rm_so));
603 } else {
604 if (rp.re_nsub == 0) {
605 v = make_integer ((quad_t)0);
606 } else {
607 v = make_str ("");
611 /* free arguments and pattern buffer */
612 free_value (a);
613 free_value (b);
614 regfree (&rp);
616 return v;