pike.git / src / array.c

version» Context lines:

pike.git/src/array.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: array.c,v 1.229 2010/07/11 12:39:11 jonasw Exp $ + || $Id$   */      #include "global.h"   #include "svalue.h"   #include "array.h"   #include "object.h"   #include "las.h"   #include "stralloc.h"   #include "interpret.h"   #include "opcodes.h"
pike.git/src/array.c:903:       get_order_fsort(current_order,    current_order+v->size-1,    fun,    ITEM(v));       UNSET_ONERROR(tmp);    return current_order;   }    - /* Returns 2 if no relation is established through lfun calls. */ - static INLINE int lfun_cmp (const struct svalue *a, const struct svalue *b) + /* Returns 2 if no relation is established through lfun calls, or 3 if +  * no order defining lfuns (i.e. `< or `>) were found. */ + static int lfun_cmp (const struct svalue *a, const struct svalue *b)   {    struct program *p; -  int fun; +  int default_res = 3, fun;       if (a->type == T_OBJECT && (p = a->u.object->prog)) {    if ((fun = FIND_LFUN(p->inherits[a->subtype].prog, LFUN_LT)) != -1) {    push_svalue(b);    apply_low(a->u.object,    fun + p->inherits[a->subtype].identifier_level, 1);    if(!UNSAFE_IS_ZERO(Pike_sp-1))    {    pop_stack();    return -1;    }    pop_stack(); -  +  default_res = 2;    }       if ((fun = FIND_LFUN(p->inherits[a->subtype].prog, LFUN_GT)) != -1) {    push_svalue(b);    apply_low(a->u.object,    fun + p->inherits[a->subtype].identifier_level, 1);    if(!UNSAFE_IS_ZERO(Pike_sp-1))    {    pop_stack();    return 1;    }    pop_stack(); -  +  default_res = 2;    }       if ((fun = FIND_LFUN(p->inherits[a->subtype].prog, LFUN_EQ)) != -1) {    push_svalue(b);    apply_low(a->u.object,    fun + p->inherits[a->subtype].identifier_level, 1);    if (!UNSAFE_IS_ZERO(Pike_sp-1)) {    pop_stack();    return 0;    }
pike.git/src/array.c:957:    if ((fun = FIND_LFUN(p->inherits[b->subtype].prog, LFUN_LT)) != -1) {    push_svalue(a);    apply_low(b->u.object,    fun + p->inherits[b->subtype].identifier_level, 1);    if(!UNSAFE_IS_ZERO(Pike_sp-1))    {    pop_stack();    return 1;    }    pop_stack(); +  default_res = 2;    }       if ((fun = FIND_LFUN(p->inherits[b->subtype].prog, LFUN_GT)) != -1) {    push_svalue(a);    apply_low(b->u.object,    fun + p->inherits[b->subtype].identifier_level, 1);    if(!UNSAFE_IS_ZERO(Pike_sp-1))    {    pop_stack();    return -1;    }    pop_stack(); -  +  default_res = 2;    }       if ((fun = FIND_LFUN(p->inherits[b->subtype].prog, LFUN_EQ)) != -1) {    push_svalue(a);    apply_low(b->u.object,    fun + p->inherits[b->subtype].identifier_level, 1);    if (!UNSAFE_IS_ZERO(Pike_sp-1)) {    pop_stack();    return 0;    }    pop_stack();    }    }    -  return 2; +  return default_res;   }    - int set_svalue_cmpfun(const struct svalue *a, const struct svalue *b) + static int obj_or_func_cmp (const struct svalue *a, const struct svalue *b) + /* Call with either two T_OBJECT or two T_FUNCTION. */   { -  int res, typediff = a->type - b->type; +  int a_subtype, b_subtype, res; +  struct svalue tmp_a, tmp_b;    -  if (!typediff) +  assert ((a->type == T_OBJECT && b->type == T_OBJECT) || +  (a->type == T_FUNCTION && b->type == T_FUNCTION)); +  +  if (a->u.object == b->u.object) +  return a->subtype - b->subtype; +  +  /* Destructed objects are considered equal to each other, and +  * (arbitrarily chosen) greater than others. */ +  if (!a->u.object->prog) +  return !b->u.object->prog ? 0 : 1; +  else if (!b->u.object->prog) +  return -1; +  +  if (a->type == T_FUNCTION) { +  if (a->u.object->prog != b->u.object->prog) +  return a->u.object->prog < b->u.object->prog ? -1 : 1; +  if (a->subtype != b->subtype) +  return a->subtype - b->subtype; +  +  /* We have the same function but in different objects. Compare the +  * objects themselves. */ +  /* FIXME: Should we try to convert the subtypes to the ones for +  * the closest inherits? That'd make some sense if the functions +  * are private, but otherwise it's doubtful. */ +  a_subtype = b_subtype = a->subtype; +  tmp_a = *a; +  tmp_a.type = T_OBJECT; +  tmp_a.subtype = 0; +  a = &tmp_a; +  tmp_b = *b; +  tmp_b.type = T_OBJECT; +  tmp_b.subtype = 0; +  b = &tmp_b; +  } +  +  else { +  a_subtype = a->subtype; +  b_subtype = b->subtype; +  } +  +  res = lfun_cmp (a, b); +  +  if (res == 3) { +  /* If the objects had no inequality comparison lfuns to call, use +  * their pointers to get a well defined internal sort order. Let's +  * also group objects cloned from the same program. */ +  if (a->u.object->prog == b->u.object->prog) +  return a->u.object < b->u.object ? -1 : 1; +  else +  return a->u.object->prog < b->u.object->prog ? -1 : 1; +  } +  +  return res == 2 ? 0 : res; + } +  + int set_svalue_cmpfun(const struct svalue *a, const struct svalue *b)   { -  +  int typediff = a->type - b->type; +  if (typediff) { +  if (a->type == T_OBJECT || b->type == T_OBJECT) { +  int res = lfun_cmp (a, b); +  if (res < 2) return res; +  } +  return typediff; +  } +     switch(a->type)    {    case T_FLOAT:    if(a->u.float_number < b->u.float_number) return -1;    if(a->u.float_number > b->u.float_number) return 1;    return 0;    -  case T_FUNCTION: -  if(a->u.refs < b->u.refs) return -1; -  if(a->u.refs > b->u.refs) return 1; -  return a->subtype - b->subtype; -  +     case T_INT:    if(a->u.integer < b->u.integer) return -1;    if(a->u.integer > b->u.integer) return 1;    return 0;    -  +  case T_OBJECT: +  case T_FUNCTION: +  return obj_or_func_cmp (a, b); +     default:    if(a->u.refs < b->u.refs) return -1;    if(a->u.refs > b->u.refs) return 1;    return 0; -  -  case T_OBJECT: -  if((a->u.object == b->u.object) && (a->subtype == b->subtype)) { -  return 0; +     } -  break; +  /* NOT REACHED */   } -  } +     -  res = lfun_cmp (a, b); -  if (res != 2) return res; -  -  if (typediff) return typediff; -  - #ifdef PIKE_DEBUG -  if (a->type != T_OBJECT) -  Pike_fatal ("Expected objects when both types are the same.\n"); - #endif -  -  /* FIXME: Take subtype into account! */ -  -  if(a->u.object->prog == b->u.object->prog) { -  if (a->u.object->prog) { -  if(a->u.object < b->u.object) { -  return -1; -  } else { -  return 1; -  } -  } else { -  /* Destructed objects are considered equal. */ -  return 0; -  } -  } else { -  /* Attempt to group objects cloned from the same program */ -  if (a->u.object->prog < b->u.object->prog) { -  return -1; -  } else { -  return 1; -  } -  } - } -  +    static int switch_svalue_cmpfun(const struct svalue *a, const struct svalue *b)   { -  if(a->type == b->type) -  { +  int typediff = a->type - b->type; +  if (typediff) +  return typediff; +     switch(a->type)    {    case T_INT:    if(a->u.integer < b->u.integer) return -1;    if(a->u.integer > b->u.integer) return 1;    return 0;       case T_FLOAT:    if(a->u.float_number < b->u.float_number) return -1;    if(a->u.float_number > b->u.float_number) return 1;    return 0;       case T_STRING:    return DO_NOT_WARN((int)my_quick_strcmp(a->u.string, b->u.string));    -  +  case T_OBJECT: +  case T_FUNCTION: +  return obj_or_func_cmp (a, b); +     default: -  return set_svalue_cmpfun(a,b); +  if(a->u.refs < b->u.refs) return -1; +  if(a->u.refs > b->u.refs) return 1; +  return 0;    } -  }else{ -  return a->type - b->type; +  /* NOT REACHED */   } - } +       int alpha_svalue_cmpfun(const struct svalue *a, const struct svalue *b)   { -  int res, typediff = a->type - b->type; +  int typediff = a->type - b->type; +  if (typediff) { +  if (a->type == T_OBJECT || b->type == T_OBJECT) { +  int res = lfun_cmp (a, b); +  if (res < 2) return res; +  } +  return typediff; +  }    -  if (!typediff) -  { +     switch(a->type)    {    case T_INT:    if(a->u.integer < b->u.integer) return -1;    if(a->u.integer > b->u.integer) return 1;    return 0;       case T_FLOAT:    if(a->u.float_number < b->u.float_number) return -1;    if(a->u.float_number > b->u.float_number) return 1;
pike.git/src/array.c:1120:    else    if (!b->u.array->size)    return 1;    return alpha_svalue_cmpfun(ITEM(a->u.array), ITEM(b->u.array));       case T_MULTISET:    if (a == b) return 0;    {    ptrdiff_t a_pos = multiset_first (a->u.multiset);    ptrdiff_t b_pos = multiset_first (b->u.multiset); +  int res;    struct svalue ind_a, ind_b;    if (a_pos < 0)    if (b_pos < 0)    return 0;    else    return -1;    else    if (b_pos < 0)    return 1;    res = alpha_svalue_cmpfun (    use_multiset_index (a->u.multiset, a_pos, ind_a),    use_multiset_index (b->u.multiset, b_pos, ind_b));    sub_msnode_ref (a->u.multiset);    sub_msnode_ref (b->u.multiset);    return res;    }       case T_OBJECT: -  if((a->u.object == b->u.object) && (a->subtype == b->subtype)) { -  return 0; -  } -  break; +  case T_FUNCTION: +  return obj_or_func_cmp (a, b);       default: - #if 1 -  /* I think it would be better to leave the order undefined in -  * these cases since the addresses aren't observable -  * properties in pike. /mast */ -  if(a->u.refs < b->u.refs) return -1; -  if(a->u.refs > b->u.refs) return 1; - #endif +  if(a->u.ptr < b->u.ptr) return -1; +  if(a->u.ptr > b->u.ptr) return 1;    return 0;    } -  +  /* NOT REACHED */   }    -  res = lfun_cmp (a, b); -  if (res != 2) return res; -  -  return typediff; - } -  +    #define CMP(X,Y) alpha_svalue_cmpfun(X,Y)   #define TYPE struct svalue   #define ID low_sort_svalues   #include "fsort_template.h"   #undef CMP   #undef TYPE   #undef ID      /* Same, but only integers. */   static int alpha_int_svalue_cmpfun(const struct svalue *a, const struct svalue *b)