pike.git
/
src
/
operators.c
version
»
Context lines:
10
20
40
80
file
none
3
pike.git/src/operators.c:1:
/* || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information.
-
|| $Id: operators.c,v 1.
189
2004/
04
/
15
00
:
11
:
51
nilsson
Exp $
+
|| $Id: operators.c,v 1.
190
2004/
09
/
20
12
:
10
:
52
mast
Exp $
*/ #include "global.h" #include <math.h>
-
RCSID("$Id: operators.c,v 1.
189
2004/
04
/
15
00
:
11
:
51
nilsson
Exp $");
+
RCSID("$Id: operators.c,v 1.
190
2004/
09
/
20
12
:
10
:
52
mast
Exp $");
#include "interpret.h" #include "svalue.h" #include "multiset.h" #include "mapping.h" #include "array.h" #include "stralloc.h" #include "opcodes.h" #include "operators.h" #include "language.h" #include "pike_memory.h"
pike.git/src/operators.c:218:
/*! @endclass */ /* Special case for casting to int. */ void o_cast_to_int(void) { switch(sp[-1].type) { case T_OBJECT:
+
if(!sp[-1].u.object->prog) {
+
/* Casting a destructed object should be like casting a zero. */
+
pop_stack();
+
push_int (0);
+
}
+
+
else {
{
-
+
struct object *o = sp[-1].u.object;
struct pike_string *s;
-
+
int f = FIND_LFUN(o->prog,LFUN_CAST);
+
if(f == -1)
+
Pike_error("No cast method in object.\n");
REF_MAKE_CONST_STRING(s, "int"); push_string(s);
-
if(!sp[-2].u.object->prog)
-
Pike_error("Cast called on destructed object.\n");
-
if(FIND_LFUN(sp[-2].u.object->prog,LFUN_CAST) == -1)
-
Pike_error("No cast method in object.\n");
-
apply_
lfun
(
sp[-2].u.object
,
LFUN_CAST
, 1);
-
free_svalue(sp-2);
-
sp[-2]=sp[-1];
-
sp--;
-
dmalloc
_
touch
_
svalue
(
sp
);
+
apply_
low
(
o
,
f
, 1);
+
stack
_
pop
_
keep_top
();
}
-
+
if(sp[-1].type != PIKE_T_INT) { if(sp[-1].type == T_OBJECT && sp[-1].u.object->prog) { int f=FIND_LFUN(sp[-1].u.object->prog, LFUN__IS_TYPE); if( f != -1) { struct pike_string *s; REF_MAKE_CONST_STRING(s, "int"); push_string(s); apply_low(sp[-2].u.object, f, 1); f=!UNSAFE_IS_ZERO(sp-1); pop_stack(); if(f) return; } } Pike_error("Cast failed, wanted int, got %s\n", get_name_of_type(sp[-1].type)); }
-
+
}
+
break; case T_FLOAT: { int i=DO_NOT_WARN((int)(sp[-1].u.float_number)); #ifdef AUTO_BIGNUM if((i < 0 ? -i : i) < floor(fabs(sp[-1].u.float_number))) { /* Note: This includes the case when i = 0x80000000, i.e. the absolute value is not computable. */
pike.git/src/operators.c:329:
/* Special case for casting to string. */ void o_cast_to_string(void) { char buf[200]; switch(sp[-1].type) { case PIKE_T_STRING: return; case T_OBJECT:
+
if(!sp[-1].u.object->prog) {
+
/* Casting a destructed object should be like casting a zero. */
+
pop_stack();
+
push_int (0);
+
}
+
+
else {
{
-
+
struct object *o = sp[-1].u.object;
struct pike_string *s;
-
+
int f = FIND_LFUN(o->prog,LFUN_CAST);
+
if(f == -1)
+
Pike_error("No cast method in object.\n");
REF_MAKE_CONST_STRING(s, "string"); push_string(s);
-
if(!sp[-2].u.object->prog)
-
Pike_error("Cast called on destructed object.\n");
-
if(FIND_LFUN(sp[-2].u.object->prog,LFUN_CAST) == -1)
-
Pike_error("No cast method in object.\n");
-
apply_
lfun
(
sp[-2].u.object
,
LFUN_CAST
, 1);
-
free_svalue(sp-2);
-
sp[-2]=sp[-1];
-
sp--;
-
dmalloc
_
touch
_
svalue
(
sp
);
+
apply_
low
(
o
,
f
, 1);
+
stack
_
pop
_
keep_top
();
}
-
+
if(sp[-1].type != PIKE_T_STRING) { if(sp[-1].type == T_OBJECT && sp[-1].u.object->prog) { int f=FIND_LFUN(sp[-1].u.object->prog, LFUN__IS_TYPE); if( f != -1) { struct pike_string *s; REF_MAKE_CONST_STRING(s, "string"); push_string(s); apply_low(sp[-2].u.object, f, 1); f=!UNSAFE_IS_ZERO(sp-1); pop_stack(); if(f) return; } } Pike_error("Cast failed, wanted string, got %s\n", get_name_of_type(sp[-1].type)); } return;
-
+
}
-
+
/* Fall through. */
+
+
case T_INT:
+
sprintf(buf, "%"PRINTPIKEINT"d", sp[-1].u.integer);
+
break;
+
case T_ARRAY: { int i; struct array *a = sp[-1].u.array; struct pike_string *s; int shift = 0; for(i = a->size; i--; ) { unsigned INT32 val; if (a->item[i].type != T_INT) {
pike.git/src/operators.c:436:
free_string(end_shared_string(s)); Pike_fatal("cast: Bad shift: %d.\n", shift); break; } s = end_shared_string(s); pop_stack(); push_string(s); } return;
-
case T_INT:
-
sprintf(buf, "%"PRINTPIKEINT"d", sp[-1].u.integer);
-
break;
-
+
case T_FLOAT: sprintf(buf, "%f", (double)sp[-1].u.float_number); break; default: Pike_error("Cannot cast %s to string.\n", get_name_of_type(sp[-1].type)); } sp[-1].type = PIKE_T_STRING; sp[-1].u.string = make_shared_string(buf); } void o_cast(struct pike_type *type, INT32 run_time_type) { if(run_time_type != sp[-1].type) { if(run_time_type == T_MIXED) return;
-
+
if (sp[-1].type == T_OBJECT && !sp[-1].u.object->prog) {
+
/* Casting a destructed object should be like casting a zero. */
+
pop_stack();
+
push_int (0);
+
}
+
if(sp[-1].type == T_OBJECT) {
-
+
struct object *o = sp[-1].u.object;
struct pike_string *s;
-
+
int f = FIND_LFUN(o->prog,LFUN_CAST);
+
if(f == -1)
+
Pike_error("No cast method in object.\n");
s=describe_type(type); push_string(s);
-
if(!sp[-2].u.object->prog)
-
Pike_error("Cast called on destructed object.\n");
-
if(FIND_LFUN(sp[-2].u.object->prog,LFUN_CAST) == -1)
-
Pike_error("No cast method in object.\n");
-
apply_lfun(
sp[-2].u.object
,
LFUN_CAST
, 1);
-
free
_
svalue(sp-2);
-
sp[-2]=sp[-1];
-
sp--;
-
dmalloc
_
touch
_
svalue
(
sp
);
+
apply_lfun(
o
,
f
, 1);
+
stack
_
pop
_
keep
_
top
();
}else switch(run_time_type) { default: Pike_error("Cannot perform cast to that type.\n"); case T_MIXED: return;
pike.git/src/operators.c:976:
*! *! @note *! Programs are not automatically converted to types to be compared *! type-wise. *! *! @seealso *! @[`!()], @[`!=()] */ COMPARISON(f_eq,"`==", is_eq)
+
/* HERE */
+
/*! @decl int(0..1) `<(mixed arg1, mixed arg2, mixed ... extras) *! *! Less than test. *! *! Every expression with the @expr{<@} operator becomes a call to *! this function, i.e. @expr{a<b@} is the same as *! @expr{predef::`<(a,b)@}. *!
-
+
*! If more than two arguments are given, each argument is compared
+
*! with the following one as described below, and the test is
+
*! successful iff all comparisons are successful. Thus a single
+
*! call can be used to test if a whole list of values are in
+
*! strictly increasing order.
+
*!
+
*! If the first argument is an object with an @[lfun::`<()], that
+
*! function is called with the second as argument, and the test is
+
*! successful iff its result is nonzero (according to @[`!]).
+
*!
+
*! Otherwise, if the second argument is an object with an
+
*! @[lfun::`==()], that function is called with the first as
+
*! argument, and the test is successful iff its result is nonzero
+
*! (according to @[`!]).
+
*!
+
*! Otherwise, if the arguments are of different types, the test is
+
*! unsuccessful. Function pointers to programs are automatically
+
*! converted to program pointers if necessary, though.
+
*!
+
*! Otherwise the test depends on the type of the arguments:
+
*! @mixed
+
*! @type int
+
*! Successful iff the two integers are numerically equal.
+
*! @type float
+
*! Successful iff the two floats are numerically equal or if
+
*! both are NaN.
+
*! @type string
+
*! Successful iff the two strings are identical, character for
+
*! character. (Since all strings are kept unique, this is
+
*! actually a test whether the arguments point to the same
+
*! string, and it therefore run in constant time.)
+
*! @type array|mapping|multiset|object|function|program|type
+
*! Successful iff the two arguments point to the same instance.
+
*! @endmixed
+
*!
*! @returns *! Returns @expr{1@} if the test is successful, @expr{0@} *! otherwise. *! *! @seealso *! @[`<=()], @[`>()], @[`>=()] */ COMPARISON(f_lt,"`<" , is_lt) /*! @decl int(0..1) `<=(mixed arg1, mixed arg2, mixed ... extras)