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); +  } + }    -  + void free_all_program_blocks() { +  ba_destroy(&program_allocator); + } +    /* #define COMPILER_DEBUG */   /* #define PROGRAM_BUILD_DEBUG */      #ifdef COMPILER_DEBUG   #define CDFPRINTF(X) fprintf X   #else /* !COMPILER_DEBUG */   #define CDFPRINTF(X)   #endif /* COMPILER_DEBUG */      /*
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: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: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; +     /* 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);    }       /* 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();    }
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: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",
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) && +  (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 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; +  +  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; +  /* 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; +  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--)    {
pike.git/src/program.c:4239: Inside #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;    }    return 0;   }    - /* 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;    }       /* parent offset was increased by 42 for above test.. */    if(parent_offset)    parent_offset-=42;       inherit_offset = Pike_compiler->new_program->num_inherits;
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: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:5867:    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);    } +  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); +  } +  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: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: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: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: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: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);