pike.git / src / program.c

version» Context lines:

pike.git/src/program.c:1:   /*   || This file is part of Pike. For copyright information see COPYRIGHT.   || Pike is distributed under GPL, LGPL and MPL. See the file COPYING   || for more information. - || $Id: program.c,v 1.666 2008/04/15 19:16:41 grubba Exp $ + || $Id: program.c,v 1.667 2008/04/18 19:56:01 grubba Exp $   */      #include "global.h"   #include "program.h"   #include "object.h"   #include "dynamic_buffer.h"   #include "pike_types.h"   #include "stralloc.h"   #include "las.h"   #include "lex.h"
pike.git/src/program.c:1213:      /*! @endclass    */      struct program *first_program = 0;   static int current_program_id = PROG_DYNAMIC_ID_START;      struct program *null_program=0;      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;      int compilation_depth=-1;   dynamic_buffer used_modules;   static struct mapping *resolve_cache=0;      #ifdef PIKE_DEBUG   #define CHECK_FILE_ENTRY(PROG, POS, LEN, SHIFT) \
pike.git/src/program.c:1619:       CHECK_COMPILER();       ref_push_string(ident);    ref_push_string(c->lex.current_file);    if (c->handler) {    ref_push_object(c->handler);    } else {    push_int(0);    } -  if (!safe_apply_current(CE_RESOLV_FUN_NUM, 3)) { +  if (!safe_apply_current(PC_RESOLV_FUN_NUM, 3)) {    if(Pike_compiler->compiler_pass==2) {    if (throw_value.type == T_STRING) {    my_yyerror("%S", throw_value.u.string);    free_svalue(&throw_value);    mark_free_svalue (&throw_value);    }    else {    handle_compile_exception ("Error resolving %S.", ident);    }    } else {
pike.git/src/program.c:7100:    verify_supporters();    return ret;   }         /*! @class CompilerEnviroment    *!    *! The compiler environment.    */    + /*! @decl void report(SeverityLevel severity, @ +  *! string filename, int linenumber, @ +  *! string subsystem, @ +  *! string message, mixed ... extra_args) +  *! +  *! Report a diagnostic from the compiler. +  */ + static void f_compilation_env_report(INT32 args) + { +  int level; +  struct pike_string *filename; +  INT_TYPE linenumber; +  struct pike_string *subsystem; +  struct pike_string *message; +  if (args > 5) { +  f_sprintf(args - 4); +  args = 5; +  } +  get_all_args("report", args, "%d%W%i%W%W", +  &level, &filename, &linenumber, &subsystem, &message); +  +  /* Ignore informational level messages */ +  if (level >= REPORT_WARNING) { +  if (get_master()) { +  ref_push_string(filename); +  push_int(linenumber); +  ref_push_string(message); +  if (level >= REPORT_ERROR) { +  APPLY_MASTER("compile_error", 3); +  args++; +  } else { +  APPLY_MASTER("compile_warning", 3); +  args++; +  } +  } else { +  /* We hope that errors from compiling the master +  * won't contain wide-strings... */ +  if (level >= REPORT_ERROR) { +  fprintf(stderr, "%s:%ld: %s\n", +  filename->str, linenumber, message->str); +  } else { +  fprintf(stderr, "%s:%ld: Warning: %s\n", +  filename->str, linenumber, message->str); +  } +  fflush(stderr); +  } +  } +  pop_n_elems(args); +  push_int(0); + } +  + /*! @decl program compile(string source, CompilationHandler|void handler, @ +  *! int|void major, int|void minor,@ +  *! program|void target, object|void placeholder) +  *! +  *! Compile a string to a program. +  *! +  *! This function takes a piece of Pike code as a string and +  *! compiles it into a clonable program. +  *! +  *! The optional argument @[handler] is used to specify an alternative +  *! error handler. If it is not specified the current master object will +  *! be used. +  *! +  *! The optional arguments @[major] and @[minor] are used to tell the +  *! compiler to attempt to be compatible with Pike @[major].@[minor]. +  *! +  *! @note +  *! Note that @[source] must contain the complete source for a program. +  *! It is not possible to compile a single expression or statement. +  *! +  *! Also note that @[compile()] does not preprocess the program. +  *! To preprocess the program you can use @[compile_string()] or +  *! call the preprocessor manually by calling @[cpp()]. +  *! +  *! @seealso +  *! @[compile_string()], @[compile_file()], @[cpp()], @[master()], +  *! @[CompilationHandler] +  */ + static void f_compilation_env_compile(INT32 args) + { +  apply_current(CE_PIKE_COMPILER_FUN_NUM, args); +  args = 1; +  if (Pike_sp[-1].type != 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) +  */ + 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); +  +  if(get_master()) +  { +  struct compilation *c = THIS_COMPILATION; +  DECLARE_CYCLIC(); +  if(BEGIN_CYCLIC(ident, filename)) +  { +  my_yyerror("Recursive module dependency in %S.", ident); +  }else{ +  SET_CYCLIC_RET(1); +  +  APPLY_MASTER("resolv", args); +  } +  END_CYCLIC(); +  } else { +  pop_n_elems(args); +  push_undefined(); +  } + } +  + /*! @class PikeCompiler +  *! +  *! The Pike compiler. +  *! +  *! An object of this class compiles a single string +  *! of Pike code. +  */ +    static void free_compilation(struct compilation *c)   {    debug_malloc_touch(c); -  if (c->prog) free_string(c->prog); -  if(c->handler) free_object(c->handler); -  if(c->compat_handler) free_object(c->compat_handler); -  if(c->target) free_program(c->target); -  if(c->placeholder) free_object(c->placeholder); -  if(c->lex.current_file) free_string(c->lex.current_file); +  if (c->prog) { +  free_string(c->prog); +  c->prog = NULL; +  } +  if(c->handler) { +  free_object(c->handler); +  c->handler = NULL; +  } +  if(c->compat_handler) { +  free_object(c->compat_handler); +  c->compat_handler = NULL; +  } +  if(c->target) { +  free_program(c->target); +  c->target = NULL; +  } +  if(c->placeholder) { +  free_object(c->placeholder); +  c->placeholder = NULL; +  } +  if(c->lex.current_file) { +  free_string(c->lex.current_file); +  c->lex.current_file = NULL; +  }    free_svalue(& c->default_module); -  +  c->default_module.type = T_INT;    free_supporter(&c->supporter);    verify_supporters();   }      static void run_init(struct compilation *c)   {    debug_malloc_touch(c);    c->save_depth=compilation_depth;    compilation_depth=-1;   
pike.git/src/program.c:7327:       verify_supporters();    return ret;   }      void run_pass2(struct compilation *c)   {    debug_malloc_touch(c);    debug_malloc_touch(c->placeholder);    +  if (!c->p) { +  c->flags &= ~(COMPILER_BUSY); +  c->flags |= COMPILER_DONE; +  return; +  } +     run_init(c);    low_start_new_program(c->p,2,0,0,0);    free_program(c->p);    c->p=0;       run_init2(c);       CDFPRINTF((stderr,    "th(%ld) %p run_pass2() start: "    "threads_disabled:%d, compilation_depth:%d\n",
pike.git/src/program.c:7449:    }    UNSETJMP(rec);    }    else {    debug_malloc_touch(c->placeholder);    zap_placeholder(c);    }    }    }    verify_supporters(); +  c->flags &= ~(COMPILER_BUSY); +  c->flags |= COMPILER_DONE;   }      static int call_delayed_pass2(struct compilation *cc, int finish)   {    int ok = 0;    debug_malloc_touch(cc);       debug_malloc_touch(cc->p);       CDFPRINTF((stderr, "th(%ld) %p %s delayed compile.\n",
pike.git/src/program.c:7489:    }       CDFPRINTF((stderr, "th(%ld) %p delayed compile %s.\n",    (long) th_self(), cc->target, ok ? "done" : "failed"));       verify_supporters();       return ok;   }    + /*! @class PikeCompiler +  *! +  *! The Pike compiler. +  */ +    static void compilation_event_handler(int e)   {    struct compilation *c = THIS_COMPILATION;       switch (e) {    case PROG_EVENT_INIT:    CDFPRINTF((stderr, "th(%ld) compilation: INIT(%p).\n",    (long) th_self(), c));    MEMSET(c, 0, sizeof(*c));    c->supporter.self = Pike_fp->current_object; /* NOTE: Not ref-counted! */
pike.git/src/program.c:7520:    break;    }   }      /*! @decl void report(SeverityLevel severity, @    *! string filename, int linenumber, @    *! string subsystem, @    *! string message, mixed ... extra_args)    *!    *! Report a diagnostic from the compiler. +  *! +  *! The default implementation calls the corresponding function +  *! in the active handlers, and otherwise falls back to +  *! @[CompilationEnvironment::report()] in the parent object.    */   static void f_compilation_report(INT32 args)   {    struct compilation *c = THIS_COMPILATION;    int level;    struct pike_string *filename;    INT_TYPE linenumber;    struct pike_string *subsystem;    struct pike_string *message; -  +  struct object *handler = NULL; +  int fun = -1; +  +  /* FIXME: get_all_args() ought to have a marker +  * indicating that accept more arguments... +  */ +  get_all_args("report", args, "%d", &level); +  +  if ((c->handler || c->compat_handler) && +  (level >= REPORT_WARNING)) { +  /* Ignore informational level messages */ +  const char *fun_name = "compile_warning"; +  +  if (level >= REPORT_ERROR) fun_name = "compile_error"; +  +  if((handler = c->handler) && handler->prog) { +  if ((fun = find_identifier(fun_name, handler->prog)) != +  -1) { +  goto apply_handler; +  } +  } +  if ((handler = c->compat_handler) && handler->prog) { +  if ((fun = find_identifier(fun_name, handler->prog)) != +  -1) { +  goto apply_handler; +  } +  } +  } +  /* Nothing apropriate in any handlers. +  * Call the report() in our parent. +  */ +  apply_external(1, CE_REPORT_FUN_NUM, args); +  return; +  +  apply_handler:    if (args > 5) {    f_sprintf(args - 4);    args = 5;    }    get_all_args("report", args, "%d%W%i%W%W", -  &level, &filename, &linenumber, &subsystem, &message); -  -  /* Ignore informational level messages */ -  if (level) { -  if ((c->handler && c->handler->prog) || -  (c->compat_handler && c->compat_handler->prog) || -  get_master()) { +  &level, &filename, &linenumber, +  &subsystem, &message);    ref_push_string(filename);    push_int(linenumber);    ref_push_string(message); -  if (level >= 2) { -  low_safe_apply_handler("compile_error", -  c->handler, c->compat_handler, 3); -  args++; -  } else { -  low_safe_apply_handler("compile_warning", -  c->handler, c->compat_handler, 3); -  args++; +  apply_low(handler, fun, 3); +  stack_pop_n_elems_keep_top(args);   } -  } else { -  if (level >= 2) { -  fprintf(stderr, "%s:%ld: %s\n", -  filename->str, linenumber, message->str); -  } else { -  fprintf(stderr, "%s:%ld: Warning: %s\n", -  filename->str, linenumber, message->str); -  } -  fflush(stderr); -  } -  } -  pop_n_elems(args); -  push_int(0); - } +     - /*! @decl program compile(string source, CompilationHandler|void handler, @ -  *! int|void major, int|void minor,@ -  *! program|void target, object|void placeholder) + /*! @decl void create(string|void source, @ +  *! CompilationHandler|void handler, @ +  *! int|void major, int|void minor,@ +  *! program|void target, object|void placeholder)    *! -  *! Compile a string to a program. +  *! Create a Pike compiler object for a source string.    *!    *! This function takes a piece of Pike code as a string and -  *! compiles it into a clonable program. +  *! initializes a compiler object accordingly.    *!    *! The optional argument @[handler] is used to specify an alternative -  *! error handler. If it is not specified the current master object will -  *! be used. +  *! error handler. If it is not specified the current master object +  *! at compile time will be used.    *!    *! The optional arguments @[major] and @[minor] are used to tell the    *! compiler to attempt to be compatible with Pike @[major].@[minor].    *!    *! @note    *! Note that @[source] must contain the complete source for a program.    *! It is not possible to compile a single expression or statement.    *! -  *! Also note that @[compile()] does not preprocess the program. +  *! Also note that no preprocessing is performed.    *! To preprocess the program you can use @[compile_string()] or    *! call the preprocessor manually by calling @[cpp()].    *!    *! @seealso    *! @[compile_string()], @[compile_file()], @[cpp()], @[master()],    *! @[CompilationHandler]    */ - static void f_compilation_compile(INT32 args) + static void f_compilation_create(INT32 args)   { -  struct pike_string *aprog; +  struct pike_string *aprog = NULL;    struct object *ahandler = NULL;/* error handler */    int amajor = -1;    int aminor = -1;    struct program *atarget = NULL;    struct object *aplaceholder = NULL;    int delay, dependants_ok = 1;    struct program *ret;   #ifdef PIKE_DEBUG    ONERROR tmp;   #endif    struct compilation *c = THIS_COMPILATION;    -  if (c->target) { -  Pike_error("CompilationEnvironment in use.\n"); +  if (c->flags & COMPILER_BUSY) { +  Pike_error("PikeCompiler object is in use.\n");    }       STACK_LEVEL_START(args);    -  get_all_args("compile", args, "%W.%O%d%d%P%O", +  get_all_args("create", args, ".%W%O%d%d%P%O",    &aprog, &ahandler,    &amajor, &aminor,    &atarget, &aplaceholder);       if (args == 3) { -  SIMPLE_BAD_ARG_ERROR("compile", 4, "int"); +  SIMPLE_BAD_ARG_ERROR("create", 4, "int");    }       check_c_stack(65536);    -  CDFPRINTF((stderr, "th(%ld) %p compile() enter, placeholder=%p\n", +  CDFPRINTF((stderr, "th(%ld) %p compilation create() enter, placeholder=%p\n",    (long) th_self(), atarget, aplaceholder));       debug_malloc_touch(c);       verify_supporters();    -  +  c->flags &= ~COMPILER_DONE; +     if (c->p) free_program(c->p);    c->p = NULL; -  +     if (c->prog) free_string(c->prog); -  add_ref(c->prog=aprog); -  if (ahandler) { +  if ((c->prog=aprog)) add_ref(aprog); +     if (c->handler) free_object(c->handler); -  add_ref(c->handler = ahandler); -  } +  if ((c->handler=ahandler)) add_ref(ahandler); +     c->major=amajor;    c->minor=aminor;    -  if((c->target=atarget)) add_ref(atarget); -  else c->target = low_allocate_program(); +  if (c->target) free_program(c->target); +  if ((c->target=atarget)) add_ref(atarget);       if (c->placeholder) free_object(c->placeholder);    if ((c->placeholder=aplaceholder)) add_ref(aplaceholder);       if (c->handler)    {    if (safe_apply_handler ("get_default_module", c->handler, NULL,    0, BIT_MAPPING|BIT_OBJECT|BIT_ZERO)) {    if(SAFE_IS_ZERO(Pike_sp-1))    {
pike.git/src/program.c:7671:    } else {    ref_push_mapping(get_builtin_constants());    }    }else{    ref_push_mapping(get_builtin_constants());    }    free_svalue(& c->default_module);    c->default_module=Pike_sp[-1];    dmalloc_touch_svalue(Pike_sp-1);    Pike_sp--; +  STACK_LEVEL_DONE(args); +  pop_n_elems(args); +  push_int(0); + }    -  + /*! @decl program compile() +  *! +  *! Compile the current source into a program. +  *! +  *! This function compiles the current Pike source code +  *! into a clonable program. +  *! +  *! @seealso +  *! @[compile_string()], @[compile_file()], @[cpp()], @[master()], +  *! @[CompilationHandler], @[create()] +  */ + static void f_compilation_compile(INT32 args) + { +  struct pike_string *aprog; +  struct object *ahandler = NULL;/* error handler */ +  int amajor = -1; +  int aminor = -1; +  struct program *atarget = NULL; +  struct object *aplaceholder = NULL; +  int delay, dependants_ok = 1; +  struct program *ret;   #ifdef PIKE_DEBUG -  +  ONERROR tmp; + #endif +  struct compilation *c = THIS_COMPILATION; +  +  if (c->flags & COMPILER_BUSY) { +  Pike_error("CompilationEnvironment in use.\n"); +  } +  +  get_all_args("compile", args, ""); +  +  check_c_stack(65536); +  +  CDFPRINTF((stderr, "th(%ld) %p compile() enter, placeholder=%p\n", +  (long) th_self(), c->target, c->placeholder)); +  +  debug_malloc_touch(c); +  +  verify_supporters(); +  +  if (c->flags & COMPILER_DONE) { +  /* Already compiled. */ +  pop_n_elems(args); +  if (c->p) ref_push_program(c->p); +  else push_int(0); +  return; +  } +  +  if (!c->prog) { +  /* No program text. */ +  low_start_new_program(c->target, 1, NULL, 0, NULL); +  c->p = end_program(); +  c->flags |= COMPILER_DONE; +  pop_n_elems(args); +  ref_push_program(c->p); +  return; +  } +  + #ifdef PIKE_DEBUG    SET_ONERROR(tmp, fatal_on_error,"Compiler exited with longjump!\n");   #endif    -  +  c->flags |= COMPILER_BUSY; +     low_init_threads_disable();    c->saved_threads_disabled = threads_disabled;       init_supporter(& c->supporter,    (supporter_callback *) call_delayed_pass2,    (void *)c);       delay=run_pass1(c) && c->p;    dependants_ok = call_dependants(& c->supporter, !!c->p );   #ifdef PIKE_DEBUG    /* FIXME */    UNSET_ONERROR(tmp);   #endif       if(delay)    {    CDFPRINTF((stderr, "th(%ld) %p compile() finish later, placeholder=%p.\n",    (long) th_self(), c->target, c->placeholder));    /* finish later */ -  add_ref(c->p); +     verify_supporters();    /* We're hanging in the supporter. */    ret = c->p;    }else{    /* finish now */ -  if(c->p) run_pass2(c); +  run_pass2(c);    debug_malloc_touch(c);    run_cleanup(c,0);    -  ret=c->p; -  c->p = NULL; +  ret = c->p;       debug_malloc_touch(c);       if (!dependants_ok) {    CDFPRINTF((stderr, "th(%ld) %p compile() reporting failure "    "since a dependant failed.\n",    (long) th_self(), c->target));    if (ret) free_program(ret);    throw_error_object(low_clone(compilation_error_program), 0, 0, 0,    "Compilation failed.\n");
pike.git/src/program.c:7732:    "Compilation failed.\n");    }    debug_malloc_touch(ret);   #ifdef PIKE_DEBUG    if (a_flag > 2) {    dump_program_tables(ret, 0);    }   #endif /* PIKE_DEBUG */    verify_supporters();    } -  STACK_LEVEL_DONE(args); +     pop_n_elems(args);    if (ret) -  push_program(ret); +  ref_push_program(ret);    else    push_int(0);   }    -  + /*! @decl mixed resolv(string identifier, string filename, @ +  *! object handler) +  *! +  *! Resolve the symbol @[identifier]. +  *! +  *! The default implementation calls the corresponding function +  *! in any active handler, and otherwise falls back to +  *! @[CompilationEnvironment::resolv()] in the parent object. +  */   static void f_compilation_resolv(INT32 args)   { -  struct pike_string *ident; -  struct pike_string *filename; +  struct compilation *c = THIS_COMPILATION;    struct object *handler; -  +  int fun = -1;    -  get_all_args("resolv", args, "%W%W%O", &ident, &filename, &handler); -  -  if(get_master()) -  { -  struct compilation *c = THIS_COMPILATION; -  DECLARE_CYCLIC(); -  if(BEGIN_CYCLIC(ident, filename)) -  { -  my_yyerror("Recursive module dependency in %S.", ident); -  }else{ -  SET_CYCLIC_RET(1); -  -  low_unsafe_apply_handler("resolv", handler, c->compat_handler, args); -  } -  END_CYCLIC(); +  if (((handler = c->handler) && handler->prog && +  ((fun = find_identifier("resolv", handler->prog)) != -1)) || +  ((handler = c->compat_handler) && handler->prog && +  ((fun = find_identifier("resolv", handler->prog)) != -1))) { +  apply_low(handler, fun, args);    } else { -  pop_n_elems(args); -  push_undefined(); +  apply_external(1, CE_RESOLV_FUN_NUM, args);    }   }    - /* Fake being called via CompilationEnvironment()->compile() + /* Fake being called via PikeCompiler()->compile()    *    * This function is used to set up the environment for    * compiling C efuns and modules.    *    * Note: Since this is a stack frame, it will be cleaned up    * automatically on error, so no need to use ONERROR().    *    * Note: Steals a reference from ce.    */   static void low_enter_compiler(struct object *ce, int inherit)   {    struct pike_frame *new_frame = alloc_pike_frame();   #ifdef PROFILING    new_frame->children_base = Pike_interpreter.accounted_time;    new_frame->start_time = get_cpu_time() - Pike_interpreter.unlocked_time; -  new_frame->ident = CE_COMPILE_FUN_NUM; /* Fake call of compile(). */ +  new_frame->ident = PC_COMPILE_FUN_NUM; /* Fake call of compile(). */   #endif /* PROFILING */    new_frame->next = Pike_fp;    new_frame->current_object = ce;    /* Note: The compilation environment object hangs on this frame,    * so that it will be freed when the frame dies.    */    new_frame->current_program = ce->prog;    add_ref(new_frame->current_program);    new_frame->context = compilation_program->inherits + inherit;    new_frame->current_storage = ce->storage + new_frame->context->storage_offset;   #ifdef PIKE_DEBUG    if (new_frame->context->prog != compilation_program) {    Pike_fatal("Invalid inherit for compilation context (%p != %p).\n",    new_frame->context->prog, compilation_program);    }   #endif /* PIKE_DEBUG */ -  new_frame->fun = new_frame->context->identifier_level + CE_COMPILE_FUN_NUM; +  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_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 linenumber)   { -  struct object *ce = clone_object(compilation_program, 0); +  struct object *ce = parent_clone_object(compilation_program, +  compilation_environment, +  CE_PIKE_COMPILER_FUN_NUM, 0);    struct compilation *c;       low_enter_compiler(ce, 0);       c = THIS_COMPILATION;    if (filename) {    free_string(c->lex.current_file);    copy_shared_string(c->lex.current_file, filename);    }    if (linenumber) {    c->lex.current_line = linenumber;    }   }      /* Reverse the effect of enter_compiler().    */   PMOD_EXPORT void exit_compiler(void)   {   #ifdef PIKE_DEBUG    if ((Pike_fp->current_program != compilation_program) || -  (Pike_fp->fun != 2)) { +  (Pike_fp->fun != PC_COMPILE_FUN_NUM)) {    Pike_fatal("exit_compiler(): Frame stack out of whack!\n");    }   #endif /* PIKE_DEBUG */    POP_PIKE_FRAME();   }    - /*! @class PikeCompiler + /*! @class CompilerState    *! -  *! The Pike compiler. +  *! @note +  *! Not in use yet!    */    - /*! @decl void report(SeverityLevel severity, @ -  *! string filename, int linenumber, @ -  *! string subsystem, @ -  *! string message, mixed ... extra_args) -  *! -  *! Report a diagnostic from the compiler. -  *! -  *! The default implementation calls @[CompilerEnvironment::report()] -  *! with the same arguments. -  */ -  +    #define THIS_PROGRAM_STATE ((struct program_state *)(Pike_fp->current_storage))      static void program_state_event_handler(int event)   {   #if 0    struct program_state *c = THIS_PROGRAM_STATE;    switch (event) {    case PROG_EVENT_INIT:   #define INIT   #include "compilation.h"
pike.git/src/program.c:7889:    fprintf(stderr, "program_state_event_handler(%d) obj:%p prog:%p\n",    event, Pike_fp->current_object, Pike_fp->current_program);   }      /*! @endclass    */      /*! @endclass    */    + /*! @endclass +  */ +    /* Strap the compiler by creating the compilation program by hand. */   static void compile_compiler(void)   { -  struct program *p = compilation_program = low_allocate_program(); -  struct object *ce; +  struct program *p = low_allocate_program(); +  struct program *p2 = compilation_program = low_allocate_program(); +  struct object *co;    struct inherit *inh; -  +  struct pike_string *pike_compiler_string;       p->parent_info_storage = -1; -  p->event_handler = compilation_event_handler; +  /* p->event_handler = compilation_env_event_handler; */    p->flags |= PROGRAM_HAS_C_METHODS;    -  /* ADD_STORAGE(struct compilation); */ -  p->alignment_needed = ALIGNOF(struct compilation); -  p->storage_needed = sizeof(struct compilation); + #if 0 +  /* ADD_STORAGE(struct compilation_env); */ +  p->alignment_needed = ALIGNOF(struct compilation_env); +  p->storage_needed = p->xstorage + sizeof(struct compilation_env); + #endif /* 0 */       /* Add the initial inherit, this is needed for clone_object()    * to actually call the event handler, and for low_enter_compiler()    * to find the storage and context. */    p->inherits = inh = xalloc(sizeof(struct inherit));    inh->prog = p;    inh->inherit_level = 0;    inh->identifier_level = 0;    inh->parent_identifier = -1;    inh->parent_offset = OBJECT_PARENT;    inh->identifier_ref_offset = 0; -  inh->storage_offset = 0; +  inh->storage_offset = p->xstorage;    inh->parent = NULL;    inh->name = NULL;    p->num_inherits = 1;    -  /* Force clone_object() to accept the program... */ +  /* Force clone_object() to accept the program... +  */    p->flags |= PROGRAM_PASS_1_DONE; -  ce = clone_object(p, 0); +  compilation_environment = clone_object(p, 0);    p->flags &= ~PROGRAM_PASS_1_DONE;    -  low_enter_compiler(ce, 0); +  /* Once more, this time for p2... +  */    -  +  p2->parent_info_storage = 0; +  p2->xstorage = sizeof(struct parent_info); +  p2->event_handler = compilation_event_handler; +  p2->flags |= PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT|PROGRAM_HAS_C_METHODS; +  +  /* ADD_STORAGE(struct compilation); */ +  p2->alignment_needed = ALIGNOF(struct compilation); +  p2->storage_needed = p2->xstorage + sizeof(struct compilation); +  +  p2->inherits = inh = xalloc(sizeof(struct inherit)); +  inh->prog = p2; +  inh->inherit_level = 0; +  inh->identifier_level = 0; +  inh->parent_identifier = CE_PIKE_COMPILER_FUN_NUM; +  inh->parent_offset = OBJECT_PARENT; +  inh->identifier_ref_offset = 0; +  inh->storage_offset = p2->xstorage; +  inh->parent = NULL; +  inh->name = NULL; +  p2->num_inherits = 1; +  +  p2->flags |= PROGRAM_PASS_1_DONE; +  co = parent_clone_object(p2, compilation_environment, +  CE_PIKE_COMPILER_FUN_NUM, 0); +  p2->flags &= ~PROGRAM_PASS_1_DONE; +  +  low_enter_compiler(co, 0); +     low_start_new_program(p, 1, NULL, 0, NULL);    free_program(p); /* Remove the extra ref we just got... */    -  /* low_start_new_program() has zapped the inherit we -  * created above, so we need to repair the frame pointer. +  ADD_FUNCTION("report", f_compilation_env_report, +  tFuncV(tName("SeverityLevel", tInt03) tStr tIntPos +  tStr tStr, tMix, tVoid),0); +  +  ADD_FUNCTION("compile", f_compilation_env_compile, +  tFunc(tOr(tStr, tVoid) tOr(tObj, tVoid) +  tOr(tInt, tVoid) tOr(tInt, tVoid) +  tOr(tPrg(tObj), tVoid) tOr(tObj, tVoid), +  tPrg(tObj)), 0); +  +  ADD_FUNCTION("resolv", f_compilation_env_resolv, +  tFunc(tStr tStr tObj, tMix), 0); +  +  low_start_new_program(p2, 1, NULL, 0, NULL); +  +  /* low_start_new_program() has zapped the inherit we created +  * for p2 above, so we need to repair the frame pointer.    */ -  Pike_fp->context = p->inherits; +  Pike_fp->context = p2->inherits;       /* MAGIC! We're now executing inside the object being compiled,    * and have done sufficient stuff to be able to call and use    * the normal program building functions.    */       ADD_FUNCTION("report", f_compilation_report,    tFuncV(tName("SeverityLevel", tInt03) tStr tIntPos    tStr tStr, tMix, tVoid),0);    -  +  ADD_FUNCTION("compile", f_compilation_compile, +  tFunc(tNone, tPrg(tObj)), 0); +  +  ADD_FUNCTION("resolv", f_compilation_resolv, +  tFunc(tStr tStr tObj, tMix), 0); +  +  ADD_FUNCTION("create", f_compilation_create, +  tFunc(tOr(tStr, tVoid) tOr(tObj, tVoid) +  tOr(tInt, tVoid) tOr(tInt, tVoid) +  tOr(tPrg(tObj), tVoid) tOr(tObj, tVoid), tVoid), 0); +     start_new_program();       ADD_STORAGE(struct program_state);    Pike_compiler->new_program->event_handler = program_state_event_handler;    Pike_compiler->new_program->flags |=    PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT|PROGRAM_HAS_C_METHODS;       /* Alias for report above. */ -  low_define_alias(NULL, NULL, 0, 1, CE_REPORT_FUN_NUM); +  low_define_alias(NULL, NULL, 0, 1, PC_REPORT_FUN_NUM);    -  end_class("PikeCompiler", 0); +  end_class("CompilerState", 0);    -  ADD_FUNCTION("compile", f_compilation_compile, tFunc(tStr, tPrg(tObj)), 0); +  /* Map some of our variables so that the gc can find them. */ +  PIKE_MAP_VARIABLE("prog", OFFSETOF(compilation, prog), +  tStr, PIKE_T_STRING, ID_HIDDEN); +  PIKE_MAP_VARIABLE("handler", OFFSETOF(compilation, handler), +  tObj, PIKE_T_OBJECT, 0); +  PIKE_MAP_VARIABLE("compat_handler", OFFSETOF(compilation, compat_handler), +  tObj, PIKE_T_OBJECT, 0); +  PIKE_MAP_VARIABLE("target", OFFSETOF(compilation, target), +  tPrg(tObj), PIKE_T_PROGRAM, ID_HIDDEN); +  PIKE_MAP_VARIABLE("placeholder", OFFSETOF(compilation, placeholder), +  tObj, PIKE_T_PROGRAM, ID_HIDDEN); +  PIKE_MAP_VARIABLE("p", OFFSETOF(compilation, p), +  tPrg(tObj), PIKE_T_PROGRAM, ID_HIDDEN); +  PIKE_MAP_VARIABLE("current_file", OFFSETOF(compilation, lex.current_file), +  tStr, PIKE_T_STRING, ID_HIDDEN);    -  ADD_FUNCTION("resolv", f_compilation_resolv, tFunc(tStr tStr tObj, tMix), 0); +  /* end_class()/end_program() adds the parent_info storage once more. +  * Remove the one we added above, so that we don't get it double. +  */ +  p2->xstorage = 0;    -  add_global_program("CompilerEnvironment", -  compilation_program = end_program()); +  end_class("PikeCompiler", 0); +  /* end_class()/end_program() has zapped the inherit once again, +  * so we need to repair the frame pointer. +  */ +  Pike_fp->context = compilation_program->inherits;    -  +  compilation_env_program = end_program(); +  +  add_global_program("CompilerEnvironment", compilation_env_program); +     exit_compiler(); -  +  +  ref_push_object(compilation_environment); +  low_add_constant("DefaultCompilerEnvironment", Pike_sp-1); +  pop_stack();   }      struct program *compile(struct pike_string *aprog,    struct object *ahandler,/* error handler */    int amajor, int aminor,    struct program *atarget,    struct object *aplaceholder)   {    int delay, dependants_ok = 1;    struct program *ret;
pike.git/src/program.c:8460: Inside #if defined(DO_PIKE_CLEANUP)
   {    free_program(placeholder_program);    placeholder_program=0;    }   #endif       if (compilation_program) {    free_program(compilation_program);    compilation_program = 0;    } +  if (compilation_environment) { +  free_object(compilation_environment); +  compilation_environment = 0;    } -  +  if (compilation_env_program) { +  free_program(compilation_env_program); +  compilation_env_program = 0; +  } + }      void gc_mark_program_as_referenced(struct program *p)   {    debug_malloc_touch(p);       if (p->flags & PROGRAM_AVOID_CHECK) {    /* Program is in an inconsistent state.    * don't look closer at it.    */    debug_malloc_touch(p);
pike.git/src/program.c:8773:    e=--(Pike_compiler->compiler_frame->current_number_of_locals);    if ((Pike_compiler->compiler_pass == 2) &&    !(Pike_compiler->compiler_frame->variable[e].flags &    LOCAL_VAR_IS_USED)) {    push_int(REPORT_WARNING);    ref_push_string(Pike_compiler->compiler_frame->variable[e].file);    push_int(Pike_compiler->compiler_frame->variable[e].line);    push_constant_text("parse");    push_constant_text("Unused local variable %s.");    ref_push_string(Pike_compiler->compiler_frame->variable[e].name); -  safe_apply_current(CE_REPORT_FUN_NUM, 6); +  safe_apply_current(PC_REPORT_FUN_NUM, 6);    pop_stack();    }    free_string(Pike_compiler->compiler_frame->variable[e].name);    free_type(Pike_compiler->compiler_frame->variable[e].type);    if(Pike_compiler->compiler_frame->variable[e].def)    free_node(Pike_compiler->compiler_frame->variable[e].def);       free_string(Pike_compiler->compiler_frame->variable[e].file);    }   }
pike.git/src/program.c:8805: Inside #if 1
   {    if ((Pike_compiler->compiler_pass == 2) &&    !(Pike_compiler->compiler_frame->variable[level].flags &    LOCAL_VAR_IS_USED)) {    push_int(REPORT_WARNING); /* Warning */    ref_push_string(Pike_compiler->compiler_frame->variable[level].file);    push_int(Pike_compiler->compiler_frame->variable[level].line);    push_constant_text("parse");    push_constant_text("Unused local variable %s.");    ref_push_string(Pike_compiler->compiler_frame->variable[level].name); -  safe_apply_current(CE_REPORT_FUN_NUM, 6); +  safe_apply_current(PC_REPORT_FUN_NUM, 6);    pop_stack();    /* Make sure we only warn once... */    Pike_compiler->compiler_frame->variable[level].flags |=    LOCAL_VAR_IS_USED;    }    free_string(Pike_compiler->compiler_frame->variable[level].name);    copy_shared_string(Pike_compiler->compiler_frame->variable[level].name,    empty_pike_string);    /* FIXME: Do we need to keep the filenames? */    }
pike.git/src/program.c:9040:    va_start(args,fmt);    string_builder_vsprintf(&s, fmt, args);    va_end(args);    msg = finish_string_builder(&s);       push_int(REPORT_WARNING);    ref_push_string(c->lex.current_file);    push_int(c->lex.current_line);    push_constant_text("parse");    push_string(msg); -  safe_apply_current(CE_REPORT_FUN_NUM, 5); +  safe_apply_current(PC_REPORT_FUN_NUM, 5);    pop_stack();   }            /* returns 1 if a implements b */   static int low_implements(struct program *a, struct program *b)   {    int e;    struct pike_string *s=findstring("__INIT");