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