pike.git / src / program.c

version» Context lines:

pike.git/src/program.c:25:   #include "constants.h"   #include "operators.h"   #include "builtin_functions.h"   #include "stuff.h"   #include "mapping.h"   #include "cyclic.h"   #include "pike_security.h"   #include "pike_types.h"   #include "opcodes.h"   #include "version.h" + #include "block_allocator.h"   #include "block_alloc.h"   #include "pikecode.h"   #include "pike_compiler.h"   #include "module_support.h"      #include <errno.h>   #include <fcntl.h>      #define sp Pike_sp      #undef ATTRIBUTE   #define ATTRIBUTE(X)      static void low_enter_compiler(struct object *ce, int inherit);   static void exit_program_struct(struct program *);   static size_t add_xstorage(size_t size,    size_t alignment,    ptrdiff_t modulo_orig);    - #undef EXIT_BLOCK - #define EXIT_BLOCK(P) exit_program_struct( (P) ) + static struct block_allocator program_allocator = BA_INIT_PAGES(sizeof(struct program), 4);    - #undef COUNT_OTHER - #define COUNT_OTHER() do{ \ -  struct program *p; \ -  for(p=first_program;p;p=p->next) \ -  { \ -  size+=p->total_size - sizeof (struct program); \ -  } \ - }while(0) + ATTRIBUTE((malloc)) + struct program * alloc_program() { +  return ba_alloc(&program_allocator); + }    - BLOCK_ALLOC_FILL_PAGES(program, 4) + void really_free_program(struct program * p) { +  exit_program_struct(p); +  ba_free(&program_allocator, p); + }    -  + void count_memory_in_programs(size_t *num, size_t *_size) { +  size_t size; +  struct program *p; +  ba_count_all(&program_allocator, num, &size); +  for(p=first_program;p;p=p->next) { +  size+=p->total_size - sizeof (struct program); +  } +  *_size = size; + }    -  + void free_all_program_blocks() { +  ba_destroy(&program_allocator); + } +    /* #define COMPILER_DEBUG */   /* #define PROGRAM_BUILD_DEBUG */      #ifdef COMPILER_DEBUG   #define CDFPRINTF(X) fprintf X -  + #ifndef PIKE_THREADS + /* The CDFPRINTF lines wants to print threads_disabled, so fake on of those */ + static const int threads_disabled = 1; + #endif   #else /* !COMPILER_DEBUG */   #define CDFPRINTF(X)   #endif /* COMPILER_DEBUG */      /*    * These two values should probably be fine-tuned, but doing so    * more or less requires running a predictable 'typical' application    * and testing different hashsizes and tresholds. I tried to do it    * mathematically by measuring the extremes (no cache hits, 100%    * cache hits etc.) but it seems that the processor cache becomes
pike.git/src/program.c:89:    * For normal applications, the hitrate is most likely well over 90%,    * but that should be verified.    * - Holistiska Centralbyr√•n (Hubbe)    */      /* Define the size of the cache that is used for method lookup. */   /* A value of zero disables this cache */   #define FIND_FUNCTION_HASHSIZE 16384      /* Programs with less methods will not use the cache for method lookups.. */ - #define FIND_FUNCTION_HASH_TRESHOLD 9 + #define FIND_FUNCTION_HASH_TRESHOLD 0         #define DECLARE   #include "compilation.h"      struct pike_string *this_program_string;   static struct pike_string *this_string, *this_function_string;   static struct pike_string *UNDEFINED_string;      /* Common compiler subsystems */
pike.git/src/program.c:154:    "_sprintf",    "_equal",    "_m_delete",    "_get_iterator",    "`[..]",    /* NOTE: After this point there are only fake lfuns. */    "_search",    "_types",    "_serialize",    "_deserialize", +  "_size_object", +  "_random",   };      struct pike_string *lfun_strings[NELEM(lfun_names)];      static struct mapping *lfun_ids;      /* mapping(string:type) */   static struct mapping *lfun_types;      static const char *const raw_lfun_types[] = {
pike.git/src/program.c:214:    tFuncV(tInt tOr(tMap(tStr,tInt),tVoid),tVoid,tStr), /* "_sprintf", */    tFuncV(tMix,tVoid,tInt), /* "_equal", */    tFuncV(tZero,tVoid,tMix), /* "_m_delete", */    tFuncV(tNone,tVoid,tObj), /* "_get_iterator", */    tFuncV(tZero tRangeBound tZero tRangeBound, tVoid, tMix), /* "`[..]" */    /* NOTE: After this point there are only fake lfuns. */    tFuncV(tZero tOr(tZero, tVoid), tVoid, tMix), /* "_search", */    tFuncV(tNone,tVoid,tArray), /* "_types", */    tFuncV(tObj tZero, tVoid, tVoid), /* "_serialize", */    tFuncV(tObj tZero, tVoid, tVoid), /* "_deserialize", */ +  tFuncV(tZero, tVoid, tInt), /* "_size_object", */ +  tFuncV(tNone, tVoid, tMix), /* "_random", */   };      /* These two are not true LFUNs! */   static struct pike_type *lfun_getter_type_string = NULL;   static struct pike_type *lfun_setter_type_string = NULL;      /*! @namespace lfun::    *!    *! Callback functions used to overload various builtin functions.    *!
pike.git/src/program.c:839:    *! Currently casting between object types is a noop.    *!    *! @note    *! If the returned value is not deemed to be of the requested type    *! a runtime error may be thrown.    *!    *! @note    *! It's assumed that this function is side-effect free.    */    - /*! @decl mixed lfun::`[..](zero low, int low_bound_type, @ -  *! zero high, int high_bound_type) -  *! -  *! Subrange callback. -  *! -  *! @note -  *! It's assumed that this function is side-effect free. -  *! -  *! @seealso -  *! @[predef::`[..]] -  */ -  +    /*! @decl mixed lfun::`[](zero arg1, zero|void arg2)    *!    *! Indexing callback.    *!    *! For compatibility, this is also called to do subranges unless    *! there is a @[`[..]] in the class. See @[predef::`[..]] for    *! details.    *!    *! @note    *! It's assumed that this function is side-effect free.
pike.git/src/program.c:874:    */      /*! @decl mixed lfun::`[]=(zero arg1, zero arg2)    *!    *! Index assignment callback.    *!    *! @seealso    *! @[predef::`[]=()], @[lfun::`->=()]    */    - /*! @decl mixed lfun::`->(string arg, object|void context, int|void access) + /*! @decl mixed lfun::`->(string index, object|void context, int|void access)    *!    *! Arrow index callback.    *! -  +  *! @param index +  *! Symbol in @[context] to access. +  *! +  *! @param context +  *! Context in the current object to start the search from. +  *! If @expr{UNDEFINED@} or left out, @expr{this_program::this@} +  *! is to be be used (ie start at the current context and ignore +  *! any overloaded symbols). +  *! +  *! @param access +  *! Access permission override. One of the following: +  *! @int +  *! @value 0 +  *! @value UNDEFINED +  *! See only public symbols. +  *! @value 1 +  *! See protected symbols as well. +  *! @endint +  *! +  *! @returns +  *! Returns the value at @[index] if it exists, and +  *! @expr{UNDEFINED@} otherwise. +  *!    *! @note    *! It's assumed that this function is side-effect free.    *!    *! @seealso    *! @[predef::`->()], @[::`->()]    */    - /*! @decl mixed lfun::`->=(string arg, zero value, @ + /*! @decl mixed lfun::`->=(string index, zero value, @    *! object|void context, int|void access)    *!    *! Arrow index assignment callback.    *! -  +  *! @param index +  *! Symbol in @[context] to change the value of. +  *! +  *! @param value +  *! The new value. +  *! +  *! @param context +  *! Context in the current object to start the search from. +  *! If @expr{UNDEFINED@} or left out, @expr{this_program::this@} +  *! is to be used (ie start at the current context and ignore +  *! any overloaded symbols). +  *! +  *! @param access +  *! Access permission override. One of the following: +  *! @int +  *! @value 0 +  *! @value UNDEFINED +  *! See only public symbols. +  *! @value 1 +  *! See protected symbols as well. +  *! @endint +  *! +  *! This function is to index the current object with the string @[index], +  *! and set it to @[value]. +  *! +  *! @returns +  *! Returns the set @[value]. +  *!    *! @seealso    *! @[predef::`->=()], @[::`->=()], @[lfun::`[]=()]    */      /*! @decl int lfun::_sizeof()    *!    *! Size query callback.    *!    *! Called by @[predef::sizeof()] to determine the number of elements    *! in an object. If this function is not present, the number
pike.git/src/program.c:1117:    *! references a specific item contained (in some arbitrary sense)    *! in this one.    *!    *! @note    *! It's assumed that this function is side-effect free.    *!    *! @seealso    *! @[predef::Iterator], @[predef::get_iterator], @[predef::foreach()]    */    + /*! @decl mixed lfun::`[..](zero low, int low_bound_type, @ +  *! zero high, int high_bound_type) +  *! +  *! Subrange callback. +  *! +  *! @note +  *! It's assumed that this function is side-effect free. +  *! +  *! @seealso +  *! @[predef::`[..]] +  */ +  + /**** END TRUE LFUNS ****/ + /**** BEGIN FAKE LFUNS ****/ +    /*! @decl mixed lfun::_search(mixed needle, mixed|void start)    *!    *! Search callback.    *!    *! @seealso    *! @[predef::search()]    */      /*! @decl array lfun::_types(object|void context, int|void access)    *!
pike.git/src/program.c:1209:    *!    *! @note    *! A default implementation of @[lfun::_serialize()] and    *! @[lfun::_deserialize()] is available in @[Serializer.Serializable].    *!    *! @seealso    *! @[lfun::_serialize()], @[Serializer.deserialize()],    *! @[Serializer.Serializable()->_deserialize()]    */    + /*! @decl int lfun::_size_object() +  *! +  *! @[Debug.size_object()] callback. +  *! +  *! @returns +  *! Returns an approximation of the memory use in bytes for the object. +  *! +  *! @seealso +  *! @[Debug.size_object()], @[lfun::_sizeof()] +  */ +  + /*! @decl mixed lfun::_random() +  *! Called by @[random()]. Typical use is when the object implements +  *! a ADT, when a call to this lfun should return a random member of +  *! the ADT or range implied by the ADT. +  *! +  *! @seealso +  *! @[predef::random()] +  */ +  + /**** END FAKE LFUNS ****/ + /**** BEGIN MAGIC LFUNS ****/ +    /*! @decl mixed lfun::`symbol()    *! @decl mixed lfun::`->symbol()    *!    *! Variable retrieval callback (aka "getter").    *!    *! @note    *! Note that the @expr{symbol@} in the name can be any symbol.    *!    *! @note    *! This is not a true LFUN, since it is even more low level!
pike.git/src/program.c:1322:      static struct program *reporter_program = NULL;   struct program *compilation_program = 0;   struct program *compilation_env_program = 0;   struct object *compilation_environment = NULL;      struct program *gc_internal_program = 0;   static struct program *gc_mark_program_pos = 0;      #ifdef PIKE_DEBUG - #define CHECK_FILE_ENTRY(PROG, POS, LEN, SHIFT) \ + #define CHECK_FILE_ENTRY(PROG, STRNO) \    do { \ -  if (SHIFT < 0 || SHIFT > 2 || \ -  POS + (LEN << SHIFT) > PROG->linenumbers + PROG->num_linenumbers) \ +  if ((STRNO < 0) || (STRNO >= PROG->num_strings)) \    Pike_fatal ("Invalid file entry in linenumber info.\n"); \    } while (0)   #else - #define CHECK_FILE_ENTRY(PROG, POS, LEN, SHIFT) do {} while (0) + #define CHECK_FILE_ENTRY(PROG, STRNO) do {} while (0)   #endif      INT_TYPE get_small_number(char **q);      PMOD_EXPORT void do_free_program (struct program *p)   {    if (p)    free_program(p);   }   
pike.git/src/program.c:1843:    if(!IS_UNDEFINED (Pike_sp-1))    {    ret=mkconstantsvaluenode(Pike_sp-1);    }    }    pop_stack();       return ret;   }    + /* This function is intended to simplify resolving of +  * program symbols during compile-time for C-modules. +  * +  * A typical use-case is for a C-module inheriting +  * code written in Pike. +  */ + PMOD_EXPORT struct program *resolve_program(struct pike_string *ident) + { +  struct program *ret = NULL; +  struct node_s *n = resolve_identifier(ident); +  if (n) { +  if ((n->token == F_CONSTANT) && (TYPEOF(n->u.sval) == T_PROGRAM) && +  (ret = n->u.sval.u.program)) { +  add_ref(ret); +  } else { +  my_yyerror("Invalid program identifier '%S'.", ident); +  } +  free_node(n); +  } else { +  my_yyerror("Unknown program identifier '%S'.", ident); +  } +  return ret; + } +    /*! @decl constant this    *!    *! Builtin read only variable that evaluates to the current object.    *!    *! @seealso    *! @[this_program], @[this_object()]    */      /*! @decl constant this_program    *!
pike.git/src/program.c:1898:    }       if ((inherit_num == -1) || (!TEST_COMPAT(7,6) && (inherit_num >= 0))) {    if (ident == this_string) {    /* Handle this. */    return mkthisnode(state->new_program, inherit_num);    }       /* Handle this_program */    if (ident == this_program_string) { -  node *n = mkefuncallnode("object_program", +  node *n; +  if (!state_depth && (inherit_num == -1) && colon_colon_ref && +  !TEST_COMPAT(7,8) && +  state->previous && state->previous->new_program) { +  /* ::this_program +  * +  * This refers to the previous definition of the current class +  * in its parent, and is typically used with inherit like: +  * +  * inherit Foo; +  * +  * // Override the Bar inherited from Foo. +  * class Bar { +  * // Bar is based on the implementation from Foo. +  * inherit ::this_program; +  * +  * // ... +  * } +  */ +  struct program *parent; +  struct pike_string *name = NULL; +  int e; +  int i; +  +  /* Find the name of the current class. */ +  parent = state->previous->new_program; +  for (e = parent->num_identifier_references; e--;) { +  struct identifier *id = ID_FROM_INT(parent, e); +  struct svalue *s; +  if (!IDENTIFIER_IS_CONSTANT(id->identifier_flags) || +  (id->func.const_info.offset < 0)) { +  continue; +  } +  s = &PROG_FROM_INT(parent, e)-> +  constants[id->func.const_info.offset].sval; +  if ((TYPEOF(*s) != T_PROGRAM) || +  (s->u.program != state->new_program)) { +  continue; +  } +  /* Found! */ +  name = id->name; +  break; +  } +  if (!name) { +  yyerror("Failed to find current class in its parent."); +  return NULL; +  } +  +  /* Find ::name in the parent. */ +  i = reference_inherited_identifier(state->previous, NULL, name); +  if (i == -1) { +  my_yyerror("Failed to find previous inherited definition of %S " +  "in parent.", name); +  return NULL; +  } +  n = mkexternalnode(parent, i); +  } else { +  n = mkefuncallnode("object_program",    mkthisnode(state->new_program, inherit_num)); -  +  }    /* We know this expression is constant. */    n->node_info &= ~OPT_NOT_CONST;    n->tree_info &= ~OPT_NOT_CONST;    return n;    }       /* Handle this_function */    if (ident == this_function_string) {    int i;    if ((i = Pike_compiler->compiler_frame->current_function_number) >= 0) {
pike.git/src/program.c:2060:    case PROG_PARSER_HTML_ID:    module = "Parser._parser";    break;    case PROG_GMP_MPZ_ID:    module = "Gmp";    break;    case PROG_MODULE_MIME_ID:    module = "___MIME";    break;    default: -  if ((id >= 100) && (id <= 300)) { +  if ((id >= 100) && (id < 300)) {    module = "Image"; -  +  } else if ((id >= 300) && (id < 400)) { +  module = "Nettle";    } else if ((id >= 1000) && (id < 2000)) {    module = "___GTK";    } else if ((id >= 2000) && (id < 3000)) {    module = "___GTK2";    }    break;    }    if (module && get_master()) {    /* fprintf(stderr, "%s... ", module); */    push_text(module);
pike.git/src/program.c:2212: Inside #if defined(PIKE_DEBUG) and #if defined(DEBUG_MALLOC)
   return make_shared_string(tmp);    }    }    }   #endif       return get_program_line(p, line);   }   #endif    - int override_identifier (struct reference *new_ref, struct pike_string *name) + int override_identifier (struct reference *new_ref, struct pike_string *name, +  int required_flags)   {    struct compilation *c = THIS_COMPILATION;    int id = -1, cur_id = 0, is_used = 0;       int new_is_variable =    IDENTIFIER_IS_VARIABLE(ID_FROM_PTR(Pike_compiler->new_program,    new_ref)->identifier_flags);       /* This loop could possibly be optimized by looping over    * each inherit and looking up 'name' in each inherit
pike.git/src/program.c:2241:    struct reference *ref =    Pike_compiler->new_program->identifier_references + cur_id;    struct identifier *i;       /* No need to do anything for ourselves. */    if (ref == new_ref) continue;       /* Do not zapp hidden identifiers */    if(ref->id_flags & ID_HIDDEN) continue;    +  if(ref->id_flags & ID_VARIANT) continue; +  +  if ((ref->id_flags & required_flags) != required_flags) continue; +     /* Do not zapp functions with the wrong name... */    if((i = ID_FROM_PTR(Pike_compiler->new_program, ref))->name != name)    continue;       /* Do not zapp inherited inline ('local') identifiers,    * or inherited externals with new externals,    * since this makes it hard to identify in encode_value().    */    if((ref->id_flags & (ID_INLINE|ID_INHERITED)) == (ID_INLINE|ID_INHERITED)    || (ref->id_flags & new_ref->id_flags & ID_EXTERN)) {
pike.git/src/program.c:2278:    continue;    }       if ((ref->id_flags & (ID_INHERITED|ID_USED)) == (ID_INHERITED|ID_USED)) {    struct inherit *inh = INHERIT_FROM_PTR(Pike_compiler->new_program, ref);    struct reference *sub_ref;       /* Find the inherit one level away. */    while (inh->inherit_level > 1) inh--;    + #if 0   #ifdef PIKE_DEBUG    if (!inh->inherit_level) { -  +  /* FIXME: This is valid for references that are about to be +  * overridden by the variant dispatcher. +  */    Pike_fatal("Inherit without intermediate levels.\n");    }   #endif -  + #endif       sub_ref = PTR_FROM_INT(inh->prog, cur_id - inh->identifier_level);       /* Check if the symbol was used before it was inherited. */    if ((c->lex.pragmas & ID_STRICT_TYPES) &&    (sub_ref->id_flags & ID_USED)) {    struct identifier *sub_id = ID_FROM_PTR(inh->prog, sub_ref);    if (IDENTIFIER_IS_FUNCTION(sub_id->identifier_flags)) {    if ((Pike_compiler->compiler_pass == 2) &&    !pike_types_le(ID_FROM_PTR(Pike_compiler->new_program,
pike.git/src/program.c:2364:    * Consider this a fatal?    */    p->identifiers[i].run_time_type = T_FUNCTION;    }    }       /* Fixup identifier overrides. */    for (i = 0; i < p->num_identifier_references; i++) {    struct reference *ref = p->identifier_references + i;    if (ref->id_flags & ID_HIDDEN) continue; +  if (ref->id_flags & ID_VARIANT) continue;    if (ref->inherit_offset != 0) continue; -  override_identifier (ref, ID_FROM_PTR (p, ref)->name); +  override_identifier (ref, ID_FROM_PTR (p, ref)->name, 0);    }       /* Ok, sort for binsearch */    for(e=i=0;i<(int)p->num_identifier_references;i++)    {    struct reference *funp;    struct identifier *fun;    funp=p->identifier_references+i;    if(funp->id_flags & ID_HIDDEN) continue; -  +  if(funp->id_flags & ID_VARIANT) continue;    fun=ID_FROM_PTR(p, funp);    if(funp->id_flags & ID_INHERITED)    {    int found_better=-1;    int funa_is_prototype;       /* NOTE: Mixin is currently not supported for PRIVATE symbols. */    if(funp->id_flags & ID_PRIVATE) continue;    funa_is_prototype = fun->func.offset == -1;   /* if(fun->func.offset == -1) continue; * prototype */       /* check for multiple definitions */    for(t=i+1;t<(int)p->num_identifier_references;t++)    {    struct reference *funpb;    struct identifier *funb;       funpb=p->identifier_references+t;    if (funpb->id_flags & ID_HIDDEN) continue; -  +  if (funpb->id_flags & ID_VARIANT) continue;    funb=ID_FROM_PTR(p,funpb);    /* if(funb->func.offset == -1) continue; * prototype */       if(fun->name==funb->name)    {    if (!(funpb->id_flags & ID_PROTECTED)) {    /* Only regard this symbol as better if it    * will end up in the index further below.    */    found_better=t;
pike.git/src/program.c:2494:    if (id >= 0) {    // LFUNs are used.    p->identifier_references[id].id_flags |= ID_USED;    }    }       /* Complain about unused private symbols. */    for (i = 0; i < p->num_identifier_references; i++) {    struct reference *ref = p->identifier_references + i;    if (ref->id_flags & ID_HIDDEN) continue; +  if (ref->id_flags & ID_VARIANT) continue;    if (ref->inherit_offset != 0) continue;       if ((ref->id_flags & (ID_HIDDEN|ID_PRIVATE|ID_USED)) == ID_PRIVATE) {    yywarning("%S is private but not used anywhere.",    ID_FROM_PTR(p, ref)->name);    }    }       /* Set the PROGRAM_LIVE_OBJ flag by looking for destroy() and    * inherited PROGRAM_LIVE_OBJ flags. This is done at fixation time
pike.git/src/program.c:2648:    struct pike_string *name,    int flags,    int *idp)   {    struct compilation *c = THIS_COMPILATION;    int id=0;    struct svalue tmp;       CHECK_COMPILER();    - #ifdef WITH_FACETS -  if(Pike_compiler->compiler_pass == 1 && p) { -  p->facet_index = -1; -  p->facet_group = NULL; -  } - #endif -  +     /* We don't want to change thread, but we don't want to    * wait for the other threads to complete either.    */    low_init_threads_disable();       c->compilation_depth++;    -  if (!Pike_compiler->compiler_frame) { -  new_node_s_context(); -  } -  +     SET_SVAL_TYPE(tmp, T_PROGRAM);    if(!p)    {    p=low_allocate_program();    if(name)    {    tmp.u.program=p;    id=add_constant(name, &tmp, flags & ~ID_EXTERN);   #if 0    fprintf(stderr,"Compiling class %s, depth=%d\n",
pike.git/src/program.c:2717:    "pass=%d: threads_disabled:%d, compilation_depth:%d\n",    (long)th_self(), p, name ? name->str : "-",    Pike_compiler->compiler_pass,    threads_disabled, c->compilation_depth));       init_type_stack();      #define PUSH   #include "compilation.h"    +  ba_init(&Pike_compiler->node_allocator, sizeof(struct node_s), 512); +     Pike_compiler->parent_identifier=id;    Pike_compiler->compiler_pass = pass;       Pike_compiler->num_used_modules=0; /* FIXME: Duplicate? */       if(p->flags & PROGRAM_FINISHED)    {    yyerror("Pass2: Program already done");    }   
pike.git/src/program.c:2830:   #define FOO(NUMTYPE,TYPE,ARGTYPE,NAME) \    Pike_compiler->malloc_size_program->PIKE_CONCAT(num_,NAME) = \    Pike_compiler->new_program->PIKE_CONCAT(num_,NAME);   #include "program_areas.h"       {    INT_TYPE line = 0;    INT32 off = 0;    size_t len = 0;    INT32 shift = 0; -  char *file=0; +  struct pike_string *file=0;    char *cnt=Pike_compiler->new_program->linenumbers;       while(cnt < Pike_compiler->new_program->linenumbers +    Pike_compiler->new_program->num_linenumbers)    {    if(*cnt == 127)    { -  +  int strno;    cnt++; -  len = get_small_number(&cnt); -  shift = *cnt; -  file = ++cnt; -  CHECK_FILE_ENTRY (Pike_compiler->new_program, cnt, len, shift); -  cnt += len<<shift; +  strno = get_small_number(&cnt); +  CHECK_FILE_ENTRY (Pike_compiler->new_program, strno); +  file = Pike_compiler->new_program->strings[strno];    }    off+=get_small_number(&cnt);    line+=get_small_number(&cnt);    }    Pike_compiler->last_line=line;    Pike_compiler->last_pc=off;    if(file)    { -  struct pike_string *str = begin_wide_shared_string(len, shift); +     if(Pike_compiler->last_file) free_string(Pike_compiler->last_file); -  memcpy(str->str, file, len<<shift); -  Pike_compiler->last_file = end_shared_string(str); +  copy_shared_string(Pike_compiler->last_file, file);    }    }       }else{    static struct pike_string *s;    struct inherit i;    -  +  if (Pike_compiler->new_program->strings) { +  struct pike_string **str = Pike_compiler->new_program->strings; +  int j = Pike_compiler->new_program->num_strings; +  while(j--) { +  free_string(*str); +  str++; +  } +  } +    #define START_SIZE 64   #ifdef PIKE_USE_MACHINE_CODE   #define BAR(NUMTYPE,TYPE,ARGTYPE,NAME) \    if (Pike_compiler->new_program->NAME) { \    mexec_free(Pike_compiler->new_program->NAME); \    Pike_compiler->new_program->PIKE_CONCAT(num_,NAME) = 0; \    } \    Pike_compiler->malloc_size_program->PIKE_CONCAT(num_,NAME) = \    START_SIZE; \    Pike_compiler->new_program->NAME = \
pike.git/src/program.c:3024:    {    if(p->inherits[e].prog)    free_program(p->inherits[e].prog);    }    if(p->inherits[e].parent)    free_object(p->inherits[e].parent);    }       DOUBLEUNLINK(first_program, p);    - #ifdef WITH_FACETS -  if(p->facet_group) -  { -  free_object(p->facet_group); -  } - #endif -  +     if(p->flags & PROGRAM_OPTIMIZED)    {   #ifdef PIKE_USE_MACHINE_CODE    do {    /* NOTE: Assumes all BAR's are before any FOO. */   #define BAR(NUMTYPE,TYPE,ARGTYPE,NAME) \    if (p->NAME) mexec_free(p->NAME);   #define FOO(NUMTYPE,TYPE,ARGTYPE,NAME) \    if (p->NAME) { \    dmfree(p->NAME); \
pike.git/src/program.c:3207:    Pike_compiler->last_identifier=0;    }       if(Pike_compiler->last_file)    {    free_string(Pike_compiler->last_file);    Pike_compiler->last_file=0;    }       unuse_modules(Pike_compiler->num_used_modules); +  +  free_all_nodes(); +  +  ba_destroy(&Pike_compiler->node_allocator);   }      int sizeof_variable(int run_time_type)   {    switch(run_time_type)    {    case T_FUNCTION:    case T_MIXED: return sizeof(struct svalue);    case T_FLOAT: return sizeof(FLOAT_TYPE);    case T_INT: return sizeof(INT_TYPE);
pike.git/src/program.c:3239:    case T_FLOAT: return ALIGNOF(FLOAT_TYPE);    case T_INT: return ALIGNOF(INT_TYPE);    case PIKE_T_FREE:    case PIKE_T_GET_SET: return 1;    default: return ALIGNOF(void *);    }   }      #ifdef PIKE_DEBUG    - void dump_program_tables (const struct program *p, int indent) + PMOD_EXPORT void dump_program_tables (const struct program *p, int indent)   {    int d;       if (!p) {    fprintf(stderr, "%*sProgram: NULL\n\n", indent, "");    return;    }       fprintf(stderr,    "%*sProgram flags: 0x%04x\n\n",    indent, "", p->flags);       fprintf(stderr,    "%*sReference table:\n"    "%*s ####: Flags Inherit Identifier\n",    indent, "", indent, "");    for (d=0; d < p->num_identifier_references; d++) {    struct reference *ref = p->identifier_references + d;    struct identifier *id = ID_FROM_PTR(p, ref); -  +  struct program *inh_p = INHERIT_FROM_PTR(p, ref)->prog;       fprintf(stderr,    "%*s %4d: %5x %7d %10d %s\n"    "%*s %s:%ld\n",    indent, "",    d, ref->id_flags, ref->inherit_offset,    ref->identifier_offset,    id->name->size_shift ? "(wide)" : id->name->str,    indent, "", -  p->num_strings?p->strings[id->filename_strno]->str:"-", +  inh_p->num_strings?inh_p->strings[id->filename_strno]->str:"-",    (long)id->linenumber);    if (IDENTIFIER_IS_ALIAS(id->identifier_flags)) {    fprintf (stderr, "%*s Alias for %d:%d\n",    indent, "", id->func.ext_ref.depth, id->func.ext_ref.id);    } else if (IDENTIFIER_IS_CONSTANT(id->identifier_flags)) {    fprintf (stderr, "%*s Constant #%ld\n",    indent, "", (long)id->func.const_info.offset);    } else if (IDENTIFIER_IS_VARIABLE(id->identifier_flags)) {    fprintf (stderr, "%*s Offset: 0x%08lx\n",    indent, "", (long)id->func.offset);    } else if (IDENTIFIER_IS_PIKE_FUNCTION(id->identifier_flags)) {    INT_TYPE line; -  struct program *inh_p = INHERIT_FROM_PTR(p,ref)->prog; +     struct pike_string *file =    get_line (ID_FROM_PTR(p,ref)->func.offset + inh_p->program, inh_p, &line);    if (!file->size_shift)    fprintf (stderr, "%*s %s:%ld\n",    indent, "", file->str, (long)line);    free_string (file);    } else {    fprintf (stderr, "%*s Cfun: %p\n",    indent, "", id->func.c_fun);    }
pike.git/src/program.c:3399:    fprintf(stderr, "\n"    "%*sLinenumber table:\n",    indent, "");    {    INT32 off = 0;    INT_TYPE line = 0;    char *cnt = p->linenumbers;       while (cnt < p->linenumbers + p->num_linenumbers) {    if (*cnt == 127) { -  int len, shift; -  char *file; +  int strno;    cnt++; -  len = get_small_number(&cnt); -  shift = *cnt; -  file = ++cnt; -  CHECK_FILE_ENTRY (p, cnt, len, shift); -  cnt += len << shift; -  if (!shift) { -  fprintf(stderr, "%*s Filename: \"%s\"\n", indent, "", file); -  } else { -  fprintf(stderr, "%*s Filename: len:%d, shift:%d\n", indent, "", len, shift); +  strno = get_small_number(&cnt); +  fprintf(stderr, "%*s Filename: String #%d\n", indent, "", strno);    } -  } +     off += get_small_number(&cnt);    line += get_small_number(&cnt);    fprintf(stderr, "%*s %8d:%8ld\n", indent, "", off, (long)line);    }    }       fprintf(stderr, "\n");   }      void check_program(struct program *p)
pike.git/src/program.c:3694:    p) > 0)) {    Pike_fatal("Program->identifier_index[%ld] > "    "Program->identifier_index[%ld]\n",    (long)(e-1), (long)e);    }    }      }   #endif    + static void f_dispatch_variant(INT32 args); +  + int is_variant_dispatcher(struct program *prog, int fun) + { +  struct reference *ref; +  struct identifier *id; +  if (fun < 0) return 0; +  ref = PTR_FROM_INT(prog, fun); +  id = ID_FROM_PTR(prog, ref); +  return (IDENTIFIER_IS_C_FUNCTION(id->identifier_flags) && +  !IDENTIFIER_IS_ALIAS(id->identifier_flags) && +  (id->func.c_fun == f_dispatch_variant)); + } +  + static int add_variant_dispatcher(struct pike_string *name, +  struct pike_type *type, +  int id_flags) + { +  union idptr dispatch_fun; +  dispatch_fun.c_fun = f_dispatch_variant; +  return define_function(name, type, id_flags & ~(ID_VARIANT|ID_LOCAL), +  IDENTIFIER_C_FUNCTION, &dispatch_fun, 0); + } +    /* Note: This function is misnamed, since it's run after both passes. /mast */   /* finish-states:    *    * 0: First pass.    * 1: Last pass.    * 2: Called from decode_value().    */   struct program *end_first_pass(int finish)   {    struct compilation *c = THIS_COMPILATION;    int e; -  struct program *prog; +  struct program *prog = Pike_compiler->new_program;    struct pike_string *s; -  +  int num_refs = prog->num_identifier_references; +  union idptr dispatch_fun;    -  +  dispatch_fun.c_fun = f_dispatch_variant; +  +  /* Collect variant functions that have been defined in this program, +  * and add the corresponding dispatchers. +  */ +  for (e = 0; e < num_refs; e++) { +  struct identifier *id; +  struct pike_string *name; +  struct pike_type *type; +  int id_flags; +  int opt_flags; +  int j; +  if (prog->identifier_references[e].inherit_offset) continue; +  if (!is_variant_dispatcher(prog, e)) continue; +  /* Found a dispatcher. */ +  +  id = ID_FROM_INT(prog, e); +  name = id->name; +  type = NULL; +  id_flags = 0; +  opt_flags = 0; +  +  CDFPRINTF((stderr, "Collecting variants of \"%s\"...\n", name->str)); +  +  /* Collect the variants of the function. */ +  j = prog->num_identifier_references; +  while ((j = really_low_find_variant_identifier(name, prog, NULL, j, +  SEE_PROTECTED|SEE_PRIVATE)) >= 0) { +  struct reference *ref = prog->identifier_references + j; +  id = ID_FROM_INT(prog, j); +  id_flags |= ref->id_flags; +  opt_flags |= id->opt_flags; +  /* NB: The dispatcher needs the variant references to +  * not get overloaded for the ::-operator to work. +  */ +  prog->identifier_references[j].id_flags |= ID_LOCAL; +  { +  struct pike_type * temp = type; +  type = or_pike_types(type, id->type, 1); +  if (temp) free_type(temp); +  } + #ifdef COMPILER_DEBUG +  fprintf(stderr, "type: "); +  simple_describe_type(id->type); +  fprintf(stderr, "\n"); + #endif +  } + #ifdef COMPILER_DEBUG +  fprintf(stderr, "Dispatcher type: "); +  simple_describe_type(type); +  fprintf(stderr, "\n"); + #endif +  /* Update the type of the dispatcher. */ +  id = ID_FROM_INT(prog, e); +  free_type(id->type); +  id->type = type; +  id->opt_flags = opt_flags; +  prog->identifier_references->id_flags |= id_flags & ~(ID_VARIANT|ID_LOCAL); +  next_ref: +  ; +  } +     debug_malloc_touch(Pike_compiler->fake_object);    debug_malloc_touch(Pike_compiler->fake_object->storage);       MAKE_CONST_STRING(s,"__INIT");          /* Collect references to inherited __INIT functions */    if (!(Pike_compiler->new_program->flags & PROGRAM_AVOID_CHECK)) {    for(e=Pike_compiler->new_program->num_inherits-1;e;e--)    {    int id;    if(Pike_compiler->new_program->inherits[e].inherit_level!=1) continue; -  id=low_reference_inherited_identifier(0, e, s, SEE_PROTECTED); +  id = Pike_compiler->new_program->inherits[e].prog->lfuns[LFUN___INIT]; +  id = really_low_reference_inherited_identifier(0, e, id);    if(id!=-1)    {    Pike_compiler->init_node=mknode(F_COMMA_EXPR,    mkcastnode(void_type_string,    mkapplynode(mkidentifiernode(id),0)),    Pike_compiler->init_node);    }    }    }   
pike.git/src/program.c:3749:    e=dooptcode(s,    mknode(F_COMMA_EXPR,    Pike_compiler->init_node,    mknode(F_RETURN,mkintnode(0),0)),    function_type_string,    ID_PROTECTED);    Pike_compiler->init_node=0;    } else if (finish == 2) {    /* Called from decode_value(). */    e = low_find_lfun(Pike_compiler->new_program, LFUN___INIT); +  if ((e != -1) && +  (ID_FROM_INT(Pike_compiler->new_program, e)->func.offset == -1)) { +  /* Just a prototype. Make sure not to call it. */ +  e = -1; +  }    }else{ -  +  /* Note that we may zap an __INIT that existed in pass 1 here. +  * This is intentional to avoid having to keep track of whether +  * __INIT() is just a prototype or not. +  */    e=-1;    }    Pike_compiler->new_program->lfuns[LFUN___INIT]=e;       pop_compiler_frame(); /* Pop __INIT local variables */       if(Pike_compiler->num_parse_error > 0)    {    CDFPRINTF((stderr, "th(%ld) %p Compilation errors (%d).\n",    (long)th_self(), Pike_compiler->new_program,
pike.git/src/program.c:3790:       fixate_program();    if(Pike_compiler->num_parse_error)    {    free_program(prog);    prog=0;    }else{    optimize_program(Pike_compiler->new_program);    Pike_compiler->new_program->flags |= PROGRAM_FINISHED;    } +  } else { +  /* All references in prog are now known. +  * Fixup identifier overrides or external symbols, +  * so that inherit is safe. +  */ +  for (e = 0; e < prog->num_identifier_references; e++) { +  struct reference *ref = prog->identifier_references + e; +  if (ref->id_flags & ID_HIDDEN) continue; +  if (ref->inherit_offset != 0) continue; +  override_identifier (ref, ID_FROM_PTR (prog, ref)->name, +  ID_EXTERN);    } -  +  }      #ifdef PIKE_DEBUG    if (prog) {    check_program(prog);    if(l_flag)    dump_program_desc(prog);    }   #endif    }   
pike.git/src/program.c:3832: Inside #if defined(SHARED_NODES)
     #ifdef SHARED_NODES    /* free(node_hash.table); */   #endif /* SHARED_NODES */      #define POP   #include "compilation.h"       exit_type_stack();    -  free_all_nodes(); +        CDFPRINTF((stderr,    "th(%ld) %p end_first_pass(%d): "    "threads_disabled:%d, compilation_depth:%d\n",    (long)th_self(), prog, finish,    threads_disabled, c->compilation_depth));       c->compilation_depth--;       exit_threads_disable(NULL);
pike.git/src/program.c:4140:      PMOD_EXPORT void pike_set_prog_optimize_callback(node *(*opt)(node *))   {   #ifdef PIKE_DEBUG    if(Pike_compiler->new_program->optimize)    Pike_fatal("Program already has an optimize handler!\n");   #endif    Pike_compiler->new_program->optimize = opt;   }    - int really_low_reference_inherited_identifier(struct program_state *q, -  int e, -  int i) + PMOD_EXPORT int really_low_reference_inherited_identifier(struct program_state *q, +  int i, +  int f)   {    struct program *np=(q?q:Pike_compiler)->new_program;    struct reference funp;    struct program *p;    int d, num_id_refs;    -  if(i==-1) return -1; +  if(f==-1) return -1;    -  p = np->inherits[e].prog; +  p = np->inherits[i].prog;    -  funp = p->identifier_references[i]; -  funp.inherit_offset += e; +  funp = p->identifier_references[f]; +  funp.inherit_offset += i;    funp.id_flags = (funp.id_flags & ~ID_INHERITED) | ID_INLINE|ID_HIDDEN;       num_id_refs = np->num_identifier_references;       for(d = 0; d < num_id_refs; d++)    {    struct reference *refp;    refp = np->identifier_references + d;       if ((refp->inherit_offset == funp.inherit_offset) &&    (refp->identifier_offset == funp.identifier_offset) && -  ((refp->id_flags | ID_USED) == (funp.id_flags | ID_USED))) +  ((refp->id_flags | ID_USED) == (funp.id_flags | ID_USED))) {    return d;    } -  +  }       funp.run_time_type = PIKE_T_UNKNOWN;       if(q)    low_add_to_identifier_references(q,funp);    else    add_to_identifier_references(funp);    /* NOTE: np->num_identifier_references has been increased by one by    * {low_,}add_to_identifier_references().    */   #ifdef PIKE_DEBUG    if (num_id_refs != np->num_identifier_references-1) {    fatal("Unexpected number of identifier references: %d != %d\n",    num_id_refs, np->num_identifier_references-1);    }   #endif /* PIKE_DEBUG */ -  +     return num_id_refs; /* aka np->num_identifier_references - 1 */   }    - int low_reference_inherited_identifier(struct program_state *q, + PMOD_EXPORT int low_reference_inherited_identifier(struct program_state *q,    int e,    struct pike_string *name,    int flags)   {    struct program *np=(q?q:Pike_compiler)->new_program;    struct program *p;    int i;       p=np->inherits[e].prog;    i=find_shared_string_identifier(name,p);
pike.git/src/program.c:4218:    if(p->identifier_references[i].id_flags & ID_PRIVATE)    if(!(flags & SEE_PRIVATE))    return -1;       return really_low_reference_inherited_identifier(q, e, i);   }      int find_inherit(struct program *p, struct pike_string *name)   {    int e; +  int level = p->num_inherits; /* Larger than any inherit_level. */ +  int res = 0;      #if 0    fprintf(stderr, "find_inherit(0x%08lx, \"%s\")...\n",    (unsigned long)p, name->str);   #endif /* 0 */ -  /* FIXME: This loop could be optimized by advancing by the number -  * of inherits in the inherit. But in that case the loop -  * would have to go the other way. -  */ +     for(e = p->num_inherits-1; e>0; e--) {   #if 0    fprintf(stderr, " %04d: %04d %s\n",    e, p->inherits[e].inherit_level,    p->inherits[e].name?p->inherits[e].name->str:"NULL");   #endif /* 0 */ -  if (p->inherits[e].inherit_level > 1) continue; -  if (name == p->inherits[e].name) return e; +  if (p->inherits[e].inherit_level >= level) continue; +  if (name == p->inherits[e].name) { +  res = e; +  level = p->inherits[e].inherit_level; +  if (level == 1) break;    } -  return 0; +     } -  +  return res; + }    - /* Reference the symbol super_name::function_name */ - node *reference_inherited_identifier(struct pike_string *super_name, -  struct pike_string *function_name) + /* Reference the symbol inherit::name in the lexical context +  * specified by state. +  * +  * Returns the reference in state->new_program if found. +  */ + PMOD_EXPORT int reference_inherited_identifier(struct program_state *state, +  struct pike_string *inherit, +  struct pike_string *name)   { -  int n,e,id; -  struct compilation *c = THIS_COMPILATION; -  struct program_state *state=Pike_compiler->previous; -  +  int e, id;    struct program *p;    -  +    #ifdef PIKE_DEBUG -  if(function_name!=debug_findstring(function_name)) -  Pike_fatal("reference_inherited_function on nonshared string.\n"); +  if (name != debug_findstring(name)) +  Pike_fatal("reference_inherited_identifier on nonshared string.\n");   #endif    -  p=Pike_compiler->new_program; +  if (!state) state = Pike_compiler;    -  /* FIXME: This loop could be optimized by advancing by the number -  * of inherits in the inherit. But in that case the loop -  * would have to go the other way. -  */ -  for(e=p->num_inherits-1;e>0;e--) -  { -  if(p->inherits[e].inherit_level!=1) continue; -  if(!p->inherits[e].name) continue; +  p = state->new_program;    -  if(super_name) -  if(super_name != p->inherits[e].name) -  continue; -  -  id=low_reference_inherited_identifier(0, -  e, -  function_name, -  SEE_PROTECTED); -  -  if(id!=-1) -  return mkidentifiernode(id); -  -  if(ISCONSTSTR(function_name,"`->") || -  ISCONSTSTR(function_name,"`[]")) -  { -  return mknode(F_MAGIC_INDEX,mknewintnode(e),mknewintnode(0)); -  } -  -  if(ISCONSTSTR(function_name,"`->=") || -  ISCONSTSTR(function_name,"`[]=")) -  { -  return mknode(F_MAGIC_SET_INDEX,mknewintnode(e),mknewintnode(0)); -  } -  -  if(ISCONSTSTR(function_name,"_indices")) -  { -  return mknode(F_MAGIC_INDICES,mknewintnode(e),mknewintnode(0)); -  } -  -  if(ISCONSTSTR(function_name,"_values")) -  { -  return mknode(F_MAGIC_VALUES,mknewintnode(e),mknewintnode(0)); -  } -  } -  -  -  for(n=0;n<c->compilation_depth;n++,state=state->previous) -  { -  struct program *p=state->new_program; -  +     /* FIXME: This loop could be optimized by advancing by the number    * of inherits in the inherit. But in that case the loop    * would have to go the other way.    */ -  for(e=p->num_inherits-1;e>0;e--) -  { -  if(p->inherits[e].inherit_level!=1) continue; -  if(!p->inherits[e].name) continue; +  for (e = p->num_inherits; e--;) { +  if (p->inherits[e].inherit_level != 1) continue; +  if (inherit && (inherit != p->inherits[e].name)) continue;    -  if(super_name) -  if(super_name != p->inherits[e].name) -  continue; +  id = low_reference_inherited_identifier(state, e, name, SEE_PROTECTED);    -  id=low_reference_inherited_identifier(state,e,function_name,SEE_PROTECTED); -  -  if(id!=-1) -  return mkexternalnode(p, id); -  -  if(ISCONSTSTR(function_name,"`->") || -  ISCONSTSTR(function_name,"`[]")) -  { -  return mknode(F_MAGIC_INDEX, -  mknewintnode(e),mknewintnode(n+1)); +  if (id != -1) return id;    }    -  if(ISCONSTSTR(function_name,"`->=") || -  ISCONSTSTR(function_name,"`[]=")) -  { -  return mknode(F_MAGIC_SET_INDEX, -  mknewintnode(e),mknewintnode(n+1)); +  return -1;   }    -  if(ISCONSTSTR(function_name,"_indices")) -  { -  return mknode(F_MAGIC_INDICES, -  mknewintnode(e),mknewintnode(n+1)); -  } -  -  if(ISCONSTSTR(function_name,"_values")) -  { -  return mknode(F_MAGIC_VALUES, -  mknewintnode(e),mknewintnode(n+1)); -  } -  } -  } -  -  return 0; - } -  +    /* FIXME: This function probably doesn't do what it is intended to do    * if the last inherit had inherits of its own. Consider removal.    */   void rename_last_inherit(struct pike_string *n)   {    if(Pike_compiler->new_program->inherits[Pike_compiler->new_program->num_inherits].name)    free_string(Pike_compiler->new_program->inherits[Pike_compiler->new_program->num_inherits].name);    copy_shared_string(Pike_compiler->new_program->inherits[Pike_compiler->new_program->num_inherits].name,    n);   }
pike.git/src/program.c:4436: Inside #if 0
   parent_offset+=i->parent_offset;   #endif       return locate_parent_state(&state,    &i,    &parent_identifier,    depth);   }   #endif    - #ifdef WITH_FACETS - void check_for_facet_inherit(struct program *p) - { -  /* If the inherit statement comes before the facet keyword in the -  * class declaration the class will be temporarily marked as a -  * product-class, but this will be taken care of when the facet -  * keyword is found. */ -  if (!p) return; -  if (Pike_compiler->new_program->facet_group && -  p->facet_group != Pike_compiler->new_program->facet_group) -  yyerror("A class can not belong to two facet-groups."); -  if (p->flags & PROGRAM_IS_FACET) { -  if (Pike_compiler->new_program->flags & PROGRAM_IS_FACET) { -  if(Pike_compiler->new_program->facet_index != p->facet_index) -  yyerror("Facet class can't inherit from class in different facet."); -  } -  /* Otherwise this is a product class */ -  else { -  if( !Pike_compiler->new_program->facet_group ) { -  Pike_compiler->new_program->flags |= PROGRAM_IS_PRODUCT; -  add_ref(p->facet_group); -  Pike_compiler->new_program->facet_group = p->facet_group; -  } -  push_int(Pike_compiler->new_program->id); -  push_int(p->facet_index); -  push_int(p->id); -  safe_apply(p->facet_group, "add_product_class", 3); -  pop_stack(); -  } -  } -  /* The inherited class is not a facet class */ -  else if (p->flags & PROGRAM_IS_PRODUCT) { -  if (Pike_compiler->new_program->flags & PROGRAM_IS_FACET) { -  yyerror("Facet class can't inherit from product class."); -  } -  else if(Pike_compiler->new_program->flags & PROGRAM_IS_PRODUCT){ -  yyerror("Product class can't inherit from other product class."); -  } -  /* A class that inherits from a product class is also a product class */ -  else { -  Pike_compiler->new_program->flags |= PROGRAM_IS_PRODUCT; -  add_ref(p->facet_group); -  Pike_compiler->new_program->facet_group = p->facet_group; -  } -  } - } - #endif -  -  - /* -  * make this program inherit another program -  */ - PMOD_EXPORT void low_inherit(struct program *p, + void lower_inherit(struct program *p,    struct object *parent,    int parent_identifier,    int parent_offset,    INT32 flags,    struct pike_string *name)   {    int e;    ptrdiff_t inherit_offset, storage_offset;    struct inherit inherit;   
pike.git/src/program.c:4575:    }       if (!(p->flags & (PROGRAM_FINISHED | PROGRAM_PASS_1_DONE))) {    yyerror ("Cannot inherit program in pass 1 "    "which is only a placeholder.");    yyerror ("(You probably have a cyclic symbol dependency that the "    "compiler cannot handle.)");    return;    }    - #ifdef WITH_FACETS -  /* Check if inherit is a facet inherit. */ -  check_for_facet_inherit(p); - #endif -  +     if (p == placeholder_program) {    yyerror("Trying to inherit placeholder program (resolver problem).");    return;    }    -  +  if (p->flags & PROGRAM_HAS_C_METHODS) { +  Pike_compiler->new_program->flags |= PROGRAM_HAS_C_METHODS; +  } +     /* parent offset was increased by 42 for above test.. */    if(parent_offset)    parent_offset-=42;       inherit_offset = Pike_compiler->new_program->num_inherits;       /* alignment magic */    storage_offset=p->inherits[0].storage_offset % p->alignment_needed;    storage_offset=low_add_storage(STORAGE_NEEDED(p),    p->alignment_needed,
pike.git/src/program.c:4715:    if(inherit.parent) add_ref(inherit.parent);       if(name)    {    if(e==0)    {    copy_shared_string(inherit.name,name);    }    else if(inherit.name)    { -  /* FIXME: Wide string handling. */ -  struct pike_string *s; -  s=begin_shared_string(inherit.name->len + name->len + 2); -  MEMCPY(s->str,name->str,name->len); -  MEMCPY(s->str+name->len,"::",2); -  MEMCPY(s->str+name->len+2,inherit.name->str,inherit.name->len); -  inherit.name=end_shared_string(s); +  add_ref(inherit.name);    } -  else -  { -  inherit.name=0; -  } +     }else{    inherit.name=0;    }    add_to_inherits(inherit);    }       /* This value is used by encode_value() to reverse the inherit operation. */    Pike_compiler->new_program->inherits[inherit_offset].identifier_ref_offset =    Pike_compiler->new_program->num_identifier_references;   
pike.git/src/program.c:4764:    if (fun.id_flags & ID_PUBLIC)    fun.id_flags |= flags & ~ID_PRIVATE;    else    fun.id_flags |= flags;       fun.id_flags |= ID_INHERITED;    add_to_identifier_references(fun);    }   }    + /* +  * make this program inherit another program +  */ + PMOD_EXPORT void low_inherit(struct program *p, +  struct object *parent, +  int parent_identifier, +  int parent_offset, +  INT32 flags, +  struct pike_string *name) + { +  lower_inherit(p, parent, parent_identifier, parent_offset, flags, name); +  +  /* Don't do this for OBJECT_PARENT or INHERIT_PARENT inherits. +  * They may show up here from decode_value(). +  */ +  if (parent_offset >= 42) { +  if (p->flags & (PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT)) { +  /* We'll need the parent pointer as well... */ +  struct program_state *state = Pike_compiler; +  +  /* parent offset was increased by 42 by the caller... */ +  parent_offset -= 42; +  +  while (state && state->new_program && parent_offset--) { +  state->new_program->flags |= PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT; +  state = state->previous; +  } +  } +  } + } +    PMOD_EXPORT void do_inherit(struct svalue *s,    INT32 flags,    struct pike_string *name)   {    struct object *parent_obj = NULL;    int parent_id = -1;    struct program *p = low_program_from_svalue(s, &parent_obj, &parent_id);    low_inherit(p, parent_obj, parent_id, 0, flags, name);   }   
pike.git/src/program.c:4835:    do_inherit(s,flags,name);    return;    }else{    low_inherit(s->u.program,    0,    numid,    offset+42,    flags,    name);    } -  if (n->token == F_EXTERNAL) { -  struct program *p=program_from_svalue(s); -  if (p->flags & (PROGRAM_NEEDS_PARENT|PROGRAM_NEEDS_PARENT)) { -  /* We'll need the parent pointer as well... */ -  struct program_state *state = Pike_compiler; -  -  while (state && (state->new_program->id != n->u.integer.a)) { -  state->new_program->flags |= PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT; -  state = state->previous; -  } -  } -  } +     }else{    yyerror("Inherit identifier is not a constant program");    return;    }    break;       default:    resolv_class(n);    do_inherit(Pike_sp-1, flags, name);    pop_stack();
pike.git/src/program.c:5126: Inside #if defined(PROFILING)
   dummy.opt_flags = 0;   #ifdef PROFILING    dummy.self_time=0;    dummy.num_calls=0;    dummy.recur_depth=0;    dummy.total_time=0;   #endif       if (run_time_type == PIKE_T_FREE) dummy.func.offset = -1;    -  if (flags & ID_PRIVATE) flags |= ID_INLINE; +  if (flags & ID_PRIVATE) flags |= ID_LOCAL|ID_PROTECTED;       ref.id_flags=flags;    ref.identifier_offset=Pike_compiler->new_program->num_identifiers;    ref.inherit_offset=0;    ref.run_time_type = PIKE_T_UNKNOWN;       add_to_variable_index(ref.identifier_offset);       debug_add_to_identifiers(dummy);   
