Update for backwards compatability (bug #1548)
[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 *arg_orig;
52         char *argv;
53         char *ptrptr;
54         int firsttoken;
55 } ;
56
57 static int              chk_div __P((quad_t, quad_t));
58 static int              chk_minus __P((quad_t, quad_t, quad_t));
59 static int              chk_plus __P((quad_t, quad_t, quad_t));
60 static int              chk_times __P((quad_t, quad_t, quad_t));
61 static void             free_value __P((struct val *));
62 static int              is_zero_or_null __P((struct val *));
63 static int              isstring __P((struct val *));
64 static struct val       *make_integer __P((quad_t));
65 static struct val       *make_str __P((const char *));
66 static struct val       *op_and __P((struct val *, struct val *));
67 static struct val       *op_colon __P((struct val *, struct val *));
68 static struct val       *op_div __P((struct val *, struct val *));
69 static struct val       *op_eq __P((struct val *, struct val *));
70 static struct val       *op_ge __P((struct val *, struct val *));
71 static struct val       *op_gt __P((struct val *, struct val *));
72 static struct val       *op_le __P((struct val *, struct val *));
73 static struct val       *op_lt __P((struct val *, struct val *));
74 static struct val       *op_minus __P((struct val *, struct val *));
75 static struct val       *op_ne __P((struct val *, struct val *));
76 static struct val       *op_or __P((struct val *, struct val *));
77 static struct val       *op_plus __P((struct val *, struct val *));
78 static struct val       *op_rem __P((struct val *, struct val *));
79 static struct val       *op_times __P((struct val *, struct val *));
80 static quad_t           to_integer __P((struct val *));
81 static void             to_string __P((struct val *));
82
83 /* uh, if I want to predeclare yylex with a YYLTYPE, I have to predeclare the yyltype... sigh */
84 typedef struct yyltype
85 {
86   int first_line;
87   int first_column;
88
89   int last_line;
90   int last_column;
91 } yyltype;
92
93 # define YYLTYPE yyltype
94 # define YYLTYPE_IS_TRIVIAL 1
95
96 static int              ast_yyerror __P((const char *,YYLTYPE *, struct parser_control *));
97
98 #define ast_yyerror(x) ast_yyerror(x,&yyloc,kota)
99
100 %}
101
102 %pure-parser
103 %locations
104 /* %debug  for when you are having big problems */
105
106 /* %name-prefix="ast_yy" */
107
108 %union
109 {
110         struct val *val;
111 }
112
113 %{
114 static int              ast_yylex __P((YYSTYPE *, YYLTYPE *, struct parser_control *));
115 %}
116
117
118 %left <val> '|'
119 %left <val> '&'
120 %left <val> '=' '>' '<' GE LE NE
121 %left <val> '+' '-'
122 %left <val> '*' '/' '%'
123 %left <val> ':'
124
125 %token <val> TOKEN
126 %type <val> start expr
127
128 %%
129
130 start: expr { ((struct parser_control *)kota)->result = $$; }
131         ;
132
133 expr:   TOKEN
134         | '(' expr ')' { $$ = $2; @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
135         | expr '|' expr { $$ = op_or ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
136         | expr '&' expr { $$ = op_and ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
137         | expr '=' expr { $$ = op_eq ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
138         | expr '>' expr { $$ = op_gt ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
139         | expr '<' expr { $$ = op_lt ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
140         | expr GE expr  { $$ = op_ge ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
141         | expr LE expr  { $$ = op_le ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
142         | expr NE expr  { $$ = op_ne ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
143         | expr '+' expr { $$ = op_plus ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
144         | expr '-' expr { $$ = op_minus ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
145         | expr '*' expr { $$ = op_times ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
146         | expr '/' expr { $$ = op_div ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
147         | expr '%' expr { $$ = op_rem ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
148         | expr ':' expr { $$ = op_colon ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
149         ;
150
151
152 %%
153
154 static struct val *
155 make_integer (i)
156 quad_t i;
157 {
158         struct val *vp;
159
160         vp = (struct val *) malloc (sizeof (*vp));
161         if (vp == NULL) {
162                 ast_log(LOG_WARNING, "malloc() failed\n");
163                 return(NULL);
164         }
165
166         vp->type = integer;
167         vp->u.i  = i;
168         return vp; 
169 }
170
171 static struct val *
172 make_str (s)
173 const char *s;
174 {
175         struct val *vp;
176         size_t i;
177         int isint;
178
179         vp = (struct val *) malloc (sizeof (*vp));
180         if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) {
181                 ast_log(LOG_WARNING,"malloc() failed\n");
182                 return(NULL);
183         }
184
185         for(i = 1, isint = isdigit(s[0]) || s[0] == '-';
186             isint && i < strlen(s);
187             i++)
188         {
189                 if(!isdigit(s[i]))
190                          isint = 0;
191         }
192
193         if (isint)
194                 vp->type = numeric_string;
195         else    
196                 vp->type = string;
197
198         return vp;
199 }
200
201
202 static void
203 free_value (vp)
204 struct val *vp;
205 {       
206         if (vp==NULL) {
207                 return;
208         }
209         if (vp->type == string || vp->type == numeric_string)
210                 free (vp->u.s); 
211 }
212
213
214 static quad_t
215 to_integer (vp)
216 struct val *vp;
217 {
218         quad_t i;
219
220         if (vp == NULL) {
221                 ast_log(LOG_WARNING,"vp==NULL in to_integer()\n");
222                 return(0);
223         }
224
225         if (vp->type == integer)
226                 return 1;
227
228         if (vp->type == string)
229                 return 0;
230
231         /* vp->type == numeric_string, make it numeric */
232         errno = 0;
233         i  = strtoq(vp->u.s, (char**)NULL, 10);
234         if (errno != 0) {
235                 free(vp->u.s);
236                 ast_log(LOG_WARNING,"overflow\n");
237                 return(0);
238         }
239         free (vp->u.s);
240         vp->u.i = i;
241         vp->type = integer;
242         return 1;
243 }
244
245 static void
246 to_string (vp)
247 struct val *vp;
248 {
249         char *tmp;
250
251         if (vp->type == string || vp->type == numeric_string)
252                 return;
253
254         tmp = malloc ((size_t)25);
255         if (tmp == NULL) {
256                 ast_log(LOG_WARNING,"malloc() failed\n");
257                 return;
258         }
259
260         sprintf (tmp, "%lld", (long long)vp->u.i);
261         vp->type = string;
262         vp->u.s  = tmp;
263 }
264
265
266 static int
267 isstring (vp)
268 struct val *vp;
269 {
270         /* only TRUE if this string is not a valid integer */
271         return (vp->type == string);
272 }
273
274 static int
275 ast_yylex (YYSTYPE *lvalp, YYLTYPE *yylloc, struct parser_control *karoto)
276 {
277         char *p=0;
278         char *t1=0;
279         char savep = 0;
280         char *savepp = 0;
281         
282         if (karoto->firsttoken==1) {
283                 t1 = karoto->argv;
284                 karoto->firsttoken = 0;
285         } else {
286                 t1 = karoto->ptrptr;
287         }
288         
289         while(*t1 && *t1 == ' ' )  /* we can remove worries about leading/multiple spaces being present */
290                 t1++;
291         karoto->ptrptr = t1;
292         yylloc->first_column = t1 - karoto->argv;
293         
294         while( *t1 && *t1 != ' ' && *t1 != '"') /* find the next space or quote */
295                 t1++;
296         if( *t1 == ' ' )
297         {
298                 *t1 = 0;
299                 p = karoto->ptrptr;
300                 karoto->ptrptr = t1+1;
301                 yylloc->last_column = t1 - karoto->argv;
302         }
303         else if (*t1 == '"' )
304         {
305                 /* opening quote. find the closing quote */
306                 char *t2=t1+1;
307                 while( *t2 && *t2 != '"')
308                         t2++;
309                 if( *t2 == '"' )
310                 {
311                         if( *(t2+1) == ' ' || *(t2+1) == 0 )
312                         {
313                                 if( *(t2+1) )
314                                 {
315                                         *(t2+1) = 0;
316                                         karoto->ptrptr = t2+2;
317                                 }
318                                 else
319                                 {
320                                         karoto->ptrptr = t2+1;
321                                 }
322                         }
323                         else
324                         {
325                                 /* hmmm. what if another token is here? */
326                                 /* maybe we can insert a space? */
327                                 savep = *(t2+1);
328                                 savepp = t2+1;
329                                 *(t2+1) = 0;
330                                 karoto->ptrptr = t2+1;
331                         }
332                         p = t1;
333                 }
334                 else
335                 {
336                         /* NOT GOOD -- no closing quote! */
337                         p = t1;
338                         karoto->ptrptr = t2;
339                 }
340                 yylloc->last_column = t2 - karoto->argv;
341         }
342         else if( *t1 == 0 )
343         {
344                 /* we are done. That was quick */
345                 p = karoto->ptrptr;
346                 yylloc->last_column = t1 - karoto->argv;
347         }
348         if( *p == 0 )
349                 p = 0;
350         
351         if (p==NULL) {
352                 return (0);
353         }
354
355
356         if (strlen (p) == 1) {
357                 if (strchr ("|&=<>+-*/%:()", *p))
358                         return (*p);
359         } else if (strlen (p) == 2 && p[1] == '=') {
360                 switch (*p) {
361                 case '>': return (GE);
362                 case '<': return (LE);
363                 case '!': return (NE);
364                 }
365         }
366
367         lvalp->val = make_str (p);
368         if( savep )
369         {
370                 *savepp = savep; /* restore the null terminated string */
371                 savepp = 0;
372                 savep = 0;
373         }
374         return (TOKEN);
375 }
376
377 static int
378 is_zero_or_null (vp)
379 struct val *vp;
380 {
381         if (vp->type == integer) {
382                 return (vp->u.i == 0);
383         } else {
384                 return (*vp->u.s == 0 || (to_integer (vp) && vp->u.i == 0));
385         }
386         /* NOTREACHED */
387 }
388
389 char *ast_expr (char *arg)
390 {
391         struct parser_control karoto;
392
393         char *kota;
394         char *pirouni;
395         
396         kota=strdup(arg);
397         karoto.result = NULL;
398         karoto.firsttoken=1;
399         karoto.argv=kota;
400         karoto.arg_orig = arg;
401         /* ast_yydebug = 1; */
402         
403         ast_yyparse ((void *)&karoto);
404
405         free(kota);
406
407         if (karoto.result==NULL) {
408                 pirouni=strdup("0");
409                 return(pirouni);
410         } else {
411                 if (karoto.result->type == integer) {
412                         pirouni=malloc(256);
413                         sprintf (pirouni,"%lld", (long long)karoto.result->u.i);
414                 }
415                 else {
416                         pirouni=strdup(karoto.result->u.s);
417                 }
418                 free(karoto.result);
419         }
420         return(pirouni);
421 }
422
423 #ifdef STANDALONE
424
425 int main(int argc,char **argv) {
426         char *s;
427
428         s=ast_expr(argv[1]);
429
430         printf("=====%s======\n",s);
431 }
432
433 #endif
434
435 #undef ast_yyerror
436 #define ast_yyerror(x) ast_yyerror(x, YYLTYPE *yylloc, struct parser_control *karoto)
437
438 static int
439 ast_yyerror (const char *s)
440 {       
441         char spacebuf[8000]; /* best safe than sorry */
442         char spacebuf2[8000]; /* best safe than sorry */
443         int i=0;
444         spacebuf[0] = 0;
445         
446         if( yylloc->first_column > 7990 ) /* if things get out of whack, why crash? */
447                 yylloc->first_column = 7990;
448         if( yylloc->last_column > 7990 )
449                 yylloc->last_column = 7990;
450         for(i=0;i<yylloc->first_column;i++) spacebuf[i] = ' ';
451         for(   ;i<yylloc->last_column;i++) spacebuf[i] = '^';
452         spacebuf[i] = 0;
453
454         for(i=0;i<karoto->ptrptr-karoto->argv;i++) spacebuf2[i] = ' ';
455         spacebuf2[i++]='^';
456         spacebuf2[i]= 0;
457
458         ast_log(LOG_WARNING,"ast_yyerror(): syntax error: %s; Input:\n%s\n%s\n%s\n",s, 
459                         karoto->arg_orig,spacebuf,spacebuf2);
460         return(0);
461 }
462
463
464 static struct val *
465 op_or (a, b)
466 struct val *a, *b;
467 {
468         if (is_zero_or_null (a)) {
469                 free_value (a);
470                 return (b);
471         } else {
472                 free_value (b);
473                 return (a);
474         }
475 }
476                 
477 static struct val *
478 op_and (a, b)
479 struct val *a, *b;
480 {
481         if (is_zero_or_null (a) || is_zero_or_null (b)) {
482                 free_value (a);
483                 free_value (b);
484                 return (make_integer ((quad_t)0));
485         } else {
486                 free_value (b);
487                 return (a);
488         }
489 }
490
491 static struct val *
492 op_eq (a, b)
493 struct val *a, *b;
494 {
495         struct val *r; 
496
497         if (isstring (a) || isstring (b)) {
498                 to_string (a);
499                 to_string (b);  
500                 r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) == 0));
501         } else {
502                 (void)to_integer(a);
503                 (void)to_integer(b);
504                 r = make_integer ((quad_t)(a->u.i == b->u.i));
505         }
506
507         free_value (a);
508         free_value (b);
509         return r;
510 }
511
512 static struct val *
513 op_gt (a, b)
514 struct val *a, *b;
515 {
516         struct val *r;
517
518         if (isstring (a) || isstring (b)) {
519                 to_string (a);
520                 to_string (b);
521                 r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) > 0));
522         } else {
523                 (void)to_integer(a);
524                 (void)to_integer(b);
525                 r = make_integer ((quad_t)(a->u.i > b->u.i));
526         }
527
528         free_value (a);
529         free_value (b);
530         return r;
531 }
532
533 static struct val *
534 op_lt (a, b)
535 struct val *a, *b;
536 {
537         struct val *r;
538
539         if (isstring (a) || isstring (b)) {
540                 to_string (a);
541                 to_string (b);
542                 r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) < 0));
543         } else {
544                 (void)to_integer(a);
545                 (void)to_integer(b);
546                 r = make_integer ((quad_t)(a->u.i < b->u.i));
547         }
548
549         free_value (a);
550         free_value (b);
551         return r;
552 }
553
554 static struct val *
555 op_ge (a, b)
556 struct val *a, *b;
557 {
558         struct val *r;
559
560         if (isstring (a) || isstring (b)) {
561                 to_string (a);
562                 to_string (b);
563                 r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) >= 0));
564         } else {
565                 (void)to_integer(a);
566                 (void)to_integer(b);
567                 r = make_integer ((quad_t)(a->u.i >= b->u.i));
568         }
569
570         free_value (a);
571         free_value (b);
572         return r;
573 }
574
575 static struct val *
576 op_le (a, b)
577 struct val *a, *b;
578 {
579         struct val *r;
580
581         if (isstring (a) || isstring (b)) {
582                 to_string (a);
583                 to_string (b);
584                 r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) <= 0));
585         } else {
586                 (void)to_integer(a);
587                 (void)to_integer(b);
588                 r = make_integer ((quad_t)(a->u.i <= b->u.i));
589         }
590
591         free_value (a);
592         free_value (b);
593         return r;
594 }
595
596 static struct val *
597 op_ne (a, b)
598 struct val *a, *b;
599 {
600         struct val *r;
601
602         if (isstring (a) || isstring (b)) {
603                 to_string (a);
604                 to_string (b);
605                 r = make_integer ((quad_t)(strcoll (a->u.s, b->u.s) != 0));
606         } else {
607                 (void)to_integer(a);
608                 (void)to_integer(b);
609                 r = make_integer ((quad_t)(a->u.i != b->u.i));
610         }
611
612         free_value (a);
613         free_value (b);
614         return r;
615 }
616
617 static int
618 chk_plus (a, b, r)
619 quad_t a, b, r;
620 {
621         /* sum of two positive numbers must be positive */
622         if (a > 0 && b > 0 && r <= 0)
623                 return 1;
624         /* sum of two negative numbers must be negative */
625         if (a < 0 && b < 0 && r >= 0)
626                 return 1;
627         /* all other cases are OK */
628         return 0;
629 }
630
631 static struct val *
632 op_plus (a, b)
633 struct val *a, *b;
634 {
635         struct val *r;
636
637         if (!to_integer (a) || !to_integer (b)) {
638                 ast_log(LOG_WARNING,"non-numeric argument\n");
639                 free_value(a);
640                 free_value(b);
641                 return(NULL);
642         }
643
644         r = make_integer (/*(quad_t)*/(a->u.i + b->u.i));
645         if (chk_plus (a->u.i, b->u.i, r->u.i)) {
646                 ast_log(LOG_WARNING,"overflow\n");
647                 free_value(a);
648                 free_value(b);
649                 return(NULL);
650         }
651         free_value (a);
652         free_value (b);
653         return r;
654 }
655
656 static int
657 chk_minus (a, b, r)
658 quad_t a, b, r;
659 {
660         /* special case subtraction of QUAD_MIN */
661         if (b == QUAD_MIN) {
662                 if (a >= 0)
663                         return 1;
664                 else
665                         return 0;
666         }
667         /* this is allowed for b != QUAD_MIN */
668         return chk_plus (a, -b, r);
669 }
670
671 static struct val *
672 op_minus (a, b)
673 struct val *a, *b;
674 {
675         struct val *r;
676
677         if (!to_integer (a) || !to_integer (b)) {
678                 free_value(a);
679                 free_value(b);
680                 ast_log(LOG_WARNING, "non-numeric argument\n");
681                 return(NULL);
682         }
683
684         r = make_integer (/*(quad_t)*/(a->u.i - b->u.i));
685         if (chk_minus (a->u.i, b->u.i, r->u.i)) {
686                 free_value(a);
687                 free_value(b);
688                 ast_log(LOG_WARNING, "overload\n");
689                 return(NULL);
690         }
691         free_value (a);
692         free_value (b);
693         return r;
694 }
695
696 static int
697 chk_times (a, b, r)
698 quad_t a, b, r;
699 {
700         /* special case: first operand is 0, no overflow possible */
701         if (a == 0)
702                 return 0;
703         /* cerify that result of division matches second operand */
704         if (r / a != b)
705                 return 1;
706         return 0;
707 }
708
709 static struct val *
710 op_times (a, b)
711 struct val *a, *b;
712 {
713         struct val *r;
714
715         if (!to_integer (a) || !to_integer (b)) {
716                 free_value(a);
717                 free_value(b);
718                 ast_log(LOG_WARNING, "non-numeric argument\n");
719                 return(NULL);
720         }
721
722         r = make_integer (/*(quad_t)*/(a->u.i * b->u.i));
723         if (chk_times (a->u.i, b->u.i, r->u.i)) {
724                 ast_log(LOG_WARNING, "overflow\n");
725                 free_value(a);
726                 free_value(b);
727                 return(NULL);
728         }
729         free_value (a);
730         free_value (b);
731         return (r);
732 }
733
734 static int
735 chk_div (a, b)
736 quad_t a, b;
737 {
738         /* div by zero has been taken care of before */
739         /* only QUAD_MIN / -1 causes overflow */
740         if (a == QUAD_MIN && b == -1)
741                 return 1;
742         /* everything else is OK */
743         return 0;
744 }
745
746 static struct val *
747 op_div (a, b)
748 struct val *a, *b;
749 {
750         struct val *r;
751
752         if (!to_integer (a) || !to_integer (b)) {
753                 free_value(a);
754                 free_value(b);
755                 ast_log(LOG_WARNING, "non-numeric argument\n");
756                 return(NULL);
757         }
758
759         if (b->u.i == 0) {
760                 ast_log(LOG_WARNING, "division by zero\n");             
761                 free_value(a);
762                 free_value(b);
763                 return(NULL);
764         }
765
766         r = make_integer (/*(quad_t)*/(a->u.i / b->u.i));
767         if (chk_div (a->u.i, b->u.i)) {
768                 ast_log(LOG_WARNING, "overflow\n");
769                 free_value(a);
770                 free_value(b);
771                 return(NULL);
772         }
773         free_value (a);
774         free_value (b);
775         return r;
776 }
777         
778 static struct val *
779 op_rem (a, b)
780 struct val *a, *b;
781 {
782         struct val *r;
783
784         if (!to_integer (a) || !to_integer (b)) {
785                 ast_log(LOG_WARNING, "non-numeric argument\n");
786                 free_value(a);
787                 free_value(b);
788                 return(NULL);
789         }
790
791         if (b->u.i == 0) {
792                 ast_log(LOG_WARNING, "div by zero\n");
793                 free_value(a);
794                 free_value(b);
795                 return(NULL);
796         }
797
798         r = make_integer (/*(quad_t)*/(a->u.i % b->u.i));
799         /* chk_rem necessary ??? */
800         free_value (a);
801         free_value (b);
802         return r;
803 }
804         
805 static struct val *
806 op_colon (a, b)
807 struct val *a, *b;
808 {
809         regex_t rp;
810         regmatch_t rm[2];
811         char errbuf[256];
812         int eval;
813         struct val *v;
814
815         /* coerce to both arguments to strings */
816         to_string(a);
817         to_string(b);
818
819         /* compile regular expression */
820         if ((eval = regcomp (&rp, b->u.s, 0)) != 0) {
821                 regerror (eval, &rp, errbuf, sizeof(errbuf));
822                 ast_log(LOG_WARNING,"regcomp() error : %s",errbuf);
823                 free_value(a);
824                 free_value(b);
825                 return(NULL);           
826         }
827
828         /* compare string against pattern */
829         /* remember that patterns are anchored to the beginning of the line */
830         if (regexec(&rp, a->u.s, (size_t)2, rm, 0) == 0 && rm[0].rm_so == 0) {
831                 if (rm[1].rm_so >= 0) {
832                         *(a->u.s + rm[1].rm_eo) = '\0';
833                         v = make_str (a->u.s + rm[1].rm_so);
834
835                 } else {
836                         v = make_integer ((quad_t)(rm[0].rm_eo - rm[0].rm_so));
837                 }
838         } else {
839                 if (rp.re_nsub == 0) {
840                         v = make_integer ((quad_t)0);
841                 } else {
842                         v = make_str ("");
843                 }
844         }
845
846         /* free arguments and pattern buffer */
847         free_value (a);
848         free_value (b);
849         regfree (&rp);
850
851         return v;
852 }