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