pike.git / src / operators.c

version» Context lines:

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 */ + }