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 * And then overhauled twice by Steve Murphy (murf@e-tools.com)
8 * to add double-quoted strings, allow mult. spaces, improve
9 * error messages, and then to fold in a flex scanner for the
12 * $FreeBSD: src/bin/expr/expr.y,v 1.16 2000/07/22 10:59:36 se Exp $
17 ASTERISK_FILE_VERSION
(__FILE__
, "$Revision$")
19 #include <sys/types.h>
26 #if !defined(SOLARIS) && !defined(__CYGWIN__)
29 #define quad_t int64_t
35 #include "asterisk/ast_expr.h"
36 #include "asterisk/logger.h"
38 #if defined(LONG_LONG_MIN) && !defined(QUAD_MIN)
39 #define QUAD_MIN LONG_LONG_MIN
41 #if defined(LONG_LONG_MAX) && !defined(QUAD_MAX)
42 #define QUAD_MAX LONG_LONG_MAX
45 # if ! defined(QUAD_MIN)
46 # define QUAD_MIN (-0x7fffffffffffffffLL-1)
48 # if ! defined(QUAD_MAX)
49 # define QUAD_MAX (0x7fffffffffffffffLL)
52 #define YYPARSE_PARAM parseio
53 #define YYLEX_PARAM ((struct parse_io *)parseio)->scanner
54 #define YYERROR_VERBOSE 1
55 extern
char extra_error_message
[4095];
56 extern
int extra_error_message_supplied
;
59 AST_EXPR_integer
, AST_EXPR_numeric_string
, AST_EXPR_string
63 void ast_log
(int level
, const char *file
, int line
, const char *function
, const char *fmt
, ...
) __attribute__
((format
(printf
,5,6)));
74 typedef
void *yyscan_t
;
83 static int chk_div __P
((quad_t
, quad_t
));
84 static int chk_minus __P
((quad_t
, quad_t
, quad_t
));
85 static int chk_plus __P
((quad_t
, quad_t
, quad_t
));
86 static int chk_times __P
((quad_t
, quad_t
, quad_t
));
87 static void free_value __P
((struct val
*));
88 static int is_zero_or_null __P
((struct val
*));
89 static int isstring __P
((struct val
*));
90 static struct val
*make_integer __P
((quad_t
));
91 static struct val
*make_str __P
((const char *));
92 static struct val
*op_and __P
((struct val
*, struct val
*));
93 static struct val
*op_colon __P
((struct val
*, struct val
*));
94 static struct val
*op_eqtilde __P
((struct val
*, struct val
*));
95 static struct val
*op_div __P
((struct val
*, struct val
*));
96 static struct val
*op_eq __P
((struct val
*, struct val
*));
97 static struct val
*op_ge __P
((struct val
*, struct val
*));
98 static struct val
*op_gt __P
((struct val
*, struct val
*));
99 static struct val
*op_le __P
((struct val
*, struct val
*));
100 static struct val
*op_lt __P
((struct val
*, struct val
*));
101 static struct val
*op_cond __P
((struct val
*, struct val
*, struct val
*));
102 static struct val
*op_minus __P
((struct val
*, struct val
*));
103 static struct val
*op_negate __P
((struct val
*));
104 static struct val
*op_compl __P
((struct val
*));
105 static struct val
*op_ne __P
((struct val
*, struct val
*));
106 static struct val
*op_or __P
((struct val
*, struct val
*));
107 static struct val
*op_plus __P
((struct val
*, struct val
*));
108 static struct val
*op_rem __P
((struct val
*, struct val
*));
109 static struct val
*op_times __P
((struct val
*, struct val
*));
110 static quad_t to_integer __P
((struct val
*));
111 static void to_string __P
((struct val
*));
113 /* uh, if I want to predeclare yylex with a YYLTYPE, I have to predeclare the yyltype... sigh */
114 typedef
struct yyltype
123 # define YYLTYPE yyltype
124 # define YYLTYPE_IS_TRIVIAL 1
126 /* we will get warning about no prototype for yylex! But we can't
127 define it here, we have no definition yet for YYSTYPE. */
129 int ast_yyerror
(const char *,YYLTYPE *, struct parse_io
*);
131 /* I wanted to add args to the yyerror routine, so I could print out
132 some useful info about the error. Not as easy as it looks, but it
134 #define ast_yyerror(x) ast_yyerror(x,&yyloc,parseio)
135 #define DESTROY(x) {if((x)->type == AST_EXPR_numeric_string || (x)->type == AST_EXPR_string) free((x)->u.s); (x)->u.s = 0; free(x);}
140 /* %debug for when you are having big problems */
142 /* %name-prefix="ast_yy" */
150 extern
int ast_yylex __P
((YYSTYPE *, YYLTYPE *, yyscan_t
));
152 %left
<val
> TOK_COND TOK_COLONCOLON
155 %left
<val
> TOK_EQ TOK_GT TOK_LT TOK_GE TOK_LE TOK_NE
156 %left
<val
> TOK_PLUS TOK_MINUS
157 %left
<val
> TOK_MULT TOK_DIV TOK_MOD
158 %right
<val
> TOK_COMPL
159 %left
<val
> TOK_COLON TOK_EQTILDE
160 %left
<val
> TOK_RP TOK_LP
164 %type
<val
> start expr
167 %destructor
{ free_value
($$
); } expr TOKEN TOK_COND TOK_COLONCOLON TOK_OR TOK_AND TOK_EQ
168 TOK_GT TOK_LT TOK_GE TOK_LE TOK_NE TOK_PLUS TOK_MINUS TOK_MULT TOK_DIV TOK_MOD TOK_COMPL TOK_COLON TOK_EQTILDE
173 start: expr
{ ((struct parse_io
*)parseio
)->val
= (struct val
*)calloc
(sizeof
(struct val
),1);
174 ((struct parse_io
*)parseio
)->val
->type
= $1->type
;
175 if
( $1->type
== AST_EXPR_integer
)
176 ((struct parse_io
*)parseio
)->val
->u.i
= $1->u.i
;
178 ((struct parse_io
*)parseio
)->val
->u.s
= $1->u.s
;
181 |
{/* nothing */ ((struct parse_io
*)parseio
)->val
= (struct val
*)calloc
(sizeof
(struct val
),1);
182 ((struct parse_io
*)parseio
)->val
->type
= AST_EXPR_string
;
183 ((struct parse_io
*)parseio
)->val
->u.s
= strdup
("");
188 expr: TOKEN
{ $$
= $1;}
189 | TOK_LP expr TOK_RP
{ $$
= $2;
190 @$.first_column
= @
1.first_column
; @$.last_column
= @
3.last_column
;
191 @$.first_line
=0; @$.last_line
=0;
192 DESTROY
($1); DESTROY
($3); }
193 | expr TOK_OR expr
{ $$
= op_or
($1, $3);
195 @$.first_column
= @
1.first_column
; @$.last_column
= @
3.last_column
;
196 @$.first_line
=0; @$.last_line
=0;}
197 | expr TOK_AND expr
{ $$
= op_and
($1, $3);
199 @$.first_column
= @
1.first_column
; @$.last_column
= @
3.last_column
;
200 @$.first_line
=0; @$.last_line
=0;}
201 | expr TOK_EQ expr
{ $$
= op_eq
($1, $3);
203 @$.first_column
= @
1.first_column
; @$.last_column
= @
3.last_column
;
204 @$.first_line
=0; @$.last_line
=0;}
205 | expr TOK_GT expr
{ $$
= op_gt
($1, $3);
207 @$.first_column
= @
1.first_column
; @$.last_column
= @
3.last_column
;
208 @$.first_line
=0; @$.last_line
=0;}
209 | expr TOK_LT expr
{ $$
= op_lt
($1, $3);
211 @$.first_column
= @
1.first_column
; @$.last_column
= @
3.last_column
;
212 @$.first_line
=0; @$.last_line
=0;}
213 | expr TOK_GE expr
{ $$
= op_ge
($1, $3);
215 @$.first_column
= @
1.first_column
; @$.last_column
= @
3.last_column
;
216 @$.first_line
=0; @$.last_line
=0;}
217 | expr TOK_LE expr
{ $$
= op_le
($1, $3);
219 @$.first_column
= @
1.first_column
; @$.last_column
= @
3.last_column
;
220 @$.first_line
=0; @$.last_line
=0;}
221 | expr TOK_NE expr
{ $$
= op_ne
($1, $3);
223 @$.first_column
= @
1.first_column
; @$.last_column
= @
3.last_column
;
224 @$.first_line
=0; @$.last_line
=0;}
225 | expr TOK_PLUS expr
{ $$
= op_plus
($1, $3);
227 @$.first_column
= @
1.first_column
; @$.last_column
= @
3.last_column
;
228 @$.first_line
=0; @$.last_line
=0;}
229 | expr TOK_MINUS expr
{ $$
= op_minus
($1, $3);
231 @$.first_column
= @
1.first_column
; @$.last_column
= @
3.last_column
;
232 @$.first_line
=0; @$.last_line
=0;}
233 | TOK_MINUS expr %prec TOK_COMPL
{ $$
= op_negate
($2);
235 @$.first_column
= @
1.first_column
; @$.last_column
= @
2.last_column
;
236 @$.first_line
=0; @$.last_line
=0;}
237 | TOK_COMPL expr
{ $$
= op_compl
($2);
239 @$.first_column
= @
1.first_column
; @$.last_column
= @
2.last_column
;
240 @$.first_line
=0; @$.last_line
=0;}
241 | expr TOK_MULT expr
{ $$
= op_times
($1, $3);
243 @$.first_column
= @
1.first_column
; @$.last_column
= @
3.last_column
;
244 @$.first_line
=0; @$.last_line
=0;}
245 | expr TOK_DIV expr
{ $$
= op_div
($1, $3);
247 @$.first_column
= @
1.first_column
; @$.last_column
= @
3.last_column
;
248 @$.first_line
=0; @$.last_line
=0;}
249 | expr TOK_MOD expr
{ $$
= op_rem
($1, $3);
251 @$.first_column
= @
1.first_column
; @$.last_column
= @
3.last_column
;
252 @$.first_line
=0; @$.last_line
=0;}
253 | expr TOK_COLON expr
{ $$
= op_colon
($1, $3);
255 @$.first_column
= @
1.first_column
; @$.last_column
= @
3.last_column
;
256 @$.first_line
=0; @$.last_line
=0;}
257 | expr TOK_EQTILDE expr
{ $$
= op_eqtilde
($1, $3);
259 @$.first_column
= @
1.first_column
; @$.last_column
= @
3.last_column
;
260 @$.first_line
=0; @$.last_line
=0;}
261 | expr TOK_COND expr TOK_COLONCOLON expr
{ $$
= op_cond
($1, $3, $5);
264 @$.first_column
= @
1.first_column
; @$.last_column
= @
3.last_column
;
265 @$.first_line
=0; @$.last_line
=0;}
271 make_integer
(quad_t i
)
275 vp
= (struct val
*) malloc
(sizeof
(*vp
));
277 ast_log
(LOG_WARNING
, "malloc() failed\n");
281 vp
->type
= AST_EXPR_integer
;
287 make_str
(const char *s
)
293 vp
= (struct val
*) malloc
(sizeof
(*vp
));
294 if
(vp
== NULL ||
((vp
->u.s
= strdup
(s
)) == NULL
)) {
295 ast_log
(LOG_WARNING
,"malloc() failed\n");
299 for
(i
= 1, isint
= isdigit
(s
[0]) || s
[0] == '-';
300 isint
&& i
< strlen
(s
);
308 vp
->type
= AST_EXPR_numeric_string
;
310 vp
->type
= AST_EXPR_string
;
317 free_value
(struct val
*vp
)
322 if
(vp
->type
== AST_EXPR_string || vp
->type
== AST_EXPR_numeric_string
)
329 to_integer
(struct val
*vp
)
334 ast_log
(LOG_WARNING
,"vp==NULL in to_integer()\n");
338 if
(vp
->type
== AST_EXPR_integer
)
341 if
(vp
->type
== AST_EXPR_string
)
344 /* vp->type == AST_EXPR_numeric_string, make it numeric */
346 i
= strtoll
(vp
->u.s
, (char**)NULL
, 10);
348 ast_log
(LOG_WARNING
,"Conversion of %s to integer under/overflowed!\n", vp
->u.s
);
355 vp
->type
= AST_EXPR_integer
;
360 strip_quotes
(struct val
*vp
)
362 if
(vp
->type
!= AST_EXPR_string
&& vp
->type
!= AST_EXPR_numeric_string
)
365 if
( vp
->u.s
[0] == '"' && vp
->u.s
[strlen
(vp
->u.s
)-1] == '"' )
373 if
( *f
&& *f
!= '"' )
383 to_string
(struct val
*vp
)
387 if
(vp
->type
== AST_EXPR_string || vp
->type
== AST_EXPR_numeric_string
)
390 tmp
= malloc
((size_t)25);
392 ast_log
(LOG_WARNING
,"malloc() failed\n");
396 sprintf
(tmp
, "%ld", (long int) vp
->u.i
);
397 vp
->type
= AST_EXPR_string
;
403 isstring
(struct val
*vp
)
405 /* only TRUE if this string is not a valid integer */
406 return
(vp
->type
== AST_EXPR_string
);
411 is_zero_or_null
(struct val
*vp
)
413 if
(vp
->type
== AST_EXPR_integer
) {
414 return
(vp
->u.i
== 0);
416 return
(*vp
->u.s
== 0 ||
(to_integer
(vp
) && vp
->u.i
== 0));
423 void ast_log
(int level
, const char *file
, int line
, const char *function
, const char *fmt
, ...
)
428 printf
("LOG: lev:%d file:%s line:%d func: %s ",
429 level
, file
, line
, function
);
436 int main
(int argc
,char **argv
) {
444 if
( access
(argv
[1],F_OK
)== 0 )
448 infile
= fopen
(argv
[1],"r");
451 printf
("Sorry, couldn't open %s for reading!\n", argv
[1]);
454 while
( fgets
(s
,sizeof
(s
),infile
) )
456 if
( s
[strlen
(s
)-1] == '\n' )
459 ret
= ast_expr
(s
, out
, sizeof
(out
));
460 printf
("Expression: %s Result: [%d] '%s'\n",
467 if
(ast_expr
(argv
[1], s
, sizeof
(s
)))
468 printf
("=====%s======\n",s
);
470 printf
("No result\n");
477 #define ast_yyerror(x) ast_yyerror(x, YYLTYPE *yylloc, struct parse_io *parseio)
479 /* I put the ast_yyerror func in the flex input file,
480 because it refers to the buffer state. Best to
481 let it access the BUFFER stuff there and not trying
482 define all the structs, macros etc. in this file! */
486 op_or
(struct val
*a
, struct val
*b
)
488 if
(is_zero_or_null
(a
)) {
498 op_and
(struct val
*a
, struct val
*b
)
500 if
(is_zero_or_null
(a
) || is_zero_or_null
(b
)) {
503 return
(make_integer
((quad_t
)0));
511 op_eq
(struct val
*a
, struct val
*b
)
515 if
(isstring
(a
) || isstring
(b
)) {
518 r
= make_integer
((quad_t
)(strcoll
(a
->u.s
, b
->u.s
) == 0));
520 #ifdef DEBUG_FOR_CONVERSIONS
522 sprintf
(buffer
,"Converting '%s' and '%s' ", a
->u.s
, b
->u.s
);
526 #ifdef DEBUG_FOR_CONVERSIONS
527 ast_log
(LOG_WARNING
,"%s to '%lld' and '%lld'\n", buffer
, a
->u.i
, b
->u.i
);
529 r
= make_integer
((quad_t
)(a
->u.i
== b
->u.i
));
538 op_gt
(struct val
*a
, struct val
*b
)
542 if
(isstring
(a
) || isstring
(b
)) {
545 r
= make_integer
((quad_t
)(strcoll
(a
->u.s
, b
->u.s
) > 0));
549 r
= make_integer
((quad_t
)(a
->u.i
> b
->u.i
));
558 op_lt
(struct val
*a
, struct val
*b
)
562 if
(isstring
(a
) || isstring
(b
)) {
565 r
= make_integer
((quad_t
)(strcoll
(a
->u.s
, b
->u.s
) < 0));
569 r
= make_integer
((quad_t
)(a
->u.i
< b
->u.i
));
578 op_ge
(struct val
*a
, struct val
*b
)
582 if
(isstring
(a
) || isstring
(b
)) {
585 r
= make_integer
((quad_t
)(strcoll
(a
->u.s
, b
->u.s
) >= 0));
589 r
= make_integer
((quad_t
)(a
->u.i
>= b
->u.i
));
598 op_le
(struct val
*a
, struct val
*b
)
602 if
(isstring
(a
) || isstring
(b
)) {
605 r
= make_integer
((quad_t
)(strcoll
(a
->u.s
, b
->u.s
) <= 0));
609 r
= make_integer
((quad_t
)(a
->u.i
<= b
->u.i
));
618 op_cond
(struct val
*a
, struct val
*b
, struct val
*c
)
624 if
( strlen
(a
->u.s
) && strcmp
(a
->u.s
, "\"\"") != 0 && strcmp
(a
->u.s
,"0") != 0 )
657 op_ne
(struct val
*a
, struct val
*b
)
661 if
(isstring
(a
) || isstring
(b
)) {
664 r
= make_integer
((quad_t
)(strcoll
(a
->u.s
, b
->u.s
) != 0));
668 r
= make_integer
((quad_t
)(a
->u.i
!= b
->u.i
));
677 chk_plus
(quad_t a
, quad_t b
, quad_t r
)
679 /* sum of two positive numbers must be positive */
680 if
(a
> 0 && b
> 0 && r
<= 0)
682 /* sum of two negative numbers must be negative */
683 if
(a
< 0 && b
< 0 && r
>= 0)
685 /* all other cases are OK */
690 op_plus
(struct val
*a
, struct val
*b
)
694 if
(!to_integer
(a
)) {
695 if
( !extra_error_message_supplied
)
696 ast_log
(LOG_WARNING
,"non-numeric argument\n");
697 if
(!to_integer
(b
)) {
700 return make_integer
(0);
705 } else if
(!to_integer
(b
)) {
710 r
= make_integer
(/*(quad_t)*/(a
->u.i
+ b
->u.i
));
711 if
(chk_plus
(a
->u.i
, b
->u.i
, r
->u.i
)) {
712 ast_log
(LOG_WARNING
,"overflow\n");
720 chk_minus
(quad_t a
, quad_t b
, quad_t r
)
722 /* special case subtraction of QUAD_MIN */
729 /* this is allowed for b != QUAD_MIN */
730 return chk_plus
(a
, -b
, r
);
734 op_minus
(struct val
*a
, struct val
*b
)
738 if
(!to_integer
(a
)) {
739 if
( !extra_error_message_supplied
)
740 ast_log
(LOG_WARNING
, "non-numeric argument\n");
741 if
(!to_integer
(b
)) {
744 return make_integer
(0);
746 r
= make_integer
(0 - b
->u.i
);
751 } else if
(!to_integer
(b
)) {
752 if
( !extra_error_message_supplied
)
753 ast_log
(LOG_WARNING
, "non-numeric argument\n");
758 r
= make_integer
(/*(quad_t)*/(a
->u.i
- b
->u.i
));
759 if
(chk_minus
(a
->u.i
, b
->u.i
, r
->u.i
)) {
760 ast_log
(LOG_WARNING
, "overflow\n");
768 op_negate
(struct val
*a
)
772 if
(!to_integer
(a
) ) {
774 if
( !extra_error_message_supplied
)
775 ast_log
(LOG_WARNING
, "non-numeric argument\n");
776 return make_integer
(0);
779 r
= make_integer
(/*(quad_t)*/(- a
->u.i
));
780 if
(chk_minus
(0, a
->u.i
, r
->u.i
)) {
781 ast_log
(LOG_WARNING
, "overflow\n");
788 op_compl
(struct val
*a
)
801 case AST_EXPR_integer
:
806 case AST_EXPR_string
:
813 else if
(strlen
(a
->u.s
) == 1 && a
->u.s
[0] == '0' )
818 case AST_EXPR_numeric_string
:
825 else if
(strlen
(a
->u.s
) == 1 && a
->u.s
[0] == '0' )
832 r
= make_integer
(!v1
);
838 chk_times
(quad_t a
, quad_t b
, quad_t r
)
840 /* special case: first operand is 0, no overflow possible */
843 /* cerify that result of division matches second operand */
850 op_times
(struct val
*a
, struct val
*b
)
854 if
(!to_integer
(a
) ||
!to_integer
(b
)) {
857 if
( !extra_error_message_supplied
)
858 ast_log
(LOG_WARNING
, "non-numeric argument\n");
859 return
(make_integer
(0));
862 r
= make_integer
(/*(quad_t)*/(a
->u.i
* b
->u.i
));
863 if
(chk_times
(a
->u.i
, b
->u.i
, r
->u.i
)) {
864 ast_log
(LOG_WARNING
, "overflow\n");
872 chk_div
(quad_t a
, quad_t b
)
874 /* div by zero has been taken care of before */
875 /* only QUAD_MIN / -1 causes overflow */
876 if
(a
== QUAD_MIN
&& b
== -1)
878 /* everything else is OK */
883 op_div
(struct val
*a
, struct val
*b
)
887 if
(!to_integer
(a
)) {
890 if
( !extra_error_message_supplied
)
891 ast_log
(LOG_WARNING
, "non-numeric argument\n");
892 return make_integer
(0);
893 } else if
(!to_integer
(b
)) {
896 if
( !extra_error_message_supplied
)
897 ast_log
(LOG_WARNING
, "non-numeric argument\n");
898 return make_integer
(INT_MAX
);
902 ast_log
(LOG_WARNING
, "division by zero\n");
905 return make_integer
(INT_MAX
);
908 r
= make_integer
(/*(quad_t)*/(a
->u.i
/ b
->u.i
));
909 if
(chk_div
(a
->u.i
, b
->u.i
)) {
910 ast_log
(LOG_WARNING
, "overflow\n");
918 op_rem
(struct val
*a
, struct val
*b
)
922 if
(!to_integer
(a
) ||
!to_integer
(b
)) {
923 if
( !extra_error_message_supplied
)
924 ast_log
(LOG_WARNING
, "non-numeric argument\n");
927 return make_integer
(0);
931 ast_log
(LOG_WARNING
, "div by zero\n");
936 r
= make_integer
(/*(quad_t)*/(a
->u.i % b
->u.i
));
937 /* chk_rem necessary ??? */
945 op_colon
(struct val
*a
, struct val
*b
)
953 /* coerce to both arguments to strings */
956 /* strip double quotes from both -- they'll screw up the pattern, and the search string starting at ^ */
959 /* compile regular expression */
960 if
((eval
= regcomp
(&rp
, b
->u.s
, REG_EXTENDED
)) != 0) {
961 regerror
(eval
, &rp
, errbuf
, sizeof
(errbuf
));
962 ast_log
(LOG_WARNING
,"regcomp() error : %s",errbuf
);
968 /* compare string against pattern */
969 /* remember that patterns are anchored to the beginning of the line */
970 if
(regexec
(&rp
, a
->u.s
, (size_t)2, rm
, 0) == 0 && rm
[0].rm_so
== 0) {
971 if
(rm
[1].rm_so
>= 0) {
972 *(a
->u.s
+ rm
[1].rm_eo
) = '\0';
973 v
= make_str
(a
->u.s
+ rm
[1].rm_so
);
976 v
= make_integer
((quad_t
)(rm
[0].rm_eo
- rm
[0].rm_so
));
979 if
(rp.re_nsub
== 0) {
980 v
= make_integer
((quad_t
)0);
986 /* free arguments and pattern buffer */
996 op_eqtilde
(struct val
*a
, struct val
*b
)
1004 /* coerce to both arguments to strings */
1007 /* strip double quotes from both -- they'll screw up the pattern, and the search string starting at ^ */
1010 /* compile regular expression */
1011 if
((eval
= regcomp
(&rp
, b
->u.s
, REG_EXTENDED
)) != 0) {
1012 regerror
(eval
, &rp
, errbuf
, sizeof
(errbuf
));
1013 ast_log
(LOG_WARNING
,"regcomp() error : %s",errbuf
);
1016 return make_str
("");
1019 /* compare string against pattern */
1020 /* remember that patterns are anchored to the beginning of the line */
1021 if
(regexec
(&rp
, a
->u.s
, (size_t)2, rm
, 0) == 0 ) {
1022 if
(rm
[1].rm_so
>= 0) {
1023 *(a
->u.s
+ rm
[1].rm_eo
) = '\0';
1024 v
= make_str
(a
->u.s
+ rm
[1].rm_so
);
1027 v
= make_integer
((quad_t
)(rm
[0].rm_eo
- rm
[0].rm_so
));
1030 if
(rp.re_nsub
== 0) {
1031 v
= make_integer
((quad_t
)0);
1037 /* free arguments and pattern buffer */