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.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)