diff --git a/.gitattributes b/.gitattributes index 0d8129bf23f40ecd4d2fb36cfe5e153d02f59f70..4aeb7164f77aae434f55acfa9179911d8ed62436 100644 --- a/.gitattributes +++ b/.gitattributes @@ -743,6 +743,7 @@ testfont binary /src/peep.c foreign_ident /src/peep.h foreign_ident /src/peep.in foreign_ident +/src/pike_compiler.h foreign_ident /src/pike_cpulib.c foreign_ident /src/pike_cpulib.h foreign_ident /src/pike_dlfcn.h foreign_ident diff --git a/src/builtin_functions.c b/src/builtin_functions.c index 71aed750e99d1234062aecb7f5c20e3bd11535ba..3a258a571689f143d3527c999d6e35b8149d794d 100644 --- a/src/builtin_functions.c +++ b/src/builtin_functions.c @@ -2,7 +2,7 @@ || 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: builtin_functions.c,v 1.651 2008/01/29 20:10:06 grubba Exp $ +|| $Id: builtin_functions.c,v 1.652 2008/04/14 10:14:35 grubba Exp $ */ #include "global.h" @@ -44,6 +44,7 @@ #include "docode.h" #include "lex.h" #include "pike_float.h" +#include "pike_compiler.h" #ifdef HAVE_POLL #ifdef HAVE_POLL_H @@ -1463,6 +1464,8 @@ PMOD_EXPORT void f_zero_type(INT32 args) static int generate_zero_type(node *n) { + struct compilation *c = THIS_COMPILATION; + CHECK_COMPILER(); if(count_args(CDR(n)) != 1) return 0; if(do_docode(CDR(n),DO_NOT_COPY) != 1) Pike_fatal("Count args was wrong in generate_zero_type().\n"); @@ -2386,9 +2389,24 @@ PMOD_EXPORT void f_all_constants(INT32 args) */ PMOD_EXPORT void f_get_active_compilation_handler(INT32 args) { + struct compilation *c = NULL; + + if (compilation_program) { + struct pike_frame *compiler_frame = Pike_fp; + + while (compiler_frame && + (compiler_frame->context->prog != compilation_program)) { + compiler_frame = compiler_frame->next; + } + + if (compiler_frame) { + c = (struct compilation *)compiler_frame->current_storage; + } + } + pop_n_elems(args); - if (compat_handler) { - ref_push_object(compat_handler); + if (c && c->compat_handler) { + ref_push_object(c->compat_handler); } else { push_int(0); } @@ -2408,9 +2426,24 @@ PMOD_EXPORT void f_get_active_compilation_handler(INT32 args) */ PMOD_EXPORT void f_get_active_error_handler(INT32 args) { + struct compilation *c = NULL; + + if (compilation_program) { + struct pike_frame *compiler_frame = Pike_fp; + + while (compiler_frame && + (compiler_frame->context->prog != compilation_program)) { + compiler_frame = compiler_frame->next; + } + + if (compiler_frame) { + c = (struct compilation *)compiler_frame->current_storage; + } + } + pop_n_elems(args); - if (error_handler) { - ref_push_object(error_handler); + if (c && c->handler) { + ref_push_object(c->handler); } else { push_int(0); } @@ -2550,6 +2583,8 @@ static node *optimize_this_object(node *n) static int generate_this_object(node *n) { int level; + struct compilation *c = THIS_COMPILATION; + CHECK_COMPILER(); if (CDR (n)) { if (CDR (n)->token != F_CONSTANT) @@ -4076,62 +4111,14 @@ node *optimize_replace(node *n) */ PMOD_EXPORT void f_compile(INT32 args) { - struct program *p=0; - struct object *o; - struct object *placeholder=0; - int major=-1; - int minor=-1; - - - check_all_args("compile",args, - BIT_STRING, - BIT_VOID | BIT_INT | BIT_OBJECT, - BIT_VOID | BIT_INT, - BIT_VOID | BIT_INT, - BIT_VOID | BIT_INT | BIT_PROGRAM, - BIT_VOID | BIT_INT | BIT_OBJECT, - 0); - - check_c_stack(65536); - - o=0; - switch(args) - { - case 3: - SIMPLE_BAD_ARG_ERROR("compile", 4, "int"); - default: - if(Pike_sp[5-args].type == T_OBJECT) { - if (Pike_sp[5-args].subtype) { - Pike_error("compile: " - "Subtyped placeholder objects are not supported yet.\n"); - } - placeholder=Pike_sp[5-args].u.object; - } - - case 5: - if(Pike_sp[4-args].type == T_PROGRAM) - p=Pike_sp[4-args].u.program; + struct object *ce = clone_object(compilation_program, 0); + ONERROR err; - case 4: - major=Pike_sp[2-args].u.integer; - minor=Pike_sp[3-args].u.integer; - - case 2: - if(Pike_sp[1-args].type == T_OBJECT) { - if (Pike_sp[1-args].subtype) { - Pike_error("compile: " - "Subtyped handler objects are not supported yet.\n"); - } - o=Pike_sp[1-args].u.object; - } - - case 0: case 1: break; - } + SET_ONERROR(err, do_free_object, ce); - p = compile(Pike_sp[-args].u.string, o, major, minor, p, placeholder); + apply_low(ce, CE_COMPILE_FUN_NUM, args); - pop_n_elems(args); - push_program(p); + CALL_AND_UNSET_ONERROR(err); } diff --git a/src/compilation.h b/src/compilation.h index ed13e0f46468ea2f2d74e2acd3ed105c72c08385..64c3840af61f2b623e3f030a5e6261811f7bdcf3 100644 --- a/src/compilation.h +++ b/src/compilation.h @@ -2,7 +2,7 @@ || 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: compilation.h,v 1.34 2008/04/10 10:42:29 grubba Exp $ +|| $Id: compilation.h,v 1.35 2008/04/14 10:14:35 grubba Exp $ */ /* @@ -97,6 +97,47 @@ #endif +#ifdef INIT +#define IMEMBER(X,Y,Z) MEMCPY((char *)&(c->Y), (char *)&(Pike_compiler->Y), sizeof(c->Y)); +#define STACKMEMBER(X,Y,Z) (c->Y=Pike_compiler->Y); +#define ZMEMBER(X,Y,Z) MEMSET((char *)&(c->Y), 0, sizeof(c->Y)); +#define SNAME(X,Y) { \ + c->previous = Pike_compiler; +#define SEND \ + Pike_compiler = c; \ + } + +#endif + + +#ifdef EXIT +#define IMEMBER(X,Y,Z) +#define ZMEMBER(X,Y,Z) + +#define STACKMEMBER(X,Y,Z) DO_DEBUG_CODE( \ + if(c->Y < oLd->Y) \ + Pike_fatal("Stack " #Y " shrunk %ld steps compilation, currently: %p.\n", \ + PTRDIFF_T_TO_LONG(oLd->Y - c->Y), c->Y); ) + +#define SNAME(X,Y) { \ + struct X *oLd = c->previous; + +#define SEND \ + if (Pike_compiler == c) { \ + Pike_compiler=oLd; \ + } else { \ + struct program_state *tmp = Pike_compiler; \ + while (tmp && (tmp->previous != c)) \ + tmp = tmp->previous; \ + if (tmp) tmp->previous = oLd; \ + else Pike_fatal("Lost track of compiler_state %p\n", c); \ + } \ + } +#undef PCODE +#define PCODE(X) X +#endif + + #ifdef PIKE_DEBUG #define STRMEMBER(X,Y) \ PCODE(if(Pike_compiler->X) Pike_fatal("Variable " #X " not deallocated properly.\n");) \ @@ -144,6 +185,8 @@ #undef EXTERN #undef STRUCT +#undef EXIT +#undef INIT #undef PUSH #undef POP #undef DECLARE diff --git a/src/docode.c b/src/docode.c index c4b5efb837fd081bb67a8025cc1489ee7922493f..320d5ce33b8aa98c994b9eed5479a667daddd541 100644 --- a/src/docode.c +++ b/src/docode.c @@ -2,7 +2,7 @@ || 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: docode.c,v 1.196 2008/03/22 13:22:20 grubba Exp $ +|| $Id: docode.c,v 1.197 2008/04/14 10:14:35 grubba Exp $ */ #include "global.h" @@ -27,6 +27,7 @@ #include "lex.h" #include "mapping.h" #include "multiset.h" +#include "pike_compiler.h" static int do_docode2(node *n, int flags); @@ -187,6 +188,7 @@ int alloc_label(void) { return ++label_no; } int do_jump(int token,INT32 lbl) { + struct compilation *c = THIS_COMPILATION; if(lbl==-1) lbl=alloc_label(); emit1(token, lbl); return lbl; @@ -201,6 +203,7 @@ static int lbl_cache[LBLCACHESIZE]; static int do_branch(INT32 lbl) { + struct compilation *c = THIS_COMPILATION; if(lbl==-1) { lbl=alloc_label(); @@ -232,6 +235,7 @@ static int do_branch(INT32 lbl) static void low_insert_label(int lbl) { + struct compilation *c = THIS_COMPILATION; lbl_cache[ lbl % LBLCACHESIZE ] = CURRENT_INSTR; emit1(F_LABEL, lbl); } @@ -245,6 +249,7 @@ static int ins_label(int lbl) void do_pop(int x) { + struct compilation *c = THIS_COMPILATION; #ifdef PIKE_DEBUG if (x < 0) Pike_fatal("Cannot do pop of %d args.\n", x); #endif @@ -259,22 +264,26 @@ void do_pop(int x) static void do_pop_mark(void *ignored) { + struct compilation *c = THIS_COMPILATION; emit0(F_POP_MARK); } static void do_pop_to_mark(void *ignored) { + struct compilation *c = THIS_COMPILATION; emit0(F_POP_TO_MARK); } static void do_cleanup_synch_mark(void) { + struct compilation *c = THIS_COMPILATION; if (d_flag > 2) emit0(F_CLEANUP_SYNCH_MARK); } static void do_escape_catch(void) { + struct compilation *c = THIS_COMPILATION; emit0(F_ESCAPE_CATCH); } @@ -284,16 +293,17 @@ int do_docode(node *n, int flags) { int i; int stack_depth_save = current_stack_depth; - int save_current_line=lex.current_line; + struct compilation *c = THIS_COMPILATION; + int save_current_line = c->lex.current_line; if(!n) return 0; - lex.current_line=n->line_number; + c->lex.current_line=n->line_number; #ifdef PIKE_DEBUG if (current_stack_depth == -4711) Pike_fatal("do_docode() used outside docode().\n"); #endif i=do_docode2(n, flags); current_stack_depth = stack_depth_save + i; - lex.current_line=save_current_line; + c->lex.current_line=save_current_line; return i; } @@ -312,9 +322,9 @@ static void code_expression(node *n, int flags, char *err) case 1: return; case 2: Pike_fatal("Internal compiler error (%s), line %ld, file %s\n", - err, - (long)lex.current_line, - lex.current_file?lex.current_file->str:"Unknown"); + err, + (long)THIS_COMPILATION->lex.current_line, + THIS_COMPILATION->lex.current_file->str); } } @@ -412,6 +422,7 @@ static INT32 count_cases(node *n) int generate_call_function(node *n) { + struct compilation *c = THIS_COMPILATION; emit0(F_MARK); PUSH_CLEANUP_FRAME(do_pop_mark, 0); do_docode(CDR(n),DO_NOT_COPY); @@ -433,6 +444,7 @@ static INLINE struct compiler_frame *find_local_frame(INT32 depth) static int do_lfun_call(int id, node *args) { #if 1 + struct compilation *c = THIS_COMPILATION; struct reference *ref = Pike_compiler->new_program->identifier_references + id; @@ -509,6 +521,7 @@ static int do_lfun_call(int id, node *args) static void emit_apply_builtin(char *func) { INT32 tmp1; + struct compilation *c = THIS_COMPILATION; struct pike_string *n1=make_shared_string(func); node *n=find_module_identifier(n1,0); free_string(n1); @@ -535,6 +548,7 @@ static void emit_apply_builtin(char *func) static int do_encode_automap_arg_list(node *n, int flags) { + struct compilation *c = THIS_COMPILATION; int stack_depth_save = current_stack_depth; if(!n) return 0; switch(n->token) @@ -572,6 +586,7 @@ static int do_encode_automap_arg_list(node *n, static void emit_builtin_svalue(char *func) { INT32 tmp1; + struct compilation *c = THIS_COMPILATION; struct pike_string *n1=make_shared_string(func); node *n=find_module_identifier(n1,0); free_string(n1); @@ -594,6 +609,7 @@ static void emit_builtin_svalue(char *func) static void emit_range (node *n DO_IF_DEBUG (COMMA int num_args)) { + struct compilation *c = THIS_COMPILATION; node *low = CADR (n), *high = CDDR (n); int bound_types; @@ -640,6 +656,7 @@ static void emit_range (node *n DO_IF_DEBUG (COMMA int num_args)) static void emit_multi_assign(node *vals, node *vars, int no) { + struct compilation *c = THIS_COMPILATION; node *var; node *val; node **valp = my_get_arg(&vals, no); @@ -762,6 +779,7 @@ static void emit_multi_assign(node *vals, node *vars, int no) static int do_docode2(node *n, int flags) { + struct compilation *c = THIS_COMPILATION; ptrdiff_t tmp1,tmp2,tmp3; int ret; @@ -2128,7 +2146,7 @@ static int do_docode2(node *n, int flags) if (!match_types(case_val->type, current_switch.type)) { yytype_error("Type mismatch in case.", current_switch.type, case_val->type, 0); - } else if (lex.pragmas & ID_STRICT_TYPES) { + } else if (c->lex.pragmas & ID_STRICT_TYPES) { yytype_error("Type mismatch in case.", current_switch.type, case_val->type, YYTE_IS_WARNING); } @@ -2261,11 +2279,11 @@ static int do_docode2(node *n, int flags) struct statement_label_name *lbl_name; for (lbl_name = label->name; lbl_name; lbl_name = lbl_name->next) if (lbl_name->str == name.str) { - INT32 save_line = lex.current_line; - lex.current_line = name.line_number; + INT32 save_line = c->lex.current_line; + c->lex.current_line = name.line_number; my_yyerror("Duplicate nested labels, previous one on line %d.", lbl_name->line_number); - lex.current_line = save_line; + c->lex.current_line = save_line; goto label_check_done; } } @@ -2657,6 +2675,7 @@ static int do_docode2(node *n, int flags) /* Used to generate code for functions. */ INT32 do_code_block(node *n) { + struct compilation *c = THIS_COMPILATION; INT32 entry_point; #ifdef PIKE_DEBUG if (current_stack_depth != -4711) Pike_fatal("Reentrance in do_code_block().\n"); diff --git a/src/docode.h b/src/docode.h index bc3ee3aa8587a444e7f15fae2a79bd836b2d731b..c27f3c9febe665c03fc42ba92004515156792d4c 100644 --- a/src/docode.h +++ b/src/docode.h @@ -2,7 +2,7 @@ || 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: docode.h,v 1.19 2003/11/19 17:19:29 grubba Exp $ +|| $Id: docode.h,v 1.20 2008/04/14 10:14:38 grubba Exp $ */ #ifndef DOCODE_H @@ -17,9 +17,9 @@ #define WANT_LVALUE (DO_LVALUE | DO_INDIRECT) -#define emit0(X) insert_opcode0((X),lex.current_line, lex.current_file) -#define emit1(X,Y) insert_opcode1((X),(Y),lex.current_line, lex.current_file) -#define emit2(X,Y,Z) insert_opcode2((X),(Y),(Z),lex.current_line, lex.current_file) +#define emit0(X) insert_opcode0((X),c->lex.current_line, c->lex.current_file) +#define emit1(X,Y) insert_opcode1((X),(Y),c->lex.current_line, c->lex.current_file) +#define emit2(X,Y,Z) insert_opcode2((X),(Y),(Z),c->lex.current_line, c->lex.current_file) /* Prototypes begin here */ void upd_int(int offset, INT32 tmp); diff --git a/src/dynamic_load.c b/src/dynamic_load.c index f9a283e432de4cd48abc01a947a40e6fa83a5338..ce9053d84d4155388f2075eb024bde57f985e74f 100644 --- a/src/dynamic_load.c +++ b/src/dynamic_load.c @@ -2,7 +2,7 @@ || 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: dynamic_load.c,v 1.89 2006/07/05 19:06:32 mast Exp $ +|| $Id: dynamic_load.c,v 1.90 2008/04/14 10:14:38 grubba Exp $ */ #ifdef TESTING @@ -389,9 +389,7 @@ static void cleanup_compilation(struct compilation_save *save) if (p) { free_program(p); } - free_string(lex.current_file); compilation_depth = save->compilation_depth; - lex = save->lex; } /*! @decl program load_module(string module_name) @@ -538,9 +536,8 @@ void f_load_module(INT32 args) new_module->init=init; new_module->exit=exit; - save.lex = lex; - lex.current_line=1; - lex.current_file=make_shared_string("-"); + enter_compiler(new_module->name, 1); + save.compilation_depth=compilation_depth; compilation_depth=-1; start_new_program(); @@ -570,9 +567,8 @@ void f_load_module(INT32 args) pop_n_elems(args); { struct program *p = end_program(); - free_string(lex.current_file); + exit_compiler(); compilation_depth = save.compilation_depth; - lex = save.lex; if (p) { if ( #if 0 diff --git a/src/encode.c b/src/encode.c index 5f7bb0b868976d811653a0d8ef540466bd7e0ac1..b2cc0a5951c4acb2d3b29ea257484c63f6567269 100644 --- a/src/encode.c +++ b/src/encode.c @@ -2,7 +2,7 @@ || 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: encode.c,v 1.262 2008/02/29 14:27:09 grubba Exp $ +|| $Id: encode.c,v 1.263 2008/04/14 10:14:38 grubba Exp $ */ #include "global.h" @@ -30,6 +30,7 @@ #include "pike_types.h" #include "opcodes.h" #include "peep.h" +#include "pike_compiler.h" /* #define ENCODE_DEBUG */ @@ -2413,11 +2414,6 @@ static void cleanup_new_program_decode (int *orig_compilation_depth) compilation_depth = *orig_compilation_depth; } -static void set_lex_pragmas(ptrdiff_t old_pragmas) -{ - lex.pragmas = DO_NOT_WARN((INT32)old_pragmas); -} - static DECLSPEC(noreturn) void decode_error (struct svalue *decoding, struct svalue *other, char *msg, ...) @@ -3648,7 +3644,8 @@ static void decode_value2(struct decode_data *data) int entry_type; INT16 id_flags; INT16 p_flags; - ptrdiff_t old_pragmas = lex.pragmas; + ptrdiff_t old_pragmas; + struct compilation *c; #define FOO(NUMTYPE,Y,ARGTYPE,NAME) \ NUMTYPE PIKE_CONCAT(local_num_, NAME) = 0; #include "program_areas.h" @@ -3704,11 +3701,15 @@ static void decode_value2(struct decode_data *data) else p = NULL; + enter_compiler(NULL, 0); + + c = THIS_COMPILATION; + /* We don't want to be affected by #pragma save_parent or * __pragma_save_parent__. */ - lex.pragmas = (old_pragmas & ~ID_SAVE_PARENT)|ID_DONT_SAVE_PARENT; - SET_ONERROR(err2, set_lex_pragmas, (ptrdiff_t) old_pragmas); + old_pragmas = c->lex.pragmas; + c->lex.pragmas = (old_pragmas & ~ID_SAVE_PARENT)|ID_DONT_SAVE_PARENT; /* Start the new program. */ orig_compilation_depth = compilation_depth; @@ -4400,8 +4401,7 @@ static void decode_value2(struct decode_data *data) compilation_depth = orig_compilation_depth; push_program(p); - /* Restore lex.pragmas. */ - CALL_AND_UNSET_ONERROR(err2); + exit_compiler(); EDB(5, dump_program_tables(p, data->depth)); #ifdef PIKE_DEBUG diff --git a/src/language.yacc b/src/language.yacc index 0bae5b9a2991fe3da196bbbcbc61101d2841cecb..ee7c8e64f1a181949ec1428b7d33e2b82d09a8b0 100644 --- a/src/language.yacc +++ b/src/language.yacc @@ -2,7 +2,7 @@ || 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: language.yacc,v 1.410 2008/04/06 11:49:58 grubba Exp $ +|| $Id: language.yacc,v 1.411 2008/04/14 10:14:38 grubba Exp $ */ %pure_parser @@ -189,9 +189,10 @@ static void __yy_memcpy(char *to, YY_FROM_CONST char *from, } %{ -/* Needs to be included after YYSTYPE is defined. */ +/* Need to be included after YYSTYPE is defined. */ #define INCLUDED_FROM_LANGUAGE_YACC #include "lex.h" +#include "pike_compiler.h" %} %{ @@ -948,12 +949,13 @@ def: modifiers optional_attributes type_or_error optional_constant optional_star { int f; node *check_args = NULL; - struct pike_string *save_file = lex.current_file; - int save_line = lex.current_line; + struct compilation *c = THIS_COMPILATION; + struct pike_string *save_file = c->lex.current_file; + int save_line = c->lex.current_line; int num_required_args = 0; struct identifier *i; - lex.current_file = $6->current_file; - lex.current_line = $6->line_number; + c->lex.current_file = $6->current_file; + c->lex.current_line = $6->line_number; if (($1 & ID_EXTERN) && (Pike_compiler->compiler_pass == 1)) { yywarning("Extern declared function definition."); @@ -1044,8 +1046,8 @@ def: modifiers optional_attributes type_or_error optional_constant optional_star /* Prepend the arg checking code. */ $13 = mknode(F_COMMA_EXPR, mknode(F_POP_VALUE, check_args, NULL), $13); } - lex.current_line = l; - lex.current_file = f; + c->lex.current_line = l; + c->lex.current_file = f; } f=dooptcode($6->u.sval.u.string, $13, $<n>12->u.sval.u.type, $1); @@ -1073,8 +1075,8 @@ def: modifiers optional_attributes type_or_error optional_constant optional_star } #endif - lex.current_line = save_line; - lex.current_file = save_file; + c->lex.current_line = save_line; + c->lex.current_file = save_file; } else { /* Prototype; don't warn about unused arguments. */ for (e = Pike_compiler->compiler_frame->current_number_of_locals; e--;) { @@ -1140,13 +1142,13 @@ def: modifiers optional_attributes type_or_error optional_constant optional_star | modifiers '{' { - $<number>$=lex.pragmas; - lex.pragmas|=$1; + $<number>$=THIS_COMPILATION->lex.pragmas; + THIS_COMPILATION->lex.pragmas|=$1; } program close_brace_or_eof { - lex.pragmas=$<number>3; + THIS_COMPILATION->lex.pragmas=$<number>3; } ; @@ -1188,7 +1190,7 @@ new_arg_name: type7 optional_dot_dot_dot optional_identifier i = add_local_name($3->u.sval.u.string, compiler_pop_type(),0); if (i >= 0 && (!$3->u.sval.u.string->len || - !(lex.pragmas & ID_STRICT_TYPES))) { + !(THIS_COMPILATION->lex.pragmas & ID_STRICT_TYPES))) { /* Only warn about unused arguments in strict types mode. */ Pike_compiler->compiler_frame->variable[i].flags |= LOCAL_VAR_IS_USED; } @@ -1303,7 +1305,8 @@ magic_identifier: TOK_IDENTIFIER modifiers: modifier_list { - $$=Pike_compiler->current_modifiers=$1 | (lex.pragmas & ID_MODIFIER_MASK); + $$=Pike_compiler->current_modifiers=$1 | + (THIS_COMPILATION->lex.pragmas & ID_MODIFIER_MASK); } ; @@ -1852,7 +1855,7 @@ new_local_name: optional_stars TOK_IDENTIFIER while($1--) push_type(T_ARRAY); id = add_local_name($2->u.sval.u.string, compiler_pop_type(),0); if (id >= 0) { - if (!(lex.pragmas & ID_STRICT_TYPES)) { + if (!(THIS_COMPILATION->lex.pragmas & ID_STRICT_TYPES)) { /* Only warn about unused initialized variables in strict types mode. */ Pike_compiler->compiler_frame->variable[id].flags |= LOCAL_VAR_IS_USED; } @@ -1900,7 +1903,7 @@ new_local_name2: TOK_IDENTIFIER add_ref($<n>0->u.sval.u.type); id = add_local_name($1->u.sval.u.string, $<n>0->u.sval.u.type, 0); if (id >= 0) { - if (!(lex.pragmas & ID_STRICT_TYPES)) { + if (!(THIS_COMPILATION->lex.pragmas & ID_STRICT_TYPES)) { /* Only warn about unused initialized variables in strict types mode. */ Pike_compiler->compiler_frame->variable[id].flags |= LOCAL_VAR_IS_USED; } @@ -2139,10 +2142,11 @@ lambda: TOK_LAMBDA line_number_info push_compiler_frame1 struct pike_type *type; int f,e; struct pike_string *name; - struct pike_string *save_file = lex.current_file; - int save_line = lex.current_line; - lex.current_file = $2->current_file; - lex.current_line = $2->line_number; + struct compilation *c = THIS_COMPILATION; + struct pike_string *save_file = c->lex.current_file; + int save_line = c->lex.current_line; + c->lex.current_file = $2->current_file; + c->lex.current_line = $2->line_number; debug_malloc_touch($7); $7=mknode(F_COMMA_EXPR,$7,mknode(F_RETURN,mkintnode(0),0)); @@ -2212,8 +2216,8 @@ lambda: TOK_LAMBDA line_number_info push_compiler_frame1 } free_string(name); free_type(type); - lex.current_line = save_line; - lex.current_file = save_file; + c->lex.current_line = save_line; + c->lex.current_file = save_file; free_node ($2); pop_compiler_frame(); } @@ -2306,10 +2310,11 @@ local_function: TOK_IDENTIFIER push_compiler_frame1 func_args { int localid; struct identifier *i=ID_FROM_INT(Pike_compiler->new_program, $<number>4); - struct pike_string *save_file = lex.current_file; - int save_line = lex.current_line; - lex.current_file = $1->current_file; - lex.current_line = $1->line_number; + struct compilation *c = THIS_COMPILATION; + struct pike_string *save_file = c->lex.current_file; + int save_line = c->lex.current_line; + c->lex.current_file = $1->current_file; + c->lex.current_line = $1->line_number; $5=mknode(F_COMMA_EXPR,$5,mknode(F_RETURN,mkintnode(0),0)); @@ -2321,8 +2326,8 @@ local_function: TOK_IDENTIFIER push_compiler_frame1 func_args i->opt_flags = Pike_compiler->compiler_frame->opt_flags; - lex.current_line = save_line; - lex.current_file = save_file; + c->lex.current_line = save_line; + c->lex.current_file = save_file; pop_compiler_frame(); free_node($1); @@ -2437,10 +2442,11 @@ local_function2: optional_stars TOK_IDENTIFIER push_compiler_frame1 func_args { int localid; struct identifier *i=ID_FROM_INT(Pike_compiler->new_program, $<number>5); - struct pike_string *save_file = lex.current_file; - int save_line = lex.current_line; - lex.current_file = $2->current_file; - lex.current_line = $2->line_number; + struct compilation *c = THIS_COMPILATION; + struct pike_string *save_file = c->lex.current_file; + int save_line = c->lex.current_line; + c->lex.current_file = $2->current_file; + c->lex.current_line = $2->line_number; debug_malloc_touch($6); $6=mknode(F_COMMA_EXPR,$6,mknode(F_RETURN,mkintnode(0),0)); @@ -2454,8 +2460,8 @@ local_function2: optional_stars TOK_IDENTIFIER push_compiler_frame1 func_args i->opt_flags = Pike_compiler->compiler_frame->opt_flags; - lex.current_line = save_line; - lex.current_file = save_file; + c->lex.current_line = save_line; + c->lex.current_file = save_file; pop_compiler_frame(); free_node($2); @@ -2646,8 +2652,8 @@ class: TOK_CLASS line_number_info optional_identifier } { /* Clear scoped modifiers. */ - $<number>$ = lex.pragmas; - lex.pragmas &= ~ID_MODIFIER_MASK; + $<number>$ = THIS_COMPILATION->lex.pragmas; + THIS_COMPILATION->lex.pragmas &= ~ID_MODIFIER_MASK; } optional_create_arguments failsafe_program { @@ -2807,7 +2813,7 @@ class: TOK_CLASS line_number_info optional_identifier free_node($2); free_node($3); check_tree($$,0); - lex.pragmas = $<number>5; + THIS_COMPILATION->lex.pragmas = $<number>5; } ; @@ -2970,7 +2976,7 @@ optional_else_part: { $$=0; } safe_lvalue: lvalue { - if (!(lex.pragmas & ID_STRICT_TYPES) && $1) { + if (!(THIS_COMPILATION->lex.pragmas & ID_STRICT_TYPES) && $1) { if ($1->token == F_ARRAY_LVALUE) { mark_lvalues_as_used(CAR($1)); } else if (($1->token == F_LOCAL) && !($1->u.integer.b)) { @@ -3213,7 +3219,7 @@ expr0: expr01 | bad_expr_ident '=' expr0 { $$=$3; } | open_bracket_with_line_info low_lvalue_list ']' '=' expr0 { - if (!(lex.pragmas & ID_STRICT_TYPES)) { + if (!(THIS_COMPILATION->lex.pragmas & ID_STRICT_TYPES)) { mark_lvalues_as_used($2); } $$=mknode(F_ASSIGN,$5,mknode(F_ARRAY_LVALUE,$2,0)); @@ -3386,10 +3392,11 @@ optional_block: /* EMPTY */ { $$=0; } struct pike_type *type; int f/*, e */; struct pike_string *name; - struct pike_string *save_file = lex.current_file; - int save_line = lex.current_line; - lex.current_file = $2->current_file; - lex.current_line = $2->line_number; + struct compilation *c = THIS_COMPILATION; + struct pike_string *save_file = c->lex.current_file; + int save_line = c->lex.current_line; + c->lex.current_file = $2->current_file; + c->lex.current_line = $2->line_number; /* block code */ unuse_modules(Pike_compiler->num_used_modules - $<number>1); @@ -3443,8 +3450,8 @@ optional_block: /* EMPTY */ { $$=0; } $$ = mkidentifiernode(f); } - lex.current_line = save_line; - lex.current_file = save_file; + c->lex.current_line = save_line; + c->lex.current_file = save_file; free_node ($2); free_string(name); free_type(type); @@ -3489,7 +3496,7 @@ apply: implicit_modifiers: { $$ = Pike_compiler->current_modifiers = ID_STATIC|ID_INLINE|ID_PRIVATE | - (lex.pragmas & ID_MODIFIER_MASK); + (THIS_COMPILATION->lex.pragmas & ID_MODIFIER_MASK); } ; @@ -4072,7 +4079,7 @@ catch: TOK_CATCH sscanf: TOK_SSCANF '(' expr0 ',' expr0 lvalue_list ')' { - if ($6 && !(lex.pragmas & ID_STRICT_TYPES)) { + if ($6 && !(THIS_COMPILATION->lex.pragmas & ID_STRICT_TYPES)) { mark_lvalues_as_used($6); } $$=mknode(F_SSCANF,mknode(F_ARG_LIST,$3,$5),$6); @@ -4311,6 +4318,7 @@ bad_expr_ident: void low_yyerror(struct pike_string *str) { + struct compilation *c = THIS_COMPILATION; extern int cumulative_parse_error; STACK_LEVEL_START(0); @@ -4320,38 +4328,19 @@ void low_yyerror(struct pike_string *str) Pike_fatal("Stack error (underflow)\n"); #endif + CHECK_COMPILER(); + if (Pike_compiler->num_parse_error > 20) return; Pike_compiler->num_parse_error++; cumulative_parse_error++; - if ((error_handler && error_handler->prog) || get_master()) - { - if (lex.current_file) { - ref_push_string(lex.current_file); - } else { - /* yyerror() can be called from define_function(), which - * can be called by the C module initialization code. - */ - push_empty_string(); - } - push_int(lex.current_line); - ref_push_string(str); - low_safe_apply_handler("compile_error", error_handler, compat_handler, 3); - pop_stack(); - }else{ - if (lex.current_file) { - (void)fprintf(stderr, "%s:%ld: %s\n", - lex.current_file->str, - (long)lex.current_line, - str->str); - } else { - (void)fprintf(stderr, "NULL:%ld: %s\n", - (long)lex.current_line, - str->str); - } - fflush(stderr); - } - + push_int(2); /* ERROR */ + ref_push_string(c->lex.current_file); + push_int(c->lex.current_line); + push_constant_text("parse"); + ref_push_string(str); + apply_current(0, 5); /* report(). */ + pop_stack(); STACK_LEVEL_DONE(0); } @@ -4376,7 +4365,7 @@ static struct pike_string *get_new_name() sprintf(buf,"__lambda_%ld_%ld_line_%d", (long)Pike_compiler->new_program->id, (long)(Pike_compiler->local_class_counter++ & 0xffffffff), /* OSF/1 cc bug. */ - (int) lex.current_line); + (int) THIS_COMPILATION->lex.current_line); return make_shared_string(buf); } @@ -4450,9 +4439,9 @@ int low_add_local_name(struct compiler_frame *frame, reference_shared_string(str); frame->variable[var].def = def; - frame->variable[var].line=lex.current_line; - frame->variable[var].file=lex.current_file; - reference_shared_string(lex.current_file); + frame->variable[var].line = THIS_COMPILATION->lex.current_line; + copy_shared_string(frame->variable[var].file, + THIS_COMPILATION->lex.current_file); frame->variable[var].flags = 0; @@ -4642,17 +4631,18 @@ static void safe_inc_enum(void) static int call_handle_import(struct pike_string *s) { + struct compilation *c = THIS_COMPILATION; int args; ref_push_string(s); - ref_push_string(lex.current_file); - if (error_handler && error_handler->prog) { - ref_push_object(error_handler); + ref_push_string(c->lex.current_file); + if (c->handler && c->handler->prog) { + ref_push_object(c->handler); args = 3; } else args = 2; - if (safe_apply_handler("handle_import", error_handler, compat_handler, + if (safe_apply_handler("handle_import", c->handler, c->compat_handler, args, BIT_MAPPING|BIT_OBJECT|BIT_PROGRAM|BIT_ZERO)) if (Pike_sp[-1].type != T_INT) return 1; diff --git a/src/las.c b/src/las.c index ae592f52ce3ebc79824b81ce3c56e50effcc3ab4..22126237d0b1a3639044de85a5445bb74cdc5038 100644 --- a/src/las.c +++ b/src/las.c @@ -2,7 +2,7 @@ || 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: las.c,v 1.405 2008/02/26 21:51:37 grubba Exp $ +|| $Id: las.c,v 1.406 2008/04/14 10:14:39 grubba Exp $ */ #include "global.h" @@ -30,6 +30,7 @@ #include "opcodes.h" #include "pikecode.h" #include "gc.h" +#include "pike_compiler.h" #include "block_alloc.h" /* Define this if you want the optimizer to be paranoid about aliasing @@ -375,7 +376,7 @@ static int check_node_type(node *n, struct pike_type *t, const char *msg) yytype_error(msg, t, n->type, 0); return 0; } - if (lex.pragmas & ID_STRICT_TYPES) { + if (THIS_COMPILATION->lex.pragmas & ID_STRICT_TYPES) { yytype_error(msg, t, n->type, YYTE_IS_WARNING); } if (runtime_options & RUNTIME_CHECK_TYPES) { @@ -620,6 +621,8 @@ static node *debug_mkemptynode(void) { node *res=alloc_node_s(); + CHECK_COMPILER(); + #ifdef __CHECKER__ MEMSET(res, 0, sizeof(node)); #endif /* __CHECKER__ */ @@ -627,8 +630,8 @@ static node *debug_mkemptynode(void) res->refs = 0; add_ref(res); /* For DMALLOC... */ res->token=0; - res->line_number=lex.current_line; - copy_shared_string(res->current_file, lex.current_file); + res->line_number=THIS_COMPILATION->lex.current_line; + copy_shared_string(res->current_file, THIS_COMPILATION->lex.current_file); res->type=0; res->name=0; res->node_info=0; @@ -3235,6 +3238,7 @@ struct pike_type *new_check_call(struct pike_string *fun_name, void fix_type_field(node *n) { + struct compilation *c = THIS_COMPILATION; struct pike_type *type_a, *type_b; struct pike_type *old_type; @@ -3365,7 +3369,7 @@ void fix_type_field(node *n) yytype_error("Bad type in assignment.", CDR(n)->type, CAR(n)->type, 0); } else { - if (lex.pragmas & ID_STRICT_TYPES) { + if (c->lex.pragmas & ID_STRICT_TYPES) { struct pike_string *t1 = describe_type(CAR(n)->type); struct pike_string *t2 = describe_type(CDR(n)->type); #ifdef PIKE_DEBUG @@ -3580,7 +3584,7 @@ void fix_type_field(node *n) s = pop_type(); f = CAR(n)->type?CAR(n)->type:mixed_type_string; n->type = check_call(s, f, - (lex.pragmas & ID_STRICT_TYPES) && + (c->lex.pragmas & ID_STRICT_TYPES) && !(n->node_info & OPT_WEAK_TYPE)); args = count_arguments(s); max_args = count_arguments(f); @@ -3838,7 +3842,7 @@ void fix_type_field(node *n) n->type = check_call(call_type, op_node->type ? op_node->type : mixed_type_string, - (lex.pragmas & ID_STRICT_TYPES) && + (c->lex.pragmas & ID_STRICT_TYPES) && !(op_node->node_info & OPT_WEAK_TYPE)); if (n->type) { /* Type check ok. */ @@ -3902,7 +3906,7 @@ void fix_type_field(node *n) yytype_error("Type mismatch in case range.", CAR(n)->type, CDR(n)->type, 0); } - } else if ((lex.pragmas & ID_STRICT_TYPES) && + } else if ((c->lex.pragmas & ID_STRICT_TYPES) && (CAR(n)->type != CDR(n)->type)) { /* The type should be the same for both CAR & CDR. */ if (!pike_types_le(CDR(n)->type, CAR(n)->type)) { @@ -4016,7 +4020,7 @@ void fix_type_field(node *n) if (!match_types(CADAR(n)->type, index_type)) { yytype_error("Type mismatch for index in foreach().", index_type, CADAR(n)->type, 0); - } else if (lex.pragmas & ID_STRICT_TYPES) { + } else if (c->lex.pragmas & ID_STRICT_TYPES) { yytype_error("Type mismatch for index in foreach().", index_type, CADAR(n)->type, YYTE_IS_WARNING); } @@ -4046,7 +4050,7 @@ void fix_type_field(node *n) if (!match_types(CDDAR(n)->type, value_type)) { yytype_error("Type mismatch for value in foreach().", value_type, CDDAR(n)->type, 0); - } else if (lex.pragmas & ID_STRICT_TYPES) { + } else if (c->lex.pragmas & ID_STRICT_TYPES) { yytype_error("Type mismatch for value in foreach().", value_type, CDDAR(n)->type, YYTE_IS_WARNING); } @@ -4064,7 +4068,7 @@ void fix_type_field(node *n) if (!pike_types_le(array_zero, CAAR(n)->type)) { yyerror("Bad argument 1 to foreach()."); } else { - if ((lex.pragmas & ID_STRICT_TYPES) && + if ((c->lex.pragmas & ID_STRICT_TYPES) && !pike_types_le(CAAR(n)->type, array_type_string)) { struct pike_string *t = describe_type(CAAR(n)->type); yywarning("Argument 1 to foreach() is not always an array."); @@ -4944,9 +4948,10 @@ static node *localopt(node *n) static void optimize(node *n) { node *tmp1, *tmp2, *tmp3; + struct compilation *c = THIS_COMPILATION; struct pike_string *save_file = - dmalloc_touch(struct pike_string *, lex.current_file); - INT32 save_line = lex.current_line; + dmalloc_touch(struct pike_string *, c->lex.current_file); + INT32 save_line = c->lex.current_line; do { @@ -4963,8 +4968,8 @@ static void optimize(node *n) continue; } - lex.current_line = n->line_number; - lex.current_file = dmalloc_touch(struct pike_string *, n->current_file); + c->lex.current_line = n->line_number; + c->lex.current_file = dmalloc_touch(struct pike_string *, n->current_file); n->tree_info = n->node_info; if(car_is_node(n)) n->tree_info |= CAR(n)->tree_info; @@ -5078,8 +5083,8 @@ static void optimize(node *n) n=n->parent; }while(n); - lex.current_line = save_line; - lex.current_file = dmalloc_touch(struct pike_string *, save_file); + c->lex.current_line = save_line; + c->lex.current_file = dmalloc_touch(struct pike_string *, save_file); } void optimize_node(node *n) @@ -5392,6 +5397,8 @@ int dooptcode(struct pike_string *name, int args, vargs, ret; struct svalue *foo; + CHECK_COMPILER(); + optimize_node(n); check_tree(n, 0); @@ -5451,10 +5458,12 @@ int dooptcode(struct pike_string *name, tmp.c_fun != f_backtrace) { #ifdef PIKE_DEBUG + struct compilation *c = THIS_COMPILATION; + if(a_flag > 1) fprintf(stderr,"%s:%d: IDENTIFIER OPTIMIZATION %s == %s\n", - lex.current_file->str, - lex.current_line, + c->lex.current_file->str, + c->lex.current_line, name->str, foo->u.efun->name->str); #endif diff --git a/src/lex.c b/src/lex.c index 74edceed54885ec251e4e687670eb92a42dfc275..0ccfea6a807a6e9abceb7571aff6a2a2b8c9af01 100644 --- a/src/lex.c +++ b/src/lex.c @@ -2,20 +2,20 @@ || 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: lex.c,v 1.120 2004/11/01 01:33:30 mast Exp $ +|| $Id: lex.c,v 1.121 2008/04/14 10:14:40 grubba Exp $ */ #include "global.h" #include "lex.h" #include "stuff.h" #include "bignum.h" +#include "pike_compiler.h" +#include "interpret.h" #include <ctype.h> #define LEXDEBUG 0 -struct lex lex; - /* Must do like this since at least gcc is a little too keen on * optimizing INT_TYPE_MUL_OVERFLOW otherwise. */ static unsigned INT32 eight = 8, sixteen = 16, ten = 10; @@ -34,9 +34,12 @@ static unsigned INT32 eight = 8, sixteen = 16, ten = 10; int yylex(YYSTYPE *yylval) { + struct lex *lex; + CHECK_COMPILER(); + lex = &THIS_COMPILATION->lex; #if LEXDEBUG>8 fprintf(stderr, "YYLEX: Calling lexer at 0x%08lx\n", - (long)lex.current_lexer); + (long)lex->current_lexer); #endif /* LEXDEBUG > 8 */ - return(lex.current_lexer(yylval)); + return(lex->current_lexer(lex, yylval)); } diff --git a/src/lex.h b/src/lex.h index 91e7e518fc6375d2e2b3ef4319eedec858a22562..df6efe6106eaaaeb7fdb74221bc58160e7334fe2 100644 --- a/src/lex.h +++ b/src/lex.h @@ -2,7 +2,7 @@ || 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: lex.h,v 1.35 2004/11/01 01:33:30 mast Exp $ +|| $Id: lex.h,v 1.36 2008/04/14 10:14:40 grubba Exp $ */ #ifndef LEX_H @@ -26,20 +26,18 @@ struct lex INT32 current_line; INT32 pragmas; struct pike_string *current_file; - int (*current_lexer)(YYSTYPE *); + int (*current_lexer)(struct lex *, YYSTYPE *); }; -extern struct lex lex; - /* Prototypes begin here */ int parse_esc_seq0 (p_wchar0 *buf, int *chr, ptrdiff_t *len); int parse_esc_seq1 (p_wchar1 *buf, int *chr, ptrdiff_t *len); int parse_esc_seq2 (p_wchar2 *buf, int *chr, ptrdiff_t *len); -int yylex0(YYSTYPE *); -int yylex1(YYSTYPE *); -int yylex2(YYSTYPE *); +int yylex0(struct lex *, YYSTYPE *); +int yylex1(struct lex *, YYSTYPE *); +int yylex2(struct lex *, YYSTYPE *); /* Prototypes end here */ diff --git a/src/lexer.h b/src/lexer.h index f6b7988c26f093e783570f7db6b4d647bd85de46..c85e1546bc304ed14f5a8a3175bdb62dbaed0279 100644 --- a/src/lexer.h +++ b/src/lexer.h @@ -2,7 +2,7 @@ || 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: lexer.h,v 1.65 2008/04/04 13:16:46 grubba Exp $ +|| $Id: lexer.h,v 1.66 2008/04/14 10:14:40 grubba Exp $ */ /* @@ -30,17 +30,17 @@ #define WCHAR p_wchar0 -#define LOOK() EXTRACT_UCHAR(lex.pos) -#define GETC() EXTRACT_UCHAR(lex.pos++) -#define SKIP() lex.pos++ -#define SKIPN(N) (lex.pos += (N)) +#define LOOK() EXTRACT_UCHAR(lex->pos) +#define GETC() EXTRACT_UCHAR(lex->pos++) +#define SKIP() lex->pos++ +#define SKIPN(N) (lex->pos += (N)) #define READBUF(X) do { \ register int C; \ - buf = lex.pos; \ + buf = lex->pos; \ while((C = LOOK()) && (X)) \ - lex.pos++; \ - len = (size_t)(lex.pos - buf); \ + lex->pos++; \ + len = (size_t)(lex->pos - buf); \ } while(0) #define TWO_CHAR(X,Y) ((X)<<8)+(Y) @@ -60,17 +60,17 @@ #else /* SHIFT != 0 */ -#define LOOK() INDEX_CHARP(lex.pos,0,SHIFT) -#define SKIP() (lex.pos += (1<<SHIFT)) -#define SKIPN(N) (lex.pos += ((N)<<SHIFT)) -#define GETC() (SKIP(),INDEX_CHARP(lex.pos-(1<<SHIFT),0,SHIFT)) +#define LOOK() INDEX_CHARP(lex->pos,0,SHIFT) +#define SKIP() (lex->pos += (1<<SHIFT)) +#define SKIPN(N) (lex->pos += ((N)<<SHIFT)) +#define GETC() (SKIP(),INDEX_CHARP(lex->pos-(1<<SHIFT),0,SHIFT)) #define READBUF(X) do { \ register int C; \ - buf = lex.pos; \ + buf = lex->pos; \ while((C = LOOK()) && (X)) \ SKIP(); \ - len = (size_t)((lex.pos - buf) >> SHIFT); \ + len = (size_t)((lex->pos - buf) >> SHIFT); \ } while(0) #define TWO_CHAR(X,Y) ((X)<<8)+(Y) @@ -314,11 +314,11 @@ int parse_esc_seq (WCHAR *buf, int *chr, ptrdiff_t *len) return 0; } -static int char_const(void) +static int char_const(struct lex *lex) { int c; ptrdiff_t l; - switch (parse_esc_seq ((WCHAR *)lex.pos, &c, &l)) { + switch (parse_esc_seq ((WCHAR *)lex->pos, &c, &l)) { case 0: break; case 1: @@ -326,11 +326,11 @@ static int char_const(void) return '\r'; case 2: SKIP(); - lex.current_line++; + lex->current_line++; return '\n'; case 3: yyerror("Unexpected end of file."); - lex.pos -= (1<<SHIFT); + lex->pos -= (1<<SHIFT); return 0; case 4: case 5: case 6: yywarning ("Too large character value in escape."); @@ -347,7 +347,7 @@ static int char_const(void) return c; } -static struct pike_string *readstring(void) +static struct pike_string *readstring(struct lex *lex) { int c; struct string_builder tmp; @@ -374,17 +374,17 @@ static struct pike_string *readstring(void) switch(c=GETC()) { case 0: - lex.pos -= (1<<SHIFT); + lex->pos -= (1<<SHIFT); yyerror("End of file in string."); break; case '\n': - lex.current_line++; + lex->current_line++; yyerror("Newline in string."); break; case '\\': - string_builder_putchar(&tmp,char_const()); + string_builder_putchar(&tmp, char_const(lex)); continue; case '"': @@ -403,8 +403,8 @@ static struct pike_string *readstring(void) -static int low_yylex(YYSTYPE *); -int yylex(YYSTYPE *yylval) +static int low_yylex(struct lex *lex, YYSTYPE *); +int yylex(struct lex *lex, YYSTYPE *yylval) #if LEXDEBUG>4 { int t; @@ -412,7 +412,7 @@ int yylex(YYSTYPE *yylval) fprintf(stderr, "YYLEX:\n"); #endif /* LEXDEBUG>8 */ - t=low_yylex(yylval); + t=low_yylex(lex, yylval); if(t<256) { fprintf(stderr,"YYLEX: '%c' (%d) at %s:%d\n",t,t,lex.current_file->str,lex.current_line); @@ -422,7 +422,7 @@ int yylex(YYSTYPE *yylval) return t; } -static int low_yylex(YYSTYPE *yylval) +static int low_yylex(struct lex *lex, YYSTYPE *yylval) #endif /* LEXDEBUG>4 */ { INT32 c; @@ -442,7 +442,7 @@ static int low_yylex(YYSTYPE *yylval) if((c>'9') && lex_isidchar(c)) { - lex.pos -= (1<<SHIFT); + lex->pos -= (1<<SHIFT); READBUF(lex_isidchar(C)); PIKE_MEM_WO_RANGE (yylval, sizeof (YYSTYPE)); @@ -609,8 +609,8 @@ static int low_yylex(YYSTYPE *yylval) switch(c) { case 0: - lex.pos -= (1<<SHIFT); - if(lex.end != lex.pos) + lex->pos -= (1<<SHIFT); + if(lex->end != lex->pos) yyerror("Illegal character (NUL)"); #ifdef TOK_LEX_EOF @@ -620,7 +620,7 @@ static int low_yylex(YYSTYPE *yylval) #endif /* TOK_LEX_EOF */ case '\n': - lex.current_line++; + lex->current_line++; continue; case 0x1b: case 0x9b: /* ESC or CSI */ @@ -648,22 +648,22 @@ static int low_yylex(YYSTYPE *yylval) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - lex.current_line=lex_atoi(buf)-1; + lex->current_line=lex_atoi(buf)-1; SKIPSPACE(); if(GOBBLE('"')) { - struct pike_string *tmp=readstring(); - free_string(lex.current_file); - lex.current_file = dmalloc_touch(struct pike_string *, tmp); + struct pike_string *tmp=readstring(lex); + free_string(lex->current_file); + lex->current_file = dmalloc_touch(struct pike_string *, tmp); } if (Pike_compiler->compiler_pass == 1 && !Pike_compiler->new_program->num_linenumbers) { /* A nested program will always get an entry right away in * language.yacc. */ - store_linenumber(0, lex.current_file); + store_linenumber(0, lex->current_file); #ifdef DEBUG_MALLOC - if(strcmp(lex.current_file->str,"-")) - debug_malloc_name(Pike_compiler->new_program, lex.current_file->str, 0); + if(strcmp(lex->current_file->str,"-")) + debug_malloc_name(Pike_compiler->new_program, lex->current_file->str, 0); #endif } break; @@ -675,23 +675,23 @@ static int low_yylex(YYSTYPE *yylval) READBUF(C!='\n'); if (ISWORD("all_inline")) { - lex.pragmas |= ID_INLINE; + lex->pragmas |= ID_INLINE; } else if (ISWORD("all_final") || ISWORD("all_nomask")) { - lex.pragmas |= ID_FINAL; + lex->pragmas |= ID_FINAL; } else if (ISWORD("strict_types")) { - lex.pragmas |= ID_STRICT_TYPES; + lex->pragmas |= ID_STRICT_TYPES; } else if (ISWORD("save_parent")) { - lex.pragmas |= ID_SAVE_PARENT; + lex->pragmas |= ID_SAVE_PARENT; } else if (ISWORD("dont_save_parent")) { - lex.pragmas |= ID_DONT_SAVE_PARENT; + lex->pragmas |= ID_DONT_SAVE_PARENT; } break; } @@ -763,12 +763,12 @@ static int low_yylex(YYSTYPE *yylval) switch(c=GETC()) { case 0: - lex.pos -= (1<<SHIFT); + lex->pos -= (1<<SHIFT); yyerror("Unexpected end of file\n"); break; case '\\': - c = char_const(); + c = char_const(lex); break; case '\'': @@ -783,7 +783,7 @@ static int low_yylex(YYSTYPE *yylval) case '"': { - struct pike_string *s=readstring(); + struct pike_string *s=readstring(lex); yylval->n=mkstrnode(s); free_string(s); return TOK_STRING; @@ -799,10 +799,10 @@ static int low_yylex(YYSTYPE *yylval) if(GOBBLE('.')) return TOK_DOT_DOT_DOT; return TOK_DOT_DOT; } - if (((c = INDEX_CHARP(lex.pos, 0, SHIFT)) <= '9') && + if (((c = INDEX_CHARP(lex->pos, 0, SHIFT)) <= '9') && (c >= '0')) { /* FIXME: Only in Pike 7.7 and later mode? */ - lex.pos -= (1<<SHIFT); + lex->pos -= (1<<SHIFT); goto read_float; } return '.'; @@ -825,8 +825,8 @@ static int low_yylex(YYSTYPE *yylval) sval.subtype = NUMBER_NUMBER; sval.u.integer = 0; wide_string_to_svalue_inumber(&sval, - lex.pos, - (void **)&lex.pos, + lex->pos, + (void **)&lex->pos, base, 0, SHIFT); @@ -845,23 +845,23 @@ static int low_yylex(YYSTYPE *yylval) long l = 0; struct svalue sval; - lex.pos -= (1<<SHIFT); - if(INDEX_CHARP(lex.pos, 0, SHIFT)=='0') - for(l=1;INDEX_CHARP(lex.pos, l, SHIFT)<='9' && - INDEX_CHARP(lex.pos, l, SHIFT)>='0';l++) - if(INDEX_CHARP(lex.pos, l, SHIFT)>='8') + lex->pos -= (1<<SHIFT); + if(INDEX_CHARP(lex->pos, 0, SHIFT)=='0') + for(l=1;INDEX_CHARP(lex->pos, l, SHIFT)<='9' && + INDEX_CHARP(lex->pos, l, SHIFT)>='0';l++) + if(INDEX_CHARP(lex->pos, l, SHIFT)>='8') my_yyerror("Illegal octal digit '%c'.", - INDEX_CHARP(lex.pos, l, SHIFT)); + INDEX_CHARP(lex->pos, l, SHIFT)); read_float: - f=lex_strtod(lex.pos, &p1); + f=lex_strtod(lex->pos, &p1); sval.type = PIKE_T_INT; sval.subtype = NUMBER_NUMBER; sval.u.integer = 0; wide_string_to_svalue_inumber(&sval, - lex.pos, + lex->pos, &p2, 0, 0, @@ -890,7 +890,7 @@ static int low_yylex(YYSTYPE *yylval) if ((INDEX_CHARP(p3, l, SHIFT) == ':') && (INDEX_CHARP(p3, l+1, SHIFT) == ':')) { /* Version prefix. */ - lex.pos = p3; + lex->pos = p3; yylval->n = mkversionnode(major, sval.u.integer); return TOK_VERSION; } @@ -900,12 +900,12 @@ static int low_yylex(YYSTYPE *yylval) yylval->fnum=(FLOAT_TYPE)f; #if 0 fprintf(stderr, "LEX: \"%.8s\" => %f, %f\n", - (char *)lex.pos, f, yylval->fnum); + (char *)lex->pos, f, yylval->fnum); #endif /* 0 */ - lex.pos=p1; + lex->pos=p1; if (lex_isidchar (LOOK())) { my_yyerror ("Invalid char '%c' in constant.", - INDEX_CHARP (lex.pos, l, SHIFT)); + INDEX_CHARP (lex->pos, l, SHIFT)); do SKIP(); while (lex_isidchar (LOOK())); } return TOK_FLOAT; @@ -914,10 +914,10 @@ static int low_yylex(YYSTYPE *yylval) yylval->n = mksvaluenode(&sval); free_svalue(&sval); debug_malloc_touch(yylval->n); - lex.pos=p2; + lex->pos=p2; if (lex_isidchar (LOOK())) { my_yyerror ("Invalid char '%c' in constant.", - INDEX_CHARP (lex.pos, l, SHIFT)); + INDEX_CHARP (lex->pos, l, SHIFT)); do SKIP(); while (lex_isidchar (LOOK())); } return TOK_NUMBER; @@ -1142,7 +1142,7 @@ static int low_yylex(YYSTYPE *yylval) return TOK_IDENTIFIER; } yyerror("Illegal ` identifier."); - lex.pos -= (1<<SHIFT); + lex->pos -= (1<<SHIFT); tmp="```"; break; } diff --git a/src/module.c b/src/module.c index e9f31857ef56f91df1119538c28e78077e236fbd..019de7a0110e9fc9f265922e23d47320bc22abb5 100644 --- a/src/module.c +++ b/src/module.c @@ -2,7 +2,7 @@ || 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: module.c,v 1.51 2008/03/30 01:24:10 mast Exp $ +|| $Id: module.c,v 1.52 2008/04/14 10:14:40 grubba Exp $ */ #include "global.h" @@ -383,11 +383,8 @@ void init_modules(void) { struct program *p = NULL; volatile unsigned int e; - struct lex save_lex; - save_lex = lex; - lex.current_line=1; - lex.current_file=make_shared_string("-"); + enter_compiler(NULL, 1); start_new_program(); Pike_compiler->new_program->id=PROG___BUILTIN_ID; @@ -428,8 +425,8 @@ void init_modules(void) push_object(low_clone(p=end_program())); f_add_constant(2); free_program(p); - free_string(lex.current_file); - lex = save_lex; + + exit_compiler(); } void exit_modules(void) diff --git a/src/object.c b/src/object.c index d2678f7bbcb743323b5198a93a105af33a5a0e31..19961a646261dc52cf59d084cd10df55a82e6781 100644 --- a/src/object.c +++ b/src/object.c @@ -2,7 +2,7 @@ || 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: object.c,v 1.283 2008/03/29 02:55:42 mast Exp $ +|| $Id: object.c,v 1.284 2008/04/14 10:14:40 grubba Exp $ */ #include "global.h" @@ -2505,6 +2505,8 @@ void init_object(void) { ptrdiff_t offset; + enter_compiler(NULL, 0); + init_destroy_called_mark_hash(); start_new_program(); offset=ADD_STORAGE(struct magic_index_struct); @@ -2534,6 +2536,8 @@ void init_object(void) offset + OFFSETOF(magic_index_struct, o), T_OBJECT); ADD_FUNCTION("`()",f_magic_values,tFunc(tOr(tVoid,tInt),tArray),0); magic_values_program=end_program(); + + exit_compiler(); } void exit_object(void) diff --git a/src/operators.c b/src/operators.c index c36ed12084ea1cc0146a1e50595c5ec6bae33138..b1eee0939ce69b6f22bac87906975d5352d3d5c0 100644 --- a/src/operators.c +++ b/src/operators.c @@ -2,7 +2,7 @@ || 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: operators.c,v 1.229 2008/03/29 02:04:40 mast Exp $ +|| $Id: operators.c,v 1.230 2008/04/14 10:14:40 grubba Exp $ */ #include "global.h" @@ -30,6 +30,7 @@ #include "builtin_functions.h" #include "cyclic.h" #include "pike_security.h" +#include "pike_compiler.h" #define sp Pike_sp @@ -1737,6 +1738,7 @@ PMOD_EXPORT void f_add(INT32 args) static int generate_sum(node *n) { + struct compilation *c = THIS_COMPILATION; node **first_arg, **second_arg, **third_arg; int num_args; switch(count_args(CDR(n))) @@ -2046,6 +2048,7 @@ static int generate_comparison(node *n) { if(count_args(CDR(n))==2) { + struct compilation *c = THIS_COMPILATION; if(do_docode(CDR(n),DO_NOT_COPY) != 2) Pike_fatal("Count args was wrong in generate_comparison.\n"); @@ -2366,6 +2369,7 @@ PMOD_EXPORT void f_minus(INT32 args) static int generate_minus(node *n) { + struct compilation *c = THIS_COMPILATION; switch(count_args(CDR(n))) { case 1: @@ -2703,6 +2707,7 @@ PMOD_EXPORT void f_and(INT32 args) static int generate_and(node *n) { + struct compilation *c = THIS_COMPILATION; switch(count_args(CDR(n))) { case 1: @@ -2937,6 +2942,7 @@ PMOD_EXPORT void f_or(INT32 args) static int generate_or(node *n) { + struct compilation *c = THIS_COMPILATION; switch(count_args(CDR(n))) { case 1: @@ -3176,6 +3182,7 @@ PMOD_EXPORT void f_xor(INT32 args) static int generate_xor(node *n) { + struct compilation *c = THIS_COMPILATION; switch(count_args(CDR(n))) { case 1: @@ -3259,6 +3266,7 @@ PMOD_EXPORT void f_lsh(INT32 args) static int generate_lsh(node *n) { + struct compilation *c = THIS_COMPILATION; if(count_args(CDR(n))==2) { do_docode(CDR(n),DO_NOT_COPY_TOPLEVEL); @@ -3342,6 +3350,7 @@ static int generate_rsh(node *n) { if(count_args(CDR(n))==2) { + struct compilation *c = THIS_COMPILATION; do_docode(CDR(n),DO_NOT_COPY); emit0(F_RSH); return 1; @@ -3623,6 +3632,7 @@ PMOD_EXPORT void f_multiply(INT32 args) static int generate_multiply(node *n) { + struct compilation *c = THIS_COMPILATION; switch(count_args(CDR(n))) { case 1: @@ -3993,6 +4003,7 @@ static int generate_divide(node *n) { if(count_args(CDR(n))==2) { + struct compilation *c = THIS_COMPILATION; do_docode(CDR(n),DO_NOT_COPY_TOPLEVEL); emit0(F_DIVIDE); return 1; @@ -4173,6 +4184,7 @@ static int generate_mod(node *n) { if(count_args(CDR(n))==2) { + struct compilation *c = THIS_COMPILATION; do_docode(CDR(n),DO_NOT_COPY_TOPLEVEL); emit0(F_MOD); return 1; @@ -4252,6 +4264,7 @@ static int generate_not(node *n) { if(count_args(CDR(n))==1) { + struct compilation *c = THIS_COMPILATION; do_docode(CDR(n),DO_NOT_COPY); emit0(F_NOT); return 1; @@ -4373,6 +4386,7 @@ static int generate_compl(node *n) { if(count_args(CDR(n))==1) { + struct compilation *c = THIS_COMPILATION; do_docode(CDR(n),DO_NOT_COPY); emit0(F_COMPL); return 1; @@ -5293,6 +5307,7 @@ static node *optimize_sizeof(node *n) static int generate_sizeof(node *n) { + struct compilation *c = THIS_COMPILATION; if(count_args(CDR(n)) != 1) return 0; if(do_docode(CDR(n),DO_NOT_COPY) != 1) Pike_fatal("Count args was wrong in sizeof().\n"); diff --git a/src/pike_compiler.h b/src/pike_compiler.h new file mode 100644 index 0000000000000000000000000000000000000000..bd0b7b6d3ffb32644cfcc59edb9581d77fc74af9 --- /dev/null +++ b/src/pike_compiler.h @@ -0,0 +1,55 @@ +/* +|| 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: pike_compiler.h,v 1.1 2008/04/14 10:14:41 grubba Exp $ +*/ + +#ifndef PIKE_COMPILER_H +#define PIKE_COMPILER_H + +#include "lex.h" +#include "program.h" + +struct compilation +{ + struct Supporter supporter; + struct pike_string *prog; /* String to compile. */ + struct object *handler; /* error_handler */ + struct object *compat_handler; /* compat_handler */ + int major, minor; /* compat version */ + struct program *target; /* Program being compiled. */ + struct object *placeholder; + + struct program *p; /* Compiled program or NULL. */ + struct lex lex; + int compilation_inherit; /* Inherit in supporter->self containing + * compilation_program. */ + int save_depth; + int saved_threads_disabled; + dynamic_buffer used_modules_save; + INT32 num_used_modules_save; + struct mapping *resolve_cache_save; + + struct svalue default_module; +}; + +#ifdef PIKE_DEBUG +#define CHECK_COMPILER() do { \ + if (!Pike_fp || !compilation_program || \ + Pike_fp->context->prog != compilation_program) { \ + Pike_fatal("Invalid compilation context!\n"); \ + } \ + } while(0) +#else +#define CHECK_COMPILER() +#endif +#define THIS_COMPILATION ((struct compilation *)(Pike_fp->current_storage)) +#define MAYBE_THIS_COMPILATION ((Pike_fp && compilation_program && (Pike_fp->context->prog == compilation_program))?THIS_COMPILATION:NULL) + +/* Function numbers. */ +#define CE_REPORT_FUN_NUM 0 +#define CE_PIKE_COMPILER_FUN_NUM 1 +#define CE_COMPILE_FUN_NUM 2 + +#endif /* !PIKE_COMPILER_H */ diff --git a/src/pike_types.c b/src/pike_types.c index 336553f33972617ec0d42bc2cf83c1c1ddd71ca5..f830ab95fe69351b6c2cdc2fa1e1282915ea59dd 100644 --- a/src/pike_types.c +++ b/src/pike_types.c @@ -2,7 +2,7 @@ || 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: pike_types.c,v 1.320 2008/04/01 13:20:07 mast Exp $ +|| $Id: pike_types.c,v 1.321 2008/04/14 10:14:41 grubba Exp $ */ #include "global.h" @@ -27,6 +27,7 @@ #include "opcodes.h" #include "cyclic.h" #include "gc.h" +#include "pike_compiler.h" #include "block_alloc.h" #ifdef PIKE_DEBUG @@ -55,6 +56,7 @@ * Perform weaker checking for OR-nodes. */ #define LE_A_B_GROUPED 0/*12*/ /* Both the above two flags. */ #endif +#define LE_USE_HANDLERS 16 /* Call handlers if appropriate. */ /* * Flags used by low_get_first_arg_type() @@ -1871,10 +1873,18 @@ void simple_describe_type(struct pike_type *s) break; case PIKE_T_ATTRIBUTE: - fprintf(stderr, "__attribute__(\"%s\", ", - ((struct pike_string *)s->car)->str); - simple_describe_type(s->cdr); - fprintf(stderr, ")"); + { + struct pike_string *deprecated; + MAKE_CONST_STRING(deprecated, "deprecated"); + if (((struct pike_string *)s->car) == deprecated) { + fprintf(stderr, "__deprecated__("); + } else { + fprintf(stderr, "__attribute__(\"%s\", ", + ((struct pike_string *)s->car)->str); + } + simple_describe_type(s->cdr); + fprintf(stderr, ")"); + } break; case T_SCOPE: @@ -2214,10 +2224,16 @@ static void low_describe_type(struct pike_type *t) case PIKE_T_ATTRIBUTE: if (!((struct pike_string *)t->car)->size_shift) { - my_strcat("__attribute__(\""); - my_binary_strcat(((struct pike_string *)t->car)->str, - ((struct pike_string *)t->car)->len); - my_strcat("\", "); + struct pike_string *deprecated; + MAKE_CONST_STRING(deprecated, "deprecated"); + if (((struct pike_string *)t->car) == deprecated) { + my_strcat("__deprecated__("); + } else { + my_strcat("__attribute__(\""); + my_binary_strcat(((struct pike_string *)t->car)->str, + ((struct pike_string *)t->car)->len); + my_strcat("\", "); + } my_describe_type(t->cdr); my_strcat(")"); } else { @@ -3727,9 +3743,38 @@ static int low_pike_types_le2(struct pike_type *a, struct pike_type *b, #endif /* FALL_THROUGH */ case PIKE_T_NAME: - case PIKE_T_ATTRIBUTE: a = a->cdr; goto recurse; + case PIKE_T_ATTRIBUTE: + if ((b->type == PIKE_T_ATTRIBUTE) && (a->car == b->car)) { + a = a->cdr; + b = b->cdr; + goto recurse; + } +#if 0 + if (!flags & LE_USE_HANDLERS) { + a = a->cdr; + goto recurse; + } +#endif /* 0 */ + if (!low_pike_types_le(a->cdr, b, array_cnt, flags)) return 0; +#if 0 + ref_push_string((struct pike_string *)a->car); + ref_push_type_value(a->cdr); + ref_push_type_value(b); + push_int(1); + if (safe_apply_handler("handle_attribute", error_handler, compat_handler, + 4, 0)) { + if ((Pike_sp[-1].type == T_INT) && + (Pike_sp[-1].subtype == NUMBER_NUMBER) && + (!Pike_sp[-1].u.integer)) { + pop_stack(); + return 0; + } + pop_stack(); + } +#endif /* 0 */ + return 1; case T_NOT: if (b->type == T_NOT) { @@ -3863,13 +3908,37 @@ static int low_pike_types_le2(struct pike_type *a, struct pike_type *b, b = b->car; goto recurse; + case PIKE_T_ATTRIBUTE: +#if 0 + if (!flags & LE_USE_HANDLERS) { + b = b->cdr; + goto recurse; + } +#endif /* 0 */ + if (!low_pike_types_le(a, b->cdr, array_cnt, flags)) return 0; +#if 0 + ref_push_string((struct pike_string *)b->car); + ref_push_type_value(a); + ref_push_type_value(b->cdr); + push_int(2); + if (safe_apply_handler("handle_attribute", error_handler, compat_handler, + 4, 0)) { + if ((Pike_sp[-1].type == T_INT) && + (Pike_sp[-1].subtype == NUMBER_NUMBER) && + (!Pike_sp[-1].u.integer)) { + pop_stack(); + return 0; + } + pop_stack(); + } +#endif /* 0 */ + return 1; case PIKE_T_SCOPE: #ifdef TYPE_GROUPING flags |= LE_B_GROUPED; #endif /* FALL_THROUGH */ case PIKE_T_NAME: - case PIKE_T_ATTRIBUTE: b = b->cdr; goto recurse; @@ -4318,7 +4387,9 @@ int check_soft_cast(struct pike_type *to, struct pike_type *from) */ static int low_get_return_type(struct pike_type *a, struct pike_type *b) { + struct compilation *c = THIS_COMPILATION; int tmp; + CHECK_COMPILER(); switch(a->type) { case T_OR: @@ -4380,7 +4451,7 @@ static int low_get_return_type(struct pike_type *a, struct pike_type *b) if(a) { #if 0 - if ((lex.pragmas & ID_STRICT_TYPES) && + if ((c->lex.pragmas & ID_STRICT_TYPES) && !low_pike_types_le(a, b, 0, 0)) { yywarning("Type mismatch"); } @@ -4441,6 +4512,13 @@ static struct pike_type *debug_low_index_type(struct pike_type *t, { struct pike_type *tmp; struct program *p; + int pragmas = 0; + + if (n) { + struct compilation *c = THIS_COMPILATION; + CHECK_COMPILER(); + pragmas = c->lex.pragmas; + } switch(low_check_indexing(t, index_type, n)) { @@ -4519,7 +4597,7 @@ static struct pike_type *debug_low_index_type(struct pike_type *t, return mixed_type_string; case T_MIXED: - if (lex.pragmas & ID_STRICT_TYPES) { + if (pragmas & ID_STRICT_TYPES) { yywarning("Indexing mixed."); } add_ref(mixed_type_string); @@ -4633,9 +4711,12 @@ static struct pike_type *debug_low_range_type(struct pike_type *t, struct pike_type *index1_type, struct pike_type *index2_type) { + struct compilation *c = THIS_COMPILATION; struct pike_type *tmp; struct program *p; + CHECK_COMPILER(); + while((t->type == PIKE_T_NAME) || (t->type == PIKE_T_ATTRIBUTE)) { t = t->cdr; @@ -4736,7 +4817,7 @@ static struct pike_type *debug_low_range_type(struct pike_type *t, yywarning("Ranging object without index operator."); return 0; } - if (lex.pragmas & ID_STRICT_TYPES) { + if (c->lex.pragmas & ID_STRICT_TYPES) { yywarning("Ranging generic object."); } add_ref(mixed_type_string); @@ -4744,7 +4825,7 @@ static struct pike_type *debug_low_range_type(struct pike_type *t, } case T_MIXED: - if (lex.pragmas & ID_STRICT_TYPES) { + if (c->lex.pragmas & ID_STRICT_TYPES) { yywarning("Ranging mixed."); } add_ref(mixed_type_string); @@ -5892,14 +5973,16 @@ static struct pike_type *lower_new_check_call(struct pike_type *fun_type, } if (tmp2->type == PIKE_T_ATTRIBUTE) { + struct compilation *c = MAYBE_THIS_COMPILATION; /* Perform extra argument checking based on the attribute. */ /* FIXME: Support multiple attributes. */ ref_push_string((struct pike_string *)tmp2->car); push_svalue(sval); ref_push_type_value(tmp2->cdr); ref_push_type_value(res); - if (safe_apply_handler("handle_attribute_constant", error_handler, - compat_handler, 4, 0)) { + if (safe_apply_handler("handle_attribute_constant", + c?c->handler:NULL, + c?c->compat_handler:NULL, 4, 0)) { if ((Pike_sp[-1].type == PIKE_T_TYPE)) { type_stack_mark(); push_finished_type(Pike_sp[-1].u.type); @@ -6454,11 +6537,14 @@ struct pike_type *new_check_call(struct pike_string *fun_name, struct pike_type *fun_type, node *args, INT32 *argno) { + struct compilation *c = THIS_COMPILATION; struct pike_type *tmp = NULL; struct pike_type *res = NULL; struct svalue *sval = NULL; int flags = 0; + CHECK_COMPILER(); + debug_malloc_touch(fun_type); while (args && (args->token == F_ARG_LIST) && fun_type) { @@ -6549,7 +6635,7 @@ struct pike_type *new_check_call(struct pike_string *fun_name, if (cnt == 256) { yywarning("In argument %d to %S: The @-operator argument must be an empty array.", *argno, fun_name); - } else if (lex.pragmas & ID_STRICT_TYPES) { + } else if (c->lex.pragmas & ID_STRICT_TYPES) { yywarning("In argument %d to %S: The @-operator argument has a max length of %d.", *argno, fun_name, 256-cnt); } @@ -6571,7 +6657,7 @@ struct pike_type *new_check_call(struct pike_string *fun_name, fprintf(stderr, " OK.\n"); } #endif /* PIKE_DEBUG */ - if (lex.pragmas & ID_STRICT_TYPES) { + if (c->lex.pragmas & ID_STRICT_TYPES) { if (!(tmp = low_new_check_call(fun_type, args->type, flags|CALL_STRICT, sval))) { yywarning("Type mismatch in argument %d to %S.", diff --git a/src/program.c b/src/program.c index 8d23c11f61d23866ee68fc2d9be6f4ccbe1e4d09..d058c74dbdb1d18682163e01049e08c472aa3a11 100644 --- a/src/program.c +++ b/src/program.c @@ -2,7 +2,7 @@ || 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.659 2008/04/07 01:45:53 mbaehr Exp $ +|| $Id: program.c,v 1.660 2008/04/14 10:14:41 grubba Exp $ */ #include "global.h" @@ -35,6 +35,7 @@ #include "version.h" #include "block_alloc.h" #include "pikecode.h" +#include "pike_compiler.h" #include <errno.h> #include <fcntl.h> @@ -44,6 +45,7 @@ #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, @@ -1218,9 +1220,6 @@ struct program *null_program=0; struct program *compilation_program = 0; -struct object *error_handler=0; -struct object *compat_handler=0; - struct program *gc_internal_program = 0; static struct program *gc_mark_program_pos = 0; @@ -1616,23 +1615,24 @@ struct node_s *resolve_identifier(struct pike_string *ident) if(get_master()) { + struct compilation *c = THIS_COMPILATION; DECLARE_CYCLIC(); node *ret=0; - if(BEGIN_CYCLIC(ident, lex.current_file)) + if(BEGIN_CYCLIC(ident, c->lex.current_file)) { my_yyerror("Recursive module dependency in %S.", ident); }else{ SET_CYCLIC_RET(1); ref_push_string(ident); - ref_push_string(lex.current_file); - if (error_handler) { - ref_push_object(error_handler); + ref_push_string(c->lex.current_file); + if (c->handler) { + ref_push_object(c->handler); } else { push_int(0); } - if (safe_apply_handler("resolv", error_handler, compat_handler, 3, 0)) { + if (safe_apply_handler("resolv", c->handler, c->compat_handler, 3, 0)) { if (Pike_compiler->compiler_pass == 2 && ((Pike_sp[-1].type == T_OBJECT && Pike_sp[-1].u.object == placeholder_object) || @@ -1977,6 +1977,7 @@ struct pike_string *find_program_name(struct program *p, INT32 *line) int override_identifier (struct reference *new_ref, struct pike_string *name) { + struct compilation *c = THIS_COMPILATION; int id = -1, cur_id = 0, is_used = 0; int new_is_variable = @@ -1989,6 +1990,8 @@ int override_identifier (struct reference *new_ref, struct pike_string *name) * /Hubbe */ + CHECK_COMPILER(); + for(;cur_id<Pike_compiler->new_program->num_identifier_references;cur_id++) { struct reference *ref = @@ -2040,7 +2043,7 @@ int override_identifier (struct reference *new_ref, struct pike_string *name) sub_ref = PTR_FROM_INT(inh->prog, cur_id - inh->identifier_level); /* Check if the symbol was used before it was inherited. */ - if ((lex.pragmas & ID_STRICT_TYPES) && + 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)) { @@ -2085,9 +2088,12 @@ int override_identifier (struct reference *new_ref, struct pike_string *name) void fixate_program(void) { + struct compilation *c = THIS_COMPILATION; INT32 i,e,t; struct program *p=Pike_compiler->new_program; + CHECK_COMPILER(); + if(p->flags & PROGRAM_FIXED) return; #ifdef PIKE_DEBUG if(p->flags & PROGRAM_OPTIMIZED) @@ -2161,7 +2167,7 @@ void fixate_program(void) if(funa_is_prototype && (funb->func.offset != -1) && !(funp->id_flags & ID_INLINE)) { - if ((lex.pragmas & ID_STRICT_TYPES) && + if ((c->lex.pragmas & ID_STRICT_TYPES) && (funp->id_flags & ID_USED)) { /* Verify that the types are compatible. */ if (!pike_types_le(funb->type, fun->type)) { @@ -2175,7 +2181,7 @@ void fixate_program(void) } if(!funa_is_prototype && funb->func.offset == -1) { - if ((lex.pragmas & ID_STRICT_TYPES) && + if ((c->lex.pragmas & ID_STRICT_TYPES) && (funpb->id_flags & ID_USED)) { /* Verify that the types are compatible. */ if (!pike_types_le(fun->type, funb->type)) { @@ -2267,12 +2273,12 @@ void fixate_program(void) INT32 line; struct pike_string *tmp; struct memory_map *m=0;; - if(lex.current_file && - lex.current_file->str && - lex.current_file->len && - !strcmp(lex.current_file->str,"-")) + if(c->lex.current_file && + c->lex.current_file->str && + c->lex.current_file->len && + !strcmp(c->lex.current_file->str,"-")) { - m=dmalloc_alloc_mmap( DBSTR(lex.current_file), lex.current_line); + m=dmalloc_alloc_mmap( DBSTR(c->lex.current_file), c->lex.current_line); } else if( (tmp=find_program_name(Pike_compiler->new_program, &line)) ) { @@ -2353,9 +2359,12 @@ void low_start_new_program(struct program *p, 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_class = 0; @@ -2387,7 +2396,7 @@ void low_start_new_program(struct program *p, fprintf(stderr,"Compiling class %s, depth=%d\n",name->str,compilation_depth); }else{ fprintf(stderr,"Compiling file %s, depth=%d\n", - lex.current_file ? lex.current_file->str : "-", + c->lex.current_file ? c->lex.current_file->str : "-", compilation_depth); #endif } @@ -2499,10 +2508,10 @@ void low_start_new_program(struct program *p, #endif if (compilation_depth >= 1) { - if(TEST_COMPAT(7,2) || (lex.pragmas & ID_SAVE_PARENT)) + if(TEST_COMPAT(7,2) || (c->lex.pragmas & ID_SAVE_PARENT)) { p->flags |= PROGRAM_USES_PARENT; - }else if (!(lex.pragmas & ID_DONT_SAVE_PARENT)) { + }else if (!(c->lex.pragmas & ID_DONT_SAVE_PARENT)) { struct pike_string *tmp=findstring("__pragma_save_parent__"); if(tmp) { @@ -2613,17 +2622,23 @@ void low_start_new_program(struct program *p, PMOD_EXPORT void debug_start_new_program(int line, const char *file) { - struct pike_string *save_file = - dmalloc_touch(struct pike_string *, lex.current_file); - int save_line = lex.current_line; + struct pike_string *save_file; + int save_line; + struct compilation *c; + + CHECK_COMPILER(); + c = THIS_COMPILATION; + + save_file = dmalloc_touch(struct pike_string *, c->lex.current_file); + save_line = c->lex.current_line; { /* Trim off the leading path of the compilation environment. */ const char *p = DEFINETOSTR(PIKE_SRC_ROOT), *f = file; while (*p && *p == *f) p++, f++; while (*f == '/' || *f == '\\') f++; - lex.current_file = make_shared_string(f); - lex.current_line = line; + c->lex.current_file = make_shared_string(f); + c->lex.current_line = line; } CDFPRINTF((stderr, @@ -2632,12 +2647,12 @@ PMOD_EXPORT void debug_start_new_program(int line, const char *file) (long)th_self(), line, file, threads_disabled, compilation_depth)); low_start_new_program(0,1,0,0,0); - store_linenumber(line,lex.current_file); + store_linenumber(line,c->lex.current_file); debug_malloc_name(Pike_compiler->new_program, file, line); - free_string(lex.current_file); - lex.current_file = dmalloc_touch(struct pike_string *, save_file); - lex.current_line = save_line; + free_string(c->lex.current_file); + c->lex.current_file = dmalloc_touch(struct pike_string *, save_file); + c->lex.current_line = save_line; } @@ -3044,6 +3059,17 @@ void dump_program_tables (struct program *p, int indent) #endif /* 0 */ } + fprintf(stderr, "\n" + "%*sLFUN table:\n" + "%*s LFUN Ref# Name\n", + indent, "", indent, ""); + for (d = 0; d < NUM_LFUNS; d++) { + if (p->lfuns[d] != -1) { + fprintf(stderr, "%*s %4d: %04d %s\n", + indent, "", d, p->lfuns[d], lfun_names[d]); + } + } + fprintf(stderr, "\n" "%*sLinenumber table:\n", indent, ""); @@ -4445,8 +4471,11 @@ void compiler_do_inherit(node *n, int call_handle_inherit(struct pike_string *s) { + struct compilation *c = THIS_COMPILATION; int args; + CHECK_COMPILER(); + reference_shared_string(s); push_string(s); if (!TEST_COMPAT(7,6)) { @@ -4455,14 +4484,14 @@ int call_handle_inherit(struct pike_string *s) */ f_string_to_utf8(1); } - ref_push_string(lex.current_file); - if (error_handler && error_handler->prog) { - ref_push_object(error_handler); + ref_push_string(c->lex.current_file); + if (c->handler && c->handler->prog) { + ref_push_object(c->handler); args = 3; } else args = 2; - if (safe_apply_handler("handle_inherit", error_handler, compat_handler, + if (safe_apply_handler("handle_inherit", c->handler, c->compat_handler, args, BIT_PROGRAM|BIT_FUNCTION|BIT_ZERO)) if (Pike_sp[-1].type != T_INT) return 1; @@ -5314,6 +5343,7 @@ INT32 define_function(struct pike_string *name, union idptr *func, unsigned opt_flags) { + struct compilation *c = THIS_COMPILATION; struct identifier *funp,fun; struct reference ref; struct svalue *lfun_type; @@ -5321,6 +5351,8 @@ INT32 define_function(struct pike_string *name, INT32 i; INT32 getter_setter_offset = -1; + CHECK_COMPILER(); + #ifdef PROGRAM_BUILD_DEBUG { struct pike_string *d = describe_type (type); @@ -5351,7 +5383,7 @@ INT32 define_function(struct pike_string *name, my_yyerror("Type mismatch for callback function %S:", name); yytype_error(NULL, lfun_type->u.type, type, 0); Pike_fatal("Type mismatch!\n"); - } else if (lex.pragmas & ID_STRICT_TYPES) { + } else if (c->lex.pragmas & ID_STRICT_TYPES) { yywarning("Type mismatch for callback function %S:", name); yytype_error(NULL, lfun_type->u.type, type, YYTE_IS_WARNING); @@ -5396,7 +5428,7 @@ INT32 define_function(struct pike_string *name, if (!match_types(type, gs_type)) { my_yyerror("Type mismatch for callback function %S:", name); yytype_error(NULL, gs_type, type, 0); - } else if (lex.pragmas & ID_STRICT_TYPES) { + } else if (c->lex.pragmas & ID_STRICT_TYPES) { yywarning("Type mismatch for callback function %S:", name); yytype_error(NULL, gs_type, type, YYTE_IS_WARNING); } @@ -6791,6 +6823,10 @@ struct pike_string *format_exception_for_error_msg (struct svalue *thrown) void handle_compile_exception (const char *yyerror_fmt, ...) { struct svalue thrown; + struct compilation *c = THIS_COMPILATION; + + CHECK_COMPILER(); + move_svalue (&thrown, &throw_value); mark_free_svalue (&throw_value); @@ -6802,7 +6838,7 @@ void handle_compile_exception (const char *yyerror_fmt, ...) } push_svalue(&thrown); - low_safe_apply_handler("compile_exception", error_handler, compat_handler, 1); + low_safe_apply_handler("compile_exception", c->handler, c->compat_handler, 1); if (SAFE_IS_ZERO(sp-1)) { struct pike_string *s = format_exception_for_error_msg (&thrown); @@ -6960,6 +6996,8 @@ void init_supporter(struct Supporter *s, supporter_callback *fun, void *data) { + CDFPRINTF((stderr, "th(%ld) init_supporter() supporter=%p data=%p.\n", + (long) th_self(), s, data)); verify_supporters(); #ifdef PIKE_DEBUG s->magic = 0x500b0127; @@ -6995,6 +7033,9 @@ int unlink_current_supporter(struct Supporter *c) ret++; c->next_dependant = c->depends_on->dependants; c->depends_on->dependants=c; + add_ref(c->self); + CDFPRINTF((stderr, "th(%ld) unlink_current_supporter() supporter=%p depends on %p.\n", + (long) th_self(), c, c->depends_on)); } current_supporter=c->previous; verify_supporters(); @@ -7017,9 +7058,13 @@ int call_dependants(struct Supporter *s, int finish) { int ok = 1; struct Supporter *tmp; + CDFPRINTF((stderr, "th(%ld) call_dependants() supporter=%p finish=%d.\n", + (long) th_self(), s, finish)); verify_supporters(); while((tmp=s->dependants)) { + CDFPRINTF((stderr, "th(%ld) dependant: %p (data:%p).\n", + (long) th_self(), tmp, tmp->data)); s->dependants=tmp->next_dependant; #ifdef PIKE_DEBUG tmp->next_dependant=0; @@ -7027,6 +7072,7 @@ int call_dependants(struct Supporter *s, int finish) verify_supporters(); if (!tmp->fun(tmp->data, finish)) ok = 0; verify_supporters(); + free_object(tmp->self); } return ok; } @@ -7040,6 +7086,10 @@ int report_compiler_dependency(struct program *p) /* Depends on self... */ return 0; } + + CDFPRINTF((stderr, "th(%ld) %p depends on %p\n", + (long)th_self(), Pike_compiler->new_program, p)); + verify_supporters(); if (Pike_compiler->flags & COMPILATION_FORCE_RESOLVE) return 0; @@ -7066,40 +7116,20 @@ int report_compiler_dependency(struct program *p) } -/*! @class PikeCompiler +/*! @class CompilerEnviroment *! - *! The Pike compiler. + *! The compiler environment. */ -struct compilation -{ - struct Supporter supporter; - struct pike_string *prog; - struct object *handler; - int major, minor; - struct program *target; - struct object *placeholder; - - struct program *p; - struct lex save_lex; - int save_depth; - int saved_threads_disabled; - struct object *saved_handler; - struct object *saved_compat_handler; - dynamic_buffer used_modules_save; - INT32 num_used_modules_save; - struct mapping *resolve_cache_save; - - struct svalue default_module; -}; - static void free_compilation(struct compilation *c) { debug_malloc_touch(c); - free_string(c->prog); + 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); free_svalue(& c->default_module); free_supporter(&c->supporter); verify_supporters(); @@ -7111,12 +7141,8 @@ static void run_init(struct compilation *c) c->save_depth=compilation_depth; compilation_depth=-1; - c->saved_handler = error_handler; - if((error_handler = c->handler)) - add_ref(error_handler); - - c->saved_compat_handler = compat_handler; - compat_handler=0; + if (c->compat_handler) free_object(c->compat_handler); + c->compat_handler=0; c->used_modules_save = used_modules; c->num_used_modules_save = Pike_compiler->num_used_modules; @@ -7125,31 +7151,30 @@ static void run_init(struct compilation *c) c->resolve_cache_save = resolve_cache; resolve_cache = 0; - c->save_lex=lex; - - lex.current_line=1; - lex.current_file=make_shared_string("-"); + c->lex.current_line=1; + free_string(c->lex.current_file); + c->lex.current_file=make_shared_string("-"); if (runtime_options & RUNTIME_STRICT_TYPES) { - lex.pragmas = ID_STRICT_TYPES; + c->lex.pragmas = ID_STRICT_TYPES; } else { - lex.pragmas = 0; + c->lex.pragmas = 0; } - lex.end = c->prog->str + (c->prog->len << c->prog->size_shift); + c->lex.end = c->prog->str + (c->prog->len << c->prog->size_shift); switch(c->prog->size_shift) { - case 0: lex.current_lexer = yylex0; break; - case 1: lex.current_lexer = yylex1; break; - case 2: lex.current_lexer = yylex2; break; + case 0: c->lex.current_lexer = yylex0; break; + case 1: c->lex.current_lexer = yylex1; break; + case 2: c->lex.current_lexer = yylex2; break; default: Pike_fatal("Program has bad shift %d!\n", c->prog->size_shift); break; } - lex.pos=c->prog->str; + c->lex.pos=c->prog->str; } static void run_init2(struct compilation *c) @@ -7191,14 +7216,6 @@ static void run_exit(struct compilation *c) free_mapping(resolve_cache); resolve_cache = c->resolve_cache_save; - if (error_handler) free_object(error_handler); - error_handler = c->saved_handler; - - if (compat_handler) free_object(compat_handler); - compat_handler = c->saved_compat_handler; - - free_string(lex.current_file); - lex=c->save_lex; verify_supporters(); } @@ -7286,15 +7303,16 @@ static int run_pass1(struct compilation *c) if (!Pike_compiler->new_program->num_linenumbers) { /* The lexer didn't write an initial entry. */ - store_linenumber(0, lex.current_file); + store_linenumber(0, c->lex.current_file); #ifdef DEBUG_MALLOC - if(strcmp(lex.current_file->str,"-")) - debug_malloc_name(Pike_compiler->new_program, lex.current_file->str, 0); + if(strcmp(c->lex.current_file->str,"-")) + debug_malloc_name(Pike_compiler->new_program, c->lex.current_file->str, 0); #endif } CDFPRINTF((stderr, "th(%ld) %p run_pass1() done for %s\n", - (long)th_self(), Pike_compiler->new_program, lex.current_file->str)); + (long)th_self(), Pike_compiler->new_program, + c->lex.current_file->str)); ret=unlink_current_supporter(& c->supporter); @@ -7343,12 +7361,20 @@ void run_pass2(struct compilation *c) (long)th_self(), Pike_compiler->new_program, threads_disabled, compilation_depth)); + CDFPRINTF((stderr, + "th(%ld) %p:\n" + "%s\n" + "---\n" + "%s\n", (long)th_self(), Pike_compiler->new_program, + c->prog->str, c->lex.pos)); + verify_supporters(); do_yyparse(); /* Parse da program */ CDFPRINTF((stderr, "th(%ld) %p run_pass2() done for %s\n", - (long)th_self(), Pike_compiler->new_program, lex.current_file->str)); + (long)th_self(), Pike_compiler->new_program, + c->lex.current_file->str)); verify_supporters(); @@ -7458,11 +7484,19 @@ 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", (long) th_self(), cc->p, finish ? "continuing" : "cleaning up")); + /* Reenter the delayed compilation. */ + add_ref(cc->supporter.self); + low_enter_compiler(cc->supporter.self, cc->compilation_inherit); + if(finish && cc->p) run_pass2(cc); run_cleanup(cc,1); + + exit_compiler(); debug_malloc_touch(cc); @@ -7478,48 +7512,46 @@ static int call_delayed_pass2(struct compilation *cc, int finish) CDFPRINTF((stderr, "th(%ld) %p delayed compile %s.\n", (long) th_self(), cc->target, ok ? "done" : "failed")); - free_compilation(cc); - free(cc); verify_supporters(); return ok; } -#define THIS_COMPILATION ((struct compilation *)(Pike_fp->current_storage)) - 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! */ + c->compilation_inherit = + Pike_fp->context - Pike_fp->current_object->prog->inherits; c->default_module.type = T_INT; c->default_module.subtype = NUMBER_NUMBER; + c->lex.current_line = 1; + c->lex.current_file = make_shared_string("-"); break; case PROG_EVENT_EXIT: + CDFPRINTF((stderr, "th(%ld) compilation: EXIT(%p).\n", + (long) th_self(), c)); free_compilation(c); break; } } -/*! @decl void compile(string code) - *! - *! Compile a segment of Pike code. - */ -static void f_compilation_compile(INT32 args) -{ - pop_n_elems(args); - push_int(0); -} - /*! @decl void report(SeverityLevel severity, @ - *! string filename, int linenumber, @ - *! string subsystem, @ - *! string message, mixed ... extra_args) + *! string filename, int linenumber, @ + *! string subsystem, @ + *! string message, mixed ... extra_args) *! *! Report a diagnostic from the compiler. */ static void f_compilation_report(INT32 args) { + struct compilation *c = THIS_COMPILATION; int level; struct pike_string *filename; INT_TYPE linenumber; @@ -7529,30 +7561,355 @@ static void f_compilation_report(INT32 args) f_sprintf(args - 4); args = 5; } - get_all_args("report", args, "%d%S%i%S%S", + get_all_args("report", args, "%d%W%i%W%W", &level, &filename, &linenumber, &subsystem, &message); - fprintf(stderr, "%s:%ld: %s\n", filename->str, linenumber, message->str); + + /* Ignore informational level messages */ + if (level) { + if ((c->handler && c->handler->prog) || + (c->compat_handler && c->compat_handler->prog) || + get_master()) { + 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++; + } + } 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) + *! + *! 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_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->target) { + Pike_error("CompilationEnvironment in use.\n"); + } + + STACK_LEVEL_START(args); + + get_all_args("compile", args, "%W.%O%d%d%P%O", + &aprog, &ahandler, + &amajor, &aminor, + &atarget, &aplaceholder); + + if (args == 3) { + SIMPLE_BAD_ARG_ERROR("compile", 4, "int"); + } + + check_c_stack(65536); + + CDFPRINTF((stderr, "th(%ld) %p compile() enter, placeholder=%p\n", + (long) th_self(), atarget, aplaceholder)); + + debug_malloc_touch(c); + + verify_supporters(); + + 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->handler) free_object(c->handler); + add_ref(c->handler = ahandler); + } + c->major=amajor; + c->minor=aminor; + + if((c->target=atarget)) add_ref(atarget); + else c->target = low_allocate_program(); + + 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)) + { + pop_stack(); + ref_push_mapping(get_builtin_constants()); + } + } 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--; + +#ifdef PIKE_DEBUG + SET_ONERROR(tmp, fatal_on_error,"Compiler exited with longjump!\n"); +#endif + + 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); + debug_malloc_touch(c); + run_cleanup(c,0); + + ret=c->p; + c->p = NULL; + + 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"); + } + if(!ret) { + CDFPRINTF((stderr, "th(%ld) %p compile() failed.\n", + (long) th_self(), c->target)); + throw_error_object(low_clone(compilation_error_program), 0, 0, 0, + "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); + else + push_int(0); +} + +/* Fake being called via CompilationEnvironment()->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(). */ +#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->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; +} + +void enter_compiler(struct pike_string *filename, int linenumber) +{ + struct object *ce = clone_object(compilation_program, 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(). + */ +void exit_compiler(void) +{ +#ifdef PIKE_DEBUG + if ((Pike_fp->current_program != compilation_program) || + (Pike_fp->fun != 2)) { + Pike_fatal("exit_compiler(): Frame stack out of whack!\n"); + } +#endif /* PIKE_DEBUG */ + POP_PIKE_FRAME(); +} + +/*! @class PikeCompiler + *! + *! The Pike compiler. + */ + +/*! @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" + break; + case PROG_EVENT_EXIT: +#define EXIT +#include "compilation.h" + break; + } +#endif /* 0 */ + + fprintf(stderr, "program_state_event_handler(%d) obj:%p prog:%p\n", + event, Pike_fp->current_object, Pike_fp->current_program); +} + +/*! @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 reference *ref; - struct identifier *i; - struct inherit *inh; - unsigned INT16 *ix; + struct program *p = compilation_program = low_allocate_program(), *p2; + struct program_constant *pc; + struct reference *ref, *ref2; + struct identifier *i, *i2; + struct inherit *inh, *inh2; + unsigned INT16 *ix, *ix2; + int e; p->parent_info_storage = -1; p->event_handler = compilation_event_handler; p->flags |= PROGRAM_HAS_C_METHODS; - p->inherits = inh = malloc(sizeof(struct inherit)); - p->identifier_references = ref = malloc(sizeof(struct reference) * 2); - p->identifiers = i = malloc(sizeof(struct identifier) * 2); - p->identifier_index = ix = malloc(sizeof(unsigned INT16) * 2); + p->inherits = inh = xalloc(sizeof(struct inherit)); + p->identifier_references = ref = xalloc(sizeof(struct reference) * 3); + p->identifiers = i = xalloc(sizeof(struct identifier) * 3); + p->identifier_index = ix = xalloc(sizeof(unsigned INT16) * 3); + p->constants = pc = xalloc(sizeof(struct program_constant) * 1); inh->prog = p; inh->inherit_level = 0; @@ -7570,13 +7927,19 @@ static void compile_compiler(void) p->inherits->storage_offset = 0; p->storage_needed = sizeof(struct compilation); - /* ADD_FUNCTION("compile", f_compilation_compile, ...); */ - i->name = make_shared_string("compile"); - i->type = make_pike_type(tFunc(tStr, tPrg(tObj))); + /* ADD_FUNCTION("report", f_compilation_report, ...); */ + i->name = make_shared_string("report"); + i->type = make_pike_type(tFuncV(tName("SeverityLevel", tInt03) tStr tIntPos + tStr tStr, tMix, tVoid)); i->run_time_type = T_FUNCTION; i->identifier_flags = IDENTIFIER_C_FUNCTION; - i->func.c_fun = f_compilation_compile; + i->func.c_fun = f_compilation_report; i->opt_flags = 0; +#ifdef PROFILING + i->self_time = 0; + i->num_calls = 0; + i->total_time = 0; +#endif i++; *(ix++) = ref->identifier_offset = compilation_program->num_identifiers++; p->num_identifier_index++; @@ -7585,14 +7948,108 @@ static void compile_compiler(void) ref++; p->num_identifier_references++; - /* ADD_FUNCTION("report", f_compilation_report, ...); */ - i->name = make_shared_string("report"); - i->type = make_pike_type(tFuncV(tName("SeverityLevel", tInt03) tStr tIntPos - tStr tStr, tMix, tVoid)); + p2 = low_allocate_program(); + + pc->sval.u.program = p2; + pc->sval.type = T_PROGRAM; + pc->sval.subtype = 0; + pc->offset = -1; + i->name = make_shared_string("PikeCompiler"); + i->type = get_type_of_svalue(&pc->sval); + i->run_time_type = T_PROGRAM; + i->identifier_flags = IDENTIFIER_CONSTANT; + i->func.offset = p->num_constants++; + pc++; + i->opt_flags = 0; +#ifdef PROFILING + i->self_time = 0; + i->num_calls = 0; + i->total_time = 0; +#endif + i++; + *(ix++) = ref->identifier_offset = compilation_program->num_identifiers++; + p->num_identifier_index++; + ref->id_flags = 0; + ref->inherit_offset = 0; + ref++; + p->num_identifier_references++; + + /* FIXME: Parent info. */ + p2->event_handler = program_state_event_handler; + p2->flags |= PROGRAM_NEEDS_PARENT|PROGRAM_USES_PARENT|PROGRAM_HAS_C_METHODS; + p2->parent_info_storage = 0; + p2->xstorage = sizeof(struct parent_info); + + p2->inherits = inh2 = malloc(sizeof(struct inherit)); + p2->identifier_references = ref2 = malloc(sizeof(struct reference) * 2); + p2->identifiers = i2 = malloc(sizeof(struct identifier) * 2); + p2->identifier_index = ix2 = malloc(sizeof(unsigned INT16) * 2); + + inh2->prog = p2; + inh2->inherit_level = 0; + inh2->identifier_level = 0; + inh2->parent_identifier = -1; + inh2->parent_offset = OBJECT_PARENT; + inh2->identifier_ref_offset = 0; + inh2->storage_offset = p2->xstorage; + inh2->parent = NULL; + inh2->name = NULL; + p2->num_inherits = 1; + + /* ADD_STORAGE(struct program_state); */ + p2->alignment_needed = ALIGNOF(struct program_state); + p2->inherits->storage_offset = p2->xstorage; + p2->storage_needed = p2->xstorage + sizeof(struct program_state); + + /* low_define_alias(NULL, NULL, 0, 1, 0); */ + i2->name = make_shared_string("report"); + i2->type = make_pike_type(tFuncV(tName("SeverityLevel", tInt03) tStr tIntPos + tStr tStr, tMix, tVoid)); + i2->run_time_type = T_FUNCTION; + i2->identifier_flags = IDENTIFIER_C_FUNCTION | IDENTIFIER_ALIAS; + i2->func.ext_ref.depth = 1; + i2->func.ext_ref.id = 0; + i2->opt_flags = 0; +#ifdef PROFILING + i2->self_time = 0; + i2->num_calls = 0; + i2->total_time = 0; +#endif + i2++; + *(ix2++) = ref2->identifier_offset = p2->num_identifiers++; + p2->num_identifier_index++; + ref2->id_flags = 0; + ref2->inherit_offset = 0; + ref2++; + p2->num_identifier_references++; + + + p2->flags |= PROGRAM_PASS_1_DONE; + + fsort_program_identifier_index(p2->identifier_index, ix2-1, p2); + p2->flags |= PROGRAM_FIXED; + + /* Yes, it is supposed to start at 0 /Grubba */ + for(e=0;e<NUM_LFUNS;e++) { + int id = p2->lfuns[e] = low_find_lfun(p2, e); + } + + optimize_program(p2); + p2->flags |= PROGRAM_FINISHED; + + + /* ADD_FUNCTION("compile", f_compilation_compile, ...); */ + i->name = make_shared_string("compile"); + i->type = make_pike_type(tFunc(tStr, tPrg(tObj))); i->run_time_type = T_FUNCTION; i->identifier_flags = IDENTIFIER_C_FUNCTION; - i->func.c_fun = f_compilation_report; + i->func.c_fun = f_compilation_compile; i->opt_flags = 0; +#ifdef PROFILING + i->self_time = 0; + i->num_calls = 0; + i->total_time = 0; +#endif i++; *(ix++) = ref->identifier_offset = compilation_program->num_identifiers++; p->num_identifier_index++; @@ -7606,12 +8063,16 @@ static void compile_compiler(void) fsort_program_identifier_index(p->identifier_index, ix-1, p); p->flags |= PROGRAM_FIXED; + /* Yes, it is supposed to start at 0 /Grubba */ + for(e=0;e<NUM_LFUNS;e++) { + int id = p->lfuns[e] = low_find_lfun(p, e); + } + optimize_program(p); p->flags |= PROGRAM_FINISHED; -} -/*! @endclass - */ + add_global_program("CompilerEnvironment", p); +} struct program *compile(struct pike_string *aprog, struct object *ahandler,/* error handler */ @@ -7624,14 +8085,23 @@ struct program *compile(struct pike_string *aprog, #ifdef PIKE_DEBUG ONERROR tmp; #endif - struct compilation *c=ALLOC_STRUCT(compilation); + struct object *ce; + struct compilation *c; - verify_supporters(); + /* FIXME! */ + + Pike_fatal("Old C-level compile() function called!\n"); CDFPRINTF((stderr, "th(%ld) %p compile() enter, placeholder=%p\n", (long) th_self(), atarget, aplaceholder)); + ce = clone_object(compilation_program, 0); + c = (struct compilation *)ce->storage; + debug_malloc_touch(c); + + verify_supporters(); + c->p = NULL; add_ref(c->prog=aprog); if((c->handler=ahandler)) add_ref(ahandler); @@ -7697,8 +8167,7 @@ struct program *compile(struct pike_string *aprog, ret=c->p; debug_malloc_touch(c); - free_compilation(c); - free(c); + free_object(ce); if (!dependants_ok) { CDFPRINTF((stderr, "th(%ld) %p compile() reporting failure " @@ -7955,6 +8424,8 @@ void init_program(void) compile_compiler(); + enter_compiler(NULL, 0); + MAKE_CONST_STRING(this_program_string,"this_program"); MAKE_CONST_STRING(this_string,"this"); MAKE_CONST_STRING(UNDEFINED_string,"UNDEFINED"); @@ -8036,6 +8507,8 @@ void init_program(void) low_add_constant("__placeholder_object",&s); debug_malloc_touch(placeholder_object); } + + exit_compiler(); } void cleanup_program(void) @@ -8395,6 +8868,7 @@ void push_compiler_frame(int lexical_scope) void low_pop_local_variables(int level) { + struct compilation *c = THIS_COMPILATION; while(Pike_compiler->compiler_frame->current_number_of_locals > level) { int e; @@ -8402,14 +8876,14 @@ void low_pop_local_variables(int level) if ((Pike_compiler->compiler_pass == 2) && !(Pike_compiler->compiler_frame->variable[e].flags & LOCAL_VAR_IS_USED)) { - struct pike_string *save_file = lex.current_file; - int save_line = lex.current_line; - lex.current_file = Pike_compiler->compiler_frame->variable[e].file; - lex.current_line = Pike_compiler->compiler_frame->variable[e].line; + struct pike_string *save_file = c->lex.current_file; + int save_line = c->lex.current_line; + c->lex.current_file = Pike_compiler->compiler_frame->variable[e].file; + c->lex.current_line = Pike_compiler->compiler_frame->variable[e].line; yywarning("Unused local variable %S.", Pike_compiler->compiler_frame->variable[e].name); - lex.current_file = save_file; - lex.current_line = save_line; + c->lex.current_file = save_file; + c->lex.current_line = save_line; } free_string(Pike_compiler->compiler_frame->variable[e].name); free_type(Pike_compiler->compiler_frame->variable[e].type); @@ -8423,6 +8897,7 @@ void low_pop_local_variables(int level) void pop_local_variables(int level) { #if 1 + struct compilation *c = THIS_COMPILATION; /* We need to save the variables Kuppo (but not their names) */ if(level < Pike_compiler->compiler_frame->min_number_of_locals) { @@ -8433,14 +8908,16 @@ void pop_local_variables(int level) if ((Pike_compiler->compiler_pass == 2) && !(Pike_compiler->compiler_frame->variable[level].flags & LOCAL_VAR_IS_USED)) { - struct pike_string *save_file = lex.current_file; - int save_line = lex.current_line; - lex.current_file = Pike_compiler->compiler_frame->variable[level].file; - lex.current_line = Pike_compiler->compiler_frame->variable[level].line; + struct pike_string *save_file = c->lex.current_file; + int save_line = c->lex.current_line; + c->lex.current_file = + Pike_compiler->compiler_frame->variable[level].file; + c->lex.current_line = + Pike_compiler->compiler_frame->variable[level].line; yywarning("Unused local variable %S.", Pike_compiler->compiler_frame->variable[level].name); - lex.current_file = save_file; - lex.current_line = save_line; + c->lex.current_file = save_file; + c->lex.current_line = save_line; /* Make sure we only warn once... */ Pike_compiler->compiler_frame->variable[level].flags |= LOCAL_VAR_IS_USED; @@ -8649,10 +9126,13 @@ int find_child(struct program *parent, struct program *child) void yywarning(char *fmt, ...) { + struct compilation *c = THIS_COMPILATION; struct string_builder s; struct pike_string *msg; va_list args; + CHECK_COMPILER(); + /* If we have parse errors we might get erroneous warnings, * so don't print them. * This has the additional benefit of making it easier to @@ -8667,21 +9147,17 @@ void yywarning(char *fmt, ...) msg = finish_string_builder(&s); if (master_object) { - if (lex.current_file) { - ref_push_string(lex.current_file); - } else { - push_empty_string(); - } - push_int(lex.current_line); + ref_push_string(c->lex.current_file); + push_int(c->lex.current_line); push_string(msg); low_safe_apply_handler("compile_warning", - error_handler, compat_handler, 3); + c->handler, c->compat_handler, 3); pop_stack(); } else { if (!msg->size_shift) { fprintf(stderr, "%s:%d: Warning: %s\n", - lex.current_file->str, lex.current_line, msg->str); + c->lex.current_file->str, c->lex.current_line, msg->str); } free_string(msg); } @@ -9001,6 +9477,10 @@ PMOD_EXPORT void *parent_storage(int depth) PMOD_EXPORT void change_compiler_compatibility(int major, int minor) { + struct compilation *c = THIS_COMPILATION; + + CHECK_COMPILER(); + STACK_LEVEL_START(0); if(major == PIKE_MAJOR_VERSION && minor == PIKE_MINOR_VERSION) @@ -9010,8 +9490,8 @@ PMOD_EXPORT void change_compiler_compatibility(int major, int minor) if(major == Pike_compiler->compat_major && minor == Pike_compiler->compat_minor) { /* Optimization -- reuse the current compat handler. */ - if (compat_handler) { - ref_push_object(compat_handler); + if (c->compat_handler) { + ref_push_object(c->compat_handler); } else { push_int(0); } @@ -9024,10 +9504,10 @@ PMOD_EXPORT void change_compiler_compatibility(int major, int minor) STACK_LEVEL_CHECK(1); - if(compat_handler) + if(c->compat_handler) { - free_object(compat_handler); - compat_handler = NULL; + free_object(c->compat_handler); + c->compat_handler = NULL; } if((Pike_sp[-1].type == T_OBJECT) && (Pike_sp[-1].u.object->prog)) @@ -9036,14 +9516,15 @@ PMOD_EXPORT void change_compiler_compatibility(int major, int minor) /* FIXME: */ Pike_error("Subtyped compat handlers are not supported yet.\n"); } - compat_handler = dmalloc_touch(struct object *, Pike_sp[-1].u.object); + c->compat_handler = dmalloc_touch(struct object *, Pike_sp[-1].u.object); dmalloc_touch_svalue(Pike_sp-1); Pike_sp--; } else { pop_stack(); } - if (safe_apply_handler ("get_default_module", error_handler, compat_handler, + if (safe_apply_handler ("get_default_module", + c->handler, c->compat_handler, 0, BIT_MAPPING|BIT_OBJECT|BIT_ZERO)) { if(Pike_sp[-1].type == T_INT) { diff --git a/src/program.h b/src/program.h index 03ea246d943f4b11b59bce6e2ead4eb4fe3a5e8d..32c41e269379fe3a6b366778cc78adb69b36df3e 100644 --- a/src/program.h +++ b/src/program.h @@ -2,7 +2,7 @@ || 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.h,v 1.236 2007/12/28 13:38:16 nilsson Exp $ +|| $Id: program.h,v 1.237 2008/04/14 10:14:41 grubba Exp $ */ #ifndef PROGRAM_H @@ -659,11 +659,9 @@ PMOD_EXPORT void gc_check_zapped (void *a, TYPE_T type, const char *file, int li BLOCK_ALLOC_FILL_PAGES(program, n/a); -extern struct object *error_handler; -extern struct object *compat_handler; - extern struct program *first_program; extern struct program *null_program; +extern struct program *compilation_program; extern struct program *pike_trampoline_program; extern struct program *gc_internal_program; extern struct program *placeholder_program; @@ -695,13 +693,12 @@ struct Supporter struct Supporter *depends_on; struct Supporter *dependants; struct Supporter *next_dependant; + struct object *self; supporter_callback *fun; void *data; struct program *prog; }; - - /* Prototypes begin here */ PMOD_EXPORT void do_free_program (struct program *p); void ins_int(INT32 i, void (*func)(char tmp)); @@ -887,6 +884,8 @@ int call_dependants(struct Supporter *s, int finish); int report_compiler_dependency(struct program *p); struct compilation; void run_pass2(struct compilation *c); +void enter_compiler(struct pike_string *filename, int linenumber); +void exit_compiler(void); struct program *compile(struct pike_string *aprog, struct object *ahandler, int amajor, int aminor,