Version 0.2.0 from FTP
[asterisk/asterisk.git] / ast_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.16 2000/07/22 10:59:36 se 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 #include <asterisk/ast_expr.h>
21 #include <asterisk/logger.h>
22
23 #  if ! defined(QUAD_MIN)
24 #   define QUAD_MIN     (-0x7fffffffffffffffL-1)
25 #  endif
26 #  if ! defined(QUAD_MAX)
27 #   define QUAD_MAX     (0x7fffffffffffffffL)
28 #  endif
29
30 #define YYPARSE_PARAM kota
31 #define YYLEX_PARAM kota
32
33 /* #define ast_log fprintf
34 #define LOG_WARNING stderr */
35   
36 enum valtype {
37         integer, numeric_string, string
38 } ;
39
40 struct val {
41         enum valtype type;
42         union {
43                 char *s;
44                 quad_t i;
45         } u;
46 } ;
47
48 struct parser_control {
49         struct val *result;
50         int pipa;
51         char *argv;
52         char *ptrptr;
53         int firsttoken;
54 } ;
55
56 static int              chk_div __P((quad_t, quad_t));
57 static int              chk_minus __P((quad_t, quad_t, quad_t));
58 static int              chk_plus __P((quad_t, quad_t, quad_t));
59 static int              chk_times __P((quad_t, quad_t, quad_t));
60 static void             free_value __P((struct val *));
61 static int              is_zero_or_null __P((struct val *));
62 static int              isstring __P((struct val *));
63 static struct val       *make_integer __P((quad_t));
64 static struct val       *make_str __P((const char *));
65 static struct val       *op_and __P((struct val *, struct val *));
66 static struct val       *op_colon __P((struct val *, struct val *));
67 static struct val       *op_div __P((struct val *, struct val *));
68 static struct val       *op_eq __P((struct val *, struct val *));
69 static struct val       *op_ge __P((struct val *, struct val *));
70 static struct val       *op_gt __P((struct val *, struct val *));
71 static struct val       *op_le __P((struct val *, struct val *));
72 static struct val       *op_lt __P((struct val *, struct val *));
73 static struct val       *op_minus __P((struct val *, struct val *));
74 static struct val       *op_ne __P((struct val *, struct val *));
75 static struct val       *op_or __P((struct val *, struct val *));
76 static struct val       *op_plus __P((struct val *, struct val *));
77 static struct val       *op_rem __P((struct val *, struct val *));
78 static struct val       *op_times __P((struct val *, struct val *));
79 static quad_t           to_integer __P((struct val *));
80 static void             to_string __P((struct val *));
81 static int              ast_yyerror __P((const char *));
82 static int              ast_yylex __P(());
83 %}
84
85 %pure-parser
86 /* %name-prefix="ast_yy" */
87
88
89 %union
90 {
91         struct val *val;
92 }
93
94 %left <val> '|'
95 %left <val> '&'
96 %left <val> '=' '>' '<' GE LE NE
97 %left <val> '+' '-'
98 %left <val> '*' '/' '%'
99 %left <val> ':'
100
101 %token <val> TOKEN
102 %type <val> start expr
103
104 %%
105
106 start: expr { ((struct parser_control *)kota)->result = $$; }
107
108 expr:   TOKEN
109         | '(' expr ')' { $$ = $2; }
110         | expr '|' expr { $$ = op_or ($1, $3); }
111         | expr '&' expr { $$ = op_and ($1, $3); }
112         | expr '=' expr { $$ = op_eq ($1, $3); }
113         | expr '>' expr { $$ = op_gt ($1, $3); }
114         | expr '<' expr { $$ = op_lt ($1, $3); }
115         | expr GE expr  { $$ = op_ge ($1, $3); }
116         | expr LE expr  { $$ = op_le ($1, $3); }
117         | expr NE expr  { $$ = op_ne ($1, $3); }
118         | expr '+' expr { $$ = op_plus ($1, $3); }
119         | expr '-' expr { $$ = op_minus ($1, $3); }
120         | expr '*' expr { $$ = op_times ($1, $3); }
121         | expr '/' expr { $$ = op_div ($1, $3); }
122         | expr '%' expr { $$ = op_rem ($1, $3); }
123         | expr ':' expr { $$ = op_colon ($1, $3); }
124         ;
125
126
127 %%
128
129 static struct val *
130 make_integer (i)
131 quad_t i;
132 {
133         struct val *vp;
134
135         vp = (struct val *) malloc (sizeof (*vp));
136         if (vp == NULL) {
137                 ast_log(LOG_WARNING, "malloc() failed\n");
138                 return(NULL);
139         }
140
141         vp->type = integer;
142         vp->u.i  = i;
143         return vp; 
144 }
145
146 static struct val *
147 make_str (s)
148 const char *s;
149 {
150         struct val *vp;
151         size_t i;
152         int isint;
153
154         vp = (struct val *) malloc (sizeof (*vp));
155         if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) {
156                 ast_log(LOG_WARNING,"malloc() failed\n");
157                 return(NULL);
158         }
159
160         for(i = 1, isint = isdigit(s[0]) || s[0] == '-';
161             isint && i < strlen(s);
162             i++)
163         {
164                 if(!isdigit(s[i]))
165                          isint = 0;
166         }
167
168         if (isint)
169                 vp->type = numeric_string;
170         else    
171                 vp->type = string;
172
173         return vp;
174 }
175
176
177 static void
178 free_value (vp)
179 struct val *vp;
180 {       
181         if (vp==NULL) {
182                 return;
183         }
184         if (vp->type == string || vp->type == numeric_string)
185                 free (vp->u.s); 
186 }
187
188
189 static quad_t
190 to_integer (vp)
191 struct val *vp;
192 {
193         quad_t i;
194
195         if (vp == NULL) {
196                 ast_log(LOG_WARNING,"vp==NULL in to_integer()\n");
197                 return(0);
198         }
199
200         if (vp->type == integer)
201                 return 1;
202
203         if (vp->type == string)
204                 return 0;
205
206         /* vp->type == numeric_string, make it numeric */
207         errno = 0;
208         i  = strtoq(vp->u.s, (char**)NULL, 10);
209         if (errno != 0) {
210                 free(vp->u.s);
211                 ast_log(LOG_WARNING,"overflow\n");
212                 return(0);
213         }
214         free (vp->u.s);
215         vp->u.i = i;
216         vp->type = integer;
217         return 1;
218 }
219
220 static void
221 to_string (vp)
222 struct val *vp;
223 {
224         char *tmp;
225
226         if (vp->type == string || vp->type == numeric_string)
227                 return;
228
229         tmp = malloc ((size_t)25);
230         if (tmp == NULL) {
231                 ast_log(LOG_WARNING,"malloc() failed\n");
232                 return;
233         }
234
235         sprintf (tmp, "%lld", (long long)vp->u.i);
236         vp->type = string;
237         vp->u.s  = tmp;
238 }
239
240
241 static int
242 isstring (vp)
243 struct val *vp;
244 {
245         /* only TRUE if this string is not a valid integer */
246         return (vp->type == string);
247 }
248
249
250 static int
251 ast_yylex (YYSTYPE *lvalp, struct parser_control *karoto)
252 {
253         char *p;
254
255         if (karoto->firsttoken==1) {
256                 p=strtok_r(karoto->argv," ",&(karoto->ptrptr));
257                 karoto->firsttoken=0;
258         } else {
259                 p=strtok_r(NULL," ",&(karoto->ptrptr));
260         }
261
262         if (p==NULL) {
263                 return (0);
264         }
265
266
267         if (strlen (p) == 1) {
268                 if (strchr ("|&=<>+-*/%:()", *p))
269                         return (*p);
270         } else if (strlen (p) == 2 && p[1] == '=') {
271                 switch (*p) {
272                 case '>': return (GE);
273                 case '<': return (LE);
274                 case '!': return (NE);
275                 }
276         }
277
278         lvalp->val = make_str (p);
279         return (TOKEN);
280 }
281
282 static int
283 is_zero_or_null (vp)
284 struct val *vp;
285 {
286         if (vp->type == integer) {
287                 return (vp->u.i == 0);
288         } else {
289                 return (*vp->u.s == 0 || (to_integer (vp) && vp->u.i == 0));
290         }
291         /* NOTREACHED */
292 }
293
294 char *ast_expr (char *arg)
295 {
296         struct parser_control karoto;
297
298         char *kota;
299         char *pirouni;
300         
301         kota=strdup(arg);
302         karoto.firsttoken=1;
303         karoto.argv=kota;
304
305         ast_yyparse ((void *)&karoto);
306
307         free(kota);
308
309         if (karoto.result==NULL) {
310                 pirouni=strdup("0");
311                 return(pirouni);
312         } else {
313                 if (karoto.result->type == integer) {
314                         pirouni=malloc(256);
315                         sprintf (pirouni,"%lld", (long long)karoto.result->u.i);
316                 }
317                 else {
318                         pirouni=strdup(karoto.result->u.s);
319                 }
320                 free(karoto.result);
321         }
322         return(pirouni);
323 }
324
325 #ifdef STANDALONE
326
327 int main(int argc,char **argv) {
328         char *s;
329
330         s=ast_expr(argv[1]);
331
332         printf("=====%s======\n",s);
333 }
334
335 #endif
336
337 static int
338 ast_yyerror (s)
339 const char *s;
340 {       
341         ast_log(LOG_WARNING,"ast_yyerror(): syntax error: %s\n",s);
342         return(0);
343 }
344
345
346 static struct val *
347 op_or (a, b)
348 struct val *a, *b;
349 {
350         if (is_zero_or_null (a)) {
351                 free_value (a);
352                 return (b);
353         } else {
354                 free_value (b);
355                 return (a);
356         }
357 }
358                 
359 static struct val *
360 op_and (a, b)
361 struct val *a, *b;
362 {
363         if (is_zero_or_null (a) || is_zero_or_null (b)) {
364                 free_value (a);
365                 free_value (b);
366                 return (make_integer ((quad_t)0));
367         } else {
368                 free_value (b);
369                 return (a);
370         }
371 }
372
373 static struct val *
374 op_eq (a, b)
375 struct val *a, *b;
376 {
377         struct val *r; 
378
379         if (isstring (a) || isstring (b)) {
380                 to_string (a);
381                 to_string (b);  
382                 r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) == 0));
383         } else {
384                 (void)to_integer(a);
385                 (void)to_integer(b);
386                 r = make_integer ((quad_t)(a->u.i == b->u.i));
387         }
388
389         free_value (a);
390         free_value (b);
391         return r;
392 }
393
394 static struct val *
395 op_gt (a, b)
396 struct val *a, *b;
397 {
398         struct val *r;
399
400         if (isstring (a) || isstring (b)) {
401                 to_string (a);
402                 to_string (b);
403                 r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) > 0));
404         } else {
405                 (void)to_integer(a);
406                 (void)to_integer(b);
407                 r = make_integer ((quad_t)(a->u.i > b->u.i));
408         }
409
410         free_value (a);
411         free_value (b);
412         return r;
413 }
414
415 static struct val *
416 op_lt (a, b)
417 struct val *a, *b;
418 {
419         struct val *r;
420
421         if (isstring (a) || isstring (b)) {
422                 to_string (a);
423                 to_string (b);
424                 r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) < 0));
425         } else {
426                 (void)to_integer(a);
427                 (void)to_integer(b);
428                 r = make_integer ((quad_t)(a->u.i < b->u.i));
429         }
430
431         free_value (a);
432         free_value (b);
433         return r;
434 }
435
436 static struct val *
437 op_ge (a, b)
438 struct val *a, *b;
439 {
440         struct val *r;
441
442         if (isstring (a) || isstring (b)) {
443                 to_string (a);
444                 to_string (b);
445                 r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) >= 0));
446         } else {
447                 (void)to_integer(a);
448                 (void)to_integer(b);
449                 r = make_integer ((quad_t)(a->u.i >= b->u.i));
450         }
451
452         free_value (a);
453         free_value (b);
454         return r;
455 }
456
457 static struct val *
458 op_le (a, b)
459 struct val *a, *b;
460 {
461         struct val *r;
462
463         if (isstring (a) || isstring (b)) {
464                 to_string (a);
465                 to_string (b);
466                 r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) <= 0));
467         } else {
468                 (void)to_integer(a);
469                 (void)to_integer(b);
470                 r = make_integer ((quad_t)(a->u.i <= b->u.i));
471         }
472
473         free_value (a);
474         free_value (b);
475         return r;
476 }
477
478 static struct val *
479 op_ne (a, b)
480 struct val *a, *b;
481 {
482         struct val *r;
483
484         if (isstring (a) || isstring (b)) {
485                 to_string (a);
486                 to_string (b);
487                 r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) != 0));
488         } else {
489                 (void)to_integer(a);
490                 (void)to_integer(b);
491                 r = make_integer ((quad_t)(a->u.i != b->u.i));
492         }
493
494         free_value (a);
495         free_value (b);
496         return r;
497 }
498
499 static int
500 chk_plus (a, b, r)
501 quad_t a, b, r;
502 {
503         /* sum of two positive numbers must be positive */
504         if (a > 0 && b > 0 && r <= 0)
505                 return 1;
506         /* sum of two negative numbers must be negative */
507         if (a < 0 && b < 0 && r >= 0)
508                 return 1;
509         /* all other cases are OK */
510         return 0;
511 }
512
513 static struct val *
514 op_plus (a, b)
515 struct val *a, *b;
516 {
517         struct val *r;
518
519         if (!to_integer (a) || !to_integer (b)) {
520                 ast_log(LOG_WARNING,"non-numeric argument\n");
521                 free_value(a);
522                 free_value(b);
523                 return(NULL);
524         }
525
526         r = make_integer (/*(quad_t)*/(a->u.i + b->u.i));
527         if (chk_plus (a->u.i, b->u.i, r->u.i)) {
528                 ast_log(LOG_WARNING,"overflow\n");
529                 free_value(a);
530                 free_value(b);
531                 return(NULL);
532         }
533         free_value (a);
534         free_value (b);
535         return r;
536 }
537
538 static int
539 chk_minus (a, b, r)
540 quad_t a, b, r;
541 {
542         /* special case subtraction of QUAD_MIN */
543         if (b == QUAD_MIN) {
544                 if (a >= 0)
545                         return 1;
546                 else
547                         return 0;
548         }
549         /* this is allowed for b != QUAD_MIN */
550         return chk_plus (a, -b, r);
551 }
552
553 static struct val *
554 op_minus (a, b)
555 struct val *a, *b;
556 {
557         struct val *r;
558
559         if (!to_integer (a) || !to_integer (b)) {
560                 free_value(a);
561                 free_value(b);
562                 ast_log(LOG_WARNING, "non-numeric argument\n");
563                 return(NULL);
564         }
565
566         r = make_integer (/*(quad_t)*/(a->u.i - b->u.i));
567         if (chk_minus (a->u.i, b->u.i, r->u.i)) {
568                 free_value(a);
569                 free_value(b);
570                 ast_log(LOG_WARNING, "overload\n");
571                 return(NULL);
572         }
573         free_value (a);
574         free_value (b);
575         return r;
576 }
577
578 static int
579 chk_times (a, b, r)
580 quad_t a, b, r;
581 {
582         /* special case: first operand is 0, no overflow possible */
583         if (a == 0)
584                 return 0;
585         /* cerify that result of division matches second operand */
586         if (r / a != b)
587                 return 1;
588         return 0;
589 }
590
591 static struct val *
592 op_times (a, b)
593 struct val *a, *b;
594 {
595         struct val *r;
596
597         if (!to_integer (a) || !to_integer (b)) {
598                 free_value(a);
599                 free_value(b);
600                 ast_log(LOG_WARNING, "non-numeric argument\n");
601                 return(NULL);
602         }
603
604         r = make_integer (/*(quad_t)*/(a->u.i * b->u.i));
605         if (chk_times (a->u.i, b->u.i, r->u.i)) {
606                 ast_log(LOG_WARNING, "overflow\n");
607                 free_value(a);
608                 free_value(b);
609                 return(NULL);
610         }
611         free_value (a);
612         free_value (b);
613         return (r);
614 }
615
616 static int
617 chk_div (a, b)
618 quad_t a, b;
619 {
620         /* div by zero has been taken care of before */
621         /* only QUAD_MIN / -1 causes overflow */
622         if (a == QUAD_MIN && b == -1)
623                 return 1;
624         /* everything else is OK */
625         return 0;
626 }
627
628 static struct val *
629 op_div (a, b)
630 struct val *a, *b;
631 {
632         struct val *r;
633
634         if (!to_integer (a) || !to_integer (b)) {
635                 free_value(a);
636                 free_value(b);
637                 ast_log(LOG_WARNING, "non-numeric argument\n");
638                 return(NULL);
639         }
640
641         if (b->u.i == 0) {
642                 ast_log(LOG_WARNING, "division by zero\n");             
643                 free_value(a);
644                 free_value(b);
645                 return(NULL);
646         }
647
648         r = make_integer (/*(quad_t)*/(a->u.i / b->u.i));
649         if (chk_div (a->u.i, b->u.i)) {
650                 ast_log(LOG_WARNING, "overflow\n");
651                 free_value(a);
652                 free_value(b);
653                 return(NULL);
654         }
655         free_value (a);
656         free_value (b);
657         return r;
658 }
659         
660 static struct val *
661 op_rem (a, b)
662 struct val *a, *b;
663 {
664         struct val *r;
665
666         if (!to_integer (a) || !to_integer (b)) {
667                 ast_log(LOG_WARNING, "non-numeric argument\n");
668                 free_value(a);
669                 free_value(b);
670                 return(NULL);
671         }
672
673         if (b->u.i == 0) {
674                 ast_log(LOG_WARNING, "div by zero\n");
675                 free_value(a);
676                 free_value(b);
677                 return(NULL);
678         }
679
680         r = make_integer (/*(quad_t)*/(a->u.i % b->u.i));
681         /* chk_rem necessary ??? */
682         free_value (a);
683         free_value (b);
684         return r;
685 }
686         
687 static struct val *
688 op_colon (a, b)
689 struct val *a, *b;
690 {
691         regex_t rp;
692         regmatch_t rm[2];
693         char errbuf[256];
694         int eval;
695         struct val *v;
696
697         /* coerce to both arguments to strings */
698         to_string(a);
699         to_string(b);
700
701         /* compile regular expression */
702         if ((eval = regcomp (&rp, b->u.s, 0)) != 0) {
703                 regerror (eval, &rp, errbuf, sizeof(errbuf));
704                 ast_log(LOG_WARNING,"regcomp() error : %s",errbuf);
705                 free_value(a);
706                 free_value(b);
707                 return(NULL);           
708         }
709
710         /* compare string against pattern */
711         /* remember that patterns are anchored to the beginning of the line */
712         if (regexec(&rp, a->u.s, (size_t)2, rm, 0) == 0 && rm[0].rm_so == 0) {
713                 if (rm[1].rm_so >= 0) {
714                         *(a->u.s + rm[1].rm_eo) = '\0';
715                         v = make_str (a->u.s + rm[1].rm_so);
716
717                 } else {
718                         v = make_integer ((quad_t)(rm[0].rm_eo - rm[0].rm_so));
719                 }
720         } else {
721                 if (rp.re_nsub == 0) {
722                         v = make_integer ((quad_t)0);
723                 } else {
724                         v = make_str ("");
725                 }
726         }
727
728         /* free arguments and pattern buffer */
729         free_value (a);
730         free_value (b);
731         regfree (&rp);
732
733         return v;
734 }