pike.git / src / builtin_functions.c

version» Context lines:

pike.git/src/builtin_functions.c:24:   #include "gc.h"   #include "backend.h"   #include "main.h"   #include "pike_memory.h"   #include "threads.h"   #include "time_stuff.h"   #include "version.h"   #include "encode.h"   #include <ctype.h>   #include "module_support.h" - #include "module.h" +    #include "opcodes.h"   #include "cyclic.h"   #include "signal_handler.h"   #include "builtin_functions.h"   #include "bignum.h"   #include "peep.h"   #include "docode.h"   #include "lex.h"   #include "pike_float.h" - #include "stuff.h" +    #include "pike_compiler.h"   #include "port.h"   #include "siphash24.h"      #include <errno.h>      #ifdef HAVE_POLL   #ifdef HAVE_POLL_H   #include <poll.h>   #endif /* HAVE_POLL_H */
pike.git/src/builtin_functions.c:898:    *!    *! @seealso    *! @[call_function()]    */   void f_query_num_arg(INT32 args)   {    pop_n_elems(args);    push_int(Pike_fp ? Pike_fp->args : 0);   }    - /*! @decl int search(string haystack, string|int needle, int|void start) -  *! @decl int search(array haystack, mixed needle, int|void start) + /*! @decl int search(string haystack, string|int needle, int|void start, @ +  *! int|void end) +  *! @decl int search(array haystack, mixed needle, int|void start, int|void end)    *! @decl mixed search(mapping haystack, mixed needle, mixed|void start)    *! @decl mixed search(object haystack, mixed needle, mixed|void start, @    *! mixed ... extra_args)    *!    *! Search for @[needle] in @[haystack].    *!    *! @param haystack    *! Item to search in. This can be one of:    *! @mixed    *! @type string
pike.git/src/builtin_functions.c:941:    *! elements with @[`==()] until a match with @[needle] is found.    *! If @[needle] is found @[haystack] will be advanced to the element,    *! and the iterator index will be returned. If @[needle] is not    *! found, @[haystack] will be advanced to the end.    *! @endmixed    *!    *! @param start    *! If the optional argument @[start] is present search is started at    *! this position. This has no effect on mappings.    *! +  *! @param end +  *! If the optional argument @[end] is present, the search will terminate +  *! at this position (exclusive) if not found earlier. +  *!    *! @returns    *! Returns the position of @[needle] in @[haystack] if found.    *!    *! If not found the returned value depends on the type of @[haystack]:    *! @mixed    *! @type string|array    *! @expr{-1@}.    *! @type mapping|object(Iterator)    *! @[UNDEFINED].    *! @type object
pike.git/src/builtin_functions.c:970:    *! For mappings and object @[UNDEFINED] will be returned when not found.    *! In all other cases @expr{-1@} will be returned when not found.    *!    *! @seealso    *! @[indices()], @[values()], @[zero_type()], @[has_value()],    *! @[has_prefix()], @[has_suffix()]    */   PMOD_EXPORT void f_search(INT32 args)   {    ptrdiff_t start; +  ptrdiff_t end;       if(args < 2)    SIMPLE_WRONG_NUM_ARGS_ERROR("search", 2);       switch(TYPEOF(Pike_sp[-args]))    {    case T_STRING:    {    struct pike_string *haystack = Pike_sp[-args].u.string;       start=0; -  +  end = haystack->len;    if(args > 2)    {    if(TYPEOF(Pike_sp[2-args]) != T_INT)    SIMPLE_ARG_TYPE_ERROR("search", 3, "int");       start=Pike_sp[2-args].u.integer;    if(start<0) { -  bad_arg_error("search", Pike_sp-args, args, 3, "int(0..)", Pike_sp+2-args, +  bad_arg_error("search", args, 3, "int(0..)", Pike_sp+2-args,    "Start must be greater or equal to zero.\n");    } -  +  +  if (args > 3) { +  if(TYPEOF(Pike_sp[3-args]) != T_INT) +  SIMPLE_ARG_TYPE_ERROR("search", 4, "int"); +  +  if (Pike_sp[3-args].u.integer < end) { +  end = Pike_sp[3-args].u.integer; +  if(start<0) { +  bad_arg_error("search", args, 4, "int(0..)", +  Pike_sp+3-args, +  "End must be greater or equal to zero.\n");    } -  +  } +  } +  }       if(haystack->len < start) -  bad_arg_error("search", Pike_sp-args, args, 3, "int(0..)", Pike_sp-args, +  bad_arg_error("search", args, 3, "int(0..)", Pike_sp-args,    "Start must not be greater than the "    "length of the string.\n");    -  +  if (end <= start) { +  pop_n_elems(args); +  push_int(-1); +  return; +  } +     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);    }   
pike.git/src/builtin_functions.c:1022:    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) { +  while (start < end) {    if (str[start] == val) break;    start++;    }    }    break;    case 1:    {    p_wchar1 *str = STR1(haystack);    if (val >= 65536) {    start = -1;    break;    } -  while (start < haystack->len) { +  while (start < end) {    if (str[start] == val) break;    start++;    }    }    break;    case 2:    {    p_wchar2 *str = STR2(haystack); -  while (start < haystack->len) { +  while (start < end) {    if (str[start] == (p_wchar2)val) break;    start++;    }    }    break;    } -  if (start >= haystack->len) { -  start = -1; -  } +     } else if(TYPEOF(Pike_sp[1-args]) == T_STRING) {    /* Handle searching for the empty string. */    if (Pike_sp[1-args].u.string->len) {    start = string_search(haystack,    Pike_sp[1-args].u.string,    start); -  +  end -= Pike_sp[1-args].u.string->len-1;    }    } else {    SIMPLE_ARG_TYPE_ERROR("search", 2, "string | int");    }    pop_n_elems(args); -  +  if (start >= end) { +  start = -1; +  }    push_int64(start);    break;    }       case T_ARRAY:    start=0; -  +  end = Pike_sp[-args].u.array->size;    if(args > 2)    {    if(TYPEOF(Pike_sp[2-args]) != T_INT)    SIMPLE_ARG_TYPE_ERROR("search", 3, "int");       start=Pike_sp[2-args].u.integer;    if(start<0) { -  bad_arg_error("search", Pike_sp-args, args, 3, "int(0..)", Pike_sp+2-args, +  bad_arg_error("search", args, 3, "int(0..)", Pike_sp+2-args,    "Start must be greater or equal to zero.\n");    } -  +  +  if (args > 3) { +  if(TYPEOF(Pike_sp[3-args]) != T_INT) +  SIMPLE_ARG_TYPE_ERROR("search", 4, "int"); +  +  if (Pike_sp[3-args].u.integer < end) { +  end = Pike_sp[3-args].u.integer; +  if(end<0) { +  bad_arg_error("search", args, 4, "int(0..)", +  Pike_sp+3-args, +  "End must be greater or equal to zero.\n");    } -  +  } +  } +  }    start=array_search(Pike_sp[-args].u.array,Pike_sp+1-args,start);    pop_n_elems(args); -  +  if (start >= end) { +  start = -1; +  }    push_int64(start);    break;       case T_MAPPING:    if(args > 2) {    mapping_search_no_free(Pike_sp,Pike_sp[-args].u.mapping,Pike_sp+1-args,Pike_sp+2-args);    } else {    mapping_search_no_free(Pike_sp,Pike_sp[-args].u.mapping,Pike_sp+1-args,0);    }    free_svalue(Pike_sp-args);
pike.git/src/builtin_functions.c:1162:    * On the other hand, the iterator should be false now.    */    push_undefined();    return;    }    pop_n_elems(2);    }    }    }    } -  /* FALL_THROUGH */ +  /* FALLTHRU */    default:    SIMPLE_ARG_TYPE_ERROR("search", 1, "string|array|mapping|object");    }   }      /*! @decl int has_prefix(string|object s, string prefix)    *!    *! Returns @expr{1@} if the string @[s] starts with @[prefix],    *! returns @expr{0@} (zero) otherwise.    *!
pike.git/src/builtin_functions.c:1494:    /* FIXME: It's very sad that we always have to do linear search    with `values' in case of objects. The problem is that we cannot    use `search' directly since it's undefined whether it returns    -1 (array) or 0 (mapping) during e.g. some data type emulation.       Maybe we should use object->_has_value(value) provided that    the object implements it.       /Noring */    -  /* FALL_THROUGH */ +  /* FALLTHRU */       case T_MULTISET:    /* FIXME: This behavior for multisets isn't clean. It should be    * compat only. */    stack_swap();    f_values(1);    stack_swap();    -  /* FALL_THROUGH */ +  /* FALLTHRU */       case T_STRING: /* Strings are odd. /Noring */    case T_ARRAY:    f_search(2);       if(TYPEOF(Pike_sp[-1]) == T_INT)    Pike_sp[-1].u.integer = (Pike_sp[-1].u.integer != -1);    break;       default:
pike.git/src/builtin_functions.c:1876:    struct pike_string *in;    struct pike_string *out = NULL;    ptrdiff_t len, i, num_surrogates = 0;    INT_TYPE byteorder = 0;    int swab=0;    p_wchar1 surr1, surr2, surrmask, *str0;       get_all_args("unicode_to_string", args, "%S.%i", &in, &byteorder);       if (in->len & 1) { -  bad_arg_error("unicode_to_string", Pike_sp-args, args, 1, "string", Pike_sp-args, +  bad_arg_error("unicode_to_string", args, 1, "string", Pike_sp-args,    "String length is odd.\n");    }       if (byteorder >= 2) {    if (byteorder == 2) {   #if PIKE_BYTEORDER == 1234    /* Little endian. */    byteorder = 1;   #else    byteorder = 0;
pike.git/src/builtin_functions.c:2093:    p_wchar2 c = index_shared_string(in,i);    if( (c < 0 || c > 0x10ffff) || (c>0xd7ff && c<0xe000) )    string_builder_append( &out, repl_char, 1 );    else    string_builder_putchar( &out, c );    }    push_string( finish_string_builder( &out ) );    }   }    - /*! @decl string(0..255) string_to_utf8(string s) -  *! @decl string(0..255) string_to_utf8(string s, int extended) + /*! @decl utf8_string string_to_utf8(string s) +  *! @decl utf8_string string_to_utf8(string s, int extended)    *! -  *! Converts a string into an UTF-8 compliant byte-stream. +  *! Convert a string into a UTF-8 compliant byte-stream.    *! -  +  *! @param s +  *! String to encode into UTF-8. +  *! +  *! @param extended +  *! Bitmask with extension options. +  *! @int +  *! @value 1 +  *! Accept and encode the characters outside the valid ranges +  *! using the same algorithm. Such encoded characters are +  *! however not UTF-8 compliant. +  *! @value 2 +  *! Encode characters outside the BMP with UTF-8 encoded UTF-16 +  *! (ie split them into surrogate pairs and encode). +  *! @endint +  *!    *! @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    *! @[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;    INT_TYPE extended = 0;
pike.git/src/builtin_functions.c:2140:       len = pike_string_utf8_length(in, args, extended);       if (len == in->len) {    /* 7bit string -- already valid utf8. */    pop_n_elems(args - 1);    return;    }    out = begin_shared_string(len);    -  dst = pike_string_utf8_encode(STR0(out), in); +  dst = pike_string_utf8_encode(STR0(out), in, extended);   #ifdef PIKE_DEBUG    if (len != dst - STR0(out)) {    Pike_fatal("string_to_utf8(): Calculated and actual lengths differ: "    "%"PRINTPTRDIFFT"d != %"PRINTPTRDIFFT"d\n", len, dst - STR0(out));    }   #endif /* PIKE_DEBUG */    out = end_shared_string(out);    pop_n_elems(args);    push_string(out);   }    - /*! @decl string utf8_to_string(string(0..255) s) -  *! @decl string utf8_to_string(string(0..255) s, int extended) + /*! @decl string utf8_to_string(utf8_string s) +  *! @decl string utf8_to_string(utf8_string s, int extended)    *!    *! Converts an UTF-8 byte-stream into a string.    *!    *! @param s    *! String of UTF-8 encoded data to decode.    *!    *! @param extended    *! Bitmask with extension options.    *! @int    *! @value 1
pike.git/src/builtin_functions.c:2179:    *!    *! @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    *! @[Charset.encoder()], @[string_to_unicode()], @[string_to_utf8()], -  *! @[unicode_to_string()] +  *! @[unicode_to_string()], @[validate_utf8()]    */   PMOD_EXPORT void f_utf8_to_string(INT32 args)   {    struct pike_string *in;    struct pike_string *out;    ptrdiff_t len = 0;    int shift = 0;    INT_TYPE extended = 0;    INT32 min, max;   
pike.git/src/builtin_functions.c:2215:    return;    }       out = pike_string_utf8_decode(STR0(in), (enum size_shift)shift, len);       pop_n_elems(args);       push_string(out);   }    + /*! @decl string validate_utf8(utf8_string s) +  *! @decl string validate_utf8(utf8_string s, int extended) +  *! +  *! Checks whether a string is a valid UTF-8 byte-stream. +  *! +  *! @param s +  *! String of UTF-8 encoded data to validate. +  *! +  *! @param extended +  *! Bitmask with extension options. +  *! @int +  *! @value 1 +  *! Accept the extension used by @[string_to_utf8()], including +  *! lone UTF-16 surrogates. +  *! @value 2 +  *! Accept UTF-8 encoded UTF-16 (ie accept valid surrogate-pairs). +  *! @endint +  *! +  *! @returns +  *! Returns @expr{0@} (zero) if the stream is not a legal +  *! UTF-8 byte-stream, and @expr{1@} if it is. +  *! +  *! @note +  *! In conformance with @rfc{3629@} and Unicode 3.1 and later, +  *! non-shortest forms are considered invalid. +  *! +  *! @seealso +  *! @[Charset.encoder()], @[string_to_unicode()], @[string_to_utf8()], +  *! @[unicode_to_string()], @[utf8_to_string()] +  */ + PMOD_EXPORT void f_validate_utf8(INT32 args) + { +  struct pike_string *in; +  ptrdiff_t i; +  INT_TYPE extended = 0; +  INT32 min, max; +  int ret = 1; +  p_wchar1 expect_low_surrogate = 0; +  +  get_all_args("validate_utf8", args, "%T.%i", &in, &extended); +  +  if (in->size_shift) { +  /* Wide string -- not UTF-8. */ +  pop_n_elems(args); +  push_int(0); +  return; +  } +  +  check_string_range(in, 1, &min, &max); +  +  if (min >= 0 && max <= 0x7f) { +  /* 7bit string -- already valid utf8. */ +  pop_n_elems(args); +  push_int(1); +  return; +  } +  +  for(i=0; ret && (i < in->len); i++) { +  p_wchar0 c = STR0(in)[i]; +  /* NB: unsigned INT64 to handle bit 33. */ +  unsigned INT64 ch; +  unsigned INT64 full_mask = 0x3f; +  unsigned INT64 hi_mask = 0x3e; +  +  /* 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 +  * 000000-00007f 00-7f +  * 000080-0007ff c2-df 80-bf +  * 000800-000fff e0 a0-bf 80-bf +  * 001000-00cfff e1-ec 80-bf 80-bf +  * 00d000-00d7ff ed 80-9f 80-bf +  * 00e000-00ffff ee-ef 80-bf 80-bf +  * 010000-03ffff f0 90-bf 80-bf 80-bf +  * 040000-0fffff f1-f3 80-bf 80-bf 80-bf +  * 100000-10ffff f4 80-8f 80-bf 80-bf +  */ +  +  if (!(c & 0x80)) { +  if (expect_low_surrogate) ret = 0; /* Expected low surrogate. */ +  continue; +  } +  +  if (!(c & 0x40)) { +  /* Invalid continuation char. */ +  ret = 0; +  break; +  } +  +  if (c == 0xff) { +  /* Invalid UTF-8 code-point. */ +  ret = 0; +  break; +  } +  +  ch = c; +  +  while (c & 0x40) { +  /* NB: We rely on the NUL-terminator in pike_strings. */ +  p_wchar0 cc = STR0(in)[++i]; +  if ((cc & 0xc0) != 0x80) { +  /* Expected continuation char. */ +  ret = 0; +  break; +  } +  ch = ch<<6 | (cc & 0x3f); +  full_mask |= full_mask << 5; +  hi_mask <<= 5; +  c <<= 1; +  } +  +  ch = ch & full_mask; +  +  if (!(ch & hi_mask) || (ch < 0x80)) { +  /* The 5 most significant bits of ch are all zero. +  * This means that it was a non-minimal form. +  * +  * Note that a special case is needed for the range 0x40..0x7f. +  */ +  ret = 0; +  break; +  } +  +  if ((ch & ~0x7ff) == 0xd800) { +  /* Surrogate */ +  if (!(extended & 3)) { +  ret = 0; +  break; +  } +  if (!(extended & 1) && ((ch & 0x400) != expect_low_surrogate)) { +  /* Bad surrogate pair. */ +  ret = 0; +  break; +  } +  expect_low_surrogate = (ch & 0x400) ^ 0x400; +  } else if (!(extended & 1) && expect_low_surrogate) { +  ret = 0; +  break; +  } else if (ch >= 0x110000) { +  /* Character out of range. */ +  if (!(extended & 1) || (ch >= (((unsigned INT64)1) << 32))) { +  ret = 0; +  break; +  } +  } +  } +  +  if (!(extended & 1) && expect_low_surrogate) { +  ret = 0; +  } +  +  pop_n_elems(args); +  push_int(ret); + } +    /*! @decl string(0..255) __parse_pike_type(string(0..255) t)    */   static void f_parse_pike_type( INT32 args )   {    struct pike_type *t;       if( !args || TYPEOF(Pike_sp[-1]) != T_STRING ||    Pike_sp[-1].u.string->size_shift )    Pike_error( "__parse_pike_type requires a 8bit string as its first argument\n" );    t = parse_type( (char *)STR0(Pike_sp[-1].u.string) );
pike.git/src/builtin_functions.c:2419:    *!    *! @seealso    *! @[add_constant()]    */   PMOD_EXPORT void f_all_constants(INT32 args)   {    pop_n_elems(args);    ref_push_mapping(get_builtin_constants());   }    + /*! @decl CompilerEnvironment.PikeCompiler get_active_compiler() +  *! +  *! Returns the most recent of the currently active pike compilers, +  *! or @[UNDEFINED] if none is active. +  *! +  *! @note +  *! This function should only be used during a call of @[compile()]. +  *! +  *! @seealso +  *! @[get_active_error_handler()], @[compile()], +  *! @[master()->get_compilation_handler()], @[CompilationHandler] +  */ + PMOD_EXPORT void f_get_active_compiler(INT32 args) + { +  struct compilation *c = NULL; +  +  /* NB: This is an efun, so we need to keep the stack clean. */ +  pop_n_elems(args); +  +  if (compilation_program) { +  struct pike_frame *compiler_frame = Pike_fp; +  +  while (compiler_frame && +  (compiler_frame->context->prog != compilation_program)) { +  compiler_frame = compiler_frame->next; +  } +  +  if (compiler_frame && compiler_frame->current_object->prog) { +  ref_push_object(compiler_frame->current_object); +  return; +  } +  } +  +  push_undefined(); + } +    /*! @decl CompilationHandler get_active_compilation_handler()    *!    *! Returns the currently active compilation compatibility handler, or    *! @tt{0@} (zero) if none is active.    *!    *! @note    *! This function should only be used during a call of @[compile()].    *!    *! @seealso    *! @[get_active_error_handler()], @[compile()],
pike.git/src/builtin_functions.c:2777:    exit(code);   }      /*! @decl int time();    *! @decl int time(int(1..1) one)    *! @decl float time(int(2..) t)    *!    *! This function returns the number of seconds since 00:00:00 UTC, 1 Jan 1970.    *!    *! The second syntax does not query the system for the current -  *! time. Instead the latest done by the pike process is returned -  *! again. That's slightly faster but can be wildly inaccurate. Pike +  *! time, instead the last time value used by the pike process is returned +  *! again. It avoids a system call, and thus is slightly faster, +  *! but can be wildly inaccurate. Pike    *! queries the time internally when a thread has waited for    *! something, typically in @[sleep] or in a backend (see    *! @[Pike.Backend]).    *! -  *! The third syntax can be used to measure time more preciely than one -  *! second. It return how many seconds has passed since @[t]. The precision +  *! The third syntax can be used to measure time more precisely than one +  *! second. It returns how many seconds have passed since @[t]. The precision    *! of this function varies from system to system.    *!    *! @seealso    *! @[ctime()], @[localtime()], @[mktime()], @[gmtime()], -  *! @[System.gettimeofday], @[gethrtime] +  *! @[System.gettimeofday()], @[gethrtime()]    */   PMOD_EXPORT void f_time(INT32 args)   {    struct timeval ret;    if(!args ||    (TYPEOF(Pike_sp[-args]) == T_INT && Pike_sp[-args].u.integer == 0))    {    ACCURATE_GETTIMEOFDAY(&ret);    pop_n_elems(args);    push_int(ret.tv_sec);
pike.git/src/builtin_functions.c:2859:    get_all_args("crypt", args, ".%s%s", &pwd, &saltp);       if( !pwd )    {    do {    push_random_string(16);    push_constant_text("\0");    f_minus(2);    } while(Pike_sp[-1].u.string->len<8);    pwd = Pike_sp[-1].u.string->str; +  args++;    }       if(saltp)    {    if( Pike_sp[1-args].u.string->len < 2 )    {    pop_n_elems(args);    push_int(0);    return;    }
pike.git/src/builtin_functions.c:2931:    i=!strcmp(ret,saltp);    pop_n_elems(args);    push_int(i);    }   }      /*! @decl void destruct(void|object o)    *!    *! Mark an object as destructed.    *! -  *! Calls @expr{o->destroy()@}, and then clears all variables in the +  *! Calls @expr{o->_destruct()@}, and then clears all variables in the    *! object. If no argument is given, the current object is destructed.    *!    *! All pointers and function pointers to this object will become zero.    *! The destructed object will be freed from memory as soon as possible.    */   PMOD_EXPORT void f_destruct(INT32 args)   {    struct object *o;    if(args)    {
pike.git/src/builtin_functions.c:3046:    break;       case T_FUNCTION:    {    struct program *p = program_from_svalue(Pike_sp-args);    if (p) {    a = program_indices(p);    break;    }    } -  /* FALL THROUGH */ +  /* FALLTHRU */       default:    SIMPLE_ARG_TYPE_ERROR("indices", 1,    "string|array|mapping|"    "multiset|object|program|function");    }    pop_n_elems(args);    push_array(a);   }   
pike.git/src/builtin_functions.c:3215: Inside #if defined(PIKE_DEBUG)
  #ifdef PIKE_DEBUG    if (l_flag > 4) {    fprintf(stderr, "Resulting type for arg #%d:\n", argno);    simple_describe_type(types[argno]);    }   #endif /* PIKE_DEBUG */    } else {    copy_pike_type(types[argno], arg->type);    }    argno = !argno; -  /* Handle the special case where CAR & CDR are the same. -  * Only occurrs with SHARED_NODES. -  */ +  /* Handle the special case where CAR & CDR are the same. */    } while (argno && arg->parent && CAR(arg->parent) == CDR(arg->parent));    goto retrace;    }       if (argno) {    yyerror("Odd number of arguments to aggregate_mapping().");    goto done;    }       if (!types[0]) {
pike.git/src/builtin_functions.c:3351:    break;       case T_FUNCTION:    {    struct program *p = program_from_svalue(Pike_sp - args);    if (p) {    a = program_values(p);    break;    }    } -  /* FALL THROUGH */ +  /* FALLTHRU */       default:    SIMPLE_ARG_TYPE_ERROR("values", 1,    "string|array|mapping|multiset|"    "object|program|function");    }    pop_n_elems(args);    push_array(a);   }   
pike.git/src/builtin_functions.c:3447:    break;       case T_FUNCTION:    {    struct program *p = program_from_svalue(Pike_sp-args);    if (p) {    a = program_types(p);    break;    }    } -  /* FALL THROUGH */ +  /* FALLTHRU */       default:    SIMPLE_ARG_TYPE_ERROR("types", 1,    "string|array|mapping|"    "multiset|object|program|function");    }    pop_n_elems(args);    push_array(a);   }   
pike.git/src/builtin_functions.c:4083:    *! different syntaxes do different things as follows:    *!    *! If all the arguments are strings, a copy of @[s] with every    *! occurrence of @[from] replaced with @[to] will be returned.    *! Special case: @[to] will be inserted between every character in    *! @[s] if @[from] is the empty string.    *!    *! If the first argument is a string, and the others array(string), a string    *! with every occurrance of @[from][@i{i@}] in @[s] replaced with    *! @[to][@i{i@}] will be returned. Instead of the arrays @[from] and @[to] -  *! a mapping equvivalent to @expr{@[mkmapping](@[from], @[to])@} can be +  *! a mapping equivalent to @expr{@[mkmapping](@[from], @[to])@} can be    *! used.    *!    *! If the first argument is an array or mapping, the values of @[a] which    *! are @[`==()] with @[from] will be replaced with @[to] destructively.    *! @[a] will then be returned.    *!    *! @note    *! Note that @[replace()] on arrays and mappings is a destructive operation.    */   PMOD_EXPORT void f_replace(INT32 args)
pike.git/src/builtin_functions.c:4591:    while (delay> (tv - t0) * (1.0 / CPU_TIME_TICKS))    tv = get_real_time();    }    }       /* fprintf (stderr, "slept %g\n", (tv - t0) * (1.0 / CPU_TIME_TICKS)); */   }      /*! @decl void sleep(int|float s, void|int abort_on_signal)    *! -  *! This function makes the program stop for @[s] seconds. +  *! This function makes the thread stop for @[s] seconds.    *!    *! Only signal handlers can interrupt the sleep, and only when    *! @[abort_on_signal] is set. If more than one thread is running    *! the signal must be sent to the sleeping thread. Other callbacks    *! are not called during sleep.    *!    *! If @[s] is zero then this thread will yield to other threads but    *! not sleep otherwise. Note that Pike yields internally at regular    *! intervals so it's normally not necessary to do this.    *!
pike.git/src/builtin_functions.c:4633:    pop_n_elems(args);       delaysleep(delay, do_abort_on_signal, 0);   }      #undef FIX_LEFT   #undef TIME_ELAPSED      /*! @decl void delay(int|float s)    *! -  *! This function makes the program stop for @[s] seconds. +  *! This function makes the thread stop for @[s] seconds.    *!    *! Only signal handlers can interrupt the sleep. Other callbacks are    *! not called during delay. Beware that this function uses busy-waiting    *! to achieve the highest possible accuracy.    *!    *! @seealso    *! @[signal()], @[sleep()]    */   PMOD_EXPORT void f_delay(INT32 args)   {
pike.git/src/builtin_functions.c:4691:    *! Normally there is no need to call this function since Pike will    *! call it by itself every now and then. (Pike will try to predict    *! when 20% of all arrays/object/programs in memory is 'garbage'    *! and call this routine then.)    *!    *! @returns    *! The amount of garbage is returned. This is the number of arrays,    *! mappings, multisets, objects and programs that had no nonweak    *! external references during the garbage collection. It's normally    *! the same as the number of freed things, but there might be some -  *! difference since destroy() functions are called during freeing, +  *! difference since _destruct() functions are called during freeing,    *! which can cause more things to be freed or allocated.    *!    *! @seealso    *! @[Pike.gc_parameters], @[Debug.gc_status]    */   void f_gc(INT32 args)   {    ptrdiff_t res = 0;    switch(args? TYPEOF(Pike_sp[-args]): PIKE_T_MIXED) {    case PIKE_T_MAPPING:
pike.git/src/builtin_functions.c:4806:    push_int(1);    return;       case T_FUNCTION:    if(program_from_function(Pike_sp-args))    {    pop_n_elems(args);    push_int(1);    return;    } -  /* FALL_THROUGH */ +  /* FALLTHRU */       default:    pop_n_elems(args);    push_int(0);    }   }      /*! @decl int intp(mixed arg)    *!    *! Returns @expr{1@} if @[arg] is an int, @expr{0@} (zero) otherwise.
pike.git/src/builtin_functions.c:4945:    if(TYPEOF(Pike_sp[-args]) != T_ARRAY)    SIMPLE_ARG_TYPE_ERROR("sort", 1, "array");    a = Pike_sp[-args].u.array;       for(e=1;e<args;e++)    {    if(TYPEOF(Pike_sp[e-args]) != T_ARRAY)    SIMPLE_ARG_TYPE_ERROR("sort", e+1, "array");       if(Pike_sp[e-args].u.array->size != a->size) -  bad_arg_error("sort", Pike_sp-args, args, e+1, "array", Pike_sp+e-args, +  bad_arg_error("sort", args, e+1, "array", Pike_sp+e-args,    "Argument %d has wrong size.\n", (e+1));    }       if(args > 1)    {    order = stable_sort_array_destructively(a);    for(e=1;e<args;e++) order_array(Pike_sp[e-args].u.array,order);    pop_n_elems(args-1);    free(order);    }
pike.git/src/builtin_functions.c:5055: Inside #if defined(PIKE_DEBUG)
     #ifdef PIKE_DEBUG    do_debug(); /* Calls do_gc() since d_flag > 3. */   #else    do_gc(NULL, 1);   #endif    d_flag=tmp;    pop_n_elems(args);   }    - static void encode_struct_tm(struct tm *tm) + static void encode_struct_tm(const struct tm *tm, int gmtoffset)   {    push_static_text("sec");    push_int(tm->tm_sec);    push_static_text("min");    push_int(tm->tm_min);    push_static_text("hour");    push_int(tm->tm_hour);       push_static_text("mday");    push_int(tm->tm_mday);
pike.git/src/builtin_functions.c:5077:    push_int(tm->tm_mon);    push_static_text("year");    push_int(tm->tm_year);       push_static_text("wday");    push_int(tm->tm_wday);    push_static_text("yday");    push_int(tm->tm_yday);    push_static_text("isdst");    push_int(tm->tm_isdst); +  +  push_static_text("timezone"); +  push_int(gmtoffset); +  +  f_aggregate_mapping(20);   }    -  + static void encode_tm_tz(const struct tm*tm) + { +  encode_struct_tm(tm, + #ifdef STRUCT_TM_HAS_GMTOFF +  -tm->tm_gmtoff + #elif defined(STRUCT_TM_HAS___TM_GMTOFF) +  -tm->__tm_gmtoff + #elif defined(HAVE_EXTERNAL_TIMEZONE) +  /* Assume dst is one hour. */ +  timezone - 3600*tm->tm_isdst + #else +  /* Assume dst is one hour. */ +  -3600*tm->tm_isdst + #endif +  ); + } +    /*! @decl mapping(string:int) gmtime(int timestamp)    *!    *! Convert seconds since 00:00:00 UTC, Jan 1, 1970 into components.    *!    *! This function works like @[localtime()] but the result is    *! not adjusted for the local time zone.    *!    *! @seealso -  *! @[localtime()], @[time()], @[ctime()], @[mktime()] +  *! @[localtime()], @[time()], @[ctime()], @[mktime()], +  *! @[strptime()]    */   PMOD_EXPORT void f_gmtime(INT32 args)   {   #if defined (HAVE_GMTIME_R) || defined (HAVE_GMTIME_S)    struct tm tm_s;   #endif    struct tm *tm;    INT64 tt;    time_t t;   
pike.git/src/builtin_functions.c:5116: Inside #if defined(HAVE_GMTIME_R)
  #ifdef HAVE_GMTIME_R    tm = gmtime_r (&t, &tm_s);   #elif defined (HAVE_GMTIME_S)    if (!gmtime_s (&tm_s, &t)) tm = &tm_s; else tm = NULL;   #else    tm = gmtime(&t);   #endif    if (!tm) Pike_error ("gmtime() on this system cannot handle "    "the timestamp %"PRINTINT64"d.\n", (INT64) t);    pop_n_elems(args); -  encode_struct_tm(tm); -  -  push_static_text("timezone"); -  push_int(0); -  f_aggregate_mapping(20); +  encode_struct_tm(tm, 0);   }      /*! @decl mapping(string:int) localtime(int timestamp)    *!    *! Convert seconds since 00:00:00 UTC, 1 Jan 1970 into components.    *!    *! @returns    *! This function returns a mapping with the following components:    *! @mapping    *! @member int(0..60) "sec"
pike.git/src/builtin_functions.c:5147:    *! Day of the month.    *! @member int(0..11) "mon"    *! Month of the year.    *! @member int(0..) "year"    *! Year since 1900.    *! @member int(0..6) "wday"    *! Day of week (0 = Sunday).    *! @member int(0..365) "yday"    *! Day of the year.    *! @member int(0..1) "isdst" -  *! Is daylight savings time. +  *! Is daylight-saving time active.    *! @member int "timezone" -  *! Offset from UTC, including daylight savings time adjustment. +  *! Offset from UTC, including daylight-saving time adjustment.    *! @endmapping    *!    *! An error is thrown if the localtime(2) call failed on the system.    *! It's platform dependent what time ranges that function can handle,    *! e.g. Windows doesn't handle a negative @[timestamp].    *!    *! @note    *! Prior to Pike 7.5 the field @expr{"timezone"@} was sometimes not -  *! present, and was sometimes not adjusted for daylight savings time. +  *! present, and was sometimes not adjusted for daylight-saving time.    *!    *! @seealso -  *! @[Calendar], @[gmtime()], @[time()], @[ctime()], @[mktime()] +  *! @[Calendar], @[gmtime()], @[time()], @[ctime()], @[mktime()], +  *! @[strptime()]    */   PMOD_EXPORT void f_localtime(INT32 args)   {    struct tm *tm;    INT64 tt;    time_t t;       get_all_args("localtime", args, "%l", &tt);      #if SIZEOF_TIME_T < SIZEOF_INT64    if (tt > MAX_TIME_T || tt < MIN_TIME_T)    SIMPLE_ARG_ERROR ("localtime", 1, "Timestamp outside valid range.");   #endif    t = (time_t) tt;       tm = localtime(&t);    if (!tm) Pike_error ("localtime() on this system cannot handle "    "the timestamp %ld.\n", (long) t);    pop_n_elems(args); -  encode_struct_tm(tm); -  -  push_static_text("timezone"); - #ifdef STRUCT_TM_HAS_GMTOFF -  push_int(-tm->tm_gmtoff); - #elif defined(STRUCT_TM_HAS___TM_GMTOFF) -  push_int(-tm->__tm_gmtoff); - #elif defined(HAVE_EXTERNAL_TIMEZONE) -  /* Assume dst is one hour. */ -  push_int(timezone - 3600*tm->tm_isdst); - #else -  /* Assume dst is one hour. */ -  push_int(-3600*tm->tm_isdst); - #endif -  f_aggregate_mapping(20); +  encode_tm_tz(tm);   }    - #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) -  - static const int mon_lengths[2][12] = { -  {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, -  {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} - }; -  - static void normalize_date (struct tm *t) - /* Normalizes t->tm_mday and t->tm_mon. */ + time_t mktime_zone(struct tm *date, int other_timezone, int tz)   { -  int q, year, mon, mday, leap; +  time_t retval; +  int normalised_time;    -  q = t->tm_mon / 12; -  if (t->tm_mon < 0) q--; -  t->tm_mon -= q * 12; -  t->tm_year += q; +  if (tz <= -3600*100 || tz >= 3600*100) +  Pike_error("Invalid timezone specified.\n");    -  year = t->tm_year + 1900; -  leap = isleap (year); -  mon = t->tm_mon; -  mday = t->tm_mday; +  date->tm_wday = -1; /* flag to determine failure */    -  if (mday > 0) { -  int mon_len = mon_lengths[leap][mon]; -  if (mday <= mon_len) return; -  do { -  mday -= mon_len; -  if (++mon == 12) mon = 0, year++, leap = isleap (year); -  } while (mday > (mon_len = mon_lengths[leap][mon])); -  } -  -  else -  do { -  if (mon == 0) mon = 11, year--, leap = isleap (year); -  else mon--; -  mday += mon_lengths[leap][mon]; -  } while (mday < 1); -  -  t->tm_year = year - 1900; -  t->tm_mon = mon; -  t->tm_mday = mday; - } -  - #define CHECKED_DIFF_MULT(RES, A, B, MULT, OVERFLOW) do { \ -  RES = (A - B) * (MULT); \ -  if ((A > B) != (RES > 0)) {OVERFLOW;} \ -  } while (0) -  - #define CHECKED_ADD(ACC, DIFF, OVERFLOW) do { \ -  time_t res_ = ACC + DIFF; \ -  if ((ACC > 0) == (DIFF > 0) && (ACC > 0) != (res_ > 0)) \ -  {OVERFLOW;} \ -  else \ -  ACC = res_; \ -  } while (0) -  - /* Returns the approximate difference in seconds between the -  * two struct tm's. -  */ - static time_t my_tm_diff(const struct tm *t1, const struct tm *t2) +     { -  time_t base, diff; +  int sec, min, hour; +  sec = date->tm_sec; +  min = date->tm_min; +  hour = date->tm_hour;    -  /* Win32 localtime() returns NULL for all dates before Jan 01, 1970. */ -  if (!t2) return -1; -  -  CHECKED_DIFF_MULT (base, t1->tm_year, t2->tm_year, 60*60*24*31*12, -  return base < 0 ? MAX_TIME_T : MIN_TIME_T); -  -  /* Overflow detection not necessary on these fields since we can -  * assume they're all in the valid ranges here. */ -  diff = -  (t1->tm_mon - t2->tm_mon) * (60*60*24*31) + -  (t1->tm_mday - t2->tm_mday) * (60*60*24) + -  (t1->tm_hour - t2->tm_hour) * (60*60) + -  (t1->tm_min - t2->tm_min) * 60 + -  (t1->tm_sec - t2->tm_sec); -  -  CHECKED_ADD (base, diff, -  return diff < 0 ? MIN_TIME_T : MAX_TIME_T); -  -  return base; +  min += sec / 60; +  if ((sec %= 60) < 0) +  min--, sec += 60; +  hour += min / 60; +  if ((min %= 60) < 0) +  hour--, min += 60; +  if ((hour %= 24) < 0) +  hour += 24; +  normalised_time = ((hour * 60) + min) * 60 + sec;    }    - typedef struct tm *time_fn (const time_t *); -  - /* Inverse operation of gmtime or localtime. Unlike mktime(3), this -  * doesn't fill in a normalized time in target_tm. -  */ - static int my_time_inverse (struct tm *target_tm, time_t *result, time_fn timefn) - { -  struct tm norm_tm = *target_tm; -  time_t current_ts = 0; -  time_t displacement; -  time_t diff_ts, old_diff_ts = 0; -  int loop_cnt, tried_dst_displacement = 0; -  - #ifdef DEBUG_MY_TIME_INVERSE -  fprintf (stderr, "target: y %d m %d d %d h %d m %d isdst %d\n", -  target_tm->tm_year, target_tm->tm_mon, target_tm->tm_mday, -  target_tm->tm_hour, target_tm->tm_min, target_tm->tm_isdst); +  retval = mktime(date); +  if (date->tm_wday < 0) { +  if (other_timezone) { +  /* NB: This happens for times near {MIN,MAX}_TIME_T. */ +  const char *orig_tz = getenv("TZ"); +  char tzbuf[20]; +  ONERROR uwp; +  char *tzsgn = tz < 0 ? "-" : "+"; +  if (tz < 0) tz = -tz; +  sprintf(tzbuf, "TZ=UTC%s%02d:%02d:%02d", +  tzsgn, +  tz/3600, +  (tz/60)%60, +  tz % 60); +  putenv(tzbuf); +  if (!orig_tz) { + #ifdef PUTENV_ALWAYS_REQUIRES_EQUAL +  orig_tz = "TZ="; + #else +  orig_tz = "TZ";   #endif -  -  /* An hour, minute or second value outside the valid range is -  * treated as a displacement rather than an absolute time spec. We -  * therefore zero them in the target time spec and add the -  * displacement seconds back to the time_t afterwards. This way we -  * don't need to worry about them in the date normalization. */ -  -  /* It's quicker to always move the seconds to the displacement. It -  * works just as well and we don't need to consider leap seconds. */ -  displacement = norm_tm.tm_sec; -  norm_tm.tm_sec = 0; -  -  /* Bug: The following conversions to seconds ought to compensate for -  * leap seconds. That should only happen if timefn takes leap -  * seconds into account however, which it might not do. */ -  if (norm_tm.tm_min < 0 || norm_tm.tm_min >= 60) { -  time_t d; -  CHECKED_DIFF_MULT (d, norm_tm.tm_min, 0, 60, return 0); -  CHECKED_ADD (displacement, d, return 0); -  norm_tm.tm_min = 0; +     } -  if (norm_tm.tm_hour < 0 || norm_tm.tm_hour >= 60) { -  time_t d; -  CHECKED_DIFF_MULT (d, norm_tm.tm_hour, 0, 60*60, return 0); -  CHECKED_ADD (displacement, d, return 0); -  norm_tm.tm_hour = 0; +  SET_ONERROR(uwp, putenv, orig_tz); +  /* NB: No need to call tzset(); mktime() will call it. */ +  retval = mktime_zone(date, 0, 0); +  CALL_AND_UNSET_ONERROR(uwp); +  return retval;    } -  +  Pike_error("Time conversion unsuccessful.\n"); +  }    -  /* Normalize the date. This is necessary since the simplistic diff -  * calculation in my_tm_diff doesn't work on invalid dates like -  * November 100th or March -10th. (Can't use the displacement -  * variable for an invalid tm_mday since the number of seconds per -  * day isn't constant.) */ -  normalize_date (&norm_tm); - #ifdef DEBUG_MY_TIME_INVERSE -  fprintf (stderr, "normalized: y %d m %d d %d h %d m %d isdst %d\n" -  "displacement: %ld\n", -  norm_tm.tm_year, norm_tm.tm_mon, norm_tm.tm_mday, -  norm_tm.tm_hour, norm_tm.tm_min, norm_tm.tm_isdst, -  (long) displacement); - #endif +  if(other_timezone) +  { +  normalised_time -= ((date->tm_hour * 60) + date->tm_min) * 60 + date->tm_sec; +  if (normalised_time < -12*60*60) +  normalised_time += 24*60*60; +  else if (normalised_time > 12*60*60) +  normalised_time -= 24*60*60;    -  /* This loop seems stable, and usually converges in two passes. -  * The loop counter is for paranoia reasons. + #ifdef STRUCT_TM_HAS___TM_GMTOFF +  retval += date->__tm_gmtoff; + #elif defined(STRUCT_TM_HAS_GMTOFF) +  retval += date->tm_gmtoff; + #elif defined(HAVE_EXTERNAL_TIMEZONE) && defined(HAVE_EXTERNAL_ALTZONE) +  if (date->tm_isdst) { +  retval -= altzone; +  } else { +  retval -= timezone; +  } + #else +  { +  /* NB: The tm from gmtime(3F) will always have tm_isdst == 0, +  * but mktime() is always in the local time zone, and will +  * adjust it and tm_hour if the local time zone is in dst. +  * This causes an error of typically one hour in dst when +  * used without preadjustment.    */ -  for (loop_cnt = 0; loop_cnt < 20; loop_cnt++, old_diff_ts = diff_ts) { -  struct tm *current_tm = timefn(&current_ts); - #ifdef DEBUG_MY_TIME_INVERSE -  fprintf (stderr, "curr: y %d m %d d %d h %d m %d isdst %d\n", -  current_tm->tm_year, current_tm->tm_mon, current_tm->tm_mday, -  current_tm->tm_hour, current_tm->tm_min, current_tm->tm_isdst); - #endif -  -  diff_ts = my_tm_diff (&norm_tm, current_tm); - #ifdef DEBUG_MY_TIME_INVERSE -  fprintf (stderr, "diff: %ld\n", (long) diff_ts); - #endif -  -  if (!current_tm) { - #ifdef DEBUG_MY_TIME_INVERSE -  fprintf (stderr, "outside range for timefn().\n"); - #endif -  return 0; +  struct tm gmt_tm = *gmtime(&retval); +  gmt_tm.tm_isdst = date->tm_isdst; +  normalised_time += retval - mktime(&gmt_tm);    } -  -  if (!diff_ts) { -  /* Got a satisfactory time, but if norm_tm has an opinion on -  * DST we should check if we can return an alternative in the -  * same DST zone, to cope with the overlapping DST adjustment at -  * fall. */ -  if (norm_tm.tm_isdst >= 0 && -  norm_tm.tm_isdst != current_tm->tm_isdst && -  !tried_dst_displacement) { -  /* Offset the time a day and iterate some more (only once -  * more, really), so that we approach the target time from the -  * right direction. */ -  if (norm_tm.tm_isdst) -  current_ts -= 24 * 3600; -  else -  current_ts += 24 * 3600; -  tried_dst_displacement = 1; - #ifdef DEBUG_MY_TIME_INVERSE -  fprintf (stderr, "dst displacement\n"); +    #endif -  continue; +  retval += normalised_time + tz;    } -  break; +  return retval;   }    -  if (diff_ts == -old_diff_ts) { -  /* We're oscillating. Shouldn't happen since norm_tm ought to be -  * valid. */ - #ifdef DEBUG_MY_TIME_INVERSE -  fprintf (stderr, "oscillation detected: %ld <-> %ld\n", -  (long) old_diff_ts, (long) diff_ts); - #endif -  return 0; + static void unwind_tm() + { +  push_static_text("sec"); +  push_static_text("min"); +  push_static_text("hour"); +  push_static_text("mday"); +  push_static_text("mon"); +  push_static_text("year"); +  push_static_text("isdst"); +  push_static_text("timezone"); +  f_aggregate(8); +  f_rows(2); +  Pike_sp--; +  dmalloc_touch_svalue(Pike_sp); +  push_array_items(Pike_sp->u.array);   }    -  /* It's ok to not add the full diff here since we're looping. Do -  * this since the diff calculation can overshoot the target -  * time. */ -  CHECKED_ADD (current_ts, diff_ts, { -  if (diff_ts > 0 && current_ts < MAX_TIME_T) -  current_ts = MAX_TIME_T; -  else if (diff_ts < 0 && current_ts > MIN_TIME_T) -  current_ts = MIN_TIME_T; -  else -  return 0; -  }); -  } + static int get_tm(const char *fname, int args, struct tm *date) + { +  INT_TYPE sec, min, hour, mday, mon, year; +  INT_TYPE isdst = -1, tz = 0;    -  CHECKED_ADD (current_ts, displacement, return 0); +  get_all_args(fname, args, "%i%i%i%i%i%i.%i%i", +  &sec, &min, &hour, &mday, &mon, &year, &isdst, &tz);    -  *result = current_ts; -  return 1; +  memset(date, 0, sizeof(*date)); +  date->tm_sec = sec; +  date->tm_min = min; +  date->tm_hour = hour; +  date->tm_mday = mday; +  date->tm_mon = mon; +  date->tm_year = year; +  date->tm_isdst = isdst; + #ifdef NULL_IS_SPECIAL +  date->tm_zone = NULL; + #endif +  return tz;   }      /*! @decl int mktime(mapping(string:int) tm)    *! @decl int mktime(int sec, int min, int hour, int mday, int mon, int year, @    *! int|void isdst, int|void tz)    *!    *! This function converts information about date and time into an integer    *! which contains the number of seconds since 00:00:00 UTC, Jan 1, 1970.    *!    *! You can either call this function with a mapping containing the
pike.git/src/builtin_functions.c:5440:    *! @member int(0..59) "min"    *! Minutes over the hour.    *! @member int(0..23) "hour"    *! Hour of the day.    *! @member int(1..31) "mday"    *! Day of the month.    *! @member int(0..11) "mon"    *! Month of the year.    *! @member int(0..) "year"    *! Year since 1900. -  *! @member int(0..1) "isdst" -  *! Is daylight savings time. +  *! @member int(-1..1) "isdst" +  *! Is daylight-saving time active. If omitted or set to @expr{-1@}, +  *! it means that the information is not available.    *! @member int "timezone" -  *! The timezone offset from UTC in seconds. If left out, the time +  *! The timezone offset from UTC in seconds. If omitted, the time    *! will be calculated in the local timezone.    *! @endmapping    *!    *! Or you can just send them all on one line as the second syntax suggests.    *!    *! @note -  +  *! For proper UTC calculations ensure that @expr{isdst = 0@} @b{and@} +  *! @expr{timezone = 0@}; omitting either one of these parameters +  *! @b{will@} mess up the UTC calculation. +  *! +  *! @note    *! On some operating systems (notably AIX and Win32), dates before    *! 00:00:00 UTC, Jan 1, 1970 are not supported.    *! -  *! On most systems, the supported range of dates are Dec 13, 1901 -  *! 20:45:52 UTC through Jan 19, 2038 03:14:07 UTC (inclusive). +  *! On most 32-bit systems, the supported range of dates is from Dec 13, 1901 +  *! 20:45:52 UTC through to Jan 19, 2038 03:14:07 UTC (inclusive).    *! -  +  *! On most 64-bit systems, the supported range of dates is expressed +  *! in 56 bits and is thus practically +  *! unlimited (at least up to 1141 milion years in the past +  *! and into the future). +  *!    *! @seealso -  *! @[time()], @[ctime()], @[localtime()], @[gmtime()] +  *! @[time()], @[ctime()], @[localtime()], @[gmtime()], @[strftime()]    */   PMOD_EXPORT void f_mktime (INT32 args)   { -  INT_TYPE sec, min, hour, mday, mon, year; -  INT_TYPE isdst = -1, tz = 0; +     struct tm date;    time_t retval; -  +  int normalised_time, tz;       if (args<1)    SIMPLE_WRONG_NUM_ARGS_ERROR("mktime", 1);       if(args == 1)    { -  memset(&date, 0, sizeof(date)); -  -  push_static_text("sec"); -  push_static_text("min"); -  push_static_text("hour"); -  push_static_text("mday"); -  push_static_text("mon"); -  push_static_text("year"); -  push_static_text("isdst"); -  push_static_text("timezone"); -  f_aggregate(8); -  f_rows(2); -  Pike_sp--; -  dmalloc_touch_svalue(Pike_sp); -  push_array_items(Pike_sp->u.array); -  -  args=8; +  unwind_tm(); +  args += 7;    }    -  get_all_args("mktime",args, "%i%i%i%i%i%i.%i%i", -  &sec, &min, &hour, &mday, &mon, &year, &isdst, &tz); +  tz = get_tm("mktime", args, &date);    -  memset(&date, 0, sizeof(date)); -  date.tm_sec=sec; -  date.tm_min=min; -  date.tm_hour=hour; -  date.tm_mday=mday; -  date.tm_mon=mon; -  date.tm_year=year; -  date.tm_isdst=isdst; +  retval = mktime_zone(&date, +  args > 7 && SUBTYPEOF(Pike_sp[7-args]) == NUMBER_NUMBER, +  tz);    -  /* date.tm_zone = NULL; */ -  -  if((args > 7) && (SUBTYPEOF(Pike_sp[7-args]) == NUMBER_NUMBER)) -  { -  /* UTC-relative time. Use gmtime. */ -  if (!my_time_inverse (&date, &retval, gmtime)) -  PIKE_ERROR("mktime", "Time conversion failed.\n", Pike_sp, args); -  retval += tz; -  } else -  -  { -  retval = mktime(&date); -  if (retval == -1) -  { -  /* mktime might fail on dates before 1970 (e.g. GNU libc 2.3.2), -  * so try our own inverse function with localtime. -  * -  * Note that localtime on Win32 will also fail for dates before 1970. -  */ -  if (!my_time_inverse (&date, &retval, localtime)) -  PIKE_ERROR("mktime", "Time conversion unsuccessful.\n", Pike_sp, args); -  } -  } -  +     pop_n_elems(args);   #if SIZEOF_TIME_T > SIZEOF_INT_TYPE    push_int64 (retval);   #else    push_int(retval);   #endif   }    -  + #ifdef HAVE_STRPTIME + /*! @decl mapping(string:int) strptime(string(1..255) data, string(1..255) format) +  *! +  *! Parse the given @[data] using the format in @[format] as a date. +  *! +  *! @dl +  *! @item %% +  *! The % character. +  *! +  *! @item %a or %A +  *! The weekday name according to the C locale, in abbreviated +  *! form or the full name. +  *! +  *! @item %b or %B or %h +  *! The month name according to the C locale, in abbreviated form +  *! or the full name. +  *! +  *! @item %c +  *! The date and time representation for the C locale. +  *! +  *! @item %C +  *! The century number (0-99). +  *! +  *! @item %d or %e +  *! The day of month (1-31). +  *! +  *! @item %D +  *! Equivalent to %m/%d/%y. +  *! +  *! @item %H +  *! The hour (0-23). +  *! +  *! @item %I +  *! The hour on a 12-hour clock (1-12). +  *! +  *! @item %j +  *! The day number in the year (1-366). +  *! +  *! @item %m +  *! The month number (1-12). +  *! +  *! @item %M +  *! The minute (0-59). +  *! +  *! @item %n +  *! Arbitrary whitespace. +  *! +  *! @item %p +  *! The C locale's equivalent of AM or PM. +  *! +  *! @item %R +  *! Equivalent to %H:%M. +  *! +  *! @item %S +  *! The second (0-60; 60 may occur for leap seconds; +  *! earlier also 61 was allowed). +  *! +  *! @item %t +  *! Arbitrary whitespace. +  *! +  *! @item %T +  *! Equivalent to %H:%M:%S. +  *! +  *! @item %U +  *! The week number with Sunday the first day of the week (0-53). +  *! +  *! @item %w +  *! The weekday number (0-6) with Sunday = 0. +  *! +  *! @item %W +  *! The week number with Monday the first day of the week (0-53). +  *! +  *! @item %x +  *! The date, using the C locale's date format. +  *! +  *! @item %X +  *! The time, using the C locale's time format. +  *! +  *! @item %y +  *! The year within century (0-99). When a century is not +  *! otherwise specified, values in the range 69-99 refer to years +  *! in the twentieth century (1969-1999); values in the range +  *! 00-68 refer to years in the twenty-first century (2000-2068). +  *! +  *! @item %Y +  *! The year, including century (for example, 1991). +  *! @enddl +  *! +  *! @seealso +  *! @[localtime()], @[gmtime()], @[strftime()] +  */ + PMOD_EXPORT void f_strptime (INT32 args) + { +  struct tm tm; +  const char* ret; +  if (Pike_sp[-1].u.string->size_shift || Pike_sp[-2].u.string->size_shift) +  Pike_error("Only 8bit strings are supported\n"); +  memset(&tm, 0, sizeof(tm)); +  ret = strptime(Pike_sp[-2].u.string->str, Pike_sp[-1].u.string->str, &tm); +  pop_n_elems(args); +  if (ret) +  encode_tm_tz(&tm); +  else +  push_int(0); + } + #endif /* HAVE_STRPTIME */ + /*! @decl string(1..255) strftime( string(1..255) format, mapping(string:int) tm) +  *! +  *! Convert the structure to a string. +  *! +  *! @dl +  *! @item %a +  *! The abbreviated weekday name according to the current locale +  *! +  *! @item %A +  *! The full weekday name according to the current locale. +  *! +  *! @item %b +  *! The abbreviated month name according to the current locale. +  *! +  *! @item %B +  *! The full month name according to the current locale. +  *! +  *! @item %c +  *! The preferred date and time representation for the current locale. +  *! +  *! @item %C +  *! The century number (year/100) as a 2-digit integer. +  *! +  *! @item %d +  *! The day of the month as a decimal number (range 01 to 31). +  *! +  *! @item %D +  *! Equivalent to @expr{%m/%d/%y@}. (for Americans only. +  *! Americans should note that in other countries @expr{%d/%m/%y@} +  *! is rather common. This means that in international context +  *! this format is ambiguous and should not be used.) +  *! +  *! @item %e +  *! Like @expr{%d@}, the day of the month as a decimal number, +  *! but a leading zero is replaced by a space. +  *! +  *! @item %E +  *! Modifier: use alternative format, see below. +  *! +  *! @item %F +  *! Equivalent to %Y-%m-%d (the ISO 8601 date format). (C99) +  *! +  *! @item %G +  *! The ISO 8601 week-based year (see NOTES) with century as a +  *! decimal number. The 4-digit year corresponding to the ISO +  *! week number (see @expr{%V@}). This has the same format and +  *! value as @expr{%Y@}, except that if the ISO week number +  *! belongs to the previous or next year, that year is used instead. +  *! +  *! @item %g +  *! Like @expr{%G@}, but without century, that is, +  *! with a 2-digit year (00-99). (TZ) +  *! +  *! @item %h +  *! Equivalent to %b. +  *! +  *! @item %H +  *! The hour as a decimal number using a 24-hour clock (range 00 to 23). +  *! +  *! @item %I +  *! The hour as a decimal number using a 12-hour clock (range 01 to 12). +  *! +  *! @item %j +  *! The day of the year as a decimal number (range 001 to 366). +  *! +  *! @item %k +  *! The hour (24-hour clock) as a decimal number (range 0 to 23); +  *! single digits are preceded by a blank. (See also @expr{%H@}.) +  *! +  *! @item %l +  *! The hour (12-hour clock) as a decimal number (range 1 to 12); +  *! single digits are preceded by a blank. (See also @expr{%I@}.) +  *! +  *! @item %m +  *! The month as a decimal number (range 01 to 12). +  *! +  *! @item %M +  *! The minute as a decimal number (range 00 to 59). +  *! +  *! @item %n +  *! A newline character. (SU) +  *! +  *! @item %O +  *! Modifier: use alternative format, see below. (SU) +  *! +  *! @item %p +  *! Either @expr{"AM"@} or @expr{"PM"@} according to the given time +  *! value, or the corresponding strings for the current locale. +  *! Noon is treated as @expr{"PM"@} and midnight as @expr{"AM"@}. +  *! +  *! @item %P +  *! Like @expr{%p@} but in lowercase: @expr{"am"@} or @expr{"pm"@} +  *! or a corresponding string for the current locale. +  *! +  *! @item %r +  *! The time in a.m. or p.m. notation. In the POSIX locale this is +  *! equivalent to @expr{%I:%M:%S %p@}. +  *! +  *! @item %R +  *! The time in 24-hour notation (@expr{%H:%M@}). (SU) +  *! For a version including the seconds, see @expr{%T@} below. +  *! +  *! @item %s +  *! The number of seconds since the Epoch, +  *! 1970-01-01 00:00:00 +0000 (UTC). (TZ) +  *! +  *! @item %S +  *! The second as a decimal number (range 00 to 60). +  *! (The range is up to 60 to allow for occasional leap seconds.) +  *! +  *! @item %t +  *! A tab character. (SU) +  *! +  *! @item %T +  *! The time in 24-hour notation (@expr{%H:%M:%S@}). (SU) +  *! +  *! @item %u +  *! The day of the week as a decimal, range 1 to 7, Monday being 1. +  *! See also @expr{%w@}. (SU) +  *! +  *! @item %U +  *! The week number of the current year as a decimal number, +  *! range 00 to 53, starting with the first Sunday as the first +  *! day of week 01. See also @expr{%V@} and @expr{%W@}. +  *! +  *! @item %V +  *! The ISO 8601 week number of the current year as a decimal number, +  *! range 01 to 53, where week 1 is the first week that has at least +  *! 4 days in the new year. See also @expr{%U@} and @expr{%W@}. +  *! +  *! @item %w +  *! The day of the week as a decimal, range 0 to 6, Sunday being 0. +  *! See also @expr{%u@}. +  *! @enddl +  *! +  *! @seealso +  *! @[ctime()], @[mktime()], @[strptime()], @[Gettext.setlocale] +  */ + PMOD_EXPORT void f_strftime (INT32 args) + { +  char buffer[8192]; +  struct tm date; +  buffer[0] = 0; +  +  unwind_tm(); +  get_tm("strftime", 8, &date); +  pop_n_elems(8); +  if (Pike_sp[-1].u.string->size_shift) +  Pike_error("Only 8bit strings are supported\n"); +  +  strftime(buffer, sizeof(buffer), Pike_sp[-1].u.string->str, &date); +  +  pop_stack(); +  push_text( buffer ); + } +    #define DOES_MATCH_CLASS(EXTRACT_M,EXTRACT_S,ML) \    { \    unsigned against = EXTRACT_S; \    int inverted=0,matched=0; \    j++; \    i++; \    if(EXTRACT_M == '!' || EXTRACT_M == '^') \    { \    i++; \    inverted=1; \
pike.git/src/builtin_functions.c:5611:    }    return 0;          case '[':    DOES_MATCH_CLASS(m[i],s[j],ml);    break;       case '\\':    if (++i==ml) return 0; -  /* falthrough */ +  /* FALLTHRU */       default:    if(j>=sl || m[i] != s[j] )    return 0;    j++;    }    }    return j==sl;   }   
pike.git/src/builtin_functions.c:5658:    }    return 0;          case '[':    DOES_MATCH_CLASS(m[i],s[j],ml);    break;       case '\\':    if (++i==ml) return 0; -  /* falthrough */ +  /* FALLTHRU */       default:    if(j>=sl || m[i] != s[j] )    return 0;    j++;    }    }    return j==sl;   }   
pike.git/src/builtin_functions.c:5698:    return 1;       return 0;       case '[':    DOES_MATCH_CLASS(index_shared_string(m,i),index_shared_string(s,j),m->len);    break;       case '\\':    if (++i==m->len) return 0; -  /* falthrough */ +  /* FALLTHRU */    default:    if(j>=s->len ||    index_shared_string(m,i)!=index_shared_string(s,j)) return 0;    j++;    }    }    return j==s->len;   }      static int does_match(struct pike_string *s,int j,
pike.git/src/builtin_functions.c:5868:    */   static void f_interleave_array(INT32 args)   {    struct array *arr = NULL;    struct array *min = NULL;    struct array *order = NULL;    int max = 0;    int nelems = 0;    int i;    -  get_all_args("interleave_array", args, "%a", &arr); +  get_all_args(NULL, args, "%a", &arr);       /* We're not interrested in any other arguments. */    pop_n_elems(args-1);       if( (arr->type_field & ~BIT_MAPPING) &&    (array_fix_type_field(arr) & ~BIT_MAPPING) )    SIMPLE_ARG_TYPE_ERROR("interleave_array", 1, "array(mapping(int:mixed))");       /* The order array */    ref_push_array(arr);
pike.git/src/builtin_functions.c:6114:    *! ordered sequence of elements in the array.    *!    *! @seealso    *! @[diff()]    */   static void f_longest_ordered_sequence(INT32 args)   {    struct array *a = NULL;    struct array *aa = NULL;    -  get_all_args("longest_ordered_sequence", args, "%a", &a); +  get_all_args(NULL, args, "%a", &a);       /* THREADS_ALLOW(); */       aa = longest_ordered_sequence(a);       /* THREADS_DISALLOW(); */       if (!aa) {    SIMPLE_OUT_OF_MEMORY_ERROR("longest_ordered_sequence",    (int)sizeof(int *)*a->size*2);
pike.git/src/builtin_functions.c:6805:    *!    *! @seealso    *! @[shuffle()]    */   PMOD_EXPORT void f_permute( INT32 args )   {    INT_TYPE q, i=0, n;    struct array *a;    struct svalue *it;    -  get_all_args("permute", args, "%a%+", &a, &n); +  get_all_args(NULL, args, "%a%+", &a, &n);       if( a->refs>1 )    {    a = copy_array( a );    push_array( a );    }    else    pop_n_elems(args-1);       q = a->size;
pike.git/src/builtin_functions.c:6854:    *! @[String.fuzzymatch()]    */   PMOD_EXPORT void f_diff(INT32 args)   {    struct array *seq;    struct array *cmptbl;    struct array *diff;    struct array *a, *b;    int uniq;    -  get_all_args("diff", args, "%a%a", &a, &b); +  get_all_args(NULL, args, "%a%a", &a, &b);       if ((a == b) || !a->size || !b->size) {    if (!a->size && !b->size) {    /* Both arrays are empty. */    ref_push_array(a);    ref_push_array(b);    f_aggregate(2);    } else {    /* The arrays are equal or one of them is empty. */    ref_push_array(a);
pike.git/src/builtin_functions.c:6926:    *! @}    *!    *! @seealso    *! @[diff()], @[diff_longest_sequence()], @[String.fuzzymatch()]    */   PMOD_EXPORT void f_diff_compare_table(INT32 args)   {    struct array *a;    struct array *b;    -  get_all_args("diff_compare_table", args, "%a%a", &a, &b); +  get_all_args(NULL, args, "%a%a", &a, &b);       push_array(diff_compare_table(a, b, NULL));   }      /*! @decl array(int) diff_longest_sequence(array a, array b)    *!    *! Gives the longest sequence of indices in @[b] that have corresponding    *! values in the same order in @[a].    *!    *! @seealso    *! @[diff()], @[diff_compare_table()], @[String.fuzzymatch()]    */   PMOD_EXPORT void f_diff_longest_sequence(INT32 args)   {    struct array *a;    struct array *b;    struct array *cmptbl;    -  get_all_args("diff_longest_sequence", args, "%a%a", &a, &b); +  get_all_args(NULL, args, "%a%a", &a, &b);       cmptbl = diff_compare_table(a, b, NULL);    push_array(cmptbl);       push_array(diff_longest_sequence(cmptbl, b->size));   }      /*! @decl array(int) diff_dyn_longest_sequence(array a, array b)    *!    *! Gives the longest sequence of indices in @[b] that have corresponding
pike.git/src/builtin_functions.c:6972:    *! @seealso    *! @[diff_longest_sequence()], @[diff()], @[diff_compare_table()],    *! @[String.fuzzymatch()]    */   PMOD_EXPORT void f_diff_dyn_longest_sequence(INT32 args)   {    struct array *a;    struct array *b;    struct array *cmptbl;    -  get_all_args("diff_dyn_longest_sequence", args, "%a%a", &a, &b); +  get_all_args(NULL, args, "%a%a", &a, &b);       cmptbl=diff_compare_table(a, b, NULL);    push_array(cmptbl);       push_array(diff_dyn_longest_sequence(cmptbl, b->size));   }      /*! @endmodule    */   
pike.git/src/builtin_functions.c:7113:    push_static_text(#TYPE "_bytes"); \    push_ulongest(size); \    } while(0)       COUNT(array);    COUNT(ba_mixed_frame);    COUNT(callable);    COUNT(callback);    COUNT(catch_context);    COUNT(compat_cb_box); -  COUNT(destroy_called_mark); +  COUNT(destruct_called_mark);    COUNT(gc_rec_frame);    COUNT(mapping); -  COUNT(marker); +     COUNT(mc_marker);    COUNT(multiset);    COUNT(node_s);    COUNT(object);    COUNT(pike_frame);    COUNT(pike_list_node);    COUNT(pike_type);    COUNT(program);    COUNT(string);   #ifdef PIKE_DEBUG
pike.git/src/builtin_functions.c:7236:    {    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; +  +  /* NB: We added s to the mapping above the switch, so we should +  * always find something here, but... +  */ +  x = low_mapping_lookup(*m, s); +  assert(x); +  assert(TYPEOF(*x) == PIKE_T_INT); +  assert(!SUBTYPEOF(*x)); +  x->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    *!    *!
pike.git/src/builtin_functions.c:7362:   PMOD_EXPORT void f_replace_master(INT32 args)   {    struct object *new_master;       if(!args)    SIMPLE_WRONG_NUM_ARGS_ERROR("replace_master", 1);    if(TYPEOF(Pike_sp[-args]) != T_OBJECT)    SIMPLE_ARG_TYPE_ERROR("replace_master", 1, "object");    new_master = Pike_sp[-args].u.object;    if(!new_master->prog) -  bad_arg_error("replace_master", Pike_sp-args, args, 1, "object", Pike_sp-args, +  bad_arg_error("replace_master", 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, +  bad_arg_error("replace_master", args, 1, "object", Pike_sp-args,    "Subtyped master objects are not supported yet.\n");       push_static_text ("is_pike_master");    args++;    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);   
pike.git/src/builtin_functions.c:7555:    *! @note    *! The actual accuracy on many systems is significantly less than    *! microseconds or nanoseconds. See @[System.REAL_TIME_RESOLUTION].    *!    *! @seealso    *! @[_disable_threads()], @[gethrtime()]    */   static void f_gethrdtime(INT32 args)   {    int nsec = args && !UNSAFE_IS_ZERO(Pike_sp-args); -  cpu_time_t time = threads_disabled_acc_time; -  pop_n_elems(args); -  +  cpu_time_t time; + #ifdef PIKE_THREADS +  time = threads_disabled_acc_time;    if (threads_disabled) {    time += get_real_time() - threads_disabled_start;    } -  + #else +  time = get_real_time(); + #endif +  pop_n_elems(args); +     if (nsec) {    push_int64(time);   #ifndef LONG_CPU_TIME    push_int(1000000000 / CPU_TIME_TICKS);    o_multiply();   #endif    } else {   #if CPU_TIME_TICKS_LOW > 1000000    push_int64(time / (CPU_TIME_TICKS / 1000000));   #else
pike.git/src/builtin_functions.c:7677:    */   PMOD_EXPORT void f_object_variablep(INT32 args)   {    struct object *o;    struct pike_string *s;    int ret;       get_all_args("variablep",args,"%o%S",&o, &s);       if(!o->prog) -  bad_arg_error("variablep", Pike_sp-args, args, 1, "object", Pike_sp-args, +  bad_arg_error("variablep", args, 1, "object", Pike_sp-args,    "Called on destructed object.\n");       /* FIXME: Ought to be overloadable, since `[]=() is... */       ret=find_shared_string_identifier(s,o->prog);    if(ret!=-1)    {    ret=IDENTIFIER_IS_VARIABLE(ID_FROM_INT(o->prog, ret)->identifier_flags);    }else{    ret=0;
pike.git/src/builtin_functions.c:7717:    *! Elements are compared with @[`==]. They are also hashed (see    *! @[lfun::__hash] for further details if the array contains    *! objects).    */   PMOD_EXPORT void f_uniq_array(INT32 args)   {    struct array *a, *b;    struct mapping *m;    int i, j=0,size=0;    -  get_all_args("uniq", args, "%a", &a); +  get_all_args(NULL, args, "%a", &a);    if( !a->size )    {    push_empty_array();    return;    }       push_mapping(m = allocate_mapping(a->size));    b = allocate_array(a->size);       for(i =0; i< a->size; i++)
pike.git/src/builtin_functions.c:7762:    *! This means that the returned array has the first element in the    *! first given array, then the first argument in next array and so    *! on for all arrays. Then the second elements are added, etc.    *!    *! @seealso    *! @[`/()], @[`*()], @[`+()], @[`-()], @[everynth()]    */   PMOD_EXPORT void f_splice(INT32 args)   {    struct array *out; -  INT32 size=0x7fffffff; +  INT32 size=MAX_INT32;    INT32 i,j,k;       for(i=0;i<args;i++)    if (TYPEOF(Pike_sp[i-args]) != T_ARRAY)    SIMPLE_ARG_TYPE_ERROR("splice", i+1, "array");    else    if (Pike_sp[i-args].u.array->size < size)    size=Pike_sp[i-args].u.array->size;       if(!args || !size)
pike.git/src/builtin_functions.c:7792:    for(i=-args; i<0; i++)    {    assign_svalue_no_free(out->item+k, Pike_sp[i].u.array->item+j);    out->type_field |= (1<<TYPEOF(*(out->item+(k++))));    }       push_array(out);    return;   }    - /*! @decl array(mixed) everynth(array(mixed) a, void|int n, @ -  *! void|int start) + /*! @decl array(mixed) everynth(array(mixed) a, void|int(1..) n, @ +  *! void|int(0..) start)    *!    *! Return an array with every @[n]:th element of the array @[a].    *!    *! If @[n] is zero every other element will be returned.    *!    *! @seealso    *! @[splice()], @[`/()]    */   PMOD_EXPORT void f_everynth(INT32 args)   {    INT32 k,n=2;    INT32 start=0;    struct array *a;    struct array *ina;    TYPE_FIELD types;    INT32 size=0;    -  check_all_args("everynth", args, +  check_all_args(NULL, args,    BIT_ARRAY, BIT_INT | BIT_VOID, BIT_INT | BIT_VOID , 0);       switch(args)    {    default:    case 3:    start=Pike_sp[2-args].u.integer;    if(start<0) -  bad_arg_error("everynth", Pike_sp-args, args, 3, "int", Pike_sp+2-args, +  bad_arg_error("everynth", args, 3, "int", Pike_sp+2-args,    "Argument negative.\n"); -  +  /* FALLTHRU */    case 2:    n=Pike_sp[1-args].u.integer;    if(n<1) -  bad_arg_error("everynth", Pike_sp-args, args, 2, "int", Pike_sp+1-args, +  bad_arg_error("everynth", args, 2, "int", Pike_sp+1-args,    "Argument negative.\n"); -  +  /* FALLTHRU */    case 1:    ina=Pike_sp[-args].u.array;    }       a=allocate_array(((size=ina->size)-start+n-1)/n);    types = 0;    for(k=0; start<size; k++, start+=n) {    assign_svalue_no_free(ITEM(a) + k, ina->item+start);    types |= 1 << TYPEOF(ITEM(a)[k]);    }
pike.git/src/builtin_functions.c:8709:   {    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"); +  SIMPLE_ARG_TYPE_ERROR("program_identifier_defined", 1, "program");       if( TYPEOF(Pike_sp[1-args]) != PIKE_T_STRING ) -  Pike_error("Illegal argument 2 to defined(program,string)\n"); +  SIMPLE_ARG_TYPE_ERROR("program_identifier_defined", 2, "string");    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);       if (tmp)    {
pike.git/src/builtin_functions.c:8777:    *!    *! 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;    -  get_all_args("inherit_list",args,"%*",&arg); +  get_all_args(NULL, args, "%*", &arg);    if(TYPEOF(Pike_sp[-args]) == T_OBJECT)    f_object_program(1);       p=program_from_svalue(arg);    if(!p)    SIMPLE_ARG_TYPE_ERROR("inherit_list", 1, "program");       if(TYPEOF(*arg) == T_FUNCTION)    {    par=arg->u.object;
pike.git/src/builtin_functions.c:8862:   /*! @decl string defined(function fun)    *!    *! Returns a string with filename and linenumber where @[fun]    *! was defined.    *!    *! Returns @expr{0@} (zero) when no line can be found, e.g. for    *! builtin functions and functions in destructed objects.    */   PMOD_EXPORT void f_function_defined(INT32 args)   { -  check_all_args("Function.defined",args,BIT_FUNCTION, 0); +  check_all_args(NULL, args, BIT_FUNCTION, 0);       if(SUBTYPEOF(Pike_sp[-args]) != FUNCTION_BUILTIN &&    Pike_sp[-args].u.object->prog)    {    struct program *p = Pike_sp[-args].u.object->prog;    struct program *id_prog, *p2;    int func = SUBTYPEOF(Pike_sp[-args]);    struct identifier *id;    INT_TYPE line;    struct pike_string *file = NULL;
pike.git/src/builtin_functions.c:8996:    /* function(0=mixed ...:mapping(0:0)) */    ADD_EFUN2("aggregate_mapping",f_aggregate_mapping,    tFuncV(tNone,tSetvar(0,tMix),tMap(tVar(0),tVar(0))),    OPT_TRY_OPTIMIZE, fix_aggregate_mapping_type, 0);       /* function(:mapping(string:mixed)) */    ADD_EFUN("all_constants",f_all_constants,    tFunc(tNone,tMap(tStr,tMix)),OPT_EXTERNAL_DEPEND);       /* function(:object) */ +  ADD_EFUN("get_active_compiler", f_get_active_compiler, +  tFunc(tNone, tObj), OPT_EXTERNAL_DEPEND); +  +  /* function(:object) */    ADD_EFUN("get_active_compilation_handler",    f_get_active_compilation_handler,    tFunc(tNone, tObj), OPT_EXTERNAL_DEPEND);       /* function(:object) */    ADD_EFUN("get_active_error_handler",    f_get_active_error_handler,    tFunc(tNone, tObj), OPT_EXTERNAL_DEPEND);       /* function(int,void|0=mixed:array(0)) */    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); - #if defined(__NT__) || defined(__OS2__) + #if defined(__NT__)    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,
pike.git/src/builtin_functions.c:9045:    tOr(tFunc(tOr(tStr,tVoid),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), +  tFunc(tArr(tSetvar(0,tMix)) tOr(tInt1Plus,tVoid) tOr(tIntPos,tVoid),    tArr(tVar(0))), 0, OPT_TRY_OPTIMIZE);       /* function(int:void) */    ADD_EFUN("exit",f_exit,tFuncV(tInt tOr(tVoid,tStr),tOr(tVoid,tMix),tVoid),    OPT_SIDE_EFFECT);       /* function(int:void) */    ADD_EFUN("_exit",f__exit,tFunc(tInt,tVoid),OPT_SIDE_EFFECT);       /* function(mixed:int) */
pike.git/src/builtin_functions.c:9168:    tOr6(tFunc(tMap(tSetvar(0,tMix),tSetvar(1,tMix)) tArr(tVar(0)),    tArr(tVar(1))),    tFunc(tSet(tSetvar(0,tMix)) tArr(tVar(0)), tArr(tInt01)),    tFunc(tString tArr(tInt), tArr(tInt)),    tFunc(tArr(tSetvar(0,tMix)) tArr(tInt), tArr(tVar(1))),    tFunc(tArray tArr(tNot(tInt)), tArray),    tFunc(tOr4(tObj,tFunction,tPrg(tObj),tInt) tArray, tArray)), 0);       /* FIXME: Is the third arg a good idea when the first is a mapping? */    ADD_EFUN("search",f_search, -  tOr4(tFunc(tStr tOr(tStr,tInt) tOr(tVoid,tInt), +  tOr4(tFunc(tStr tOr(tStr,tInt) tOr(tVoid,tInt) tOr(tVoid,tInt),    tInt), -  tFunc(tArr(tSetvar(0,tMix)) tVar(0) tOr(tVoid,tInt), +  tFunc(tArr(tSetvar(0,tMix)) tVar(0) tOr(tVoid,tInt) tOr(tVoid,tInt),    tInt),    tFunc(tMap(tSetvar(1,tMix),tSetvar(2,tMix)) tVar(2)    tOr(tVoid,tVar(1)), tVar(1)),    tFuncV(tObj tMix tOr(tVoid, tSetvar(3, tMix)), tMix, tVar(3))),    0);       ADD_EFUN2("has_prefix", f_has_prefix, tFunc(tOr(tStr,tObj) tStr,tInt01),    OPT_TRY_OPTIMIZE, 0, 0);       ADD_EFUN2("has_suffix", f_has_suffix, tFunc(tStr tStr,tInt01),
pike.git/src/builtin_functions.c:9283:    /* Some Wide-string stuff */       /* function(string,int(0..2)|void:string(0..255)) */    ADD_EFUN("string_to_unicode", f_string_to_unicode,    tFunc(tStr tOr(tInt02,tVoid),tStr8), OPT_TRY_OPTIMIZE);       /* function(string(0..255),int(0..2)|void:string) */    ADD_EFUN("unicode_to_string", f_unicode_to_string,    tFunc(tStr8 tOr(tInt02,tVoid),tStr), OPT_TRY_OPTIMIZE);    -  /* function(string,int|void:string(0..255)) */ +  /* function(string,int|void:utf8_string) */    ADD_EFUN("string_to_utf8", f_string_to_utf8, -  tFunc(tStr tOr(tInt,tVoid),tStr8), OPT_TRY_OPTIMIZE); +  tFunc(tStr tOr(tInt,tVoid),tUtf8Str), OPT_TRY_OPTIMIZE);       ADD_EFUN("string_filter_non_unicode", f_string_filter_non_unicode,    tFunc(tStr tOr(tInt,tVoid),tStr8), OPT_TRY_OPTIMIZE);    -  /* function(string(0..255),int|void:string) */ +  /* function(utf8_string,int|void:string) */    ADD_EFUN("utf8_to_string", f_utf8_to_string, -  tFunc(tStr8 tOr(tInt,tVoid),tStr), OPT_TRY_OPTIMIZE); +  tFunc(tUtf8Str tOr(tInt,tVoid),tStr), OPT_TRY_OPTIMIZE);    -  +  /* function(string(8bit),int|void:int(0..1)) */ +  ADD_EFUN("validate_utf8", f_validate_utf8, +  tFunc(tStr8 tOr(tInt,tVoid),tInt01), OPT_TRY_OPTIMIZE);    -  +     ADD_EFUN("__parse_pike_type", f_parse_pike_type,    tFunc(tStr8,tStr8),OPT_TRY_OPTIMIZE);       ADD_EFUN("__soft_cast", f___soft_cast,    tFunc(tSetvar(0, tType(tMix)) tSetvar(1, tType(tMix)),    tAnd(tVar(0), tVar(1))),    OPT_TRY_OPTIMIZE);       ADD_EFUN("__low_check_call", f___low_check_call,    tFunc(tType(tCallable) tType(tMix) tOr(tInt,tVoid) tOr(tMix,tVoid),
pike.git/src/builtin_functions.c:9329:    tFunc(tType(tMix), tArr(tString)),    OPT_TRY_OPTIMIZE);       /* function(int:mapping(string:int)) */    ADD_EFUN("localtime",f_localtime,    tFunc(tInt,tMap(tStr,tInt)),OPT_EXTERNAL_DEPEND);       /* function(int:mapping(string:int)) */    ADD_EFUN("gmtime",f_gmtime,tFunc(tInt,tMap(tStr,tInt)),OPT_TRY_OPTIMIZE);    -  /* function(int,int,int,int,int,int,int,void|int:int)|function(object|mapping:int) */ +  /* function(int,int,int,int,int,int,int,void|int:int)|function(object|mapping(string:int):int) */    ADD_EFUN("mktime",f_mktime,    tOr(tFunc(tInt tInt tInt tInt tInt tInt    tOr(tVoid,tInt) tOr(tVoid,tInt),tInt), -  tFunc(tOr(tObj,tMapping),tInt)),OPT_TRY_OPTIMIZE); +  tFunc(tOr(tObj, tMap(tStr, tInt)),tInt)),OPT_TRY_OPTIMIZE);    -  + #ifdef HAVE_STRPTIME +  /* function(string, string:mapping(string:int)) */ +  ADD_EFUN("strptime", f_strptime, +  tFunc(tStr tStr, tMap(tStr, tInt)), OPT_TRY_OPTIMIZE); + #endif +  +  /* function(string,mapping(string:int):string) */ +  ADD_EFUN("strftime", f_strftime, +  tFunc(tStr tMap(tStr,tInt), tStr), OPT_TRY_OPTIMIZE); +     /* function(:void) */    ADD_EFUN("_verify_internals",f__verify_internals,    tFunc(tNone,tVoid),OPT_SIDE_EFFECT|OPT_EXTERNAL_DEPEND);       /* 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);