2 * The Regina Rexx Interpreter
3 * Copyright (C) 1993-1994 Anders Christensen <anders@pvv.unit.no>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the Free
17 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #define TRACEVALUE(a,b) if (TSD->trace_stat=='I') tracevalue(TSD,a,b)
28 static void mark_in_expr( const tsd_t
*TSD
)
31 markmemory( TSD
->rdes
.num
, TRC_STATIC
) ;
33 markmemory( TSD
->ldes
.num
, TRC_STATIC
) ;
38 * COMP_IGNORE returns 1 if c shall be ignored on a non-strict comparison
39 * between non-numbers. Previously, this was equal to isspace(c). This was
40 * wrong according to ANSI, section 7.4.7. This fixes bug 594674.
42 #define ANSI_COMP_IGNORE(c) ( (c) == ' ' )
43 #define REGINA_COMP_IGNORE(c) ( rx_isspace(c) )
45 #define FREE_TMP_STRING(str) if ( str ) \
48 int init_expr( tsd_t
*TSD
)
51 regmarker( TSD
, mark_in_expr
) ;
53 TSD
= TSD
; /* keep compiler happy */
58 static num_descr
*copy_num( const tsd_t
*TSD
, const num_descr
*input
)
60 num_descr
*newptr
=NULL
;
62 newptr
= (num_descr
*)MallocTSD( sizeof( num_descr
)) ;
63 newptr
->negative
= input
->negative
;
64 newptr
->size
= input
->size
;
65 newptr
->max
= (input
->max
< 1) ? 1 : input
->max
;
66 newptr
->exp
= input
->exp
;
67 newptr
->num
= (char *)MallocTSD( newptr
->max
) ;
68 newptr
->used_digits
= input
->used_digits
;
69 memcpy( newptr
->num
, input
->num
, newptr
->size
) ;
70 TSD
= TSD
; /* keep compiler happy */
75 static streng
*num_to_str( const tsd_t
*TSD
, num_descr
*input
)
77 return str_norm( TSD
, input
, NULL
) ;
80 static int num_to_bool( const num_descr
*input
)
85 exiterror( ERR_UNLOGICAL_VALUE
, 0 ) ;
87 if (input
->size
!=1 || input
->negative
|| input
->exp
!=1)
88 exiterror( ERR_UNLOGICAL_VALUE
, 0 ) ;
91 if (ch
!='0' && ch
!='1')
92 exiterror( ERR_UNLOGICAL_VALUE
, 0 ) ;
97 static int str_to_bool( const streng
*input
)
102 exiterror( ERR_UNLOGICAL_VALUE
, 0 ) ;
104 ch
= input
->value
[0] ;
105 if (ch
!='0' && ch
!='1')
106 exiterror( ERR_UNLOGICAL_VALUE
, 0 ) ;
111 static streng
*bool_to_str( const tsd_t
*TSD
, int input
)
113 return Str_creTSD( input
? "1" : "0" ) ;
116 static num_descr
*bool_to_num( const tsd_t
*TSD
, int input
)
118 num_descr
*num
=NULL
;
120 num
= (num_descr
*)MallocTSD( sizeof( num_descr
)) ;
122 num
->num
= (char *)MallocTSD( 8 ) ;
126 num
->num
[0] = (char) ((input
) ? '1' : '0') ;
127 num
->used_digits
= TSD
->currlevel
->currnumsize
;
132 * calcul evaluates a numeric expression. thisptr is the current evaluation tree.
133 * kill? return value?
134 * Note: This is one of the most time-consuming routines. Be careful.
136 num_descr
*calcul( tsd_t
*TSD
, nodeptr thisptr
, num_descr
**kill
)
138 num_descr
*numthr
, *numone
, *numtwo
;
139 num_descr
*ntmp1
=NULL
, *ntmp2
=NULL
;
142 int strip2
= 0; /* fixes bug 1107763, second part */
144 switch ( thisptr
->type
)
149 numone
= calcul( TSD
, thisptr
->p
[0], &ntmp1
) ;
150 numtwo
= calcul( TSD
, thisptr
->p
[1], &ntmp2
) ;
152 ntmp2
= numtwo
= copy_num( TSD
, numtwo
) ;
154 numtwo
->negative
= !numtwo
->negative
;
158 numone
= calcul( TSD
, thisptr
->p
[0], &ntmp1
) ;
159 numtwo
= calcul( TSD
, thisptr
->p
[1], &ntmp2
) ;
172 numthr
= copy_num( TSD
, numtwo
) ;
174 string_add( TSD
, numone
, numtwo
, numthr
, thisptr
->p
[0], thisptr
->p
[1] ) ;
178 numone
= calcul( TSD
, thisptr
->p
[0], &ntmp1
) ;
179 numtwo
= calcul( TSD
, thisptr
->p
[1], &ntmp2
) ;
191 numthr
= copy_num( TSD
, numtwo
) ;
193 string_mul( TSD
, numone
, numtwo
, numthr
, thisptr
->p
[0], thisptr
->p
[1] );
199 numone
= calcul( TSD
, thisptr
->p
[0], &ntmp1
) ;
200 numtwo
= calcul( TSD
, thisptr
->p
[1], &ntmp2
) ;
201 if (numtwo
->size
==1 && numtwo
->num
[0]=='0')
202 exiterror( ERR_ARITH_OVERFLOW
, 3 ) ;
204 numthr
= copy_num( TSD
, numtwo
) ;
205 string_div( TSD
, numone
, numtwo
, numthr
, NULL
,
206 ((thisptr
->type
==X_DEVIDE
) ? DIVTYPE_NORMAL
:
207 ((thisptr
->type
==X_MODULUS
) ? DIVTYPE_REMAINDER
: DIVTYPE_INTEGER
)),
208 thisptr
->p
[0], thisptr
->p
[1] );
213 numone
= calcul( TSD
, thisptr
->p
[0], &ntmp1
) ;
214 numtwo
= ntmp2
= calcul( TSD
, thisptr
->p
[1], NULL
) ;
215 numthr
= copy_num( TSD
, numone
) ;
216 string_pow( TSD
, numone
, numtwo
, numthr
, thisptr
->p
[0], thisptr
->p
[1] ) ;
222 if ( !thisptr
->u
.number
)
223 thisptr
->u
.number
= get_a_descr( TSD
, NULL
, 0, thisptr
->name
) ;
225 if (TSD
->trace_stat
=='I')
226 tracenumber( TSD
, thisptr
->u
.number
, 'L' ) ;
231 return thisptr
->u
.number
;
234 return copy_num( TSD
, thisptr
->u
.number
) ;
241 nptr
= shortcutnum( TSD
, thisptr
) ;
243 exiterror( ERR_BAD_ARITHMETIC
, 0 ) ;
248 return copy_num( TSD
, nptr
) ;
254 nptr
= fix_compoundnum( TSD
, thisptr
, NULL
, NULL
);
256 exiterror( ERR_BAD_ARITHMETIC
, 0 ) ;
261 return copy_num( TSD
, nptr
) ;
265 numthr
= calcul( TSD
, thisptr
->p
[0], &ntmp1
) ;
267 numthr
= copy_num( TSD
, numthr
) ;
269 if (thisptr
->type
==X_U_MINUS
)
270 numthr
->negative
= !numthr
->negative
;
275 if (TSD
->trace_stat
=='I')
276 tracenumber( TSD
, numthr
, 'P' ) ;
288 numthr
= get_a_descr( TSD
, NULL
, 0, evaluate( TSD
, thisptr
, &sptr
) );
289 FREE_TMP_STRING( sptr
);
324 numthr
= bool_to_num( TSD
, isboolean( TSD
, thisptr
, 0, NULL
)) ;
330 exiterror( ERR_INTERPRETER_FAILURE
, 1, __FILE__
, __LINE__
, "" ) ;
336 FreeTSD( numone
->num
) ;
341 FreeTSD( numtwo
->num
) ;
347 if (TSD
->trace_stat
=='I')
348 tracenumber( TSD
, numthr
, 'O' ) ;
350 str_strip( numthr
) ;
351 str_round( numthr
, TSD
->currlevel
->currnumsize
) ;
355 * ANSI 7.4.10, PostOp, add. rounding for / and **
357 strip2
= numthr
->size
;
358 while ( ( strip2
> 1 ) &&
359 ( numthr
->exp
< strip2
) &&
360 ( numthr
->num
[strip2
- 1] == '0' ) )
362 if ( strip2
!= numthr
->size
)
364 numthr
->size
= strip2
;
365 if ( strip2
< numthr
->used_digits
)
366 numthr
->used_digits
= strip2
;
372 static void strip_whitespace( tsd_t
*TSD
, unsigned char **s1
,
373 unsigned char **e1
, unsigned char **s2
,
376 if ( get_options_flag( TSD
->currlevel
, EXT_STRICT_ANSI
)
377 || get_options_flag( TSD
->currlevel
, EXT_STRICT_WHITE_SPACE_COMPARISONS
) )
380 * ANSI 7.4.7 behaviour; non-strict comparisons
381 * removed ONLY spaces, so single TAB not equal to single SPACE
384 * Strip leading spaces - ignored in comparison
386 for( ; ( *s1
< *e1
) && ANSI_COMP_IGNORE( **s1
); (*s1
)++ )
389 for( ; ( *s2
< *e2
) && ANSI_COMP_IGNORE( **s2
); (*s2
)++ )
392 for ( ; ( *s1
< *e1
) && ( *s2
< *e2
) && ( **s1
== **s2
); (*s1
)++, (*s2
)++ )
396 * Strip trailing spaces - ignored in comparison
398 for ( ; ( *e1
> *s1
) && ANSI_COMP_IGNORE( *( *e1
- 1 ) ); (*e1
)-- )
401 for ( ; ( *e2
> *s2
) && ANSI_COMP_IGNORE( *( *e2
- 1 ) ); (*e2
)-- )
408 * Original Regina behaviour; non-strict comparisons
409 * removed ALL white space, so single TAB equalled single SPACE
412 * Strip leading white space - ignored in comparison
414 for( ; ( *s1
< *e1
) && REGINA_COMP_IGNORE( **s1
); (*s1
)++ )
417 for( ; ( *s2
< *e2
) && REGINA_COMP_IGNORE( **s2
); (*s2
)++ )
420 for ( ; ( *s1
< *e1
) && ( *s2
< *e2
) && ( **s1
== **s2
); (*s1
)++, (*s2
)++ )
424 * Strip trailing white space - ignored in comparison
426 for ( ; ( *e1
> *s1
) && REGINA_COMP_IGNORE( *( *e1
- 1 ) ); (*e1
)-- )
429 for ( ; ( *e2
> *s2
) && REGINA_COMP_IGNORE( *( *e2
- 1 ) ); (*e2
)-- )
437 * evaluate evaluates an expression. The nodeptr "thisptr" must point to an
438 * expression part. The return value is the value of the expression.
439 * For a proper cleanup the caller probably has to delete a the returned
440 * value. For this purpose, the caller may set "kill" to non-NULL.
441 * *kill is set to NULL, if the returned value is a const value and must
442 * not be freed. *kill is set to a temporary value which has to be deleted
443 * after the use of the returned value.
444 * The caller may omit kill, this forces evaluate to create a freshly allocated
447 streng
*evaluate( tsd_t
*TSD
, nodeptr thisptr
, streng
**kill
)
449 #define RETURN_NEW(val) if ( kill ) \
452 streng
*strone
,*strtwo
,*strthr
;
453 streng
*stmp1
,*stmp2
;
459 switch ( thisptr
->type
)
473 stmp1
= num_to_str( TSD
, calcul( TSD
, thisptr
, &ntmp
) );
476 FreeTSD( ntmp
->num
);
486 cstmp
= thisptr
->name
;
487 if ( TSD
->trace_stat
== 'I' )
488 tracevalue( TSD
, cstmp
, 'L' );
490 return (streng
*) cstmp
; /* and *kill is set to NULL above */
491 stmp1
= Str_dupTSD( cstmp
);
495 /* always duplicate, since stmp1 might point to tmp area */
496 stmp1
= Str_dupTSD( fix_compound( TSD
, thisptr
, NULL
) );
501 cstmp
= shortcut(TSD
,thisptr
) ;
503 return (streng
*) cstmp
; /* and *kill is set to NULL above */
504 stmp1
= Str_dupTSD( cstmp
);
511 if ( ( entry
= getlabel( TSD
, thisptr
->name
) ) != NULL
)
513 if ( entry
->u
.trace_only
)
514 exiterror( ERR_UNEXISTENT_LABEL
, 3, tmpstr_of( TSD
, thisptr
->name
) );
515 thisptr
->type
= X_IS_INTERNAL
;
516 thisptr
->u
.node
= entry
;
519 thisptr
->u
.node
= NULL
;
529 * Check if the internal function name ends with a '.'.
530 * This is an error in the ANSI standard, but it is possible
531 * that existing code allows this, so only generate an error
532 * if STRICT_ANSI OPTION is set.
534 if ( get_options_flag( TSD
->currlevel
, EXT_STRICT_ANSI
) )
536 if ( thisptr
->name
->value
[(thisptr
->name
->len
)-1] == '.' )
537 exiterror( ERR_UNQUOTED_FUNC_STOP
, 1, tmpstr_of( TSD
, thisptr
->name
) ) ;
539 if ( ( entry
= thisptr
->u
.node
) != NULL
)
541 set_reserved_value( TSD
, POOL0_SIGL
, NULL
,
542 TSD
->currentnode
->lineno
, VFLAG_NUM
);
543 args
= initplist( TSD
, thisptr
);
545 ptr
= CallInternalFunction( TSD
, entry
->next
, TSD
->currentnode
,
548 if (ptr
==NULL
) /* fixes bug 592393 */
549 exiterror( ERR_NO_DATA_RETURNED
, 1, tmpstr_of( TSD
, thisptr
->name
) );
551 if (TSD
->trace_stat
=='I')
552 tracevalue( TSD
, ptr
, 'F' );
557 /* THIS IS MEANT TO FALL THROUGH! */
563 if ((ptr
=buildtinfunc( TSD
, thisptr
)) != NOFUNC
)
565 if (thisptr
->type
!= X_IS_BUILTIN
)
566 thisptr
->type
= X_IS_BUILTIN
;
569 exiterror( ERR_NO_DATA_RETURNED
, 1, tmpstr_of( TSD
, thisptr
->name
) ) ;
571 if (TSD
->trace_stat
=='I')
572 tracevalue( TSD
, ptr
, 'F' ) ;
577 thisptr
->type
= X_IS_EXTERNAL
;
579 /* THIS IS MEANT TO FALL THROUGH! */
582 streng
*ptr
, *command
;
583 int stackmark
,len
,err
;
584 paramboxptr args
, targs
;
586 if ( TSD
->restricted
)
587 exiterror( ERR_RESTRICTED
, 5 );
589 update_envirs( TSD
, TSD
->currlevel
);
591 args
= initplist( TSD
, thisptr
);
592 stackmark
= pushcallstack( TSD
, TSD
->currentnode
);
593 ptr
= execute_external( TSD
, thisptr
->name
,
595 TSD
->systeminfo
->environment
,
597 TSD
->systeminfo
->hooks
,
599 popcallstack( TSD
, stackmark
);
601 if ( err
== -ERR_PROG_UNREADABLE
)
604 * "thisptr->name" wasn't a Rexx program, so
605 * see if it is an OS command.
606 * Only do thisptr if the OPTIONS EXT_COMMANDS_AS_FUNCS is
607 * set and STRICT_ANSI is NOT set.
609 if ( get_options_flag( TSD
->currlevel
, EXT_EXT_COMMANDS_AS_FUNCS
)
610 && !get_options_flag( TSD
->currlevel
, EXT_STRICT_ANSI
) )
612 len
= Str_len( thisptr
->name
);
613 for( targs
= args
; targs
; targs
= targs
->next
)
616 len
+= 1 + Str_len( targs
->value
);
618 command
= Str_makeTSD( len
);
619 command
= Str_catTSD( command
, thisptr
->name
);
620 for( targs
= args
; targs
; targs
= targs
->next
)
624 command
= Str_catstrTSD( command
, " " );
625 command
= Str_catTSD( command
, targs
->value
);
628 ptr
= run_popen( TSD
, command
, TSD
->currlevel
->environment
);
631 Free_stringTSD( command
);
635 deallocplink( TSD
, args
);
637 if ( ptr
&& ( TSD
->trace_stat
== 'I' ) )
638 tracevalue( TSD
, ptr
, 'F' );
640 if ( err
== -ERR_PROG_UNREADABLE
)
642 exiterror( ERR_ROUTINE_NOT_FOUND
, 1, tmpstr_of( TSD
, thisptr
->name
) );
646 post_process_system_call( TSD
, thisptr
->name
, -err
, NULL
, thisptr
);
650 exiterror( ERR_NO_DATA_RETURNED
, 1, tmpstr_of( TSD
, thisptr
->name
) );
660 strone
= evaluate( TSD
, thisptr
->p
[0], &stmp1
) ;
661 strtwo
= evaluate( TSD
, thisptr
->p
[1], &stmp2
) ;
662 strthr
= Str_makeTSD(Str_len(strone
)+Str_len(strtwo
)+1) ;
663 cptr
= strthr
->value
;
664 memcpy( cptr
, strone
->value
, strone
->len
) ;
665 cptr
+= strone
->len
;
666 if (thisptr
->type
==X_SPACE
)
669 memcpy( cptr
, strtwo
->value
, strtwo
->len
) ;
670 strthr
->len
= (cptr
-strthr
->value
) + strtwo
->len
;
672 FREE_TMP_STRING( stmp1
);
673 FREE_TMP_STRING( stmp2
);
675 if (TSD
->trace_stat
=='I')
676 tracevalue( TSD
, strthr
, 'O' ) ;
679 RETURN_NEW( strthr
);
713 stmp1
= bool_to_str( TSD
, isboolean( TSD
, thisptr
, 0, NULL
)) ;
717 exiterror( ERR_INTERPRETER_FAILURE
, 1, __FILE__
, __LINE__
, "" ) ;
725 * isboolean evaluates a boolean expression and returns 0 for false, another
726 * value for true. "thisptr" is the current evaluation tree.
727 * Note: This is one of the most time-consuming routines. Be careful.
729 int isboolean( tsd_t
*TSD
, nodeptr thisptr
, int suberror
, const char *op
)
731 streng
*strone
,*strtwo
;
732 streng
*stmp1
,*stmp2
;
736 switch ( thisptr
->type
)
750 tmp
= num_to_bool( calcul( TSD
, thisptr
, &ntmp
)) ;
753 FreeTSD( ntmp
->num
) ;
760 if ( !thisptr
->u
.number
)
761 thisptr
->u
.number
= get_a_descr( TSD
, NULL
, 0, thisptr
->name
) ;
762 if ( Str_len( thisptr
->name
) != 1 )
764 /* fixes bug 1111931, "01" is not a logical value in ANSI */
765 if ( get_options_flag( TSD
->currlevel
, EXT_STRICT_ANSI
) )
769 exiterror( ERR_UNLOGICAL_VALUE
, suberror
, op
, tmpstr_of( TSD
, thisptr
->name
) );
773 exiterror( ERR_UNLOGICAL_VALUE
, suberror
, tmpstr_of( TSD
, thisptr
->name
) );
777 return num_to_bool( thisptr
->u
.number
) ;
781 if ( get_options_flag( TSD
->currlevel
, EXT_STRICT_ANSI
) )
783 /* fixes bug 1111931 */
784 stmp1
= (streng
*) shortcut( TSD
, thisptr
);
785 tmp
= Str_val( stmp1
)[0] - '0';
786 if ( ( Str_len( stmp1
) != 1 ) || ( ( tmp
!= 0 ) && ( tmp
!= 1 ) ) )
790 exiterror( ERR_UNLOGICAL_VALUE
, suberror
, op
, tmpstr_of( TSD
, stmp1
) );
794 exiterror( ERR_UNLOGICAL_VALUE
, suberror
, tmpstr_of( TSD
, stmp1
) );
799 return num_to_bool( shortcutnum( TSD
, thisptr
)) ;
802 if ( get_options_flag( TSD
->currlevel
, EXT_STRICT_ANSI
) )
804 /* fixes bug 1111931 */
807 stmp1
= (streng
*) fix_compound( TSD
, thisptr
, NULL
);
808 tmp
= Str_val( stmp1
)[0] - '0';
809 if ( ( Str_len( stmp1
) != 1 ) || ( ( tmp
!= 0 ) && ( tmp
!= 1 ) ) )
811 s
= tmpstr_of( TSD
, stmp1
);
812 Free_stringTSD( stmp1
);
815 exiterror( ERR_UNLOGICAL_VALUE
, suberror
, op
, s
);
819 exiterror( ERR_UNLOGICAL_VALUE
, suberror
, s
);
822 Free_stringTSD( stmp1
);
825 return num_to_bool( fix_compoundnum( TSD
, thisptr
, NULL
, NULL
) );
834 tmp
= str_to_bool( evaluate( TSD
, thisptr
, &stmp1
) );
835 FREE_TMP_STRING( stmp1
);
839 sint
= !isboolean( TSD
, thisptr
->p
[0], 6, "\\" ) ;
840 if (TSD
->trace_stat
=='I')
841 tracebool( TSD
, sint
, 'U' ) ;
845 sint
= ( isboolean(TSD
, thisptr
->p
[0], 5, "|") | isboolean( TSD
, thisptr
->p
[1], 6, "|" )) ;
846 if (TSD
->trace_stat
=='I')
847 tracebool( TSD
, sint
, 'U' ) ;
851 sint
= ( isboolean(TSD
, thisptr
->p
[0], 5, "&" ) & isboolean( TSD
, thisptr
->p
[1], 6, "&" )) ;
852 if (TSD
->trace_stat
=='I')
853 tracebool( TSD
, sint
, 'U' ) ;
857 /* Well, sort of ... */
858 sint
= ( isboolean( TSD
, thisptr
->p
[0], 5, "&&" ) ^ isboolean( TSD
, thisptr
->p
[1], 6, "&&" )) ;
859 if (TSD
->trace_stat
=='I')
860 tracebool( TSD
, sint
, 'U' ) ;
872 num_descr
*rnum
, *lnum
;
873 streng
*lval
, *rval
;
875 flags
= thisptr
->u
.flags
;
878 stmp1
= stmp2
= NULL
;
882 if ( !thisptr
->p
[0]->u
.number
)
883 thisptr
->p
[0]->u
.number
= get_a_descr( TSD
, NULL
, 0, thisptr
->p
[0]->name
);
885 lnum
= thisptr
->p
[0]->u
.number
;
886 if (TSD
->trace_stat
=='I')
887 tracenumber( TSD
, lnum
, 'L' ) ;
889 else if (flags
.lsvar
)
890 lnum
= shortcutnum( TSD
, thisptr
->p
[0] ) ;
891 else if (flags
.lcvar
)
892 lnum
= fix_compoundnum( TSD
, thisptr
->p
[0], NULL
, NULL
);
895 lval
= evaluate( TSD
, thisptr
->p
[0], &stmp1
) ;
899 if ( !thisptr
->p
[1]->u
.number
)
900 thisptr
->p
[1]->u
.number
= get_a_descr( TSD
, NULL
, 0, thisptr
->p
[1]->name
);
902 rnum
= thisptr
->p
[1]->u
.number
;
903 if (TSD
->trace_stat
=='I')
904 tracenumber( TSD
, rnum
, 'L' ) ;
906 else if (flags
.rsvar
)
907 rnum
= shortcutnum( TSD
, thisptr
->p
[1] ) ;
908 else if (flags
.rcvar
)
909 rnum
= fix_compoundnum( TSD
, thisptr
->p
[1], NULL
, NULL
);
912 rval
= evaluate( TSD
, thisptr
->p
[1], &stmp2
) ;
914 if (!lnum
&& !getdescr( TSD
, lval
, &TSD
->ldes
))
917 if (!rnum
&& !getdescr( TSD
, rval
, &TSD
->rdes
))
921 tmp
= string_test( TSD
, lnum
, rnum
) ;
924 unsigned char *s1
,*s2
,*e1
,*e2
;
929 stmp1
= lval
= str_norm( TSD
, lnum
, NULL
);
935 stmp2
= rval
= str_norm( TSD
, rnum
, NULL
);
938 s1
= (unsigned char *) lval
->value
;
939 s2
= (unsigned char *) rval
->value
;
940 e1
= (unsigned char *) s1
+ lval
->len
;
941 e2
= (unsigned char *) s2
+ rval
->len
;
943 strip_whitespace( TSD
, &s1
, &e1
, &s2
, &e2
);
945 if ( s1
== e1
&& s2
== e2
)
947 else if ( s1
< e1
&& s2
< e2
)
948 tmp
= ( *s1
< *s2
) ? -1 : 1;
950 tmp
= ( s1
< e1
) ? 1 : -1;
953 FREE_TMP_STRING( stmp1
);
954 FREE_TMP_STRING( stmp2
);
956 type
= thisptr
->type
;
958 sint
= (type
==X_GTE
|| type
==X_LTE
|| type
==X_EQUAL
) ;
960 sint
= (type
==X_GT
|| type
==X_GTE
|| type
==X_DIFF
) ;
962 sint
= (type
==X_LT
|| type
==X_LTE
|| type
==X_DIFF
) ;
964 if (TSD
->trace_stat
=='I')
965 tracebool( TSD
, sint
, 'O' ) ;
976 { /* string comparison */
977 unsigned char *s1
, *s2
, *e1
, *e2
;
980 type
= thisptr
->type
;
981 strone
= evaluate( TSD
, thisptr
->p
[0], &stmp1
) ;
982 strtwo
= evaluate( TSD
, thisptr
->p
[1], &stmp2
) ;
984 s1
= (unsigned char *) strone
->value
;
985 s2
= (unsigned char *) strtwo
->value
;
986 e1
= (unsigned char *) s1
+ strone
->len
;
987 e2
= (unsigned char *) s2
+ strtwo
->len
;
989 strip_whitespace( TSD
, &s1
, &e1
, &s2
, &e2
);
991 if (s1
==e1
&& s2
==e2
)
993 else if (s1
<e1
&& s2
<e2
)
994 tmp
= (*s1
<*s2
) ? -1 : 1 ;
996 tmp
= (s1
<e1
) ? 1 : -1 ;
998 FREE_TMP_STRING( stmp1
);
999 FREE_TMP_STRING( stmp2
);
1002 sint
= (type
==X_SGTE
|| type
==X_SLTE
|| type
==X_SEQUAL
) ;
1004 sint
= (type
==X_SGT
|| type
==X_SGTE
|| type
==X_SDIFF
) ;
1006 sint
= (type
==X_SLT
|| type
==X_SLTE
|| type
==X_SDIFF
) ;
1008 if (TSD
->trace_stat
=='I')
1009 tracebool( TSD
, sint
, 'O' ) ;
1021 /* numeric NOT comparison */
1023 num_descr
*ntmp1
, *ntmp2
;
1024 num_descr
*numone
, *numtwo
;
1026 type
= thisptr
->type
;
1028 ntmp1
= ntmp2
= NULL
;
1029 numone
= calcul( TSD
, thisptr
->p
[0], &ntmp1
) ;
1030 numtwo
= calcul( TSD
, thisptr
->p
[1], &ntmp2
) ;
1031 tmp
= string_test( TSD
, numone
, numtwo
) ;
1035 FreeTSD( ntmp1
->num
) ;
1040 FreeTSD( ntmp2
->num
) ;
1045 sint
= (type
==X_NGTE
|| type
==X_NLTE
|| type
==X_NEQUAL
) ;
1047 sint
= (type
==X_NGT
|| type
==X_NGTE
|| type
==X_NDIFF
) ;
1049 sint
= (type
==X_NLT
|| type
==X_NLTE
|| type
==X_NDIFF
) ;
1051 if (TSD
->trace_stat
=='I')
1052 tracebool( TSD
, sint
, 'O' ) ;
1058 strone
= evaluate( TSD
, thisptr
->p
[0], &stmp1
) ;
1059 strtwo
= evaluate( TSD
, thisptr
->p
[1], &stmp2
) ;
1060 tmp
= Str_cmp(strone
,strtwo
)!=0 ;
1062 FREE_TMP_STRING( stmp1
);
1063 FREE_TMP_STRING( stmp2
);
1065 if (TSD
->trace_stat
=='I')
1066 tracebool( TSD
, tmp
, 'O' ) ;
1072 strone
= evaluate( TSD
, thisptr
->p
[0], &stmp1
) ;
1073 strtwo
= evaluate( TSD
, thisptr
->p
[1], &stmp2
) ;
1074 tmp
= Str_cmp(strone
,strtwo
)==0 ;
1076 FREE_TMP_STRING( stmp1
);
1077 FREE_TMP_STRING( stmp2
);
1079 if (TSD
->trace_stat
=='I')
1080 tracebool( TSD
, tmp
, 'O' ) ;
1086 { /* strict string NOT comparison */
1087 unsigned char *s1
, *s2
, *e1
, *e2
;
1090 type
= thisptr
->type
;
1091 strone
= evaluate( TSD
, thisptr
->p
[0], &stmp1
) ;
1092 strtwo
= evaluate( TSD
, thisptr
->p
[1], &stmp2
) ;
1094 s1
= (unsigned char *) strone
->value
;
1095 s2
= (unsigned char *) strtwo
->value
;
1096 e1
= (unsigned char *) s1
+ strone
->len
;
1097 e2
= (unsigned char *) s2
+ strtwo
->len
;
1099 * same compare as non-strict except that leading and trailing spaces
1100 * are retained for comparison.
1102 for (;(s1
<e1
)&&(s2
<e2
)&&(*s1
==*s2
);s1
++,s2
++) ;
1103 if (s1
==e1
&& s2
==e2
)
1105 else if (s1
<e1
&& s2
<e2
)
1106 tmp
= (*s1
<*s2
) ? 1 : -1 ;
1108 tmp
= (s1
<e1
) ? -1 : 1 ;
1110 FREE_TMP_STRING( stmp1
);
1111 FREE_TMP_STRING( stmp2
);
1116 sint
= (type
==X_S_NGT
) ;
1118 sint
= (type
==X_S_NLT
) ;
1120 if (TSD
->trace_stat
=='I')
1121 tracebool( TSD
, sint
, 'O' ) ;
1130 { /* strict string comparison */
1131 unsigned char *s1
, *s2
, *e1
, *e2
;
1134 type
= thisptr
->type
;
1135 strone
= evaluate( TSD
, thisptr
->p
[0], &stmp1
) ;
1136 strtwo
= evaluate( TSD
, thisptr
->p
[1], &stmp2
) ;
1138 s1
= (unsigned char *) strone
->value
;
1139 s2
= (unsigned char *) strtwo
->value
;
1140 e1
= (unsigned char *) s1
+ strone
->len
;
1141 e2
= (unsigned char *) s2
+ strtwo
->len
;
1143 * same compare as non-strict except that leading and trailing spaces
1144 * are retained for comparison.
1146 for (;(s1
<e1
)&&(s2
<e2
)&&(*s1
==*s2
);s1
++,s2
++) ;
1147 if (s1
==e1
&& s2
==e2
)
1149 else if (s1
<e1
&& s2
<e2
)
1150 tmp
= (*s1
<*s2
) ? -1 : 1 ;
1152 tmp
= (s1
<e1
) ? 1 : -1 ;
1154 FREE_TMP_STRING( stmp1
);
1155 FREE_TMP_STRING( stmp2
);
1158 sint
= (type
==X_S_GTE
|| type
==X_S_LTE
) ;
1160 sint
= (type
==X_S_GT
|| type
==X_S_GTE
) ;
1162 sint
= (type
==X_S_LT
|| type
==X_S_LTE
) ;
1164 if (TSD
->trace_stat
=='I')
1165 tracebool( TSD
, sint
, 'O' ) ;
1172 exiterror( ERR_INTERPRETER_FAILURE
, 1, __FILE__
, __LINE__
, "" ) ;