pike.git/src/program.c:5174:    free_string(n);    free_type(t);    return ret;   }      /* type is a serialized tokenized type. */   PMOD_EXPORT int quick_map_variable(const char *name,    int name_length,    size_t offset,    const char *type, -  int type_length, +  int UNUSED(type_length),    INT32 run_time_type,    INT32 flags)   {    int ret;    struct pike_string *n;    struct pike_type *t;       n = make_shared_binary_string(name, name_length);    t = make_pike_type(type);   
pike.git/src/program.c:5339:    }    }       if (flags & ID_EXTERN) {    run_time_type = PIKE_T_FREE;    } else {    run_time_type=compile_type_to_runtime_type(type);       switch(run_time_type)    { - #ifdef AUTO_BIGNUM +     case T_INT: - #endif +     case T_OBJECT:    /* Make place for the object subtype. */    case T_FUNCTION:    case T_PROGRAM:    run_time_type = T_MIXED;    }    }       n=low_define_variable(name,type,flags,    low_add_storage(sizeof_variable(run_time_type),
pike.git/src/program.c:5502:    id=ID_FROM_INT(Pike_compiler->new_program,n);    if(id->func.const_info.offset>=0) {    /* Update the stored constant. */    assign_svalue (&PROG_FROM_INT(Pike_compiler->new_program,n)->    constants[id->func.const_info.offset].sval, c);    } else {    id->run_time_type = (unsigned char) TYPEOF(*c);    id->func.const_info.offset = store_constant(c, 0, 0);    }    free_type(id->type); -  if ((TYPEOF(*c) == T_INT) && !(flags & ID_INLINE)) { -  if (c->u.integer) { -  copy_pike_type(id->type, int_type_string); -  } else { -  copy_pike_type(id->type, zero_type_string); -  } -  } else { -  id->type = get_type_of_svalue(c); -  } +  if( !(flags & ID_INLINE) ) +  id->type = get_lax_type_of_svalue( c ); +  else +  id->type = get_type_of_svalue( c );   #ifdef PROGRAM_BUILD_DEBUG    fprintf (stderr, "%.*sstored constant #%d at %d\n",    cc->compilation_depth, "",    n, id->func.const_info.offset);   #endif    }    return n;    }      #ifdef PIKE_DEBUG
pike.git/src/program.c:5540:   #endif       copy_shared_string(dummy.name, name);    dummy.identifier_flags = IDENTIFIER_CONSTANT;    dummy.filename_strno = store_prog_string(cc->lex.current_file);    dummy.linenumber = cc->lex.current_line;      #if 1    if (c) {   #endif -  if ((TYPEOF(*c) == T_INT) && !(flags & ID_INLINE)) { -  if (c->u.integer) { -  copy_pike_type(dummy.type, int_type_string); -  } else { -  copy_pike_type(dummy.type, zero_type_string); -  } -  } else { -  dummy.type = get_type_of_svalue(c); -  } +  if( !(flags & ID_INLINE) ) +  dummy.type = get_lax_type_of_svalue( c ); +  else +  dummy.type = get_type_of_svalue( c );    dummy.run_time_type = (unsigned char) TYPEOF(*c);    dummy.func.const_info.offset = store_constant(c, 0, 0);    dummy.opt_flags=OPT_SIDE_EFFECT | OPT_EXTERNAL_DEPEND;    if(TYPEOF(*c) == PIKE_T_PROGRAM && (c->u.program->flags & PROGRAM_CONSTANT))    dummy.opt_flags=0;   #if 1    }    else {    copy_pike_type(dummy.type, mixed_type_string);    dummy.run_time_type=T_MIXED;    dummy.func.const_info.offset = -1;    dummy.opt_flags=0;    }   #endif    -  if (flags & ID_PRIVATE) flags |= ID_INLINE; +  if (flags & ID_PRIVATE) flags |= ID_LOCAL|ID_PROTECTED;       ref.id_flags=flags;    ref.identifier_offset=Pike_compiler->new_program->num_identifiers;    ref.inherit_offset=0;    ref.run_time_type = PIKE_T_UNKNOWN;      #ifdef PROFILING    dummy.self_time=0;    dummy.num_calls=0;    dummy.recur_depth=0;
pike.git/src/program.c:5602:    }       /* not inherited */    if(Pike_compiler->new_program->identifier_references[n].inherit_offset == 0)    {    my_yyerror("Identifier %S defined twice.", name);    return n;    }       /* override */ -  if ((overridden = override_identifier (&ref, name)) >= 0) { +  if ((overridden = override_identifier (&ref, name, 0)) >= 0) {   #ifdef PIKE_DEBUG    struct reference *oref =    Pike_compiler->new_program->identifier_references+overridden;    if((oref->inherit_offset != ref.inherit_offset) ||    (oref->identifier_offset != ref.identifier_offset) ||    ((oref->id_flags | ID_USED) != (ref.id_flags | ID_USED))) {    Pike_fatal("New constant overriding algorithm failed!\n");    }   #endif    return overridden;
pike.git/src/program.c:5774:    * if func isn't given, it is supposed to be a prototype.    */   INT32 define_function(struct pike_string *name,    struct pike_type *type,    unsigned flags,    unsigned function_flags,    union idptr *func,    unsigned opt_flags)   {    struct compilation *c = THIS_COMPILATION; +  struct program *prog = Pike_compiler->new_program;    struct identifier *funp,fun;    struct reference ref;    struct svalue *lfun_type;    int run_time_type = T_FUNCTION;    INT32 i;    int getter_setter = -1;    int is_setter = 0;       CHECK_COMPILER();   
pike.git/src/program.c:5805: Inside #if defined(PROFILING)
     #ifdef PROFILING    fun.self_time=0;    fun.num_calls=0;    fun.recur_depth=0;    fun.total_time=0;   #endif       /* If this is an lfun, match against the predefined type. */    if ((lfun_type = low_mapping_string_lookup(lfun_types, name))) { +  int orig_pragmas = c->lex.pragmas;   #ifdef PIKE_DEBUG    if (TYPEOF(*lfun_type) != T_TYPE) {    Pike_fatal("Bad entry in lfun_types for key \"%s\"\n", name->str);    }   #endif /* PIKE_DEBUG */ -  +  /* Inhibit deprecation warnings during the comparison. */ +  c->lex.pragmas |= ID_NO_DEPRECATION_WARNINGS;    if (!pike_types_le(type, lfun_type->u.type)) {    int level = REPORT_NOTICE;    if (!match_types(type, lfun_type->u.type)) {    level = REPORT_ERROR;    } else if (c->lex.pragmas & ID_STRICT_TYPES) {    level = REPORT_WARNING;    }    if (level != REPORT_NOTICE) {    yytype_report(level, NULL, 0, lfun_type->u.type,    NULL, 0, type, 0,    "Type mismatch for callback function %S:", name);    }    } -  +  c->lex.pragmas = orig_pragmas;    } else if (((name->len > 3) &&    (index_shared_string(name, 0) == '`') &&    (index_shared_string(name, 1) == '-') &&    (index_shared_string(name, 2) == '>')) ||    ((name->len > 1) &&    (index_shared_string(name, 0) == '`') &&    ((index_shared_string(name, 1) >= 256) ||    isidchar(index_shared_string(name, 1))))) {    /* Getter setter. */    struct pike_string *symbol = NULL;
pike.git/src/program.c:5856:    /* fprintf(stderr, "Got setter: %s\n", name->str); */    gs_type = lfun_setter_type_string;    is_setter = 1;    symbol = string_slice(name, delta, name->len-(delta+1));    symbol_type = get_argument_type(type, 0);    }       if (symbol) {    /* We got a getter or a setter. */    struct reference *ref; +  int orig_pragmas = c->lex.pragmas; +  /* Inhibit deprecation warnings during the comparison. */ +  c->lex.pragmas |= ID_NO_DEPRECATION_WARNINGS;    if (!pike_types_le(type, gs_type)) {    int level = REPORT_NOTICE;    if (!match_types(type, gs_type)) {    level = REPORT_ERROR;    } else if (c->lex.pragmas & ID_STRICT_TYPES) {    level = REPORT_WARNING;    }    yytype_report(level, NULL, 0, gs_type,    NULL, 0, type, 0,    "Type mismatch for callback function %S:", name);    } -  +  c->lex.pragmas = orig_pragmas; +  if (flags & ID_VARIANT) { +  my_yyerror("Variants not supported for getter/setters: %S", name); +  flags &= ~ID_VARIANT; +  }    i = isidentifier(symbol);    if ((i >= 0) && -  !((ref = PTR_FROM_INT(Pike_compiler->new_program, i))-> -  id_flags & ID_INHERITED)) { +  !((ref = PTR_FROM_INT(prog, i))->id_flags & ID_INHERITED)) {    /* Not an inherited symbol. */ -  struct identifier *id = ID_FROM_INT(Pike_compiler->new_program, i); +  struct identifier *id = ID_FROM_INT(prog, i);    if (!IDENTIFIER_IS_VARIABLE(id->identifier_flags)) {    my_yyerror("Illegal to redefine function %S with variable.", symbol);    } else if (id->run_time_type != PIKE_T_GET_SET) {    my_yyerror("Illegal to redefine a current variable with a getter/setter: %S.", symbol);    } else {    if ((ref->id_flags | ID_USED) != (flags | ID_USED)) {    if (Pike_compiler->compiler_pass == 1) {    yywarning("Modifier mismatch for variable %S.", symbol);    }    ref->id_flags &= flags | ID_USED;    }    getter_setter = i;    }    /* FIXME: Update id->type here. */    } else {    struct identifier *id;    i = low_define_variable(symbol, symbol_type, flags,    ~0, PIKE_T_GET_SET); -  id = ID_FROM_INT(Pike_compiler->new_program, i); +  id = ID_FROM_INT(prog, i);       /* Paranoia. */    id->func.gs_info.getter = -1;    id->func.gs_info.setter = -1;       getter_setter = i;    }    /* NOTE: The function needs to have the same PRIVATE/INLINE    * behaviour as the variable for overloading to behave    * as expected.    *    * FIXME: Force PRIVATE?    */    flags |= ID_PROTECTED /* | ID_PRIVATE | ID_INLINE | ID_USED */;    free_type(symbol_type);    free_string(symbol);    }    }       if(IDENTIFIER_IS_C_FUNCTION(function_flags)) -  Pike_compiler->new_program->flags |= PROGRAM_HAS_C_METHODS; +  prog->flags |= PROGRAM_HAS_C_METHODS;       if (Pike_compiler->compiler_pass == 1) {    /* Mark the type as tentative by setting the runtime-type    * to T_MIXED.    *    * NOTE: This should be reset to T_FUNCTION in pass 2.    */    run_time_type = T_MIXED;    }    -  i=isidentifier(name); +  i = isidentifier(name); +  if (Pike_compiler->compiler_pass == 1) { +  if (flags & ID_VARIANT) { +  if (i >= 0) { +  if (!is_variant_dispatcher(prog, i)) { +  /* This function will be the termination function for +  * our variant dispatcher. +  */ +  struct reference ref = prog->identifier_references[i]; +  /* Make sure to not get complaints about multiple +  * definitions when adding the variant dispatcher. +  */ +  prog->identifier_references[i].id_flags |= ID_INHERITED; +  add_variant_dispatcher(name, type, flags); +  /* Restore the termination function as a variant. */ +  ref.id_flags |= ID_VARIANT; +  if (is_variant_dispatcher(prog, i)) { +  /* The termination function got replaced with +  * the variant dispatcher. +  */ +  add_to_identifier_references(ref); +  } else { +  /* The termination function is still in the same place. */ +  prog->identifier_references[i].id_flags = ref.id_flags; +  } +  } else if (prog->identifier_references[i].inherit_offset) { +  /* NB: If we are overriding an inherited dispatcher, there's +  * no need to go via it, since our new dispatcher can +  * just continue on with the old ones variant functions. +  */ +  add_variant_dispatcher(name, type, flags); +  } +  } else { +  add_variant_dispatcher(name, type, flags); +  } +  i = really_low_find_variant_identifier(name, prog, type, +  prog->num_identifier_references, +  SEE_PROTECTED|SEE_PRIVATE); +  } else if (is_variant_dispatcher(prog, i) && +  !prog->identifier_references[i].inherit_offset) { +  if (!func || (func->c_fun != f_dispatch_variant) || +  !IDENTIFIER_IS_C_FUNCTION(function_flags)) { +  /* FIXME: What about the case +  * +  * non-variant prototype; +  * +  * variant; +  * +  * non-variant definition. +  */ +  my_yyerror("Overriding variant function %S() with " +  "non-variant in the same class.", +  name); +  } +  } +  } else if (i >= 0) { +  /* Pass 2 */ +  if (is_variant_dispatcher(prog, i)) { +  if (!func || (func->c_fun != f_dispatch_variant) || +  !IDENTIFIER_IS_C_FUNCTION(function_flags)) { +  /* Variant or variant termination function in second pass. */ +  flags |= ID_VARIANT; +  i = really_low_find_variant_identifier(name, prog, type, +  prog->num_identifier_references, +  SEE_PROTECTED|SEE_PRIVATE); +  } +  } +  }       if(i >= 0)    {    int overridden;       /* already defined */      #ifdef PROGRAM_BUILD_DEBUG    fprintf(stderr, "%.*sexisted as identifier #%d\n",    c->compilation_depth, "", i);   #endif    -  funp=ID_FROM_INT(Pike_compiler->new_program, i); -  ref=Pike_compiler->new_program->identifier_references[i]; +  funp = ID_FROM_INT(prog, i); +  ref = prog->identifier_references[i];       if (funp->identifier_flags & IDENTIFIER_HAS_BODY)    /* Keep this flag. */    function_flags |= IDENTIFIER_HAS_BODY;       if(!(ref.id_flags & ID_INHERITED)) /* not inherited */    {       if( !( IDENTIFIER_IS_FUNCTION(funp->identifier_flags) &&    ( (!func || func->offset == -1) || (funp->func.offset == -1))))    {    my_yyerror("Identifier %S defined twice.", name);       if (getter_setter != -1) { -  struct identifier *id = ID_FROM_INT(Pike_compiler->new_program, -  getter_setter); +  struct identifier *id = ID_FROM_INT(prog, getter_setter);    (&id->func.gs_info.getter)[is_setter] = i;    }    return i;    }       /* Note: The type from pass 1 may be incompatible with the one from    * pass 2. Only do this in pass 2, and only if the previous    * type isn't from pass 1.    */    if ((Pike_compiler->compiler_pass == 2) &&    (funp->run_time_type == T_FUNCTION)) {    /* match types against earlier prototype or vice versa */    if(!match_types(type, funp->type))    { -  if (!(flags & ID_VARIANT)) { +     yytype_report(REPORT_ERROR, NULL, 0,    funp->type,    NULL, 0, type, 0,    "Prototype doesn't match for function %S.", name);    }    } -  } +        if(func)    funp->func = *func;   #if 0 /* prototypes does not override non-prototypes, ok? */    else    funp->func.offset = -1;   #endif       funp->identifier_flags=function_flags;    funp->run_time_type = run_time_type;
pike.git/src/program.c:6006:       if((ref.id_flags & ID_FINAL)   #if 0    && !(funp->func.offset == -1)   #endif    )    {    my_yyerror("Illegal to redefine 'final' function %S.", name);    }    +  if (!(flags & ID_VARIANT) && (Pike_compiler->compiler_pass == 1) && +  (funp->func.c_fun == f_dispatch_variant) && +  (!func || (func->c_fun != f_dispatch_variant) || +  !IDENTIFIER_IS_C_FUNCTION(function_flags)) && +  IDENTIFIER_IS_C_FUNCTION(funp->identifier_flags)) { +  /* Overriding a variant function dispatcher with +  * a non-variant function in pass 1. +  * +  * Hide the corresponding variant functions. +  */ +  int j = prog->num_identifier_references; +  while ((j = really_low_find_variant_identifier(name, prog, NULL, j, +  SEE_PROTECTED|SEE_PRIVATE)) != -1) { +  if (!prog->identifier_references[j].inherit_offset) { +  /* FIXME: This doesn't catch all cases, and should probably +  * be moved to a place where it does. +  */ +  my_yyerror("Overloading variant function %S with non-variant in same class.", +  name); +  } +  prog->identifier_references[j].id_flags |= ID_HIDDEN; +  } +  }       if(ref.id_flags & ID_INLINE)    {   #ifdef PROGRAM_BUILD_DEBUG    fprintf(stderr, "%.*sidentifier is local\n",    c->compilation_depth, "");   #endif    /* Hide the previous definition, and make a new definition. */ -  Pike_compiler->new_program->identifier_references[i].id_flags |= -  ID_PROTECTED; +  prog->identifier_references[i].id_flags |= ID_PROTECTED;    goto make_a_new_def;    }       /* Otherwise we alter the existing definition */   #ifdef PROGRAM_BUILD_DEBUG    fprintf(stderr, "%.*saltering the existing definition\n",    c->compilation_depth, "");   #endif       copy_shared_string(fun.name, name);
pike.git/src/program.c:6041:       fun.identifier_flags=function_flags;       if(func)    fun.func = *func;    else    fun.func.offset = -1;       fun.opt_flags = opt_flags;    -  ref.identifier_offset=Pike_compiler->new_program->num_identifiers; +  ref.identifier_offset = prog->num_identifiers;    debug_add_to_identifiers(fun);    }    -  if (flags & ID_PRIVATE) flags |= ID_INLINE; +  if (flags & ID_PRIVATE) flags |= ID_LOCAL|ID_PROTECTED;       ref.inherit_offset = 0;    ref.id_flags = flags; -  if ((overridden = override_identifier (&ref, name)) >= 0) { +  if (flags & ID_VARIANT) { +  ref.id_flags |= ID_USED; +  prog->identifier_references[i] = ref; +  overridden = i; +  } else { +  overridden = override_identifier(&ref, name, 0); +  } +  if (overridden >= 0) {   #ifdef PIKE_DEBUG -  struct reference *oref = -  Pike_compiler->new_program->identifier_references+overridden; +  struct reference *oref = prog->identifier_references+overridden;    if((oref->inherit_offset != ref.inherit_offset) ||    (oref->identifier_offset != ref.identifier_offset) ||    ((oref->id_flags | ID_USED) != (ref.id_flags | ID_USED))) {    fprintf(stderr,    "ref: %d:%d 0x%04x\n"    "got: %d:%d 0x%04x (%d)\n",    ref.inherit_offset, ref.identifier_offset,    ref.id_flags,    oref->inherit_offset,    oref->identifier_offset,    oref->id_flags,    overridden);    Pike_fatal("New function overloading algorithm failed!\n");    }   #endif       if (getter_setter != -1) { -  struct identifier *id = ID_FROM_INT(Pike_compiler->new_program, -  getter_setter); +  struct identifier *id = ID_FROM_INT(prog, getter_setter);    INT32 old_i = (&id->func.gs_info.getter)[is_setter];    if ((old_i >= 0) && (old_i != overridden)) {    my_yyerror("Multiple definitions for %S.", name);    }    (&id->func.gs_info.getter)[is_setter] = overridden;    }    return overridden;    }    /* NOTE: At this point we already have the identifier in the    * new program, and just need to add the reference.
pike.git/src/program.c:6113:    else    fun.func.offset = -1;       fun.opt_flags = opt_flags;      #ifdef PIKE_DEBUG    if (a_flag > 5) {    fprintf(stderr,    "Adding new function #%d: '%s'\n"    " identifier_flags:0x%02x opt_flags:0x%04x\n", -  Pike_compiler->new_program->num_identifiers, +  prog->num_identifiers,    fun.name->str,    fun.identifier_flags, fun.opt_flags);    }   #endif /* PIKE_DEBUG */    -  i=Pike_compiler->new_program->num_identifiers; +  i = prog->num_identifiers;       debug_add_to_identifiers(fun);    -  if (flags & ID_PRIVATE) flags |= ID_INLINE; +  if (flags & ID_PRIVATE) flags |= ID_LOCAL|ID_PROTECTED;       ref.id_flags = flags;    ref.identifier_offset = i;    ref.inherit_offset = 0;    }       ref.run_time_type = PIKE_T_UNKNOWN;       /* Add the reference. */    -  i=Pike_compiler->new_program->num_identifier_references; +  i = prog->num_identifier_references;    add_to_identifier_references(ref);      #ifdef PROGRAM_BUILD_DEBUG    fprintf(stderr, "%.*sadded new definition #%d\n",    c->compilation_depth, "", i);   #endif       if (getter_setter != -1) { -  struct identifier *id = ID_FROM_INT(Pike_compiler->new_program, -  getter_setter); +  struct identifier *id = ID_FROM_INT(prog, getter_setter);    INT32 old_i = (&id->func.gs_info.getter)[is_setter];    if (old_i >= 0) {    my_yyerror("Multiple definitions for %S.", name);    }    (&id->func.gs_info.getter)[is_setter] = i;    }       return i;   }   
pike.git/src/program.c:6257:    * B-+-foo All versions of Pike    * |    * +-A---foo    *    * External lookup of identifier "foo" in E():    *    * F-+-A---foo --- Pike 7.7.33    * |    * +-E---foo Pike 7.7.34 ---    */ - int really_low_find_shared_string_identifier(struct pike_string *name, + PMOD_EXPORT int really_low_find_shared_string_identifier(struct pike_string *name,    struct program *prog,    int flags)   {    struct reference *funp;    struct identifier *fun;    int id, i, depth, last_inh;      #if 0    CDFPRINTF((stderr,"th(%ld) %p Trying to find %s flags=%d\n",    (long)th_self(), prog, name->str, flags));
pike.git/src/program.c:6285:   #endif /* PIKE_DEBUG */       id = -1;    depth = 0;    last_inh = prog->num_inherits;    i = (int)prog->num_identifier_references;    while(i--)    {    funp = prog->identifier_references + i;    if(funp->id_flags & ID_HIDDEN) continue; +  if(funp->id_flags & ID_VARIANT) continue;    if(funp->id_flags & ID_PROTECTED)    if(!(flags & SEE_PROTECTED))    continue;    fun = ID_FROM_PTR(prog, funp);    /* if(fun->func.offset == -1) continue; * Prototype */    if(!is_same_string(fun->name,name)) continue;    if(funp->id_flags & ID_INHERITED)    {    struct inherit *inh = INHERIT_FROM_PTR(prog, funp);    if ((funp->id_flags & ID_PRIVATE) && !(flags & SEE_PRIVATE)) continue;
pike.git/src/program.c:6325:    depth = inh->inherit_level;    id = i;    }    } else {    return i;    }    }    return id;   }    + int really_low_find_variant_identifier(struct pike_string *name, +  struct program *prog, +  struct pike_type *type, +  int start_pos, +  int flags) + { +  struct reference *funp; +  struct identifier *fun; +  int id, i, depth, last_inh; +  + #if 1 + #ifdef COMPILER_DEBUG +  fprintf(stderr,"th(%ld) %p Trying to find variant \"%s\" start=%d flags=%d\n" +  " type: ", +  (long)th_self(), prog, name->str, start_pos, flags); +  simple_describe_type(type); +  fprintf(stderr, "\n"); + #endif + #endif +  + #ifdef PIKE_DEBUG +  if (!prog) { +  Pike_fatal("really_low_find_variant_identifier(\"%s\", NULL, %p, %d, %d)\n" +  "prog is NULL!\n", name->str, type, start_pos, flags); +  } + #endif /* PIKE_DEBUG */ +  +  id = -1; +  depth = 0; +  last_inh = prog->num_inherits; +  i = start_pos; + #ifdef PIKE_DEBUG +  if (i > (int)prog->num_identifier_references) { +  Pike_fatal("really_low_find_variant_identifier(\"%s\", %p, %p, %d, %d):\n" +  "Start position is past max: %d\n", +  name->str, prog, type, start_pos, flags, +  prog->num_identifier_references); +  } + #endif /* PIKE_DEBUG */ +  while(i--) +  { +  funp = prog->identifier_references + i; +  if(funp->id_flags & ID_HIDDEN) continue; +  if(!(funp->id_flags & ID_VARIANT)) continue; +  if(funp->id_flags & ID_PROTECTED) +  if(!(flags & SEE_PROTECTED)) +  continue; +  fun = ID_FROM_PTR(prog, funp); +  /* if(fun->func.offset == -1) continue; * Prototype */ +  if(!is_same_string(fun->name,name)) continue; +  if(type && (fun->type != type)) continue; +  if(funp->id_flags & ID_INHERITED) +  { +  struct inherit *inh = INHERIT_FROM_PTR(prog, funp); +  if ((funp->id_flags & ID_PRIVATE) && !(flags & SEE_PRIVATE)) continue; +  if (!depth || (depth > inh->inherit_level)) { +  if (id != -1) { +  int j; +  int min_level = depth; +  for (j=last_inh-1; j > funp->inherit_offset; j--) { +  struct inherit *inh2 = prog->inherits + j; +  if (inh2->inherit_level >= min_level) { +  /* Got deeper in the inherit graph */ +  continue; +  } +  min_level = inh2->inherit_level; +  } +  if (!(inh->inherit_level < min_level)) { +  continue; +  } +  /* Found new identifier on the path from the old identifier to +  * the root. +  */ +  } +  last_inh = funp->inherit_offset; +  depth = inh->inherit_level; +  id = i; +  } +  } else { +  CDFPRINTF((stderr, "Found %d\n", i)); +  return i; +  } +  } +  CDFPRINTF((stderr, "Found %d\n", id)); +  return id; + } +  + /** +  * This is the dispatcher function for variant functions. +  * +  * cf end_first_pass(). +  */ + static void f_dispatch_variant(INT32 args) + { +  struct pike_frame *fp = Pike_fp; +  struct program *prog = fp->context->prog; +  struct reference *funp = PTR_FROM_INT(fp->current_program, fp->fun); +  struct identifier *id = ID_FROM_PTR(fp->current_program, funp); +  struct pike_string *name = id->name; +  int fun_num = prog->num_identifier_references; +  int flags = 0; +  +  /* NB: The following is mostly to support a potential future +  * case where a mixed set of protections would cause +  * multiple dispatchers with the same name to be added +  * (but different protection (and types)). +  */ +  if (funp->id_flags & ID_PRIVATE) { +  flags = SEE_PRIVATE|SEE_PROTECTED; +  } else if (funp->id_flags & ID_PROTECTED) { +  flags = SEE_PROTECTED; +  } +  +  while ((fun_num = really_low_find_variant_identifier(name, prog, NULL, +  fun_num, flags)) != -1) { +  int i; +  struct pike_type *t; +  struct pike_type *ret; +  +  id = ID_FROM_INT(prog, fun_num); +  add_ref(t = id->type); +  +  /* Check whether the type is compatible with our arguments. */ +  for (i = 0; i < args; i++) { +  struct pike_type *cont = check_call_svalue(t, 0, Pike_sp+i - args); +  free_type(t); +  if (!(t = cont)) break; +  } +  if (!t) continue; +  ret = new_get_return_type(t, 0); +  free_type(t); +  if (!ret) continue; +  free_type(ret); +  +  /* Found a function to call! */ +  apply_current(fun_num, args); +  return; +  } +  Pike_error("Invalid arguments to %S()!\n", name); + } +    PMOD_EXPORT int low_find_lfun(struct program *p, ptrdiff_t lfun)   {    struct pike_string *lfun_name = lfun_strings[lfun];    unsigned int flags = 0;   #if 0    struct identifier *id;   #endif    int i =    really_low_find_shared_string_identifier(lfun_name,    dmalloc_touch(struct program *,
pike.git/src/program.c:6483:    return i;       reference_shared_string(str);    add_to_strings(str);    return i;   }      /* NOTE: O(n¬≤)! */   int store_constant(const struct svalue *foo,    int equal, -  struct pike_string *constant_name) +  struct pike_string *UNUSED(constant_name))   {    struct program_constant tmp;    volatile unsigned int e;       JMP_BUF jmp;    if (SETJMP(jmp)) {    handle_compile_exception ("Error comparing constants.");    /* Assume that if `==() throws an error, the svalues aren't equal. */    e = Pike_compiler->new_program->num_constants;    } else {
pike.git/src/program.c:6548:    */      struct array *program_indices(struct program *p)   {    int e;    int n = 0;    struct array *res;    for (e = p->num_identifier_references; e--; ) {    struct identifier *id;    if (p->identifier_references[e].id_flags & -  (ID_HIDDEN|ID_PROTECTED|ID_PRIVATE)) { +  (ID_HIDDEN|ID_VARIANT|ID_PROTECTED|ID_PRIVATE)) {    continue;    }    id = ID_FROM_INT(p, e);    if (IDENTIFIER_IS_ALIAS(id->identifier_flags)) {    /* FIXME!    */    continue;    } else if (IDENTIFIER_IS_CONSTANT(id->identifier_flags)) {    if (id->func.const_info.offset >= 0) {    struct program *p2 = PROG_FROM_INT(p, e);
pike.git/src/program.c:6587:   }      struct array *program_values(struct program *p)   {    int e;    int n = 0;    struct array *res;    for(e = p->num_identifier_references; e--; ) {    struct identifier *id;    if (p->identifier_references[e].id_flags & -  (ID_HIDDEN|ID_PROTECTED|ID_PRIVATE)) { +  (ID_HIDDEN|ID_VARIANT|ID_PROTECTED|ID_PRIVATE)) {    continue;    }    id = ID_FROM_INT(p, e);    if (IDENTIFIER_IS_ALIAS(id->identifier_flags)) {    /* FIXME!    */    continue;    } else if (IDENTIFIER_IS_CONSTANT(id->identifier_flags)) {    if (id->func.const_info.offset >= 0) {    struct program *p2 = PROG_FROM_INT(p, e);
pike.git/src/program.c:6626:   }      struct array *program_types(struct program *p)   {    int e;    int n = 0;    struct array *res;    for (e = p->num_identifier_references; e--; ) {    struct identifier *id;    if (p->identifier_references[e].id_flags & -  (ID_HIDDEN|ID_PROTECTED|ID_PRIVATE)) { +  (ID_HIDDEN|ID_VARIANT|ID_PROTECTED|ID_PRIVATE)) {    continue;    }    id = ID_FROM_INT(p, e);    if (IDENTIFIER_IS_ALIAS(id->identifier_flags)) {    /* FIXME!    */    continue;    } else if (IDENTIFIER_IS_CONSTANT(id->identifier_flags)) {    if (id->func.const_info.offset >= 0) {    struct program *p2 = PROG_FROM_INT(p, e);
pike.git/src/program.c:6769:    if (low_program_index_no_free(to, p, e, parent, parent_identifier))    return 1;    }       SET_SVAL(*to, T_INT, NUMBER_UNDEFINED, integer, 0);    return 1;   }      /*    * Line number support routines, now also tells what file we are in. -  * -  * FIXME: Consider storing the filenames in strings (like what is now done -  * for identifiers). +     */      /* program.linenumbers format:    *    * Filename entry:    * 1. char 127 (marker). -  * 2. small number Filename string length. -  * 3. char Filename string size shift. -  * 4. string data (Possibly wide) filename string without null -  * termination. -  * Each character is stored in native byte order. +  * 2. small number Filename entry number in string table.    *    * Line number entry:    * 1. small number Index in program.program (pc).    * Stored as the difference from the pc in the    * closest previous line number entry. The first    * stored entry is absolute.    * 2. small number Line number. Stored in the same way as the pc.    *    * Small number:    * If -127 < n < 127:
pike.git/src/program.c:6958:    *(*ptr)++ = a>>8;    *(*ptr)++ = a;    }   }      void ext_store_program_line (struct program *prog, INT_TYPE line, struct pike_string *file)   {    char *ptr;      #ifdef PIKE_DEBUG -  if (prog->linenumbers) +  if (prog->linenumbers || prog->strings)    Pike_fatal ("Program already got linenumber info.\n");    if (Pike_compiler->new_program == prog)    Pike_fatal ("Use store_linenumber instead when the program is compiled.\n");   #endif    -  ptr = prog->linenumbers = xalloc (1 + 5 + 1 + (file->len << file->size_shift) + 1 + 11); +  add_ref((prog->strings = xalloc(sizeof(struct pike_string *)))[0] = file); +  prog->num_strings = 1; +  +  ptr = prog->linenumbers = xalloc (1 + 1 + 1 + 11);    *ptr++ = 127; /* 1 */ -  ext_insert_small_number (&ptr, file->len); /* 5 */ -  *ptr++ = (char) file->size_shift; /* 1 */ -  MEMCPY (ptr, file->str, file->len << file->size_shift); /* - */ -  ptr += file->len << file->size_shift; +  *ptr++ = 0; /* String #0 */ /* 1 */    *ptr++ = 0; /* PC */ /* 1 */    ext_insert_small_number (&ptr, line); /* 11 */    prog->num_linenumbers = ptr - prog->linenumbers;   }      void store_linenumber(INT_TYPE current_line, struct pike_string *current_file)   {   /* if(!store_linenumbers) Pike_fatal("Fnord.\n"); */   #ifdef PIKE_DEBUG    if(a_flag)    {    INT_TYPE line=0;    INT32 off=0; -  size_t len = 0; -  INT32 shift = 0; -  char *file=0; +     char *cnt=Pike_compiler->new_program->linenumbers; -  +  struct pike_string *file = NULL;       if (a_flag > 50) {    fprintf(stderr, "store_linenumber(%ld, \"%s\") at pc %d\n",    (long)current_line, current_file->str,    (INT32) PIKE_PC);    fprintf(stderr, " last_line:%ld last_file:\"%s\"\n",    (long)Pike_compiler->last_line,    Pike_compiler->last_file?Pike_compiler->last_file->str:"");    }       while(cnt < Pike_compiler->new_program->linenumbers +    Pike_compiler->new_program->num_linenumbers)    {    char *start = cnt;    if(*cnt == 127)    { -  +  int strno;    cnt++; -  len = get_small_number(&cnt); -  shift = *cnt; -  file = ++cnt; -  CHECK_FILE_ENTRY (Pike_compiler->new_program, cnt, len, shift); -  cnt += len<<shift; +  strno = get_small_number(&cnt); +  CHECK_FILE_ENTRY (Pike_compiler->new_program, strno);    if (a_flag > 100) { -  +  file = Pike_compiler->new_program->strings[strno];    fprintf(stderr, "Filename entry:\n"    " len: %"PRINTSIZET"d, shift: %d\n", -  len, shift); +  file->len, file->size_shift);    }    }    off+=get_small_number(&cnt);    line+=get_small_number(&cnt);    if (a_flag > 100) {    fprintf(stderr, " off: %d, line: %ld\n"    " raw: ",    off, (long)line);    for (;start < cnt; start++) {    fprintf(stderr, "%02x ", *((unsigned char *)start));    }    fprintf(stderr, "\n");    }    }       if(Pike_compiler->last_line != line ||    Pike_compiler->last_pc != off || -  (Pike_compiler->last_file && file && -  MEMCMP(Pike_compiler->last_file->str, file, len<<shift))) +  (file && (Pike_compiler->last_file != file)))    {    Pike_fatal("Line numbering out of whack\n"    " (line : %ld ?= %ld)!\n"    " ( pc : %d ?= %d)!\n"    " (shift: %d ?= %d)!\n"    " (len : %"PRINTSIZET"d ?= %"PRINTSIZET"d)!\n"    " (file : %s ?= %s)!\n",    (long)Pike_compiler->last_line, (long)line,    Pike_compiler->last_pc, off,    Pike_compiler->last_file?Pike_compiler->last_file->size_shift:0, -  shift, -  Pike_compiler->last_file?Pike_compiler->last_file->len:0, len, +  file?file->size_shift:0, +  Pike_compiler->last_file?Pike_compiler->last_file->len:0, +  file?file->len:0,    Pike_compiler->last_file?Pike_compiler->last_file->str:"N/A", -  file?file:"N/A"); +  file?file->str:"N/A");    }    }   #endif    if(Pike_compiler->last_line != current_line ||    Pike_compiler->last_file != current_file)    {    if(Pike_compiler->last_file != current_file)    { -  char *tmp; -  INT32 remain = DO_NOT_WARN((INT32)current_file->len)<< -  current_file->size_shift; -  +     if(Pike_compiler->last_file) free_string(Pike_compiler->last_file);    add_to_linenumbers(127); -  insert_small_number(DO_NOT_WARN((INT32)current_file->len)); -  add_to_linenumbers(current_file->size_shift); -  for(tmp=current_file->str; remain-- > 0; tmp++) -  add_to_linenumbers(*tmp); +  insert_small_number(store_prog_string(current_file));    copy_shared_string(Pike_compiler->last_file, current_file);    }    insert_small_number(DO_NOT_WARN((INT32)(PIKE_PC-Pike_compiler->last_pc)));    insert_small_number(current_line-Pike_compiler->last_line);    Pike_compiler->last_line = current_line;    Pike_compiler->last_pc = DO_NOT_WARN((INT32)PIKE_PC);    }   }    - #define FIND_PROGRAM_LINE(prog, file, len, shift, line) do { \ + #define FIND_PROGRAM_LINE(prog, file, line) do { \    char *pos = prog->linenumbers; \ -  len = 0; \ -  shift = 0; \ +     file = NULL; \    \    if (pos < prog->linenumbers + prog->num_linenumbers) { \    if (*pos == 127) { \ -  +  int strno; \    pos++; \ -  len = get_small_number(&pos); \ -  shift = *pos; \ -  file = ++pos; \ -  CHECK_FILE_ENTRY (prog, pos, len, shift); \ -  pos += len<<shift; \ +  strno = get_small_number(&pos); \ +  CHECK_FILE_ENTRY (prog, strno); \ +  file = prog->strings[strno]; \    } \    get_small_number(&pos); /* Ignore the offset */ \    line = get_small_number(&pos); \    } \    } while (0)      PMOD_EXPORT struct pike_string *low_get_program_line (struct program *prog,    INT_TYPE *linep)   {    *linep = 0;       if (prog->linenumbers) { -  size_t len; -  INT32 shift; -  char *file; +  struct pike_string *file;    -  FIND_PROGRAM_LINE (prog, file, len, shift, (*linep)); +  FIND_PROGRAM_LINE (prog, file, (*linep));       if (file) { -  struct pike_string *str = begin_wide_shared_string(len, shift); -  memcpy(str->str, file, len<<shift); -  return end_shared_string(str); +  add_ref(file); +  return file;    }    }       return NULL;   }    - static char *make_plain_file (char *file, size_t len, INT32 shift, int malloced) + static char *make_plain_file (struct pike_string *filename, int malloced)   {    static char buf[1000]; -  +  char *file = filename->str; +  size_t len = filename->len; +  INT32 shift = filename->size_shift; +     if(shift)    {    size_t bufsize;    char *buffer;    PCHARP from=MKPCHARP(file, shift);    size_t ptr=0;       if (malloced) { -  bufsize = len + 1; +  bufsize = len + 21;    buffer = malloc (bufsize);    }    else {    bufsize = NELEM(buf) - 1;    buffer = buf;    }       for (; len--; INC_PCHARP(from, 1))    {    size_t space;
pike.git/src/program.c:7193:    * can't be touched. It also converts wide strings to ordinary ones    * with escaping.    */   PMOD_EXPORT char *low_get_program_line_plain(struct program *prog,    INT_TYPE *linep,    int malloced)   {    *linep = 0;       if (prog->linenumbers) { -  char *file; -  size_t len; -  INT32 shift; -  FIND_PROGRAM_LINE (prog, file, len, shift, (*linep)); -  if (file) return make_plain_file (file, len, shift, malloced); +  struct pike_string *file; +  FIND_PROGRAM_LINE (prog, file, (*linep)); +  if (file) +  return make_plain_file(file, malloced);    }       return NULL;   }      /* Returns the file where the program is defined. The line of the    * class start is written to linep, or 0 if the program is the top    * level of the file. */   PMOD_EXPORT struct pike_string *get_program_line(struct program *prog,    INT_TYPE *linep)
pike.git/src/program.c:7227:      PMOD_EXPORT struct pike_string *low_get_line (PIKE_OPCODE_T *pc,    struct program *prog,    INT_TYPE *linep)   {    linep[0] = 0;       if (prog->program && prog->linenumbers) {    ptrdiff_t offset = pc - prog->program;    if ((offset < (ptrdiff_t)prog->num_program) && (offset >= 0)) { -  static char *file = NULL; +  static struct pike_string *file = NULL;    static char *base, *cnt;    static ptrdiff_t off;    static INT32 pid;    static INT_TYPE line; -  static size_t len; -  static INT32 shift; +        if(prog->linenumbers == base && prog->id == pid && offset > off &&    cnt < prog->linenumbers + prog->num_linenumbers)    goto fromold;       base = cnt = prog->linenumbers;    off=line=0;    pid=prog->id;    file = 0;       while(cnt < prog->linenumbers + prog->num_linenumbers)    {    if(*cnt == 127)    { -  +  int strno;    cnt++; -  len = get_small_number(&cnt); -  shift = *cnt; -  file = ++cnt; -  CHECK_FILE_ENTRY (prog, cnt, len, shift); -  cnt += len<<shift; +  strno = get_small_number(&cnt); +  CHECK_FILE_ENTRY (prog, strno); +  file = prog->strings[strno];    continue;    }    off+=get_small_number(&cnt);    fromold:    if(off > offset) break;    line+=get_small_number(&cnt);    }    if (cnt >= prog->linenumbers + prog->num_linenumbers) {    /* We reached the end of the table. Make sure    * we get in sync again next time we're called.    */    base = NULL;    }    linep[0]=line;    if (file) { -  struct pike_string *res = begin_wide_shared_string(len, shift); -  memcpy(res->str, file, len<<shift); -  return end_shared_string(res); +  add_ref(file); +  return file;    }    } else {    fprintf(stderr, "Bad offset: pc:%p program:%p (%p)\n",    pc, prog->program, (void *)prog->num_program);    }    } else {    fprintf(stderr, "No program of linenumbers program:%p linenumbers:%p\n",    prog->program, prog->linenumbers);    }   
pike.git/src/program.c:7299:   {    linep[0] = 0;       if (prog->program && prog->linenumbers) {    ptrdiff_t offset = pc - prog->program;       if ((offset < (ptrdiff_t)prog->num_program) && (offset >= 0)) {    char *cnt = prog->linenumbers;    INT32 off = 0;    INT_TYPE line = 0; -  char *file = NULL; -  size_t len = 0; -  INT32 shift = 0; +  struct pike_string *file = NULL;       while(cnt < prog->linenumbers + prog->num_linenumbers)    {    if(*cnt == 127)    { -  +  int strno;    cnt++; -  len = get_small_number(&cnt); -  shift = *cnt; -  file = ++cnt; -  CHECK_FILE_ENTRY (prog, cnt, len, shift); -  cnt += len<<shift; +  strno = get_small_number(&cnt); +  CHECK_FILE_ENTRY (prog, strno); +  file = prog->strings[strno];    }    off+=get_small_number(&cnt);    if(off > offset) break;    line+=get_small_number(&cnt);    }    linep[0]=line;    -  if (file) return make_plain_file (file, len, shift, malloced); +  if (file) +  return make_plain_file(file, malloced);    }    }       return NULL;   }      #ifdef PIKE_DEBUG   /* Variants for convenient use from a debugger. */      void gdb_program_line (struct program *prog)
pike.git/src/program.c:7669:    if (s) {    push_string(s);    yyreport(REPORT_ERROR, parser_system_string, 1, "%s");    }    }       pop_stack();    free_svalue(&thrown);   }    - extern void yyparse(void); + extern int yyparse(void);      #ifdef PIKE_DEBUG   #define do_yyparse() do { \    struct svalue *save_sp=Pike_sp; \    yyparse(); /* Parse da program */ \    if(save_sp != Pike_sp) { \    Pike_fatal("yyparse() left %"PRINTPTRDIFFT"d droppings on the stack!\n", \    Pike_sp - save_sp); \    } \   }while(0)
pike.git/src/program.c:7696: Inside #if defined(PIKE_DEBUG)
     #ifdef PIKE_DEBUG      struct supporter_marker   {    struct supporter_marker *next;    void *data;    int level, verified;   };    - #undef EXIT_BLOCK - #define EXIT_BLOCK(P) - #undef COUNT_OTHER - #define COUNT_OTHER() -  +    #undef INIT_BLOCK   #define INIT_BLOCK(X) do { (X)->level = (X)->verified = 0; }while(0)   PTR_HASH_ALLOC(supporter_marker, 128);      static int supnum;      #define SNUM(X) (get_supporter_marker((X))->level)      static void mark_supporters(struct Supporter *s)   {
pike.git/src/program.c:8152:    args = 1;    if (TYPEOF(Pike_sp[-1]) != T_OBJECT) {    Pike_error("Bad return value from PikeCompiler().\n");    }    apply(Pike_sp[-1].u.object, "compile", 0);    stack_pop_n_elems_keep_top(args);   }      /*! @decl mixed resolv(string identifier, string filename, @    *! object|void handler) +  *! +  *! Look up @[identifier] in the current context. +  *! +  *! The default implementation calls the corresponding +  *! function in the master object.    */   static void f_compilation_env_resolv(INT32 args)   {    struct pike_string *ident;    struct pike_string *filename;    struct object *handler = NULL;       get_all_args("resolv", args, "%W%W.%O",    &ident, &filename, &handler);   
pike.git/src/program.c:8625:    c->p=debug_malloc_pass(end_program());       run_exit(c);   }      static void run_cleanup(struct compilation *c, int delayed)   {    debug_malloc_touch(c);    debug_malloc_touch(c->placeholder);   #if 0 /* FIXME */ + #ifdef PIKE_THREADS    if (threads_disabled != c->saved_threads_disabled) {    Pike_fatal("compile(): threads_disabled:%d saved_threads_disabled:%d\n",    threads_disabled, c->saved_threads_disabled);    } -  + #endif   #endif /* PIKE_DEBUG */       exit_threads_disable(NULL);       CDFPRINTF((stderr,    "th(%ld) %p run_cleanup(): "    "threads_disabled:%d, compilation_depth:%d\n",    (long)th_self(), c->target,    threads_disabled, c->compilation_depth));    if (!c->p)
pike.git/src/program.c:9089:    return;    }      #ifdef PIKE_DEBUG    SET_ONERROR(tmp, fatal_on_error,"Compiler exited with longjump!\n");   #endif       c->flags |= COMPILER_BUSY;       low_init_threads_disable(); + #ifdef PIKE_THREADS    c->saved_threads_disabled = threads_disabled; -  + #endif       init_supporter(& c->supporter,    (supporter_callback *) call_delayed_pass2,    (void *)c);       delay=run_pass1(c);    dependants_ok = call_dependants(& c->supporter, !!c->p );   #ifdef PIKE_DEBUG    /* FIXME */    UNSET_ONERROR(tmp);
pike.git/src/program.c:9666: Inside #if defined(PIKE_DEBUG)
   new_frame->context->prog, compilation_program);    }   #endif /* PIKE_DEBUG */    new_frame->fun = new_frame->context->identifier_level + PC_COMPILE_FUN_NUM;    new_frame->expendible = Pike_sp;    new_frame->locals = Pike_sp;    new_frame->save_sp = Pike_sp;    new_frame->save_mark_sp = Pike_mark_sp;    new_frame->mark_sp_base = Pike_mark_sp;    new_frame->args = 0; +  new_frame->num_args = 0;    new_frame->num_locals = 0;    new_frame->pc = 0;    new_frame->return_addr = 0;    new_frame->scope = 0;    new_frame->save_sp = Pike_sp;    Pike_fp = new_frame;   }      PMOD_EXPORT void enter_compiler(struct pike_string *filename,    INT_TYPE linenumber)
pike.git/src/program.c:9717:   /*! @class CompilerState    *!    *! Keeps the state of a single program/class during compilation.    *!    *! @note    *! Not in use yet!    */      #define THIS_PROGRAM_STATE ((struct program_state *)(Pike_fp->current_storage))    - static void program_state_event_handler(int event) + static void program_state_event_handler(int UNUSED(event))   {   #if 0    struct program_state *c = THIS_PROGRAM_STATE;    switch (event) {    case PROG_EVENT_INIT:   #define INIT   #include "compilation.h"    break;    case PROG_EVENT_EXIT:   #define EXIT
pike.git/src/program.c:10046:    ref_push_mapping(get_builtin_constants());    }    free_svalue(& c->default_module);    move_svalue (&c->default_module, --Pike_sp);      #ifdef PIKE_DEBUG    SET_ONERROR(tmp, fatal_on_error,"Compiler exited with longjump!\n");   #endif       low_init_threads_disable(); + #ifdef PIKE_THREADS    c->saved_threads_disabled = threads_disabled; -  + #endif       init_supporter(& c->supporter,    (supporter_callback *) call_delayed_pass2,    (void *)c);       delay=run_pass1(c);    dependants_ok = call_dependants(& c->supporter, !!c->p );   #ifdef PIKE_DEBUG    /* FIXME */    UNSET_ONERROR(tmp);
pike.git/src/program.c:10145:    }    free_string(name_tmp);    free_type(type_tmp);    return ret;   }      PMOD_EXPORT int quick_add_function(const char *name,    int name_length,    void (*cfun)(INT32),    const char *type, -  int type_length, +  int UNUSED(type_length),    unsigned flags,    unsigned opt_flags)   {    int ret;    struct pike_string *name_tmp;    struct pike_type *type_tmp;    union idptr tmp;   /* fprintf(stderr,"ADD_FUNC: %s\n",name); */    name_tmp = make_shared_binary_string(name, name_length);    type_tmp = make_pike_type(type);
pike.git/src/program.c:10211: Inside #if defined(PIKE_DEBUG)
   }   #endif      }   #endif      #undef THIS   #define THIS ((struct pike_trampoline *)(CURRENT_STORAGE))   struct program *pike_trampoline_program=0;    - static void apply_trampoline(INT32 args) + static void apply_trampoline(INT32 UNUSED(args))   {    Pike_error("Internal error: Trampoline magic failed!\n");   }      static void not_trampoline(INT32 args)   {    pop_n_elems(args);    if (!THIS->frame || !THIS->frame->current_object ||    !THIS->frame->current_object->prog) {    push_int(1);
pike.git/src/program.c:10249:       ref_push_function (THIS->frame->current_object, THIS->func);    init_buf(&save_buf);    describe_svalue (sp - 1, 0, 0);    str = complex_free_buf(&save_buf);    pop_stack();    push_string (make_shared_binary_string (str.str, str.len));    free (str.str);   }    - static void init_trampoline(struct object *o) + static void init_trampoline(struct object *UNUSED(o))   {    THIS->frame=0;   }    - static void exit_trampoline(struct object *o) + static void exit_trampoline(struct object *UNUSED(o))   {    if(THIS->frame)    {    free_pike_scope(THIS->frame);    THIS->frame=0;    }   }      static void gc_check_frame(struct pike_frame *f)   {
pike.git/src/program.c:10277:    if(f->current_object)    debug_gc_check (f->current_object, " as current_object in trampoline frame");    if(f->current_program)    debug_gc_check (f->current_program, " as current_program in trampoline frame");    debug_gc_check_svalues (f->locals, f->num_locals, " in locals of trampoline frame");    if(f->scope && !debug_gc_check (f->scope, " as scope frame of trampoline frame"))    gc_check_frame(f->scope);    }   }    - static void gc_check_trampoline(struct object *o) + static void gc_check_trampoline(struct object *UNUSED(o))   {    if (THIS->frame &&    !debug_gc_check (THIS->frame, " as trampoline frame"))    gc_check_frame(THIS->frame);   }      static void gc_recurse_frame(struct pike_frame *f)   {    if(f->current_object) gc_recurse_object(f->current_object);    if(f->current_program) gc_recurse_program(f->current_program);    if(f->flags & PIKE_FRAME_MALLOCED_LOCALS)    gc_recurse_svalues(f->locals,f->num_locals);    if(f->scope) gc_recurse_frame(f->scope);   }    - static void gc_recurse_trampoline(struct object *o) + static void gc_recurse_trampoline(struct object *UNUSED(o))   {    if (THIS->frame) gc_recurse_frame(THIS->frame);   }         /* This placeholder should be used    * in the first compiler pass to take the place    * of unknown things    */   struct program *placeholder_program;
pike.git/src/program.c:10333:    MAKE_CONST_STRING (s, "__placeholder_object");    ref_push_string (s);   }      void init_program(void)   {    size_t i;    struct svalue key;    struct svalue val;    struct svalue id; -  init_program_blocks(); +        MAKE_CONST_STRING(this_function_string,"this_function");    MAKE_CONST_STRING(this_program_string,"this_program");    MAKE_CONST_STRING(this_string,"this");    MAKE_CONST_STRING(UNDEFINED_string,"UNDEFINED");       MAKE_CONST_STRING(parser_system_string, "parser");    MAKE_CONST_STRING(type_check_system_string, "type_check");       lfun_ids = allocate_mapping(NUM_LFUNS);
pike.git/src/program.c:10925:    free_type(f->current_type);       if(f->current_return_type)    free_type(f->current_return_type);       Pike_compiler->compiler_frame=f->previous;    dmfree((char *)f);   }       + PMOD_EXPORT char *get_inherit_storage(struct object *o, int inherit) + { +  if (!o || !o->prog) return NULL; + #ifdef PIKE_DEBUG +  if ((inherit < 0) || (inherit >= o->prog->num_inherits)) +  Pike_fatal("Inherit #%d out of range [0..%d]\n", +  inherit, o->prog->num_inherits-1); + #endif +  return o->storage + o->prog->inherits[inherit].storage_offset; + } +    #define GET_STORAGE_CACHE_SIZE 1024   static struct get_storage_cache   {    INT32 oid, pid;    ptrdiff_t offset;   } get_storage_cache[GET_STORAGE_CACHE_SIZE];      PMOD_EXPORT ptrdiff_t low_get_storage(struct program *o, struct program *p)   {    INT32 oid, pid;
pike.git/src/program.c:10984: Inside #if defined(_REENTRANT)
     #ifdef _REENTRANT    if(d_flag) CHECK_INTERPRETER_LOCK();   #endif       offset= low_get_storage(o->prog, p);    if(offset == -1) return 0;    return o->storage + offset;   }    - struct program *low_program_from_function(struct object *o, INT32 i) + PMOD_EXPORT struct program *low_program_from_function(struct object *o, INT32 i)   {    struct svalue *f;    struct program *p;    struct identifier *id;    while(1) {    struct external_variable_context loc;    p = o->prog;       if(!p) return 0;   
pike.git/src/program.c:11121:      /* returns 1 if a implements b */   static int low_implements(struct program *a, struct program *b)   {    int e;    struct pike_string *s=findstring("__INIT");    for(e=0;e<b->num_identifier_references;e++)    {    struct identifier *bid;    int i; -  if (b->identifier_references[e].id_flags & (ID_PROTECTED|ID_HIDDEN)) +  if (b->identifier_references[e].id_flags & (ID_PROTECTED|ID_HIDDEN|ID_VARIANT))    continue; /* Skip protected & hidden */    bid = ID_FROM_INT(b,e);    if(s == bid->name) continue; /* Skip __INIT */    i = find_shared_string_identifier(bid->name,a);    if (i == -1) {    if (b->identifier_references[e].id_flags & (ID_OPTIONAL))    continue; /* It's ok... */   #if 0    fprintf(stderr, "Missing identifier \"%s\"\n", bid->name->str);   #endif /* 0 */
pike.git/src/program.c:11202:    if (a->num_identifier_references < b->num_identifier_references) {    struct program *tmp = a;    a = b;    b = tmp;    }       for(e=0;e<b->num_identifier_references;e++)    {    struct identifier *bid;    int i; -  if (b->identifier_references[e].id_flags & (ID_PROTECTED|ID_HIDDEN)) +  if (b->identifier_references[e].id_flags & (ID_PROTECTED|ID_HIDDEN|ID_VARIANT))    continue; /* Skip protected & hidden */       /* FIXME: What if they aren't protected & hidden in a? */       bid = ID_FROM_INT(b,e);    if(s == bid->name) continue; /* Skip __INIT */    i = find_shared_string_identifier(bid->name,a);    if (i == -1) {    continue; /* It's ok... */    }
pike.git/src/program.c:11324:    }    SET_CYCLIC_RET(1);       a_file = get_program_line(a, &a_line);    b_file = get_program_line(b, &b_line);       for(e=0;e<b->num_identifier_references;e++)    {    struct identifier *bid;    int i; -  if (b->identifier_references[e].id_flags & (ID_PROTECTED|ID_HIDDEN)) +  if (b->identifier_references[e].id_flags & (ID_PROTECTED|ID_HIDDEN|ID_VARIANT))    continue; /* Skip protected & hidden */       /* FIXME: What if they aren't protected & hidden in a? */       bid = ID_FROM_INT(b,e);    if(s == bid->name) continue; /* Skip __INIT */    i = find_shared_string_identifier(bid->name,a);    if (i == -1) {    continue; /* It's ok... */    }
pike.git/src/program.c:11386:    }    SET_CYCLIC_RET(1);       a_file = get_program_line(a, &a_line);    b_file = get_program_line(b, &b_line);       for(e=0;e<b->num_identifier_references;e++)    {    struct identifier *bid;    int i; -  if (b->identifier_references[e].id_flags & (ID_PROTECTED|ID_HIDDEN)) +  if (b->identifier_references[e].id_flags & (ID_PROTECTED|ID_HIDDEN|ID_VARIANT))    continue; /* Skip protected & hidden */    bid = ID_FROM_INT(b,e);    if(s == bid->name) continue; /* Skip __INIT */    i = find_shared_string_identifier(bid->name,a);    if (i == -1) {    INT_TYPE bid_line = b_line;    struct pike_string *bid_file;    if (b->identifier_references[e].id_flags & (ID_OPTIONAL))    continue; /* It's ok... */    bid_file = get_identifier_line(b, e, &bid_line);
pike.git/src/program.c:11433:    bid->name);    }    continue;    }    }    free_string(b_file);    free_string(a_file);    END_CYCLIC();   }    + /* FIXME: Code duplication of yyexplain_not_compatible() above! */ + /* Explains why a is not compatible with b */ + void string_builder_explain_not_compatible(struct string_builder *s, +  struct program *a, +  struct program *b) + { +  int e; +  struct pike_string *init_string = findstring("__INIT"); +  int res = 1; +  DECLARE_CYCLIC(); +  +  /* Optimize the loop somewhat */ +  if (a->num_identifier_references < b->num_identifier_references) { +  struct program *tmp = a; +  a = b; +  b = tmp; +  } +  +  if (BEGIN_CYCLIC(a, b)) { +  END_CYCLIC(); +  return; +  } +  SET_CYCLIC_RET(1); +  +  for(e=0;e<b->num_identifier_references;e++) +  { +  struct identifier *bid; +  int i; +  if (b->identifier_references[e].id_flags & (ID_PROTECTED|ID_HIDDEN|ID_VARIANT)) +  continue; /* Skip protected & hidden */ +  +  /* FIXME: What if they aren't protected & hidden in a? */ +  +  bid = ID_FROM_INT(b,e); +  if(init_string == bid->name) continue; /* Skip __INIT */ +  i = find_shared_string_identifier(bid->name,a); +  if (i == -1) { +  continue; /* It's ok... */ +  } +  +  /* Note: Uses weaker check for constant integers. */ +  if(((bid->run_time_type != PIKE_T_INT) || +  (ID_FROM_INT(a, i)->run_time_type != PIKE_T_INT)) && +  !match_types(ID_FROM_INT(a,i)->type, bid->type)) { +  ref_push_program(a); +  ref_push_program(b); +  ref_push_type_value(ID_FROM_INT(a, i)->type); +  ref_push_type_value(bid->type); +  string_builder_sprintf(s, +  "Identifier %S in %O is incompatible with " +  "the same in %O.\n" +  "Expected: %O\n" +  "Got : %O\n", +  bid->name, Pike_sp-4, +  Pike_sp-3, +  Pike_sp-2, +  Pike_sp-1); +  pop_n_elems(4); +  } +  } +  END_CYCLIC(); +  return; + } +  + /* FIXME: code duplication of yyexplain_not_implements() above! */ + /* Explains why a does not implement b */ + void string_builder_explain_not_implements(struct string_builder *s, +  struct program *a, +  struct program *b) + { +  int e; +  struct pike_string *init_string = findstring("__INIT"); +  DECLARE_CYCLIC(); +  +  if (BEGIN_CYCLIC(a, b)) { +  END_CYCLIC(); +  return; +  } +  SET_CYCLIC_RET(1); +  +  for(e=0;e<b->num_identifier_references;e++) +  { +  struct identifier *bid; +  int i; +  if (b->identifier_references[e].id_flags & (ID_PROTECTED|ID_HIDDEN|ID_VARIANT)) +  continue; /* Skip protected & hidden */ +  bid = ID_FROM_INT(b,e); +  if(init_string == bid->name) continue; /* Skip __INIT */ +  i = find_shared_string_identifier(bid->name,a); +  if (i == -1) { +  if (b->identifier_references[e].id_flags & (ID_OPTIONAL)) +  continue; /* It's ok... */ +  ref_push_type_value(bid->type); +  string_builder_sprintf(s, +  "Missing identifier %O %S.\n", +  Pike_sp-1, bid->name); +  pop_stack(); +  continue; +  } +  +  if (!pike_types_le(bid->type, ID_FROM_INT(a, i)->type)) { +  ref_push_type_value(bid->type); +  ref_push_type_value(ID_FROM_INT(a, i)->type); +  if(!match_types(ID_FROM_INT(a,i)->type, bid->type)) { +  string_builder_sprintf(s, +  "Type of identifier %S does not match.\n" +  "Expected: %O.\n" +  "Got : %O.\n", +  bid->name, +  Pike_sp-2, +  Pike_sp-1); +  } else { +  string_builder_sprintf(s, +  "Type of identifier %S is not strictly compatible.", +  "Expected: %O.\n" +  "Got : %O.\n", +  bid->name, +  Pike_sp-2, +  Pike_sp-1); +  } +  pop_n_elems(2); +  continue; +  } +  } +  END_CYCLIC(); + } +    PMOD_EXPORT void *parent_storage(int depth)   {    struct external_variable_context loc;       loc.o = Pike_fp->current_object;    loc.parent_identifier = 0;    loc.inherit = Pike_fp->context;       find_external_context(&loc, depth);