pike.git / src / builtin_functions.c

version» Context lines:

pike.git/src/builtin_functions.c:250:    *!    *! If @[max] is given, the result will be >= 0 and < @[max],    *! otherwise the result will be >= 0 and <= 0x7fffffff.    *!    *! @note    *! This function is provided for backward compatibility reasons.    *!    *! This function is byte-order dependant for wide strings.    *!    *! @seealso -  *! @[hash()], @[7.0::hash()] +  *! @[predef::hash()], @[7.0::hash()]    */   static void f_hash_7_4(INT32 args)   {    size_t i = 0;    struct pike_string *s = Pike_sp[-args].u.string;       if(!args)    SIMPLE_TOO_FEW_ARGS_ERROR("7.4::hash",1);       if(TYPEOF(Pike_sp[-args]) != T_STRING)
pike.git/src/builtin_functions.c:318:    *!    *! If @[max] is given, the result will be >= 0 and < @[max],    *! otherwise the result will be >= 0 and <= 0x7fffffff.    *!    *! @note    *! This function is provided for backward compatibility reasons.    *!    *! This function is not NUL-safe, and is byte-order dependant.    *!    *! @seealso -  *! @[hash()], @[7.4::hash()] +  *! @[predef::hash()], @[7.4::hash()]    */   static void f_hash_7_0( INT32 args )   {    struct pike_string *s = Pike_sp[-args].u.string;    unsigned int i;    if(!args)    SIMPLE_TOO_FEW_ARGS_ERROR("7.0::hash",1);    if(TYPEOF(Pike_sp[-args]) != T_STRING)    SIMPLE_BAD_ARG_ERROR("7.0::hash", 1, "string");   
pike.git/src/builtin_functions.c:638:    *!    *! Convert a string or character to lower case.    *!    *! @returns    *! Returns a copy of the string @[s] with all upper case characters    *! converted to lower case, or the character @[c] converted to lower    *! case.    *!    *! @note    *! Assumes the string or character to be coded according to -  *! ISO-10646 (aka Unicode). If they are not, @[Locale.Charset.decoder] -  *! can do the initial conversion for you. +  *! ISO-10646 (aka Unicode). If they are not, @[Charset.decoder] can +  *! do the initial conversion for you.    *!    *! @note    *! Prior to Pike 7.5 this function only accepted strings.    *!    *! @seealso -  *! @[upper_case()], @[Locale.Charset.decoder] +  *! @[upper_case()], @[Charset.decoder]    */   PMOD_EXPORT void f_lower_case(INT32 args)   {    ptrdiff_t i;    struct pike_string *orig;    struct pike_string *ret;       check_all_args("lower_case", args, BIT_STRING|BIT_INT, 0);       if (TYPEOF(Pike_sp[-args]) == T_INT) {    /* NOTE: Performs the case change in place. */    DO_LOWER_CASE(Pike_sp[-args].u.integer);    pop_n_elems(args-1);    return;    }       orig = Pike_sp[-args].u.string; -  +  +  if( orig->flags & STRING_IS_LOWERCASE ) +  return; +     ret = begin_wide_shared_string(orig->len, orig->size_shift);       MEMCPY(ret->str, orig->str, orig->len << orig->size_shift);       i = orig->len;       if (!orig->size_shift) {    p_wchar0 *str = STR0(ret);       while(i--) {
pike.git/src/builtin_functions.c:693:       while(i--) {    DO_LOWER_CASE(str[i]);    }   #ifdef PIKE_DEBUG    } else {    Pike_fatal("lower_case(): Bad string shift:%d\n", orig->size_shift);   #endif    }    +  ret = end_shared_string(ret); +  ret->flags |= STRING_IS_LOWERCASE;    pop_n_elems(args); -  push_string(end_shared_string(ret)); +  push_string(ret);   }      /*! @decl string upper_case(string s)    *! @decl int upper_case(int c)    *!    *! Convert a string or character to upper case.    *!    *! @returns    *! Returns a copy of the string @[s] with all lower case characters    *! converted to upper case, or the character @[c] converted to upper    *! case.    *!    *! @note    *! Assumes the string or character to be coded according to -  *! ISO-10646 (aka Unicode). If they are not, @[Locale.Charset.decoder] -  *! can do the initial conversion for you. +  *! ISO-10646 (aka Unicode). If they are not, @[Charset.decoder] can +  *! do the initial conversion for you.    *!    *! @note    *! Prior to Pike 7.5 this function only accepted strings.    *!    *! @seealso -  *! @[lower_case()], @[Locale.Charset.decoder] +  *! @[lower_case()], @[Charset.decoder]    */   PMOD_EXPORT void f_upper_case(INT32 args)   {    ptrdiff_t i;    struct pike_string *orig;    struct pike_string *ret;    check_all_args("upper_case", args, BIT_STRING|BIT_INT, 0);       if (TYPEOF(Pike_sp[-args]) == T_INT) {    /* NOTE: Performs the case change in place. */    DO_UPPER_CASE(Pike_sp[-args].u.integer);    pop_n_elems(args-1);    return;    }       orig = Pike_sp[-args].u.string; -  +  if( orig->flags & STRING_IS_UPPERCASE ) +  { +  return; +  } +     ret=begin_wide_shared_string(orig->len,orig->size_shift);    MEMCPY(ret->str, orig->str, orig->len << orig->size_shift);       i = orig->len;       if (!orig->size_shift) {    p_wchar0 *str = STR0(ret);       while(i--) {    if(str[i]!=0xff && str[i]!=0xb5) {
pike.git/src/builtin_functions.c:793:    while(i--) {    DO_UPPER_CASE(str[i]);    }   #ifdef PIKE_DEBUG    } else {    Pike_fatal("lower_case(): Bad string shift:%d\n", orig->size_shift);   #endif    }       pop_n_elems(args); -  push_string(end_shared_string(ret)); +  ret = end_shared_string(ret); +  ret->flags |= STRING_IS_UPPERCASE; +  push_string(ret);   }      /*! @decl string random_string(int len)    *!    *! Returns a string of random characters 0-255 with the length @[len].    */   PMOD_EXPORT void f_random_string(INT32 args)   {    struct pike_string *ret;    INT_TYPE len, e;
pike.git/src/builtin_functions.c:821:   /*! @decl void random_seed(int seed)    *!    *! This function sets the initial value for the random generator.    *!    *! @seealso    *! @[random()]    */   PMOD_EXPORT void f_random_seed(INT32 args)   {    INT_TYPE i; - #ifdef AUTO_BIGNUM +     check_all_args("random_seed",args,BIT_INT | BIT_OBJECT, 0);    if(TYPEOF(Pike_sp[-args]) == T_INT)    {    i=Pike_sp[-args].u.integer;    }else{    i=hash_svalue(Pike_sp-args);    } - #else -  get_all_args("random_seed",args,"%i",&i); - #endif +     my_srand(i);    pop_n_elems(args);   }      /*! @decl int query_num_arg()    *!    *! Returns the number of arguments given when the previous function was    *! called.    *!    *! This is useful for functions that take a variable number of arguments.
pike.git/src/builtin_functions.c:948:    if ((TYPEOF(Pike_sp[1-args]) == T_INT) ||    ((TYPEOF(Pike_sp[1-args]) == T_STRING) &&    (Pike_sp[1-args].u.string->len == 1))) {    INT_TYPE val;    if (TYPEOF(Pike_sp[1-args]) == T_INT) {    val = Pike_sp[1-args].u.integer;    } else {    val = index_shared_string(Pike_sp[1-args].u.string, 0);    }    +  if( !string_range_contains( haystack, val ) ) +  { +  pop_n_elems(args); +  push_int( -1 ); +  return; +  }    switch(Pike_sp[-args].u.string->size_shift) {    case 0:    {    p_wchar0 *str = STR0(haystack);    if (val >= 256) {    start = -1;    break;    }    while (start < haystack->len) {    if (str[start] == val) break;
pike.git/src/builtin_functions.c:1171:    }    }    pop_n_elems(args+1);    push_int(1);    return;    }       a = Pike_sp[-args].u.string;       /* First handle some common special cases. */ -  if ((b->len > a->len) || (b->size_shift > a->size_shift)) { +  if ((b->len > a->len) || (b->size_shift > a->size_shift) +  || !string_range_contains_string(a, b)) {    pop_n_elems(args);    push_int(0);    return;    }       /* Trivial cases. */    if ((a == b)||(!b->len)) {    pop_n_elems(args);    push_int(1);    return;
pike.git/src/builtin_functions.c:1243:    SIMPLE_TOO_FEW_ARGS_ERROR("has_suffix", 2);    if(TYPEOF(Pike_sp[-args]) != T_STRING)    SIMPLE_ARG_TYPE_ERROR("has_suffix", 1, "string");    if(TYPEOF(Pike_sp[1-args]) != T_STRING)    SIMPLE_ARG_TYPE_ERROR("has_suffix", 2, "string");       a = Pike_sp[-args].u.string;    b = Pike_sp[1-args].u.string;       /* First handle some common special cases. */ -  if ((b->len > a->len) || (b->size_shift > a->size_shift)) { +  if ((b->len > a->len) || (b->size_shift > a->size_shift) +  || !string_range_contains_string(a, b)) {    pop_n_elems(args);    push_int(0);    return;    }       /* Trivial cases. */    if ((a == b)||(!b->len)) {    pop_n_elems(args);    push_int(1);    return;
pike.git/src/builtin_functions.c:1630:    *! Converts a string into an UTF16 compliant byte-stream.    *!    *! @note    *! Throws an error if characters not legal in an UTF16 stream are    *! encountered. Valid characters are in the range 0x00000 - 0x10ffff,    *! except for characters 0xfffe and 0xffff.    *!    *! Characters in range 0x010000 - 0x10ffff are encoded using surrogates.    *!    *! @seealso -  *! @[Locale.Charset.decoder()], @[string_to_utf8()], @[unicode_to_string()], +  *! @[Charset.decoder()], @[string_to_utf8()], @[unicode_to_string()],    *! @[utf8_to_string()]    */   PMOD_EXPORT void f_string_to_unicode(INT32 args)   {    struct pike_string *in;    struct pike_string *out = NULL;    ptrdiff_t len;    ptrdiff_t i;       get_all_args("string_to_unicode", args, "%W", &in);
pike.git/src/builtin_functions.c:1766:   }      /*! @decl string unicode_to_string(string(0..255) s)    *!    *! Converts an UTF16 byte-stream into a string.    *!    *! @note    *! This function did not decode surrogates in Pike 7.2 and earlier.    *!    *! @seealso -  *! @[Locale.Charset.decoder()], @[string_to_unicode()], @[string_to_utf8()], +  *! @[Charset.decoder()], @[string_to_unicode()], @[string_to_utf8()],    *! @[utf8_to_string()]    */   PMOD_EXPORT void f_unicode_to_string(INT32 args)   {    struct pike_string *in;    struct pike_string *out = NULL;    ptrdiff_t len, i, num_surrogates = 0;    int swab=0;    p_wchar1 surr1, surr2, surrmask, *str0;   
pike.git/src/builtin_functions.c:1932:    *! @note    *! Throws an error if characters not valid in an UTF-8 stream are    *! encountered. Valid characters are in the ranges    *! @expr{0x00000000-0x0000d7ff@} and @expr{0x0000e000-0x0010ffff@}.    *!    *! If @[extended] is 1 then characters outside the valid ranges are    *! accepted too and encoded using the same algorithm. Such encoded    *! characters are however not UTF-8 compliant.    *!    *! @seealso -  *! @[Locale.Charset.encoder()], @[string_to_unicode()], +  *! @[Charset.encoder()], @[string_to_unicode()],    *! @[unicode_to_string()], @[utf8_to_string()]    */   PMOD_EXPORT void f_string_to_utf8(INT32 args)   {    ptrdiff_t len;    struct pike_string *in;    struct pike_string *out;    ptrdiff_t i,j;    INT_TYPE extended = 0; -  +  PCHARP src; +  INT32 min, max;       get_all_args("string_to_utf8", args, "%W.%i", &in, &extended);       len = in->len;    -  for(i=0; i < in->len; i++) { -  unsigned INT32 c = index_shared_string(in, i); +  check_string_range(in, 1, &min, &max); +  +  if (min >= 0 && max <= 0x7f) { +  /* 7bit string -- already valid utf8. */ +  pop_n_elems(args - 1); +  return; +  } +  +  for(i=0,src=MKPCHARP_STR(in); i < in->len; INC_PCHARP(src,1),i++) { +  unsigned INT32 c = EXTRACT_PCHARP(src);    if (c & ~0x7f) {    /* 8bit or more. */    len++;    if (c & ~0x7ff) {    /* 12bit or more. */    len++;    if (c & ~0xffff) {    /* 17bit or more. */    len++;    if (!extended && c > 0x10ffff)
pike.git/src/builtin_functions.c:1994:    }    }    }    if (len == in->len) {    /* 7bit string -- already valid utf8. */    pop_n_elems(args - 1);    return;    }    out = begin_shared_string(len);    -  for(i=j=0; i < in->len; i++) { -  unsigned INT32 c = index_shared_string(in, i); +  for(i=j=0,src=MKPCHARP_STR(in); i < in->len; INC_PCHARP(src,1),i++) { +  unsigned INT32 c = EXTRACT_PCHARP(src);    if (!(c & ~0x7f)) {    /* 7bit */    out->str[j++] = c;    } else if (!(c & ~0x7ff)) {    /* 11bit */    out->str[j++] = 0xc0 | (c >> 6);    out->str[j++] = 0x80 | (c & 0x3f);    } else if (!(c & ~0xffff)) {    /* 16bit */    out->str[j++] = 0xe0 | (c >> 12);
pike.git/src/builtin_functions.c:2077:    *! @endint    *!    *! @note    *! Throws an error if the stream is not a legal UTF-8 byte-stream.    *!    *! @note    *! In conformance with RFC 3629 and Unicode 3.1 and later,    *! non-shortest forms are not decoded. An error is thrown instead.    *!    *! @seealso -  *! @[Locale.Charset.encoder()], @[string_to_unicode()], @[string_to_utf8()], +  *! @[Charset.encoder()], @[string_to_unicode()], @[string_to_utf8()],    *! @[unicode_to_string()]    */   PMOD_EXPORT void f_utf8_to_string(INT32 args)   {    struct pike_string *in;    struct pike_string *out;    ptrdiff_t len = 0;    int shift = 0;    ptrdiff_t i,j=0;    INT_TYPE extended = 0; -  +  INT32 min, max;       get_all_args("utf8_to_string", args, "%S.%i", &in, &extended);    -  +  check_string_range(in, 1, &min, &max); +  +  if (min >= 0 && max <= 0x7f) { +  /* 7bit string -- already valid utf8. */ +  pop_n_elems(args - 1); +  return; +  } +     for(i=0; i < in->len; i++) {    unsigned int c = STR0(in)[i];    len++;    if (c & 0x80) {    int cont = 0;       /* From table 3-6 in the Unicode standard 4.0: Well-Formed UTF-8    * Byte Sequences    *    * Code Points 1st Byte 2nd Byte 3rd Byte 4th Byte
pike.git/src/builtin_functions.c:2995:    pop_n_elems(args);    push_float( - (FLOAT_TYPE)tmp.tv_sec-((FLOAT_TYPE)tmp.tv_usec)/1000000 );    return;    }    }    pop_n_elems(args);    INACCURATE_GETTIMEOFDAY(&ret);    push_int(ret.tv_sec);   }    - /*! @decl string crypt(string password) + /*! @decl string(0..127) crypt(string password)    *! @decl int(0..1) crypt(string typed_password, string crypted_password)    *!    *! This function crypts and verifies a short string (only the first    *! 8 characters are significant).    *!    *! The first syntax crypts the string @[password] into something that    *! is hopefully hard to decrypt.    *!    *! The second syntax is used to verify @[typed_password] against    *! @[crypted_password], and returns @expr{1@} if they match, and
pike.git/src/builtin_functions.c:3211:    }    pop_n_elems(args);    push_array(a);   }      /* this should probably be moved to pike_types.c or something */   #define FIX_OVERLOADED_TYPE(n, lf, X) fix_overloaded_type(n,lf,X,CONSTANT_STRLEN(X))   /* FIXME: This function messes around with the implementation of pike_type,    * and should probably be in pike_types.h instead.    */ - static node *fix_overloaded_type(node *n, int lfun, const char *deftype, int deftypelen) + static node *fix_overloaded_type(node *n, int lfun, const char *deftype, int UNUSED(deftypelen))   {    node **first_arg;    struct pike_type *t, *t2;    first_arg=my_get_arg(&_CDR(n), 0);    if(!first_arg) return 0;    t=first_arg[0]->type;    if(!t || match_types(t, object_type_string))    {    /* Skip any name-nodes. */    while(t && t->type == PIKE_T_NAME) {
pike.git/src/builtin_functions.c:4590:    *!    *! @seealso    *! @[mappingp()], @[programp()], @[arrayp()], @[stringp()], @[functionp()],    *! @[multisetp()], @[floatp()], @[intp()]    */   PMOD_EXPORT void f_objectp(INT32 args)   {    if(args<1)    SIMPLE_TOO_FEW_ARGS_ERROR("objectp", 1);    if(TYPEOF(Pike_sp[-args]) != T_OBJECT || !Pike_sp[-args].u.object->prog - #ifdef AUTO_BIGNUM -  || is_bignum_object(Pike_sp[-args].u.object) - #endif -  ) +  || is_bignum_object(Pike_sp[-args].u.object))    {    pop_n_elems(args);    push_int(0);    }else{    pop_n_elems(args);    push_int(1);    }   }      /*! @decl int functionp(mixed arg)
pike.git/src/builtin_functions.c:4624:    if(args<1)    SIMPLE_TOO_FEW_ARGS_ERROR("functionp", 1);    if( TYPEOF(Pike_sp[-args]) == T_FUNCTION &&    (SUBTYPEOF(Pike_sp[-args]) == FUNCTION_BUILTIN ||    Pike_sp[-args].u.object->prog))    res=1;    pop_n_elems(args);    push_int(res);   }    - /*! @decl int callablep(mixed arg) -  *! -  *! Returns @expr{1@} if @[arg] is a callable, @expr{0@} (zero) otherwise. -  *! -  *! @seealso -  *! @[mappingp()], @[programp()], @[arrayp()], @[stringp()], @[objectp()], -  *! @[multisetp()], @[floatp()], @[intp()] -  */ - PMOD_EXPORT void f_callablep(INT32 args) + static int callablep(struct svalue *s)   { -  int res = 0; -  if(args<1) -  SIMPLE_TOO_FEW_ARGS_ERROR("callablep", 1); +  int ret = 0; +  DECLARE_CYCLIC();    -  switch( TYPEOF(Pike_sp[-args]) ) +  if (BEGIN_CYCLIC(s, NULL)) { +  END_CYCLIC(); +  return 1; +  } +  +  SET_CYCLIC_RET((ptrdiff_t)1); +  +  switch( TYPEOF(*s) )    {    case T_FUNCTION: -  if( SUBTYPEOF(Pike_sp[-args]) != FUNCTION_BUILTIN -  && !Pike_sp[-args].u.object->prog) +  if( SUBTYPEOF(*s) == FUNCTION_BUILTIN +  || s->u.object->prog) +  ret = 1;    break; -  res = 1; -  break; +     case T_PROGRAM: -  res = 1; +  ret = 1;    break;    case T_OBJECT:    {    struct program *p; -  if((p = Pike_sp[-args].u.object->prog) && -  FIND_LFUN(p->inherits[SUBTYPEOF(Pike_sp[-args])].prog, +  if((p = s->u.object->prog) && +  FIND_LFUN(p->inherits[SUBTYPEOF(*s)].prog,    LFUN_CALL ) != -1) -  res = 1; +  ret = 1;    }    break;    case T_ARRAY: -  /* FIXME: What about the recursive case? */ -  array_fix_type_field(Pike_sp[-args].u.array); -  if( (Pike_sp[-args].u.array->type_field==BIT_CALLABLE) || -  !Pike_sp[-args].u.array->type_field) { -  res = 1; +  array_fix_type_field(s->u.array); +  if( !s->u.array->type_field) { +  ret = 1; +  break;    } -  else if( !(Pike_sp[-args].u.array->type_field & -  ~(BIT_CALLABLE|BIT_INT)) ) { -  struct array *a = Pike_sp[-args].u.array; +  if( !(s->u.array->type_field & ~(BIT_CALLABLE|BIT_INT)) ) { +  struct array *a = s->u.array;    int i; -  res = 1; +  ret = 1;    for(i=0; i<a->size; i++) -  if( TYPEOF(ITEM(a)[i]) == T_INT && ITEM(a)[i].u.integer ) { -  res = 0; -  break; +  if( TYPEOF(ITEM(a)[i])!=T_INT && !callablep(&ITEM(a)[i]) ) +  ret = 0;    } -  } +     break;    } -  +  +  END_CYCLIC(); +  return ret; + } +  + /*! @decl int callablep(mixed arg) +  *! +  *! Returns @expr{1@} if @[arg] is a callable, @expr{0@} (zero) otherwise. +  *! +  *! @seealso +  *! @[mappingp()], @[programp()], @[arrayp()], @[stringp()], @[objectp()], +  *! @[multisetp()], @[floatp()], @[intp()] +  */ + PMOD_EXPORT void f_callablep(INT32 args) + { +  int res = 0; +  if(args<1) +  SIMPLE_TOO_FEW_ARGS_ERROR("callablep", 1); +  +  res = callablep(&Pike_sp[-args]);    pop_n_elems(args);    push_int(res);   }   #ifndef HAVE_AND_USE_POLL   #undef HAVE_POLL   #endif      static void delaysleep(double delay, unsigned do_abort_on_signal,    unsigned do_microsleep)   {
pike.git/src/builtin_functions.c:5179:    types |= 1 << TYPEOF(ITEM(a)[e]);    }    a->type_field = types;       Pike_sp--;    dmalloc_touch_svalue(Pike_sp);    pop_n_elems(args);    push_array(a);   }    +  + /*! @decl int map_all_objects(function(object:void) cb) +  *! @belongs Debug +  *! +  *! Call cb for all objects that currently exist. The callback will +  *! not be called with destructed objects as it's argument. +  *! +  *! Objects might be missed if @[cb] creates new objects or destroys +  *! old ones. +  *! +  *! This function is only intended to be used for debug purposes. +  *! +  *! @returns +  *! The total number of objects +  *! +  *! @seealso +  *! @[next_object()] +  */ + static void f_map_all_objects( INT32 args ) + { +  struct object *o = first_object; +  INT32 total = 0; +  ASSERT_SECURITY_ROOT("_map_all_objects"); +  while( o ) +  { +  struct object *next = o->next; +  if( o->prog ) +  { +  ref_push_object( o ); +  safe_apply_svalue( Pike_sp-2, 1, 1 ); +  pop_stack(); +  } +  total++; +  o = next; +  } +  pop_stack(); +  push_int(total); + } +    /*! @decl void verify_internals()    *! @belongs Debug    *!    *! Perform sanity checks.    *!    *! This function goes through most of the internal Pike structures and    *! generates a fatal error if one of them is found to be out of order.    *! It is only used for debugging.    *!    *! @note
pike.git/src/builtin_functions.c:7569: Inside #if defined(DEBUG_MALLOC)
   COUNT(memloc);    COUNT(memhdr);    }   #endif       call_callback(&memory_usage_callback, NULL);       f_aggregate_mapping(DO_NOT_WARN(Pike_sp - ss));   }    + /* Estimate the size of an svalue, not including objects. +  this is used from size_object. +  +  It should not include the size of the svalue itself, so the basic +  types count as 0 bytes. +  +  This is an estimate mainly because it is very hard to know to whom +  a certain array/mapping/multiset or string "belongs". +  +  The returned size will be the memory usage of the svalue divided by +  the number of references to it. + */ +  + struct string_header + { +  PIKE_STRING_CONTENTS; + }; +  + unsigned int rec_size_svalue( struct svalue *s, struct mapping **m ) + { +  unsigned int res = 0; +  int i; +  ptrdiff_t node_ref; +  INT32 e; +  struct svalue *x; +  struct keypair *k; +  +  switch( s->type ) +  { +  case PIKE_T_STRING: +  /* FIXME: This makes assumptions about the threshold for short strings. */ +  if( s->u.string->flags & STRING_IS_SHORT ) +  return (16+sizeof(struct string_header)) / s->u.string->refs; +  return ((s->u.string->len << s->u.string->size_shift) + +  sizeof(struct string_header)) / s->u.string->refs; +  case PIKE_T_INT: +  case PIKE_T_OBJECT: +  case PIKE_T_FLOAT: +  case PIKE_T_FUNCTION: +  case PIKE_T_TYPE: +  return 0; +  } +  if( !m ) return 0; +  +  if( !*m ) +  *m = allocate_mapping( 10 ); +  else if( (x = low_mapping_lookup( *m, s )) ) +  { +  /* Already counted. Use the old size. */ +  return x->u.integer; +  } +  +  low_mapping_insert( *m, s, &svalue_int_one, 0 ); +  switch( s->type ) +  { +  case PIKE_T_ARRAY: +  res = sizeof( struct array ); +  for( i=0; i<s->u.array->size; i++ ) +  res += sizeof(struct svalue) + rec_size_svalue( s->u.array->item+i, m ); +  break; +  +  case PIKE_T_MULTISET: +  res = sizeof(struct multiset) + sizeof(struct multiset_data); +  node_ref = multiset_last( s->u.multiset ); +  while( node_ref != -1 ) +  { +  res += rec_size_svalue( get_multiset_value (s->u.multiset, node_ref), m ) +  /* each node has the index and left/right node pointers. */ +  + sizeof(struct svalue) + (sizeof(void*)*2); +  node_ref = multiset_prev( s->u.multiset, node_ref ); +  } +  break; +  +  case PIKE_T_MAPPING: +  res = sizeof(struct mapping); +  { +  struct mapping_data *d = s->u.mapping->data; +  struct keypair *f = d->free_list; +  int data_size = sizeof( struct mapping_data ); +  data_size += d->hashsize * sizeof(struct keypair *) - sizeof(struct keypair *); +  while( f ) +  { +  data_size += sizeof(struct keypair); +  f = f->next; +  } +  NEW_MAPPING_LOOP( s->u.mapping->data ) +  { +  data_size += rec_size_svalue( &k->ind, m ); +  data_size += rec_size_svalue( &k->val, m ); +  data_size += sizeof( struct keypair ); +  } +  res += data_size / (d->hardlinks+1); +  } +  break; +  } +  res /= *s->u.refs; +  low_mapping_lookup(*m,s)->u.integer = res; +  return res; + } +  + /*! @decl int size_object(object o) +  *! @belongs Debug +  *! +  *! Return the aproximate size of the object, in bytes. +  *! This might not work very well for native objects +  *! +  *! +  *! The function tries to estimate the memory usage of variables +  *! belonging to the object. +  *! +  *! It will not, however, include the size of objects assigned to +  *! variables in the object. +  *! +  *! +  *! If the object has a @[lfun::_size_object()] it will be called +  *! without arguments, and the return value will be added to the final +  *! size. It is primarily intended to be used by C-objects that +  *! allocate memory that is not normally visible to pike. +  *! +  *! @seealso +  *! @[lfun::_size_object()], @[sizeof()] +  */ + static void f__size_object( INT32 args ) + { +  size_t sum; +  unsigned int i; +  ptrdiff_t fun; +  struct object *o; +  struct program *p; +  struct mapping *map = NULL; +  if( Pike_sp[-1].type != PIKE_T_OBJECT ) +  Pike_error("Expected an object as argument\n"); +  o = Pike_sp[-1].u.object; +  +  if( !(p=o->prog) ) +  { +  pop_stack(); +  push_int(0); +  return; +  } +  sum = sizeof(struct object); +  sum += p->storage_needed; +  +  if( (fun = low_find_lfun( p, LFUN__SIZE_OBJECT)) != -1 ) +  { +  apply_low( o, fun, 0 ); +  if( Pike_sp[-1].type == PIKE_T_INT ) +  sum += Pike_sp[-1].u.integer; +  pop_stack(); +  } +  +  Pike_sp++; +  for (i = 0; i < p->num_identifier_references; i++) +  { +  struct reference *ref = PTR_FROM_INT(p, i); +  struct identifier *id = ID_FROM_PTR(p, ref); +  struct inherit *inh = p->inherits; +  if (!IDENTIFIER_IS_VARIABLE(id->identifier_flags) || +  id->run_time_type == PIKE_T_GET_SET) +  { +  continue; +  } +  +  /* NOTE: makes the assumption that a variable saved in an +  * object has at least one reference. +  */ +  low_object_index_no_free(Pike_sp-1, o, i + inh->identifier_level); +  if (REFCOUNTED_TYPE(TYPEOF(Pike_sp[-1]))) +  sub_ref( Pike_sp[-1].u.dummy ); +  sum += rec_size_svalue(Pike_sp-1, &map); +  } +  Pike_sp--; +  if( map ) free_mapping(map); +  +  pop_stack(); +  push_int(sum); + } +  +    /*! @decl mixed _next(mixed x)    *!    *! Find the next object/array/mapping/multiset/program or string.    *!    *! All objects, arrays, mappings, multisets, programs and strings are    *! stored in linked lists inside Pike. This function returns the next    *! item on the corresponding list. It is mainly meant for debugging    *! the Pike runtime, but can also be used to control memory usage.    *!    *! @seealso
pike.git/src/builtin_functions.c:7681:    *! @seealso    *! @[_next()], @[_prev()]    */   PMOD_EXPORT void f__refs(INT32 args)   {    INT32 i;       if(!args)    SIMPLE_TOO_FEW_ARGS_ERROR("_refs", 1);    -  if(TYPEOF(Pike_sp[-args]) > MAX_REF_TYPE) +  if(!REFCOUNTED_TYPE(TYPEOF(Pike_sp[-args])))    SIMPLE_BAD_ARG_ERROR("refs", 1,    "array|mapping|multiset|object|"    "function|program|string");       i=Pike_sp[-args].u.refs[0];    pop_n_elems(args);    push_int(i);   }      #ifdef PIKE_DEBUG   /* This function is for debugging *ONLY*    * do not document please. /Hubbe    */   PMOD_EXPORT void f__leak(INT32 args)   {    INT32 i;       if(!args)    SIMPLE_TOO_FEW_ARGS_ERROR("_leak", 1);    -  if(TYPEOF(Pike_sp[-args]) > MAX_REF_TYPE) +  if(!REFCOUNTED_TYPE(TYPEOF(Pike_sp[-args])))    SIMPLE_BAD_ARG_ERROR("_leak", 1,    "array|mapping|multiset|object|"    "function|program|string");       add_ref(Pike_sp[-args].u.dummy);    i=Pike_sp[-args].u.refs[0];    pop_n_elems(args);    push_int(i);   }   #endif
pike.git/src/builtin_functions.c:7768:    if(!new_master->prog)    bad_arg_error("replace_master", Pike_sp-args, args, 1, "object", Pike_sp-args,    "Called with destructed object.\n");       if (SUBTYPEOF(Pike_sp[-args]))    bad_arg_error("replace_master", Pike_sp-args, args, 1, "object", Pike_sp-args,    "Subtyped master objects are not supported yet.\n");       push_constant_text ("is_pike_master");    args++; -  object_set_index (new_master, 0, Pike_sp - 1, &svalue_int_one); +  object_set_index (new_master, 0, Pike_sp - 1, (struct svalue *) &svalue_int_one);       free_object(master_object);    master_object=new_master;    add_ref(master_object);       free_program(master_program);    master_program=master_object->prog;    add_ref(master_program);       pop_n_elems(args);
pike.git/src/builtin_functions.c:8389: Inside #if defined(PIKE_DEBUG)
   *! @note    *! This function only exists if the Pike runtime has been compiled    *! with RTL debug.    */   PMOD_EXPORT void f__gc_set_watch(INT32 args)   {    ASSERT_SECURITY_ROOT("_gc_set_watch");       if (args < 1)    SIMPLE_TOO_FEW_ARGS_ERROR("_gc_set_watch", 1); -  if (TYPEOF(Pike_sp[-args]) > MAX_REF_TYPE) +  if (!REFCOUNTED_TYPE(TYPEOF(Pike_sp[-args])))    SIMPLE_BAD_ARG_ERROR("_gc_set_watch", 1, "reference type");    gc_watch(Pike_sp[-args].u.refs);    pop_n_elems(args);   }      /*! @decl void dump_backlog()    *! @belongs Debug    *!    *! Dumps the 1024 latest executed opcodes, along with the source    *! code lines, to standard error. The backlog is only collected on
pike.git/src/builtin_functions.c:9157:       get_all_args("enumerate", args, "%i%i%i", &n, &step, &start);    if (n<0)    SIMPLE_BAD_ARG_ERROR("enumerate",1,"int(0..)");       pop_n_elems(args);    push_array(d=allocate_array(n));    for (i=0; i<n; i++)    {    ITEM(d)[i].u.integer=start; - #ifdef AUTO_BIGNUM +     if ((step>0 && start+step<start) ||    (step<0 && start+step>start)) /* overflow */    {    pop_stack();    push_int(n);    push_int(step);    convert_stack_top_to_bignum();    push_int(start);    convert_stack_top_to_bignum();    f_enumerate(3);    return;    } - #endif +     start+=step;    }    d->type_field = BIT_INT;    }    else if (args<=3 &&    ((TYPEOF(Pike_sp[1-args]) == T_INT ||    TYPEOF(Pike_sp[1-args]) == T_FLOAT) &&    (TYPEOF(Pike_sp[2-args]) == T_INT ||    TYPEOF(Pike_sp[2-args]) == T_FLOAT) ) )    {
pike.git/src/builtin_functions.c:9243:    }    d->type_field = types;    pop_stack();    stack_pop_n_elems_keep_top(args);    }   }      /*! @module Program    */    +  + /*! @decl string defined(program x, string identifier) +  *! +  *! Returns a string with filename and linenumber where @[idenfifier] +  *! in @[x] was defined. +  *! +  *! Returns @expr{0@} (zero) when no line can be found, e.g. for +  *! builtin functions. +  *! +  *! If @[idenfier] can not be found in @[x] this function returns +  *! where the program is defined. +  */ + PMOD_EXPORT void f_program_identifier_defined(INT32 args) + { +  struct program *p; +  struct pike_string *ident; +  struct program *id_prog, *p2; +  struct identifier *id; +  INT_TYPE line; +  INT_TYPE offset; +  struct pike_string *file = NULL; +  +  if( !(p = program_from_svalue(Pike_sp-args)) ) +  Pike_error("Illegal argument 1 to defined(program,string)\n"); +  +  if( Pike_sp[-args+1].type != PIKE_T_STRING ) +  Pike_error("Illegal argument 2 to defined(program,string)\n"); +  else +  ident = Pike_sp[-args+1].u.string; +  +  if( (offset = find_shared_string_identifier( ident, p )) == -1 ) +  { +  INT_TYPE line; +  struct pike_string *tmp = low_get_program_line(p, &line); +  +  pop_n_elems(args); +  +  if (tmp) +  { +  push_string(tmp); +  if(line >= 1) +  { +  push_constant_text(":"); +  push_int(line); +  f_add(3); +  } +  } +  else +  push_int(0); +  return; +  } +  +  id = ID_FROM_INT(p, offset); +  id_prog = PROG_FROM_INT (p, offset); +  +  if(IDENTIFIER_IS_PIKE_FUNCTION( id->identifier_flags ) && +  id->func.offset != -1) +  file = low_get_line(id_prog->program + id->func.offset, id_prog, &line); +  else if (IDENTIFIER_IS_CONSTANT (id->identifier_flags) && +  id->func.const_info.offset >= 0 && +  (p2 = program_from_svalue (&id_prog->constants[id->func.const_info.offset].sval))) +  file = low_get_program_line (p2, &line); +  else +  /* The program line is better than nothing for C functions. */ +  file = low_get_program_line (p, &line); +  +  if (file) +  { +  pop_n_elems(args); +  if (line) { +  push_string(file); +  push_constant_text(":"); +  push_int(line); +  f_add(3); +  } +  else +  push_string (file); +  return; +  } +  pop_n_elems(args); +  push_int(0); + } +    /*! @decl array(program) inherit_list(program p)    *!    *! Returns an array with the programs that @[p] has inherited.    */   PMOD_EXPORT void f_inherit_list(INT32 args)   {    struct program *p;    struct svalue *arg;    struct object *par;    int parid,e,q=0;
pike.git/src/builtin_functions.c:9533:    ADD_EFUN("allocate", f_allocate,    tFunc(tInt tOr(tVoid,tSetvar(0,tMix)),tArr(tVar(0))), 0);      /* function(mixed:int) */    ADD_EFUN("arrayp", f_arrayp,tFunc(tMix,tInt01),0);      /* function(string...:string) */    ADD_EFUN("combine_path_nt",f_combine_path_nt,tFuncV(tNone,tStr,tStr),0);    ADD_EFUN("combine_path_unix",f_combine_path_unix,tFuncV(tNone,tStr,tStr),0);    ADD_EFUN("combine_path_amigaos",f_combine_path_amigaos,tFuncV(tNone,tStr,tStr),0); - #ifdef __NT__ + #if defined(__NT__) || defined(__OS2__)    ADD_EFUN("combine_path",f_combine_path_nt,tFuncV(tNone,tStr,tStr),0);   #else   #ifdef __amigaos__    ADD_EFUN("combine_path",f_combine_path_amigaos,tFuncV(tNone,tStr,tStr),0);   #else    ADD_EFUN("combine_path",f_combine_path_unix,tFuncV(tNone,tStr,tStr),0);   #endif   #endif       ADD_EFUN("compile", f_compile,    tFunc(tStr tOr(tObj, tVoid) tOr(tInt, tVoid) tOr(tInt, tVoid) tOr(tPrg(tObj), tVoid) tOr(tObj, tVoid) ,tPrg(tObj)),    OPT_EXTERNAL_DEPEND);      /* function(1=mixed:1) */    ADD_EFUN("copy_value",f_copy_value,tFunc(tSetvar(1,tMix),tVar(1)),0);      /* function(string:string)|function(string,string:int) */    ADD_EFUN("crypt",f_crypt, -  tOr(tFunc(tStr,tStr),tFunc(tStr tStr,tInt01)),OPT_EXTERNAL_DEPEND); +  tOr(tFunc(tStr,tStr7),tFunc(tStr tStr,tInt01)),OPT_EXTERNAL_DEPEND);      /* function(object|void:void) */    ADD_EFUN("destruct",f_destruct,tFunc(tOr(tObj,tVoid),tVoid),OPT_SIDE_EFFECT);      /* function(mixed,mixed:int) */    ADD_EFUN("equal",f_equal,tFunc(tMix tMix,tInt01),OPT_TRY_OPTIMIZE);       /* function(array(0=mixed),int|void,int|void:array(0)) */    ADD_FUNCTION2("everynth",f_everynth,    tFunc(tArr(tSetvar(0,tMix)) tOr(tInt,tVoid) tOr(tInt,tVoid),
pike.git/src/builtin_functions.c:9633:    ADD_EFUN("set_weak_flag",f_set_weak_flag,    tFunc(tSetvar(1,tMix) tInt,tVar(1)),OPT_SIDE_EFFECT);       ADD_INT_CONSTANT("PIKE_WEAK_INDICES", PIKE_WEAK_INDICES, 0);    ADD_INT_CONSTANT("PIKE_WEAK_VALUES", PIKE_WEAK_VALUES, 0);      /* function(void|object:object) */    ADD_EFUN("next_object",f_next_object,    tFunc(tOr(tVoid,tObj),tObj),OPT_EXTERNAL_DEPEND);    +  ADD_EFUN("_map_all_objects",f_map_all_objects, +  tFunc(tFunction,tIntPos),OPT_EXTERNAL_DEPEND); +    /* function(string:string)|function(object:object)|function(mapping:mapping)|function(multiset:multiset)|function(program:program)|function(array:array) */    ADD_EFUN("_next",f__next,    tOr6(tFunc(tStr,tStr),    tFunc(tObj,tObj),    tFunc(tMapping,tMapping),    tFunc(tMultiset,tMultiset),    tFunc(tPrg(tObj),tPrg(tObj)),    tFunc(tArray,tArray)),OPT_EXTERNAL_DEPEND);      /* function(object:object)|function(mapping:mapping)|function(multiset:multiset)|function(program:program)|function(array:array) */
pike.git/src/builtin_functions.c:9908: Inside #if defined(PIKE_DEBUG) and #if defined(YYDEBUG)
  /* function(int:int) */    ADD_EFUN("_compiler_trace",f__compiler_trace,    tFunc(tInt,tInt),OPT_SIDE_EFFECT|OPT_EXTERNAL_DEPEND);   #endif /* YYDEBUG */   #endif      /* function(:mapping(string:int)) */    ADD_EFUN("_memory_usage",f__memory_usage,    tFunc(tNone,tMap(tStr,tInt)),OPT_EXTERNAL_DEPEND);    +  ADD_EFUN("_size_object",f__size_object, +  tFunc(tObj,tInt),OPT_EXTERNAL_DEPEND);    -  +    /* function(:int) */    ADD_EFUN("gc",f_gc,tFunc(tNone,tInt),OPT_SIDE_EFFECT);      /* function(:string) */    ADD_EFUN("version", f_version,tFunc(tNone,tStr), OPT_TRY_OPTIMIZE);       /* Note: The last argument to the encode and decode functions is    * intentionally not part of the prototype, to keep it free for    * other uses in the future. */      /* function(mixed,void|object:string) */    ADD_EFUN("encode_value", f_encode_value, -  tFunc(tMix tOr(tVoid,tObj),tStr), OPT_TRY_OPTIMIZE); +  tFunc(tMix tOr(tVoid,tObj),tStr8), OPT_TRY_OPTIMIZE);       /* function(mixed,void|object:string) */    ADD_EFUN("encode_value_canonic", f_encode_value_canonic, -  tFunc(tMix tOr(tVoid,tObj),tStr), OPT_TRY_OPTIMIZE); +  tFunc(tMix tOr(tVoid,tObj),tStr8), OPT_TRY_OPTIMIZE);      /* function(string,void|object:mixed) */    ADD_EFUN("decode_value", f_decode_value,    tFunc(tStr tOr(tVoid,tObj),tMix), OPT_TRY_OPTIMIZE);      /* function(object,string:int) */    ADD_EFUN("object_variablep", f_object_variablep,    tFunc(tObj tStr,tInt), OPT_EXTERNAL_DEPEND);       /* function(array(mapping(int:mixed)):array(int)) */
pike.git/src/builtin_functions.c:10053:    tFunc(tIntPos tFloat tOr3(tVoid,tInt,tFloat),tArr(tFloat)),    tFunc(tIntPos tOr(tInt,tFloat) tFloat,tArr(tFloat)),    tFunc(tIntPos tMix tObj,tArr(tVar(1))),    tFunc(tIntPos tObj tOr(tVoid,tMix),tArr(tVar(1))),    tFunc(tIntPos tMix tMix    tFuncV(tNone,tMix,tSetvar(1,tMix)),tArr(tVar(1)))),    OPT_TRY_OPTIMIZE);       ADD_FUNCTION2("inherit_list", f_inherit_list,    tFunc(tOr(tObj,tPrg(tObj)),tArr(tPrg(tObj))), 0, OPT_TRY_OPTIMIZE); +  ADD_FUNCTION2("program_identifier_defined", f_program_identifier_defined, +  tFunc(tOr(tObj,tPrg(tObj)) tString,tString), 0, OPT_TRY_OPTIMIZE);    ADD_FUNCTION2("function_defined", f_function_defined,    tFunc(tFunction,tString), 0, OPT_TRY_OPTIMIZE);      #ifdef DEBUG_MALLOC      /* function(void:void) */    ADD_EFUN("_reset_dmalloc",f__reset_dmalloc,    tFunc(tVoid,tVoid),OPT_SIDE_EFFECT);    ADD_EFUN("_dmalloc_set_name",f__dmalloc_set_name,    tOr(tFunc(tStr tInt,tVoid), tFunc(tVoid,tVoid)),OPT_SIDE_EFFECT);