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.
184
2003/11/
13
22
:27:
59
mast Exp $
+
|| $Id: operators.c,v 1.
185
2003/11/
14
09
:27:
29
mast Exp $
*/ #include "global.h" #include <math.h>
-
RCSID("$Id: operators.c,v 1.
184
2003/11/
13
22
:27:
59
mast Exp $");
+
RCSID("$Id: operators.c,v 1.
185
2003/11/
14
09
:27:
29
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:23:
#include "constants.h" #include "peep.h" #include "lex.h" #include "program.h" #include "object.h" #include "pike_types.h" #include "module_support.h" #include "pike_macros.h" #include "bignum.h" #include "builtin_functions.h"
+
#include "cyclic.h"
#define sp Pike_sp #define OP_DIVISION_BY_ZERO_ERROR(FUNC) \ math_error(FUNC, sp-2, 2, 0, "Division by zero.\n") #define OP_MODULO_BY_ZERO_ERROR(FUNC) \ math_error(FUNC, sp-2, 2, 0, "Modulo by zero.\n")
-
+
void index_no_free(struct svalue *to,struct svalue *what,struct svalue *ind)
+
{
+
#ifdef PIKE_SECURITY
+
if(what->type <= MAX_COMPLEX)
+
if(!CHECK_DATA_SECURITY(what->u.array, SECURITY_BIT_INDEX))
+
Pike_error("Index permission denied.\n");
+
#endif
+
+
switch(what->type)
+
{
+
case T_ARRAY:
+
simple_array_index_no_free(to,what->u.array,ind);
+
break;
+
+
case T_MAPPING:
+
mapping_index_no_free(to,what->u.mapping,ind);
+
break;
+
+
case T_OBJECT:
+
object_index_no_free(to, what->u.object, ind);
+
break;
+
+
case T_MULTISET: {
+
int i=multiset_member(what->u.multiset, ind);
+
to->type=T_INT;
+
to->subtype=i ? 0 : NUMBER_UNDEFINED;
+
to->u.integer=i;
+
break;
+
}
+
+
case T_STRING:
+
if(ind->type==T_INT)
+
{
+
ptrdiff_t len = what->u.string->len;
+
INT_TYPE p = ind->u.integer;
+
INT_TYPE i = p < 0 ? p + len : p;
+
if(i<0 || i>=len)
+
{
+
if(len == 0)
+
Pike_error("Attempt to index the empty string with %"PRINTPIKEINT"d.\n", i);
+
else
+
Pike_error("Index %"PRINTPIKEINT"d is out of string range "
+
"%"PRINTPTRDIFFT"d..%"PRINTPTRDIFFT"d.\n",
+
i, -len, len - 1);
+
} else
+
i=index_shared_string(what->u.string,i);
+
to->type=T_INT;
+
to->subtype=NUMBER_NUMBER;
+
to->u.integer=i;
+
break;
+
}else{
+
if (ind->type == T_STRING && !ind->u.string->size_shift)
+
Pike_error ("Expected integer as string index, got \"%s\".\n",
+
ind->u.string->str);
+
else
+
Pike_error ("Expected integer as string index, got %s.\n",
+
get_name_of_type (ind->type));
+
}
+
+
case T_PROGRAM:
+
program_index_no_free(to, what->u.program, ind);
+
break;
+
+
case T_FUNCTION:
+
{
+
struct program *p = program_from_svalue(what);
+
if (p) {
+
program_index_no_free(to, p, ind);
+
break;
+
}
+
}
+
/* FALL THROUGH */
+
+
#ifdef AUTO_BIGNUM
+
case T_INT:
+
if (ind->type == T_STRING) {
+
INT_TYPE val = what->u.integer;
+
+
convert_svalue_to_bignum(what);
+
index_no_free(to, what, ind);
+
if(IS_UNDEFINED(to)) {
+
if (val) {
+
if (!ind->u.string->size_shift)
+
Pike_error("Indexing the integer %"PRINTPIKEINT"d "
+
"with unknown method \"%s\".\n",
+
val, ind->u.string->str);
+
else
+
Pike_error("Indexing the integer %"PRINTPIKEINT"d "
+
"with a wide string.\n",
+
val);
+
} else {
+
if(!ind->u.string->size_shift)
+
Pike_error("Indexing the NULL value with \"%s\".\n",
+
ind->u.string->str);
+
else
+
Pike_error("Indexing the NULL value with a wide string.\n");
+
}
+
}
+
break;
+
}
+
+
/* FALL_THROUGH */
+
#endif /* AUTO_BIGNUM */
+
+
default:
+
if (ind->type == T_INT)
+
Pike_error ("Cannot index %s with %"PRINTPIKEINT"d.\n",
+
(what->type == T_INT && !what->u.integer)?
+
"the NULL value":get_name_of_type(what->type),
+
ind->u.integer);
+
else if (ind->type == T_FLOAT)
+
Pike_error ("Cannot index %s with %"PRINTPIKEFLOAT"g.\n",
+
(what->type == T_INT && !what->u.integer)?
+
"the NULL value":get_name_of_type(what->type),
+
ind->u.float_number);
+
else if (ind->type == T_STRING && !ind->u.string->size_shift)
+
Pike_error ("Cannot index %s with \"%s\".\n",
+
(what->type == T_INT && !what->u.integer)?
+
"the NULL value":get_name_of_type(what->type),
+
ind->u.string->str);
+
else
+
Pike_error ("Cannot index %s with %s.\n",
+
(what->type == T_INT && !what->u.integer)?
+
"the NULL value":get_name_of_type(what->type),
+
get_name_of_type (ind->type));
+
}
+
}
+
+
void o_index(void)
+
{
+
struct svalue s;
+
index_no_free(&s,sp-2,sp-1);
+
pop_n_elems(2);
+
*sp=s;
+
dmalloc_touch_svalue(sp);
+
sp++;
+
dmalloc_touch_svalue(Pike_sp-1);
+
}
+
+
/*! @class MasterObject
+
*/
+
+
/*! @decl object cast_to_object(string str, string|void current_file)
+
*!
+
*! Called by the Pike runtime to cast strings to objects.
+
*!
+
*! @param str
+
*! String to cast to object.
+
*!
+
*! @param current_file
+
*! Filename of the file that attempts to perform the cast.
+
*!
+
*! @returns
+
*! Returns the resulting object.
+
*!
+
*! @seealso
+
*! @[cast_to_program()]
+
*/
+
+
/*! @decl program cast_to_program(string str, string|void current_file)
+
*!
+
*! Called by the Pike runtime to cast strings to programs.
+
*!
+
*! @param str
+
*! String to cast to object.
+
*!
+
*! @param current_file
+
*! Filename of the file that attempts to perform the cast.
+
*!
+
*! @returns
+
*! Returns the resulting program.
+
*!
+
*! @seealso
+
*! @[cast_to_object()]
+
*/
+
+
/*! @endclass
+
*/
+
+
/* Special case for casting to int. */
+
void o_cast_to_int(void)
+
{
+
switch(sp[-1].type)
+
{
+
case T_OBJECT:
+
{
+
struct pike_string *s;
+
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);
+
}
+
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. */
+
convert_stack_top_to_bignum();
+
return; /* FIXME: OK to return? Cast tests below indicates
+
we have to do this, at least for now... /Noring */
+
/* Yes, it is ok to return, it is actually an optimization :)
+
* /Hubbe
+
*/
+
}
+
else
+
#endif /* AUTO_BIGNUM */
+
{
+
sp[-1].type=T_INT;
+
sp[-1].u.integer=i;
+
}
+
}
+
break;
+
+
case T_STRING:
+
/* This can be here independently of AUTO_BIGNUM. Besides,
+
we really want to reduce the number of number parsers
+
around here. :) /Noring */
+
#ifdef AUTO_BIGNUM
+
+
/* The generic function is rather slow, so I added this
+
* code for benchmark purposes. :-) /per
+
*/
+
if( sp[-1].u.string->len < 10 &&
+
!sp[-1].u.string->size_shift )
+
{
+
int i=atoi(sp[-1].u.string->str);
+
free_string(sp[-1].u.string);
+
sp[-1].type=T_INT;
+
sp[-1].u.integer=i;
+
}
+
else
+
convert_stack_top_string_to_inumber(10);
+
return; /* FIXME: OK to return? Cast tests below indicates
+
we have to do this, at least for now... /Noring */
+
/* Yes, it is ok to return, it is actually an optimization :)
+
* /Hubbe
+
*/
+
#else
+
{
+
int i=STRTOL(sp[-1].u.string->str,0,10);
+
free_string(sp[-1].u.string);
+
sp[-1].type=T_INT;
+
sp[-1].u.integer=i;
+
}
+
#endif /* AUTO_BIGNUM */
+
break;
+
+
case PIKE_T_INT:
+
break;
+
+
default:
+
Pike_error("Cannot cast %s to int.\n", get_name_of_type(sp[-1].type));
+
}
+
}
+
+
/* 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:
+
{
+
struct pike_string *s;
+
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);
+
}
+
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;
+
+
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_error("cast: Item %d is not an integer.\n", i);
+
}
+
val = (unsigned INT32)a->item[i].u.integer;
+
if (val > 0xff) {
+
shift = 1;
+
if (val > 0xffff) {
+
shift = 2;
+
while(i--)
+
if (a->item[i].type != T_INT)
+
Pike_error("cast: Item %d is not an integer.\n", i);
+
break;
+
}
+
while(i--) {
+
if (a->item[i].type != T_INT) {
+
Pike_error("cast: Item %d is not an integer.\n", i);
+
}
+
val = (unsigned INT32)a->item[i].u.integer;
+
if (val > 0xffff) {
+
shift = 2;
+
while(i--)
+
if (a->item[i].type != T_INT)
+
Pike_error("cast: Item %d is not an integer.\n", i);
+
break;
+
}
+
}
+
break;
+
}
+
}
+
s = begin_wide_shared_string(a->size, shift);
+
switch(shift) {
+
case 0:
+
for(i = a->size; i--; ) {
+
s->str[i] = a->item[i].u.integer;
+
}
+
break;
+
case 1:
+
{
+
p_wchar1 *str1 = STR1(s);
+
for(i = a->size; i--; ) {
+
str1[i] = a->item[i].u.integer;
+
}
+
}
+
break;
+
case 2:
+
{
+
p_wchar2 *str2 = STR2(s);
+
for(i = a->size; i--; ) {
+
str2[i] = a->item[i].u.integer;
+
}
+
}
+
break;
+
default:
+
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)
+
{
+
struct pike_string *s;
+
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);
+
}else
+
+
switch(run_time_type)
+
{
+
default:
+
Pike_error("Cannot perform cast to that type.\n");
+
+
case T_MIXED:
+
return;
+
+
case T_MULTISET:
+
switch(sp[-1].type)
+
{
+
case T_ARRAY:
+
{
+
extern void f_mkmultiset(INT32);
+
f_mkmultiset(1);
+
break;
+
}
+
+
default:
+
Pike_error("Cannot cast %s to multiset.\n",get_name_of_type(sp[-1].type));
+
}
+
break;
+
+
case T_MAPPING:
+
switch(sp[-1].type)
+
{
+
case T_ARRAY:
+
{
+
struct array *a=sp[-1].u.array;
+
struct array *b;
+
struct mapping *m;
+
INT32 i;
+
m=allocate_mapping(a->size); /* MAP_SLOTS(a->size) */
+
push_mapping(m);
+
for (i=0; i<a->size; i++)
+
{
+
if (ITEM(a)[i].type!=T_ARRAY)
+
Pike_error("Cast array to mapping: "
+
"element %d is not an array\n", i);
+
b=ITEM(a)[i].u.array;
+
if (b->size!=2)
+
Pike_error("Cast array to mapping: "
+
"element %d is not an array of size 2\n", i);
+
mapping_insert(m,ITEM(b)+0,ITEM(b)+1);
+
}
+
stack_swap();
+
pop_n_elems(1);
+
break;
+
}
+
+
default:
+
Pike_error("Cannot cast %s to mapping.\n",get_name_of_type(sp[-1].type));
+
}
+
break;
+
+
case T_ARRAY:
+
switch(sp[-1].type)
+
{
+
case T_MAPPING:
+
{
+
struct array *a=mapping_to_array(sp[-1].u.mapping);
+
pop_stack();
+
push_array(a);
+
break;
+
}
+
+
case T_STRING:
+
f_values(1);
+
break;
+
+
case T_MULTISET:
+
f_indices(1);
+
break;
+
+
default:
+
Pike_error("Cannot cast %s to array.\n",get_name_of_type(sp[-1].type));
+
+
}
+
break;
+
+
case T_INT:
+
o_cast_to_int();
+
return;
+
+
case T_STRING:
+
o_cast_to_string();
+
return;
+
+
case T_FLOAT:
+
{
+
FLOAT_TYPE f = 0.0;
+
+
switch(sp[-1].type)
+
{
+
case T_INT:
+
f=(FLOAT_TYPE)(sp[-1].u.integer);
+
break;
+
+
case T_STRING:
+
f =
+
(FLOAT_TYPE)STRTOD_PCHARP(MKPCHARP(sp[-1].u.string->str,
+
sp[-1].u.string->size_shift),
+
0);
+
free_string(sp[-1].u.string);
+
break;
+
+
default:
+
Pike_error("Cannot cast %s to float.\n",get_name_of_type(sp[-1].type));
+
}
+
+
sp[-1].type=T_FLOAT;
+
sp[-1].u.float_number=f;
+
break;
+
}
+
+
case T_OBJECT:
+
switch(sp[-1].type)
+
{
+
case T_STRING: {
+
struct pike_string *file;
+
INT32 lineno;
+
if(Pike_fp->pc &&
+
(file = low_get_line(Pike_fp->pc, Pike_fp->context.prog, &lineno))) {
+
push_string(file);
+
}else{
+
push_int(0);
+
}
+
/* FIXME: Ought to allow compile_handler to override.
+
*/
+
APPLY_MASTER("cast_to_object",2);
+
return;
+
}
+
+
case T_FUNCTION:
+
if (Pike_sp[-1].subtype == FUNCTION_BUILTIN) {
+
Pike_error("Cannot cast builtin functions to object.\n");
+
} else if (Pike_sp[-1].u.object->prog == pike_trampoline_program) {
+
ref_push_object(((struct pike_trampoline *)
+
(Pike_sp[-1].u.object->storage))->
+
frame->current_object);
+
stack_pop_keep_top();
+
} else {
+
Pike_sp[-1].type = T_OBJECT;
+
}
+
break;
+
+
default:
+
Pike_error("Cannot cast %s to object.\n",get_name_of_type(sp[-1].type));
+
}
+
break;
+
+
case T_PROGRAM:
+
switch(sp[-1].type)
+
{
+
case T_STRING: {
+
struct pike_string *file;
+
INT32 lineno;
+
if(Pike_fp->pc &&
+
(file = low_get_line(Pike_fp->pc, Pike_fp->context.prog, &lineno))) {
+
push_string(file);
+
}else{
+
push_int(0);
+
}
+
/* FIXME: Ought to allow compile_handler to override.
+
*/
+
APPLY_MASTER("cast_to_program",2);
+
return;
+
}
+
+
case T_FUNCTION:
+
{
+
struct program *p=program_from_function(sp-1);
+
if(p)
+
{
+
add_ref(p);
+
pop_stack();
+
push_program(p);
+
}else{
+
pop_stack();
+
push_int(0);
+
}
+
}
+
return;
+
+
default:
+
Pike_error("Cannot cast %s to a program.\n",get_name_of_type(sp[-1].type));
+
}
+
}
+
}
+
+
if(run_time_type != sp[-1].type)
+
{
+
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)
+
{
+
push_text(get_name_of_type(run_time_type));
+
apply_low(sp[-2].u.object, f, 1);
+
f=!UNSAFE_IS_ZERO(sp-1);
+
pop_stack();
+
if(f) goto emulated_type_ok;
+
}
+
}
+
Pike_error("Cast failed, wanted %s, got %s\n",
+
get_name_of_type(run_time_type),
+
get_name_of_type(sp[-1].type));
+
}
+
+
emulated_type_ok:
+
+
if (!type) return;
+
+
switch(run_time_type)
+
{
+
case T_ARRAY:
+
{
+
struct pike_type *itype;
+
INT32 run_time_itype;
+
+
push_type_value(itype = index_type(type, int_type_string, 0));
+
run_time_itype = compile_type_to_runtime_type(itype);
+
+
if(run_time_itype != T_MIXED)
+
{
+
struct array *a;
+
struct array *tmp=sp[-2].u.array;
+
DECLARE_CYCLIC();
+
+
if((a=(struct array *)BEGIN_CYCLIC(tmp,0)))
+
{
+
ref_push_array(a);
+
}else{
+
INT32 e;
+
TYPE_FIELD types = 0;
+
#ifdef PIKE_DEBUG
+
struct svalue *save_sp=sp+1;
+
#endif
+
push_array(a=allocate_array(tmp->size));
+
SET_CYCLIC_RET(a);
+
+
for(e=0;e<a->size;e++)
+
{
+
push_svalue(tmp->item+e);
+
o_cast(itype, run_time_itype);
+
stack_pop_to_no_free (ITEM(a) + e);
+
types |= 1 << ITEM(a)[e].type;
+
}
+
a->type_field = types;
+
#ifdef PIKE_DEBUG
+
if(save_sp!=sp)
+
Pike_fatal("o_cast left stack droppings.\n");
+
#endif
+
}
+
END_CYCLIC();
+
assign_svalue(sp-3,sp-1);
+
pop_stack();
+
}
+
pop_stack();
+
}
+
break;
+
+
case T_MULTISET:
+
{
+
struct pike_type *itype;
+
INT32 run_time_itype;
+
+
push_type_value(itype = key_type(type, 0));
+
run_time_itype = compile_type_to_runtime_type(itype);
+
+
if(run_time_itype != T_MIXED)
+
{
+
struct multiset *m;
+
#ifdef PIKE_NEW_MULTISETS
+
struct multiset *tmp=sp[-2].u.multiset;
+
#else
+
struct array *tmp=sp[-2].u.multiset->ind;
+
#endif
+
DECLARE_CYCLIC();
+
+
if((m=(struct multiset *)BEGIN_CYCLIC(tmp,0)))
+
{
+
ref_push_multiset(m);
+
}else{
+
#ifdef PIKE_DEBUG
+
struct svalue *save_sp=sp+1;
+
#endif
+
+
#ifdef PIKE_NEW_MULTISETS
+
ptrdiff_t nodepos;
+
if (multiset_indval (tmp))
+
Pike_error ("FIXME: Casting not implemented for multisets with values.\n");
+
push_multiset (m = allocate_multiset (multiset_sizeof (tmp),
+
multiset_get_flags (tmp),
+
multiset_get_cmp_less (tmp)));
+
+
SET_CYCLIC_RET(m);
+
+
if ((nodepos = multiset_first (tmp)) >= 0) {
+
ONERROR uwp;
+
SET_ONERROR (uwp, do_sub_msnode_ref, tmp);
+
do {
+
push_multiset_index (tmp, nodepos);
+
o_cast(itype, run_time_itype);
+
multiset_insert_2 (m, sp - 1, NULL, 0);
+
pop_stack();
+
} while ((nodepos = multiset_next (tmp, nodepos)) >= 0);
+
UNSET_ONERROR (uwp);
+
sub_msnode_ref (tmp);
+
}
+
+
#else /* PIKE_NEW_MULTISETS */
+
INT32 e;
+
struct array *a;
+
TYPE_FIELD types = 0;
+
push_multiset(m=allocate_multiset(a=allocate_array(tmp->size)));
+
+
SET_CYCLIC_RET(m);
+
+
for(e=0;e<a->size;e++)
+
{
+
push_svalue(tmp->item+e);
+
o_cast(itype, run_time_itype);
+
stack_pop_to_no_free (ITEM(a) + e);
+
types |= 1 << ITEM(a)[e].type;
+
}
+
a->type_field = types;
+
order_multiset(m);
+
#endif
+
+
#ifdef PIKE_DEBUG
+
if(save_sp!=sp)
+
Pike_fatal("o_cast left stack droppings.\n");
+
#endif
+
}
+
END_CYCLIC();
+
assign_svalue(sp-3,sp-1);
+
pop_stack();
+
}
+
pop_stack();
+
}
+
break;
+
+
case T_MAPPING:
+
{
+
struct pike_type *itype, *vtype;
+
INT32 run_time_itype;
+
INT32 run_time_vtype;
+
+
push_type_value(itype = key_type(type, 0));
+
run_time_itype = compile_type_to_runtime_type(itype);
+
+
push_type_value(vtype = index_type(type, mixed_type_string, 0));
+
run_time_vtype = compile_type_to_runtime_type(vtype);
+
+
if(run_time_itype != T_MIXED ||
+
run_time_vtype != T_MIXED)
+
{
+
struct mapping *m;
+
struct mapping *tmp=sp[-3].u.mapping;
+
DECLARE_CYCLIC();
+
+
if((m=(struct mapping *)BEGIN_CYCLIC(tmp,0)))
+
{
+
ref_push_mapping(m);
+
}else{
+
INT32 e;
+
struct keypair *k;
+
#ifdef PIKE_DEBUG
+
struct svalue *save_sp=sp+1;
+
#endif
+
push_mapping(m=allocate_mapping(m_sizeof(tmp)));
+
+
SET_CYCLIC_RET(m);
+
+
MAPPING_LOOP(tmp)
+
{
+
push_svalue(& k->ind);
+
o_cast(itype, run_time_itype);
+
push_svalue(& k->val);
+
o_cast(vtype, run_time_vtype);
+
mapping_insert(m,sp-2,sp-1);
+
pop_n_elems(2);
+
}
+
#ifdef PIKE_DEBUG
+
if(save_sp!=sp)
+
Pike_fatal("o_cast left stack droppings.\n");
+
#endif
+
}
+
END_CYCLIC();
+
assign_svalue(sp-4,sp-1);
+
pop_stack();
+
}
+
pop_n_elems(2);
+
}
+
}
+
}
+
+
PMOD_EXPORT void f_cast(void)
+
{
+
#ifdef PIKE_DEBUG
+
struct svalue *save_sp=sp;
+
if(sp[-2].type != T_TYPE)
+
Pike_fatal("Cast expression destroyed stack or left droppings! (Type:%d)\n",
+
sp[-2].type);
+
#endif
+
o_cast(sp[-2].u.type,
+
compile_type_to_runtime_type(sp[-2].u.type));
+
#ifdef PIKE_DEBUG
+
if(save_sp != sp)
+
Pike_fatal("Internal error: o_cast() left droppings on stack.\n");
+
#endif
+
free_svalue(sp-2);
+
sp[-2]=sp[-1];
+
sp--;
+
dmalloc_touch_svalue(sp);
+
}
+
#define COMPARISON(ID,NAME,FUN) \ PMOD_EXPORT void ID(INT32 args) \ { \ int i; \ switch(args) \ { \ case 0: case 1: \ SIMPLE_TOO_FEW_ARGS_ERROR(NAME, 2); \ case 2: \ i=FUN (sp-2,sp-1); \
pike.git/src/operators.c:4070:
void exit_operators(void) { if(string_assignment_program) { free_program(string_assignment_program); string_assignment_program=0; } }
+
+
void o_breakpoint(void)
+
{
+
/* Does nothing */
+
}