diff --git a/src/acconfig.h b/src/acconfig.h index a1de6a690a1437629e06334d7ad1e1afc835bb36..a5bc2a68a08e0cf00f332a4d56ec891cce4bcb82 100644 --- a/src/acconfig.h +++ b/src/acconfig.h @@ -150,6 +150,9 @@ #undef _SGI_SPROC_THREADS #undef _SGI_MP_SOURCE +/* Define this if you have Windows NT threads */ +#undef NT_THREADS + /* Define this if your pthreads have pthread_condattr_default */ #undef HAVE_PTHREAD_CONDATTR_DEFAULT diff --git a/src/builtin_functions.c b/src/builtin_functions.c index 49e348a9f5cabf88cf6e3165fe8554422e512204..5bacfdb4a2996998e613af91409e5d9e91a96465 100644 --- a/src/builtin_functions.c +++ b/src/builtin_functions.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: builtin_functions.c,v 1.58 1997/11/17 03:23:14 hubbe Exp $"); +RCSID("$Id: builtin_functions.c,v 1.59 1998/01/13 22:56:39 hubbe Exp $"); #include "interpret.h" #include "svalue.h" #include "pike_macros.h" @@ -261,27 +261,6 @@ void f_search(INT32 args) } } -void f_call_function(INT32 args) -{ - INT32 expected_stack=sp-args+2-evaluator_stack; - - strict_apply_svalue(sp-args, args - 1); - if(sp < expected_stack + evaluator_stack) - { -#ifdef DEBUG - if(sp+1 != expected_stack + evaluator_stack) - fatal("Stack underflow!\n"); -#endif - - pop_stack(); - push_int(0); - }else{ - free_svalue(sp-2); - sp[-2]=sp[-1]; - sp--; - } -} - void f_backtrace(INT32 args) { INT32 frames; @@ -372,20 +351,6 @@ void f_add_constant(INT32 args) pop_n_elems(args); } -void f_compile_file(INT32 args) -{ - struct program *p; - if(args<1) - error("Too few arguments to compile_file.\n"); - - if(sp[-args].type!=T_STRING) - error("Bad argument 1 to compile_file.\n"); - - p=compile_file(sp[-args].u.string); - pop_n_elems(args); - push_program(p); -} - static char *combine_path(char *cwd,char *file) { /* cwd is supposed to be combined already */ @@ -874,24 +839,36 @@ void f_next_object(INT32 args) void f_object_program(INT32 args) { - struct program *p; if(args < 1) error("Too few argumenets to object_program()\n"); if(sp[-args].type == T_OBJECT) - p=sp[-args].u.object->prog; - else - p=0; - - pop_n_elems(args); - - if(!p) { - push_int(0); - }else{ - p->refs++; - push_program(p); + struct object *o=sp[-args].u.object; + struct program *p; + if((p=o->prog)) + { + if(o->parent && o->parent->prog) + { + INT32 id=o->parent_identifier; + o=o->parent; + o->refs++; + pop_n_elems(args); + push_object(o); + sp[-1].subtype=id; + sp[-1].type=T_FUNCTION; + return; + }else{ + p->refs++; + pop_n_elems(args); + push_program(p); + return; + } + } } + + pop_n_elems(args); + push_int(0); } void f_reverse(INT32 args) @@ -1103,26 +1080,17 @@ void f_replace(INT32 args) } } -void f_compile_string(INT32 args) +void f_compile(INT32 args) { struct program *p; if(args < 1) - error("Too few arguments to compile_string()\n"); + error("Too few arguments to compile()\n"); if(sp[-args].type != T_STRING) - error("Bad argument 1 to compile_string()\n"); - - if(args < 2) - { - push_string(make_shared_string("-")); - args++; - } - - if(sp[1-args].type != T_STRING) - error("Bad argument 2 to compile_string()\n"); + error("Bad argument 1 to compile()\n"); - p=compile_string(sp[-args].u.string,sp[1-args].u.string); + p=compile(sp[-args].u.string); pop_n_elems(args); push_program(p); } @@ -1239,7 +1207,32 @@ void ID(INT32 args) \ push_int(t); \ } -TYPEP(f_programp, "programp", T_PROGRAM) + +void f_programp(INT32 args) +{ + if(args<1) + error("Too few arguments to programp()\n"); + switch(sp[-args].type) + { + case T_PROGRAM: + pop_n_elems(args); + push_int(1); + return; + + case T_FUNCTION: + if(program_from_function(sp-args)) + { + pop_n_elems(args); + push_int(1); + return; + } + + default: + pop_n_elems(args); + push_int(0); + } +} + TYPEP(f_intp, "intpp", T_INT) TYPEP(f_mappingp, "mappingp", T_MAPPING) TYPEP(f_arrayp, "arrayp", T_ARRAY) @@ -1825,12 +1818,10 @@ void init_builtin_efuns(void) add_efun("allocate", f_allocate, "function(int, string|void:mixed *)", 0); add_efun("arrayp", f_arrayp, "function(mixed:int)",0); add_efun("backtrace",f_backtrace,"function(:array(array(function|int|string)))",OPT_EXTERNAL_DEPEND); - add_efun("call_function",f_call_function,"function(mixed,mixed ...:mixed)",OPT_SIDE_EFFECT | OPT_EXTERNAL_DEPEND); add_efun("column",f_column,"function(array,mixed:array)",0); add_efun("combine_path",f_combine_path,"function(string,string:string)",0); - add_efun("compile_file",f_compile_file,"function(string:program)",OPT_EXTERNAL_DEPEND); - add_efun("compile_string",f_compile_string,"function(string,string|void:program)",OPT_EXTERNAL_DEPEND); + add_efun("compile",f_compile,"function(string:program)",OPT_EXTERNAL_DEPEND); add_efun("copy_value",f_copy_value,"function(mixed:mixed)",0); add_efun("crypt",f_crypt,"function(string:string)|function(string,string:int)",OPT_EXTERNAL_DEPEND); add_efun("ctime",f_ctime,"function(int:string)",OPT_TRY_OPTIMIZE); diff --git a/src/builtin_functions.h b/src/builtin_functions.h index 3dbb24c7b67d62b8f2cf431ca5e297263dbbb985..f7385358f6721f3855f309fbc091a9afba6eee2b 100644 --- a/src/builtin_functions.h +++ b/src/builtin_functions.h @@ -26,7 +26,6 @@ void f_search(INT32 args); void f_call_function(INT32 args); void f_backtrace(INT32 args); void f_add_constant(INT32 args); -void f_compile_file(INT32 args); void f_combine_path(INT32 args); void f_function_object(INT32 args); void f_function_name(INT32 args); @@ -40,7 +39,6 @@ struct callback *add_exit_callback(callback_func call, void *arg, callback_func free_func); void f_exit(INT32 args); -void f_query_host_name(INT32 args); void f_time(INT32 args); void f_crypt(INT32 args); void f_destruct(INT32 args); @@ -51,13 +49,13 @@ void f_object_program(INT32 args); void f_reverse(INT32 args); struct tupel; void f_replace(INT32 args); -void f_compile_string(INT32 args); +void f_compile(INT32 args); void f_mkmapping(INT32 args); void f_objectp(INT32 args); void f_functionp(INT32 args); void f_sleep(INT32 args); void f_gc(INT32 args); -TYPEP(f_programp, "programp", T_PROGRAM) +void f_programp(INT32 args); TYPEP(f_intp, "intpp", T_INT) TYPEP(f_mappingp, "mappingp", T_MAPPING) TYPEP(f_arrayp, "arrayp", T_ARRAY) @@ -68,12 +66,21 @@ void f_sort(INT32 args); void f_rows(INT32 args); void f_column(INT32 args); void f__verify_internals(INT32 args); +void f__debug(INT32 args); void f_localtime(INT32 args); void f_glob(INT32 args); struct callback *add_memory_usage_callback(callback_func call, - void *arg, - callback_func free_func); + void *arg, + callback_func free_func); void f__memory_usage(INT32 args); +void f__next(INT32 args); +void f__prev(INT32 args); +void f__refs(INT32 args); +void f_replace_master(INT32 args); +void f_master(INT32 args); +void f_gethrvtime(INT32 args); +void f_gethrtime(INT32 args); +void f_object_variablep(INT32 args); void init_builtin_efuns(void); /* Prototypes end here */ diff --git a/src/compilation.h b/src/compilation.h index 6c614ed7fecbf76ff2adc8dc149654a8f480b07b..4be9a7a69013b7af80d03762370a0c15e2aa5028 100644 --- a/src/compilation.h +++ b/src/compilation.h @@ -14,7 +14,6 @@ * defining PUSH pushes the selected state(s) on the stack(s) * defining POP pops the selected state(s) from the stack(s) * - * define FILE_STATE to select the file state * define PROGRAM_STATE to select the program state */ @@ -75,35 +74,19 @@ ZMEMBER(struct pike_string *,X) #endif -#ifdef PROGRAM_STATE SNAME(program_state,previous_program_state) ZMEMBER(INT32,last_line) STRMEMBER(last_file,"last_file") - ZMEMBER(struct program,fake_program) + ZMEMBER(struct program *,new_program) + ZMEMBER(struct program *,malloc_size_program) ZMEMBER(node *,init_node) ZMEMBER(INT32,last_pc) ZMEMBER(int,num_parse_error) - ZMEMBER(struct locals *,local_variables) - ZMEMBER(dynamic_buffer,inherit_names) + ZMEMBER(struct compiler_frame *,compiler_frame) ZMEMBER(dynamic_buffer,used_modules) - ZMEMBER2(dynamic_buffer,areas,[NUM_AREAS]) IMEMBER(int,comp_stackp) + IMEMBER(int,compiler_pass) SEND -#endif - -#ifdef FILE_STATE - SNAME(file_state,previous_file_state) - ZMEMBER(INT32,old_line) - ZMEMBER(INT32,current_line) - ZMEMBER(INT32,nexpands) - ZMEMBER(int,pragma_all_inline) - ZMEMBER(struct inputstate *,istate) - ZMEMBER(struct hash_table *,defines) - ZMEMBER(struct program_state *,previous_program_state) - STRMEMBER(current_file,"current_file") - SEND -#endif - #undef PCODE #undef STRMEMBER @@ -113,3 +96,8 @@ #undef ZMEMBER2 #undef SNAME #undef SEND + +#undef STRUCT +#undef PUSH +#undef POP +#undef DECLARE diff --git a/src/configure.in b/src/configure.in index 8be1d18e9dbe611fbc97846cbfd974cc9c18b3a1..bb3241c011630c05b2ec73efbca83903062f3765 100644 --- a/src/configure.in +++ b/src/configure.in @@ -1,4 +1,4 @@ -AC_REVISION("$Id: configure.in,v 1.148 1998/01/10 21:19:08 hubbe Exp $") +AC_REVISION("$Id: configure.in,v 1.149 1998/01/13 22:56:40 hubbe Exp $") AC_INIT(interpret.c) AC_CONFIG_HEADER(machine.h) @@ -692,6 +692,16 @@ fi if test x$with_threads = xyes ; then OLDLIBS="$LIBS" +if test "x$pike_cv_sys_os" = "xWindows_NT" ; then + # NT has threads... + + AC_DEFINE(_REENTRANT) + AC_DEFINE(_THREAD_SAFE) + AC_DEFINE(_UNIX_THREADS) + AC_DEFINE(NT_THREADS) + +else + AC_MSG_CHECKING(unix threads) case "x$pike_cv_sys_os" in *) @@ -872,6 +882,7 @@ int main() # fi fi fi +fi # NT else # Without threads : diff --git a/src/cpp.c b/src/cpp.c index 55a84216ff08b2a4ce9e4ddb7b9b84c98b09f61e..c745da50288c4d2cd29554d146a327690d8b9dff 100644 --- a/src/cpp.c +++ b/src/cpp.c @@ -1781,7 +1781,7 @@ static void check_constant(struct cpp *this, if(!isidchar(data[dlen])) break; - push_string(binary_findstring(data, dlen)); + push_string(make_shared_binary_string(data, dlen)); if((sv=low_mapping_string_lookup(get_builtin_constants(), sp[-1].u.string))) { diff --git a/src/docode.c b/src/docode.c index 6db4d0f002b9306e047d431523b0f309acc1003d..4110312c1cad4b1dc525c8f3938e87593a0eb15d 100644 --- a/src/docode.c +++ b/src/docode.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: docode.c,v 1.23 1997/09/22 01:01:15 hubbe Exp $"); +RCSID("$Id: docode.c,v 1.24 1998/01/13 22:56:42 hubbe Exp $"); #include "las.h" #include "program.h" #include "language.h" @@ -15,7 +15,7 @@ RCSID("$Id: docode.c,v 1.23 1997/09/22 01:01:15 hubbe Exp $"); #include "array.h" #include "pike_macros.h" #include "error.h" -#include "pike_memory.h" +#include "memory.h" #include "svalue.h" #include "main.h" #include "lex.h" @@ -32,47 +32,14 @@ static INT32 current_switch_default; static INT32 current_switch_values_on_stack; static INT32 *current_switch_jumptable =0; -void ins_byte(unsigned char b,int area) -{ - add_to_mem_block(area, (char *)&b, 1); -} - -void ins_signed_byte(char b,int area) -{ - add_to_mem_block(area, (char *)&b, 1); -} - -void ins_short(INT16 l,int area) -{ - add_to_mem_block(area, (char *)&l, sizeof(INT16)); -} - -/* - * Store an INT32. - */ -void ins_int(INT32 l,int area) -{ - add_to_mem_block(area, (char *)&l+0, sizeof(INT32)); -} - void upd_int(int offset, INT32 tmp) { -#ifdef HANDLES_UNALIGNED_MEMORY_ACCESS - *((int *)(areas[A_PROGRAM].s.str+offset))=tmp; -#else - MEMCPY(areas[A_PROGRAM].s.str+offset, (char *)&tmp,sizeof(tmp)); -#endif + MEMCPY(new_program->program+offset, (char *)&tmp,sizeof(tmp)); } INT32 read_int(int offset) { - INT32 tmp; -#ifdef HANDLES_UNALIGNED_MEMORY_ACCESS - tmp=*((int *)(areas[A_PROGRAM].s.str+offset)); -#else - MEMCPY((char *)&tmp, areas[A_PROGRAM].s.str+offset,sizeof(tmp)); -#endif - return tmp; + return EXTRACT_INT(new_program->program+offset); } int store_linenumbers=1; @@ -148,12 +115,12 @@ void do_pop(int x) int do_docode(node *n,INT16 flags) { int i; - int save_current_line=current_line; + int save_current_line=lex.current_line; if(!n) return 0; - current_line=n->line_number; + lex.current_line=n->line_number; i=do_docode2(n, flags); - current_line=save_current_line; + lex.current_line=save_current_line; return i; } @@ -174,8 +141,8 @@ static void code_expression(node *n, int flags, char *err) case 2: fatal("Internal compiler error (%s), line %ld, file %s\n", err, - (long)current_line, - current_file?current_file->str:"Unknown"); + (long)lex.current_line, + lex.current_file?lex.current_file->str:"Unknown"); } } @@ -279,8 +246,7 @@ static int do_docode2(node *n,int flags) default: yyerror("Illegal lvalue."); emit(F_NUMBER,0); - emit(F_NUMBER,0); - return 2; + return 1; case F_LVALUE_LIST: case F_LOCAL: @@ -289,12 +255,30 @@ static int do_docode2(node *n,int flags) case F_INDEX: case F_ARROW: case F_ARG_LIST: + case F_EXTERNAL: break; } } switch(n->token) { + case F_EXTERNAL: + emit(F_LDA, n->u.integer.a); + if(flags & DO_LVALUE) + { + emit(F_EXTERNAL_LVALUE, n->u.integer.b); + return 2; + }else{ + emit(F_EXTERNAL, n->u.integer.b); + return 1; + } + break; + + case F_UNDEFINED: + yyerror("Undefined identifier"); + emit(F_NUMBER,0); + return 1; + case F_PUSH_ARRAY: code_expression(CAR(n), 0, "`@"); emit2(F_PUSH_ARRAY); @@ -368,7 +352,7 @@ static int do_docode2(node *n,int flags) tmp1=do_docode(CAR(n),DO_LVALUE); #ifdef DEBUG if(tmp1 != 2) - fatal("HELP! FATAL INTERNAL COMPILER ERROR\n"); + fatal("HELP! FATAL INTERNAL COMPILER ERROR (7)\n"); #endif if(match_types(CAR(n)->type,array_type_string) || @@ -441,7 +425,7 @@ static int do_docode2(node *n,int flags) switch(CDR(n)->token) { case F_LOCAL: - if(CDR(n)->u.number >= local_variables->max_number_of_locals) + if(CDR(n)->u.number >= compiler_frame->max_number_of_locals) yyerror("Illegal to use local variable here."); code_expression(CAR(n), 0, "RHS"); @@ -450,7 +434,7 @@ static int do_docode2(node *n,int flags) break; case F_IDENTIFIER: - if(!IDENTIFIER_IS_VARIABLE( ID_FROM_INT(& fake_program, CDR(n)->u.number)->identifier_flags)) + if(!IDENTIFIER_IS_VARIABLE( ID_FROM_INT(new_program, CDR(n)->u.number)->identifier_flags)) { yyerror("Cannot assign functions or constants.\n"); }else{ @@ -501,7 +485,7 @@ static int do_docode2(node *n,int flags) case F_RANGE: tmp1=do_docode(CAR(n),DO_NOT_COPY); if(do_docode(CDR(n),DO_NOT_COPY)!=2) - fatal("Compiler internal error (at %ld).\n",(long)current_line); + fatal("Compiler internal error (at %ld).\n",(long)lex.current_line); emit2(n->token); return tmp1; @@ -510,7 +494,7 @@ static int do_docode2(node *n,int flags) tmp1=do_docode(CAR(n),DO_LVALUE); #ifdef DEBUG if(tmp1 != 2) - fatal("HELP! FATAL INTERNAL COMPILER ERROR (again)\n"); + fatal("HELP! FATAL INTERNAL COMPILER ERROR (1)\n"); #endif if(flags & DO_POP) @@ -527,7 +511,7 @@ static int do_docode2(node *n,int flags) tmp1=do_docode(CAR(n),DO_LVALUE); #ifdef DEBUG if(tmp1 != 2) - fatal("HELP! FATAL INTERNAL COMPILER ERROR (yet again)\n"); + fatal("HELP! FATAL INTERNAL COMPILER ERROR (2)\n"); #endif if(flags & DO_POP) { @@ -703,7 +687,7 @@ static int do_docode2(node *n,int flags) return 1; } else if(CAR(n)->token == F_IDENTIFIER && - IDENTIFIER_IS_FUNCTION(ID_FROM_INT(& fake_program, CAR(n)->u.number)->identifier_flags)) + IDENTIFIER_IS_FUNCTION(ID_FROM_INT(new_program, CAR(n)->u.number)->identifier_flags)) { emit2(F_MARK); do_docode(CDR(n),0); @@ -722,14 +706,15 @@ static int do_docode2(node *n,int flags) tmp=findstring("call_function"); if(!tmp) yyerror("No call_function efun."); - if(!find_module_identifier(tmp)) + foo=find_module_identifier(tmp); + if(!foo || !foo->token==F_CONSTANT) { yyerror("No call_function efun."); }else{ - tmp1=store_constant(sp-1, 1); - pop_stack(); + tmp1=store_constant(& foo->u.sval, 1); emit(F_APPLY, tmp1); } + free_node(foo); return 1; } @@ -790,12 +775,12 @@ static int do_docode2(node *n,int flags) current_switch_jumptable[current_switch_case++]=-1; DO_CODE_BLOCK(CDR(n)); - + #ifdef DEBUG if(sp-save_sp != cases) fatal("Count cases is wrong!\n"); #endif - + f_aggregate(cases); order=get_switch_order(sp[-1].u.array); @@ -1065,7 +1050,7 @@ static int do_docode2(node *n,int flags) } case F_LOCAL: - if(n->u.number >= local_variables->max_number_of_locals) + if(n->u.number >= compiler_frame->max_number_of_locals) yyerror("Illegal to use local variable here."); if(flags & DO_LVALUE) { @@ -1077,7 +1062,7 @@ static int do_docode2(node *n,int flags) } case F_IDENTIFIER: - if(IDENTIFIER_IS_FUNCTION(ID_FROM_INT(& fake_program, n->u.number)->identifier_flags)) + if(IDENTIFIER_IS_FUNCTION(ID_FROM_INT(new_program, n->u.number)->identifier_flags)) { if(flags & DO_LVALUE) { diff --git a/src/docode.h b/src/docode.h index 0fa3162fe513b21c110c70bd0833a885785cb74f..ba04a4bf8ffe8ff78f1dce8c03ba8e9833bb3379 100644 --- a/src/docode.h +++ b/src/docode.h @@ -21,20 +21,20 @@ extern int store_linenumbers; extern int comp_stackp; extern INT32 comp_stack[COMPILER_STACK_SIZE]; -#define emit(X,Y) insert_opcode((X),(Y),current_line, current_file) -#define emit2(X) insert_opcode2((X),current_line, current_file) +#define emit(X,Y) insert_opcode((X),(Y),lex.current_line, lex.current_file) +#define emit2(X) insert_opcode2((X),lex.current_line, lex.current_file) /* Prototypes begin here */ -void ins_byte(unsigned char b,int area); -void ins_signed_byte(char b,int area); -void ins_short(INT16 l,int area); -void ins_int(INT32 l,int area); void upd_int(int offset, INT32 tmp); INT32 read_int(int offset); void push_address(void); void push_explicit(INT32 address); INT32 pop_address(void); +int alloc_label(void); +int do_jump(int token,INT32 lbl); +void do_pop(int x); int do_docode(node *n,INT16 flags); +void do_cond_jump(node *n, int label, int iftrue, int flags); void do_code_block(node *n); int docode(node *n); /* Prototypes end here */ diff --git a/src/gc.c b/src/gc.c index 9a7f6f56514979a5d434040dadb80311b4a2e13a..941e9fe7c141105a671099bf298573770f7d7953 100644 --- a/src/gc.c +++ b/src/gc.c @@ -276,7 +276,7 @@ void describe_something(void *a, int t) break; } - for(pos=0;pos<(long)p->program_size && pos<100;pos++) + for(pos=0;pos<(long)p->num_program && pos<100;pos++) { tmp=get_line(p->program+pos, p, &line); if(tmp && line) diff --git a/src/interpret.c b/src/interpret.c index 5b66151e4ad00c88ce09d2e74e3e1809086e4779..73837899a2dc929e4a45c82e12cf0bac1a6bc769 100644 --- a/src/interpret.c +++ b/src/interpret.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: interpret.c,v 1.56 1997/12/22 17:35:23 hubbe Exp $"); +RCSID("$Id: interpret.c,v 1.57 1998/01/13 22:56:43 hubbe Exp $"); #include "interpret.h" #include "object.h" #include "program.h" @@ -180,7 +180,7 @@ void check_mark_stack(INT32 size) } -static void eval_instruction(unsigned char *pc); +static int eval_instruction(unsigned char *pc); /* @@ -476,9 +476,9 @@ void dump_backlog(void) static int o_catch(unsigned char *pc); -static void eval_instruction(unsigned char *pc) +static int eval_instruction(unsigned char *pc) { - unsigned INT32 instr, prefix=0; + unsigned INT32 accumulator=0,instr, prefix=0; while(1) { fp->pc = pc; @@ -562,6 +562,9 @@ static void eval_instruction(unsigned char *pc) CASE(F_PREFIX_CHARX256); prefix+=EXTRACT_UCHAR(pc++)<<8; break; + + CASE(F_LDA); accumulator=GET_ARG(); break; + /* Push number */ CASE(F_CONST0); push_int(0); break; CASE(F_CONST1); push_int(1); break; @@ -616,6 +619,84 @@ static void eval_instruction(unsigned char *pc) print_return_value(); break; + CASE(F_EXTERNAL); + { + struct inherit *inherit; + struct program *p; + INT32 id=GET_ARG(); + struct object *o=fp->context.parent; + INT32 i=fp->context.parent_identifier; + + while(1) + { + if(!o) + error("Parent no longer exists\n"); + + if(!(p=o->prog)) + error("Attempting to access variable in destructed object\n"); + + inherit=INHERIT_FROM_INT(p, i); + + if(!accumulator) break; + --accumulator; + + if(p->identifier_references[id].inherit_offset==0) + { + i=o->parent_identifier; + o=o->parent; + }else{ + i=inherit->parent_identifier; + o=inherit->parent; + } + } + + low_object_index_no_free(sp, + o, + id + inherit->identifier_level); + sp++; + print_return_value(); + break; + } + + CASE(F_EXTERNAL_LVALUE); + { + struct inherit *inherit; + struct program *p; + INT32 id=GET_ARG(); + struct object *o=fp->context.parent; + INT32 i=fp->context.parent_identifier; + + while(1) + { + if(!o) + error("Parent no longer exists\n"); + + if(!(p=o->prog)) + error("Attempting to access variable in destructed object\n"); + + inherit=INHERIT_FROM_INT(p, i); + + if(!accumulator) break; + accumulator--; + + if(p->identifier_references[id].inherit_offset==0) + { + i=o->parent_identifier; + o=o->parent; + }else{ + i=inherit->parent_identifier; + o=inherit->parent; + } + } + + ref_push_object(o); + sp->type=T_LVALUE; + sp->u.integer=id + inherit->identifier_level; + sp++; + break; + } + + CASE(F_MARK_AND_LOCAL); *(mark_sp++)=sp; CASE(F_LOCAL); assign_svalue_no_free(sp++,fp->locals+GET_ARG()); @@ -1075,7 +1156,7 @@ static void eval_instruction(unsigned char *pc) CASE(F_CATCH); if(o_catch(pc+sizeof(INT32))) - return; /* There was a return inside the evaluated code */ + return -1; /* There was a return inside the evaluated code */ else pc+=EXTRACT_INT(pc); break; @@ -1122,34 +1203,59 @@ static void eval_instruction(unsigned char *pc) break; } + CASE(F_APPLY_AND_RETURN); + { + INT32 args=sp - *--mark_sp; + if(fp->locals >= sp-args) + { + MEMMOVE(sp-args+1,sp-args,args*sizeof(struct svalue)); + sp++; + sp[-args-1].type=T_INT; + } + /* We sabotage the stack here */ + assign_svalue(sp-args-1,fp->context.prog->constants+GET_ARG()); + return args+1; + } + + CASE(F_CALL_LFUN_AND_RETURN); + { + INT32 args=sp - *--mark_sp; + if(fp->locals >= sp-args) + { + MEMMOVE(sp-args+1,sp-args,args*sizeof(struct svalue)); + sp++; + sp[-args-1].type=T_INT; + }else{ + free_svalue(sp-args-1); + } + /* More stack sabotage */ + sp[-args-1].u.object=fp->current_object; + sp[-args-1].subtype=GET_ARG()+fp->context.identifier_level; + sp[-args-1].type=T_FUNCTION; + fp->current_object->refs++; + + return args+1; + } + CASE(F_RETURN_1); - pop_n_elems(sp-fp->locals); push_int(1); goto do_return; CASE(F_RETURN_0); - pop_n_elems(sp-fp->locals); push_int(0); goto do_return; CASE(F_RETURN); - if(fp->locals != sp-1) - { - assign_svalue(fp->locals, sp-1); - pop_n_elems(sp - fp->locals - 1); - } - do_return: -#ifdef DEBUG - if(d_flag > 2) - do_gc(); -#endif +#if defined(DEBUG) && defined(GC2) + if(d_flag > 2) do_gc(); check_threads_etc(); +#endif /* fall through */ CASE(F_DUMB_RETURN); - return; + return -1; CASE(F_NEGATE); if(sp[-1].type == T_INT) @@ -1313,12 +1419,368 @@ static void eval_instruction(unsigned char *pc) pop_stack(); break; + CASE(F_CALL_FUNCTION); + mega_apply(APPLY_STACK,sp - *--mark_sp,0,0); + break; + + CASE(F_CALL_FUNCTION_AND_RETURN); + return sp - *--mark_sp; + default: fatal("Strange instruction %ld\n",(long)instr); } } } +void mega_apply(enum apply_type type, INT32 args, void *arg1, void *arg2) +{ + struct object *o; + int fun, tailrecurse=-1; + struct svalue *save_sp=sp-args; + + switch(type) + { + case APPLY_STACK: + apply_stack: + if(!args) + error("Too few arguments to `()\n"); + args--; + if(sp-save_sp-args > (args<<2) + 32) + { + /* The test above assures these two areas + * are not overlapping + */ + assign_svalues(save_sp, sp-args-1, args+1, BIT_MIXED); + pop_n_elems(sp-save_sp-args-1); + } + arg1=(void *)(sp-args-1); + + case APPLY_SVALUE: + apply_svalue: + { + struct svalue *s=(struct svalue *)arg1; + switch(s->type) + { + case T_INT: + if (!s->u.integer) { + error("Attempt to call the NULL-value\n"); + } else { + error("Attempt to call the value %d\n", s->u.integer); + } + + case T_STRING: + if (s->u.string->len > 20) { + error("Attempt to call the string \"%20s\"...\n", s->u.string->str); + } else { + error("Attempt to call the string \"%s\"\n", s->u.string->str); + } + case T_MAPPING: + error("Attempt to call a mapping\n"); + default: + error("Call to non-function value type:%d.\n", s->type); + + case T_FUNCTION: + if(s->subtype == FUNCTION_BUILTIN) + { + (*(s->u.efun->function))(args); + break; + }else{ + o=s->u.object; + fun=s->subtype; + goto apply_low; + } + break; + + case T_ARRAY: + apply_array(s->u.array,args); + break; + + case T_PROGRAM: + push_object(clone_object(s->u.program,args)); + break; + + case T_OBJECT: + o=s->u.object; + fun=LFUN_CALL; + goto call_lfun; + } + break; + } + + call_lfun: +#ifdef DEBUG + if(fun < 0 || fun >= NUM_LFUNS) + fatal("Apply lfun on illegal value!\n"); +#endif + if(!o->prog) + error("Apply on destructed object.\n"); + fun=FIND_LFUN(o->prog,fun); + goto apply_low; + + + case APPLY_LOW: + o=(struct object *)arg1; + fun=(long)arg2; + + apply_low: + { + struct program *p; + struct reference *ref; + struct frame new_frame; + struct identifier *function; + + if(fun<0) + { + pop_n_elems(args); + push_int(0); + return; + } + + check_threads_etc(); + check_stack(256); + check_mark_stack(256); + +#ifdef DEBUG + if(d_flag>2) do_debug(); +#endif + + p=o->prog; + if(!p) + error("Cannot call functions in destructed objects.\n"); +#ifdef DEBUG + if(fun>=(int)p->num_identifier_references) + fatal("Function index out of range.\n"); +#endif + + ref = p->identifier_references + fun; +#ifdef DEBUG + if(ref->inherit_offset>=p->num_inherits) + fatal("Inherit offset out of range in program.\n"); +#endif + + /* init a new evaluation frame */ + new_frame.parent_frame = fp; + new_frame.current_object = o; + new_frame.context = p->inherits[ ref->inherit_offset ]; + if(!ref->inherit_offset) new_frame.context.parent=o->parent; + + function = new_frame.context.prog->identifiers + ref->identifier_offset; + + new_frame.locals = sp - args; + new_frame.args = args; + new_frame.fun = fun; + new_frame.current_storage = o->storage+new_frame.context.storage_offset; + new_frame.pc = 0; + + new_frame.current_object->refs++; + new_frame.context.prog->refs++; + if(new_frame.context.parent) new_frame.context.parent->refs++; + +#ifdef DEBUG + if(t_flag) + { + char *file, *f; + INT32 linep,e,nonblock; + char buf[50],*s; + + if((nonblock=query_nonblocking(2))) + set_nonblocking(2,0); + + if(fp && fp->pc) + { + file=get_line(fp->pc,fp->context.prog,&linep); + while((f=STRCHR(file,'/'))) file=f+1; + }else{ + linep=0; + file="-"; + } + + init_buf(); + sprintf(buf,"%lx->",(long)o); + my_strcat(buf); + my_strcat(function->name->str); + my_strcat("("); + for(e=0;e<args;e++) + { + if(e) my_strcat(","); + describe_svalue(sp-args+e,0,0); + } + my_strcat(")"); + s=simple_free_buf(); + if((long)strlen(s) > (long)TRACE_LEN) + { + s[TRACE_LEN]=0; + s[TRACE_LEN-1]='.'; + s[TRACE_LEN-2]='.'; + s[TRACE_LEN-2]='.'; + } + fprintf(stderr,"- %s:%4ld: %s\n",file,(long)linep,s); + free(s); + + if(nonblock) + set_nonblocking(2,1); + } +#endif + + fp = &new_frame; + + if(function->func.offset == -1) + error("Calling undefined function '%s'.\n",function->name->str); + + switch(function->identifier_flags & (IDENTIFIER_FUNCTION | IDENTIFIER_CONSTANT)) + { + case IDENTIFIER_C_FUNCTION: + fp->num_args=args; + new_frame.num_locals=args; + (*function->func.c_fun)(args); + break; + + case IDENTIFIER_CONSTANT: + { + struct svalue *s=fp->context.prog->constants+function->func.offset; + if(s->type == T_PROGRAM) + { + struct object *tmp=parent_clone_object(s->u.program, + o, + fun, + args); + push_object(tmp); + break; + } + /* Fall through */ + } + + case 0: + { + if(sp-save_sp-args<=0) + { + /* Create an extra svalue for tail recursion style call */ + sp++; + MEMMOVE(sp-args,sp-args-1,sizeof(struct svalue)*args); + sp[-args-1].type=T_INT; + } + low_object_index_no_free(sp-args-1,o,fun); + tailrecurse=args+1; + break; + } + + case IDENTIFIER_PIKE_FUNCTION: + { + int num_args; + int num_locals; + unsigned char *pc; + pc=new_frame.context.prog->program + function->func.offset; + + num_locals=EXTRACT_UCHAR(pc++); + num_args=EXTRACT_UCHAR(pc++); + + /* adjust arguments on stack */ + if(args < num_args) /* push zeros */ + { + clear_svalues(sp, num_args-args); + sp += num_args-args; + args += num_args-args; + } + + if(function->identifier_flags & IDENTIFIER_VARARGS) + { + f_aggregate(args - num_args); /* make array */ + args = num_args+1; + }else{ + if(args > num_args) + { + /* pop excessive */ + pop_n_elems(args - num_args); + args=num_args; + } + } + + clear_svalues(sp, num_locals - args); + sp += num_locals - args; +#ifdef DEBUG + if(num_locals < num_args) + fatal("Wrong number of arguments or locals in function def.\n"); +#endif + new_frame.num_locals=num_locals; + new_frame.num_args=num_args; + tailrecurse=eval_instruction(pc); +#ifdef DEBUG + if(sp<evaluator_stack) + fatal("Stack error (also simple).\n"); +#endif + break; + } + + } + +#if 0 + if(sp - new_frame.locals > 1) + { + pop_n_elems(sp - new_frame.locals -1); + }else if(sp - new_frame.locals < 1){ +#ifdef DEBUG + if(sp - new_frame.locals<0) fatal("Frame underflow.\n"); +#endif + sp->u.integer = 0; + sp->subtype=NUMBER_NUMBER; + sp->type = T_INT; + sp++; + } +#endif + + if(new_frame.context.parent) free_object(new_frame.context.parent); + free_object(new_frame.current_object); + free_program(new_frame.context.prog); + + fp = new_frame.parent_frame; + + if(tailrecurse>=0) + { + args=tailrecurse; + goto apply_stack; + } + +#ifdef DEBUG + if(t_flag) + { + char *s; + int nonblock; + + if((nonblock=query_nonblocking(2))) + set_nonblocking(2,0); + + init_buf(); + my_strcat("Return: "); + describe_svalue(sp-1,0,0); + s=simple_free_buf(); + if((long)strlen(s) > (long)TRACE_LEN) + { + s[TRACE_LEN]=0; + s[TRACE_LEN-1]='.'; + s[TRACE_LEN-2]='.'; + s[TRACE_LEN-2]='.'; + } + fprintf(stderr,"%-*s%s\n",4,"-",s); + free(s); + + if(nonblock) + set_nonblocking(2,1); + } +#endif + } + } + + if(save_sp+1 < sp) + { + assign_svalue(save_sp,sp-1); + pop_n_elems(sp-save_sp-1); + } + + if(save_sp+1 > sp && type != APPLY_SVALUE) + push_int(0); +} + + /* Put catch outside of eval_instruction, so * the setjmp won't affect the optimization of * eval_instruction @@ -1334,13 +1796,13 @@ static int o_catch(unsigned char *pc) UNSETJMP(tmp); return 0; }else{ - eval_instruction(pc); + int x=eval_instruction(pc); + if(x!=-1) mega_apply(APPLY_STACK, x, 0,0); UNSETJMP(tmp); return 1; } } - int apply_low_safe_and_stupid(struct object *o, INT32 offset) { JMP_BUF tmp; @@ -1357,6 +1819,7 @@ int apply_low_safe_and_stupid(struct object *o, INT32 offset) new_frame.fun = -1; new_frame.pc = 0; new_frame.current_storage=o->storage; + new_frame.context.parent=0; fp = & new_frame; new_frame.current_object->refs++; @@ -1366,7 +1829,9 @@ int apply_low_safe_and_stupid(struct object *o, INT32 offset) { ret=1; }else{ - eval_instruction(o->prog->program + offset); + int tmp=eval_instruction(o->prog->program + offset); + if(tmp!=-1) mega_apply(APPLY_STACK, tmp, 0,0); + #ifdef DEBUG if(sp<evaluator_stack) fatal("Stack error (simple).\n"); @@ -1382,207 +1847,6 @@ int apply_low_safe_and_stupid(struct object *o, INT32 offset) return ret; } -void apply_low(struct object *o, int fun, int args) -{ - struct program *p; - struct reference *ref; - struct frame new_frame; - struct identifier *function; - - if(fun<0) - { - pop_n_elems(args); - push_int(0); - return; - } - - o->refs++; - - fast_check_threads_etc(4); - check_stack(256); - check_mark_stack(256); - -#ifdef DEBUG - if(d_flag>2) do_debug(); -#endif - - p=o->prog; - if(!p) - error("Cannot call functions in destructed objects.\n"); -#ifdef DEBUG - if(fun>=(int)p->num_identifier_references) - fatal("Function index out of range.\n"); -#endif - - ref = p->identifier_references + fun; -#ifdef DEBUG - if(ref->inherit_offset>=p->num_inherits) - fatal("Inherit offset out of range in program.\n"); -#endif - - /* init a new evaluation frame */ - new_frame.parent_frame = fp; - new_frame.current_object = o; - new_frame.context = p->inherits[ ref->inherit_offset ]; - function = new_frame.context.prog->identifiers + ref->identifier_offset; - - new_frame.locals = sp - args; - new_frame.args = args; - new_frame.fun = fun; - new_frame.current_storage = o->storage+new_frame.context.storage_offset; - new_frame.pc = 0; - -/* new_frame.current_object->refs++; Moved to beginning of function / Hubbe */ - new_frame.context.prog->refs++; - - if(t_flag) - { - char *file, *f; - INT32 linep,e,nonblock; - char buf[50],*s; - - if((nonblock=query_nonblocking(2))) - set_nonblocking(2,0); - - if(fp && fp->pc) - { - file=get_line(fp->pc,fp->context.prog,&linep); - while((f=STRCHR(file,'/'))) file=f+1; - }else{ - linep=0; - file="-"; - } - - init_buf(); - sprintf(buf,"%lx->",(long)o); - my_strcat(buf); - my_strcat(function->name->str); - my_strcat("("); - for(e=0;e<args;e++) - { - if(e) my_strcat(","); - describe_svalue(sp-args+e,0,0); - } - my_strcat(")"); - s=simple_free_buf(); - if((long)strlen(s) > (long)TRACE_LEN) - { - s[TRACE_LEN]=0; - s[TRACE_LEN-1]='.'; - s[TRACE_LEN-2]='.'; - s[TRACE_LEN-2]='.'; - } - fprintf(stderr,"- %s:%4ld: %s\n",file,(long)linep,s); - free(s); - - if(nonblock) - set_nonblocking(2,1); - } - - fp = &new_frame; - -#ifdef PROFILING - function->num_calls++; -#endif /* PROFILING */ - - if(function->func.offset == -1) - error("Calling undefined function '%s'.\n",function->name->str); - - if(function->identifier_flags & IDENTIFIER_C_FUNCTION) - { - fp->num_args=args; - new_frame.num_locals=args; - (*function->func.c_fun)(args); - }else{ - int num_args; - int num_locals; - unsigned char *pc; - pc=new_frame.context.prog->program + function->func.offset; - - num_locals=EXTRACT_UCHAR(pc++); - num_args=EXTRACT_UCHAR(pc++); - - /* adjust arguments on stack */ - if(args < num_args) /* push zeros */ - { - clear_svalues(sp, num_args-args); - sp += num_args-args; - args += num_args-args; - } - - if(function->identifier_flags & IDENTIFIER_VARARGS) - { - f_aggregate(args - num_args); /* make array */ - args = num_args+1; - }else{ - if(args > num_args) - { - /* pop excessive */ - pop_n_elems(args - num_args); - args=num_args; - } - } - - clear_svalues(sp, num_locals - args); - sp += num_locals - args; -#ifdef DEBUG - if(num_locals < num_args) - fatal("Wrong number of arguments or locals in function def.\n"); -#endif - new_frame.num_locals=num_locals; - new_frame.num_args=num_args; - eval_instruction(pc); -#ifdef DEBUG - if(sp<evaluator_stack) - fatal("Stack error (also simple).\n"); -#endif - } - - if(sp - new_frame.locals > 1) - { - pop_n_elems(sp - new_frame.locals -1); - }else if(sp - new_frame.locals < 1){ -#ifdef DEBUG - if(sp - new_frame.locals<0) fatal("Frame underflow.\n"); -#endif - sp->u.integer = 0; - sp->subtype=NUMBER_NUMBER; - sp->type = T_INT; - sp++; - } - - free_object(new_frame.current_object); - free_program(new_frame.context.prog); - - fp = new_frame.parent_frame; - - if(t_flag) - { - char *s; - int nonblock; - - if((nonblock=query_nonblocking(2))) - set_nonblocking(2,0); - - init_buf(); - my_strcat("Return: "); - describe_svalue(sp-1,0,0); - s=simple_free_buf(); - if((long)strlen(s) > (long)TRACE_LEN) - { - s[TRACE_LEN]=0; - s[TRACE_LEN-1]='.'; - s[TRACE_LEN-2]='.'; - s[TRACE_LEN-2]='.'; - } - fprintf(stderr,"%-*s%s\n",4,"-",s); - free(s); - - if(nonblock) - set_nonblocking(2,1); - } -} - void safe_apply_low(struct object *o,int fun,int args) { JMP_BUF recovery; @@ -1621,9 +1885,9 @@ void safe_apply_low(struct object *o,int fun,int args) } } UNSETJMP(recovery); - } + void safe_apply(struct object *o, char *fun ,INT32 args) { #ifdef DEBUG @@ -1641,7 +1905,7 @@ void apply_lfun(struct object *o, int fun, int args) if(!o->prog) error("Apply on destructed object.\n"); - apply_low(o, o->prog->lfuns[fun], args); + apply_low(o, (int)FIND_LFUN(o->prog,fun), args); } void apply_shared(struct object *o, @@ -1656,129 +1920,6 @@ void apply(struct object *o, char *fun, int args) apply_low(o, find_identifier(fun, o->prog), args); } -void strict_apply_svalue(struct svalue *s, INT32 args) -{ - struct svalue *save_sp; - save_sp=sp-args; - if(t_flag>1) - { - char *file, *f; - INT32 linep,e,nonblock; - char *st; - - if((nonblock=query_nonblocking(2))) - set_nonblocking(2,0); - - if(fp && fp->pc) - { - file=get_line(fp->pc,fp->context.prog,&linep); - while((f=STRCHR(file,'/'))) file=f+1; - }else{ - linep=0; - file="-"; - } - - init_buf(); - describe_svalue(s,0,0); - my_strcat("("); - for(e=0;e<args;e++) - { - if(e) my_strcat(","); - describe_svalue(sp-args+e,0,0); - } - my_strcat(")"); - st=simple_free_buf(); - if((long)strlen(st) > (long)TRACE_LEN) - { - st[TRACE_LEN]=0; - st[TRACE_LEN-1]='.'; - st[TRACE_LEN-2]='.'; - st[TRACE_LEN-2]='.'; - } - fprintf(stderr,"- %s:%4ld: %s\n",file,(long)linep,st); - free(st); - - if(nonblock) - set_nonblocking(2,1); - } - - switch(s->type) - { - case T_FUNCTION: - if(s->subtype == FUNCTION_BUILTIN) - { - (*(s->u.efun->function))(args); - }else{ - apply_low(s->u.object, s->subtype, args); - } - break; - - case T_ARRAY: - apply_array(s->u.array,args); - break; - - case T_PROGRAM: - { - struct object *o=clone_object(s->u.program,args); - push_object(o); - } - break; - - case T_OBJECT: - if(!s->u.object->prog) - error("Calling a destructed object.\n"); - - if(s->u.object->prog->lfuns[LFUN_CALL] == -1) - error("Calling object without `() operator\n"); - - apply_lfun(s->u.object, LFUN_CALL, args); - break; - - case T_INT: - if (!s->u.integer) { - error("Attempt to call the NULL-value\n"); - } else { - error("Attempt to call the value %d\n", s->u.integer); - } - case T_STRING: - if (s->u.string->len > 20) { - error("Attempt to call the string \"%20s\"...\n", s->u.string->str); - } else { - error("Attempt to call the string \"%s\"\n", s->u.string->str); - } - case T_MAPPING: - error("Attempt to call a mapping\n"); - case T_MULTISET: - error("Attempt to call a multiset\n"); - default: - error("Call to non-function value type:%d.\n", s->type); - } - - if(t_flag>1 && sp>save_sp) - { - char *s; - int nonblock; - if((nonblock=query_nonblocking(2))) - set_nonblocking(2,0); - - init_buf(); - my_strcat("Return: "); - describe_svalue(sp-1,0,0); - s=simple_free_buf(); - if((long)strlen(s) > (long)TRACE_LEN) - { - s[TRACE_LEN]=0; - s[TRACE_LEN-1]='.'; - s[TRACE_LEN-2]='.'; - s[TRACE_LEN-2]='.'; - } - fprintf(stderr,"%-*s%s\n",4,"-",s); - free(s); - - if(nonblock) - set_nonblocking(2,1); - } -} void apply_svalue(struct svalue *s, INT32 args) { diff --git a/src/interpret.h b/src/interpret.h index 9b5fd6783e9cabbf0bc3f84f811b19b2de879b43..8a7d46afc16553bf1b18b4519c924bd9869f1bd6 100644 --- a/src/interpret.h +++ b/src/interpret.h @@ -43,6 +43,7 @@ struct frame #define push_object(O) do{ struct object *_=(O); sp->u.object=_; sp++->type=T_OBJECT; }while(0) #define push_float(F) do{ float _=(F); sp->u.float_number=_; sp++->type=T_FLOAT; }while(0) #define push_text(T) push_string(make_shared_string((T))) +#define push_constant_text(T) do{ sp->subtype=0; MAKE_CONSTANT_SHARED_STRING(sp->u.string,T); sp++->type=T_STRING; }while(0) #define ref_push_program(P) do{ struct program *_=(P); _->refs++; sp->u.program=_; sp++->type=T_PROGRAM; }while(0) #define ref_push_mapping(M) do{ struct mapping *_=(M); _->refs++; sp->u.mapping=_; sp++->type=T_MAPPING; }while(0) @@ -53,6 +54,19 @@ struct frame #define push_svalue(S) do { struct svalue *_=(S); assign_svalue_no_free(sp,_); sp++; }while(0) +enum apply_type +{ + APPLY_STACK, /* The function is the first argument */ + APPLY_SVALUE, /* arg1 points to an svalue containing the function */ + APPLY_LOW /* arg1 is the object pointer,(int)arg2 the function */ +}; + +#define apply_low(O,FUN,ARGS) \ + mega_apply(APPLY_LOW, (ARGS), (void*)(O),(void*)(FUN)) + +#define strict_apply_svalue(SVAL,ARGS) \ + mega_apply(APPLY_SVALUE, (ARGS), (void*)(SVAL),0) + #define APPLY_MASTER(FUN,ARGS) \ do{ \ static int fun_,master_cnt=0; \ @@ -103,8 +117,8 @@ void pop_n_elems(INT32 x); void reset_evaluator(void); struct backlog; void dump_backlog(void); +void mega_apply(enum apply_type type, INT32 args, void *arg1, void *arg2); int apply_low_safe_and_stupid(struct object *o, INT32 offset); -void apply_low(struct object *o, int fun, int args); void safe_apply_low(struct object *o,int fun,int args); void safe_apply(struct object *o, char *fun ,INT32 args); void apply_lfun(struct object *o, int fun, int args); @@ -112,7 +126,6 @@ void apply_shared(struct object *o, struct pike_string *fun, int args); void apply(struct object *o, char *fun, int args); -void strict_apply_svalue(struct svalue *s, INT32 args); void apply_svalue(struct svalue *s, INT32 args); void slow_check_stack(void); void cleanup_interpret(void); diff --git a/src/language.yacc b/src/language.yacc index 186321928026016148cdadcb1a266f08996ac730..3f9fa70ce4d4957c3007198c9d67aeab9d58db6e 100644 --- a/src/language.yacc +++ b/src/language.yacc @@ -11,9 +11,10 @@ */ %token F_PREFIX_256 F_PREFIX_512 F_PREFIX_768 F_PREFIX_1024 %token F_PREFIX_CHARX256 F_PREFIX_WORDX256 F_PREFIX_24BITX256 -%token F_POP_VALUE F_POP_N_ELEMS F_MARK F_MARK2 -%token F_CALL_LFUN F_CALL_LFUN_AND_POP +%token F_POP_VALUE F_POP_N_ELEMS F_MARK F_MARK2 F_LDA +%token F_CALL_LFUN F_CALL_LFUN_AND_POP F_CALL_LFUN_AND_RETURN %token F_APPLY F_APPLY_AND_POP F_MARK_APPLY F_MARK_APPLY_POP +%token F_APPLY_AND_RETURN %token F_BRANCH F_BRANCH_WHEN_ZERO F_BRANCH_WHEN_NON_ZERO %token F_BRANCH_WHEN_LT F_BRANCH_WHEN_GT @@ -31,8 +32,10 @@ /* * Basic value pushing */ -%token F_LFUN F_GLOBAL F_LOCAL F_2_LOCALS F_MARK_AND_LOCAL -%token F_GLOBAL_LVALUE F_LOCAL_LVALUE +%token F_LFUN +%token F_GLOBAL F_GLOBAL_LVALUE +%token F_LOCAL F_2_LOCALS F_LOCAL_LVALUE F_MARK_AND_LOCAL +%token F_EXTERNAL F_EXTERNAL_LVALUE %token F_CLEAR_LOCAL F_CLEAR_2_LOCAL F_CLEAR_STRING_SUBTYPE %token F_CONSTANT F_FLOAT F_STRING F_ARROW_STRING %token F_NUMBER F_NEG_NUMBER F_CONST_1 F_CONST0 F_CONST1 F_BIGNUM @@ -49,6 +52,7 @@ %token F_ASSIGN_LOCAL F_ASSIGN_LOCAL_AND_POP %token F_ASSIGN_GLOBAL F_ASSIGN_GLOBAL_AND_POP %token F_ADD F_SUBTRACT F_ADD_INT F_ADD_NEG_INT +%token F_ADD_TO_AND_POP %token F_MULTIPLY F_DIVIDE F_MOD %token F_LT F_GT F_EQ F_GE F_LE F_NE @@ -63,7 +67,7 @@ %token F_FOREACH %token F_SIZEOF F_SIZEOF_LOCAL -%token F_ADD_TO_AND_POP +%token F_CALL_FUNCTION F_CALL_FUNCTION_AND_RETURN /* * These are token values that needn't have an associated code for the @@ -130,6 +134,7 @@ %token F_WHILE %token F_XOR_EQ %token F_NOP +%token F_UNDEFINED %token F_ALIGN %token F_POINTER @@ -157,7 +162,7 @@ /* This is the grammar definition of Pike. */ #include "global.h" -RCSID("$Id: language.yacc,v 1.50 1997/10/27 09:59:21 hubbe Exp $"); +RCSID("$Id: language.yacc,v 1.51 1998/01/13 22:56:43 hubbe Exp $"); #ifdef HAVE_MEMORY_H #include <memory.h> #endif @@ -177,19 +182,14 @@ RCSID("$Id: language.yacc,v 1.50 1997/10/27 09:59:21 hubbe Exp $"); #include "docode.h" #include "machine.h" -#define YYMAXDEPTH 600 +#define YYMAXDEPTH 1000 #ifdef DEBUG #define YYDEBUG 1 #endif -void free_all_local_names(void); -void add_local_name(struct pike_string *,struct pike_string *); -/* - * The names and types of arguments and auto variables. - */ -struct locals *local_variables = 0; +void add_local_name(struct pike_string *,struct pike_string *); static int varargs; static INT32 current_modifiers; @@ -206,6 +206,7 @@ void fix_comp_stack(int sp) } } + /* * Kludge for Bison not using prototypes. */ @@ -332,7 +333,6 @@ int yylex(YYSTYPE *yylval); %type <n> m_expr_list %type <n> m_expr_list2 %type <n> new_local_name -%type <n> optional_comma_expr %type <n> optional_else_part %type <n> return %type <n> sscanf @@ -344,6 +344,7 @@ int yylex(YYSTYPE *yylval); %type <n> unused %type <n> unused2 %type <n> while +%type <n> optional_comma_expr %% all: program; @@ -359,9 +360,7 @@ optional_semi_colon: /* empty */ string_constant: low_string | string_constant '+' low_string { - $$=add_shared_strings($1,$3); - free_string($1); - free_string($3); + $$=add_and_free_shared_strings($1,$3); } ; @@ -371,11 +370,9 @@ optional_rename_inherit: ':' F_IDENTIFIER { $$=$2; } program_ref: string_constant { - reference_shared_string($1); - push_string($1); + ref_push_string($1); push_string($1); - reference_shared_string(current_file); - push_string(current_file); + ref_push_string(lex.current_file); SAFE_APPLY_MASTER("handle_inherit", 2); if(sp[-1].type != T_PROGRAM) @@ -388,43 +385,51 @@ program_ref: string_constant push_string(last_identifier); last_identifier->refs++; }else{ - push_text(""); + push_constant_text(""); } resolv_constant($1); - if(sp[-1].type == T_OBJECT) + switch(sp[-1].type) { - struct program *p=sp[-1].u.object->prog; - if(!p) + case T_OBJECT: + if(!sp[-1].u.object->prog) { pop_stack(); push_int(0); }else{ + struct program *p=sp[-1].u.object->prog; p->refs++; pop_stack(); push_program(p); } - } - if(sp[-1].type != T_PROGRAM) - { + break; + + case T_FUNCTION: + if(program_from_function(sp-1)) + break; + + default: yyerror("Illegal program identifier"); pop_stack(); push_int(0); + + case T_PROGRAM: + break; } + free_node($1); } ; inheritance: modifiers F_INHERIT program_ref optional_rename_inherit ';' { - struct pike_string *s; - if(sp[-1].type == T_PROGRAM) + if(!(new_program->flags & PROGRAM_PASS_1_DONE)) { - s=sp[-2].u.string; + struct pike_string *s=sp[-2].u.string; if($4) s=$4; - do_inherit(sp[-1].u.program,$1,s); - if($4) free_string($4); + do_inherit(sp-1,$1,s); } + if($4) free_string($4); pop_n_elems(2); } ; @@ -441,19 +446,20 @@ import: modifiers F_IMPORT idents ';' constant_name: F_IDENTIFIER '=' expr0 { int tmp; - node *n; /* This can be made more lenient in the future */ - n=mknode(F_ARG_LIST,$3,0); /* Make sure it is optimized */ - if(!is_const(n)) + + /* Ugly hack to make sure that $3 is optimized */ + tmp=compiler_pass; + $3=mknode(F_ARG_LIST,$3,0); + compiler_pass=tmp; + + if(!is_const($3)) { - struct svalue tmp; - yyerror("Constant definition is not constant."); - tmp.type=T_INT; - tmp.u.integer=0; - add_constant($1,&tmp, current_modifiers); + if(compiler_pass==2) + yyerror("Constant definition is not constant."); + add_constant($1,0, current_modifiers); /* Prototype */ } else { - tmp=eval_low(n); - free_node(n); + tmp=eval_low($3); if(tmp < 1) { yyerror("Error in constant definition."); @@ -462,8 +468,9 @@ constant_name: F_IDENTIFIER '=' expr0 add_constant($1,sp-1,current_modifiers); pop_stack(); } - free_string($1); } + if($3) free_node($3); + free_string($1); } ; @@ -484,35 +491,49 @@ block_or_semi: block type_or_error: simple_type { - if(local_variables->current_type) - free_string(local_variables->current_type); - local_variables->current_type=$1; + if(compiler_frame->current_type) + free_string(compiler_frame->current_type); + compiler_frame->current_type=$1; } | /* empty */ { yyerror("Missing type."); - copy_shared_string(local_variables->current_type, + copy_shared_string(compiler_frame->current_type, mixed_type_string); } -def: modifiers type_or_error optional_stars F_IDENTIFIER '(' arguments ')' +def: modifiers type_or_error optional_stars F_IDENTIFIER + { + push_compiler_frame(); + if(!compiler_frame->previous || + !compiler_frame->previous->current_type) + { + yyerror("Internal compiler fault"); + copy_shared_string(compiler_frame->current_type, + mixed_type_string); + }else{ + copy_shared_string(compiler_frame->current_type, + compiler_frame->previous->current_type); + } + } + '(' arguments ')' { int e; /* construct the function type */ - push_finished_type(local_variables->current_type); + push_finished_type(compiler_frame->current_type); while(--$3>=0) push_type(T_ARRAY); - if(local_variables->current_return_type) - free_string(local_variables->current_return_type); - local_variables->current_return_type=pop_type(); + if(compiler_frame->current_return_type) + free_string(compiler_frame->current_return_type); + compiler_frame->current_return_type=pop_type(); - push_finished_type(local_variables->current_return_type); + push_finished_type(compiler_frame->current_return_type); - e=$6-1; + e=$7-1; if(varargs) { - push_finished_type(local_variables->variable[e].type); + push_finished_type(compiler_frame->variable[e].type); e--; varargs=0; pop_type_stack(); @@ -522,7 +543,7 @@ def: modifiers type_or_error optional_stars F_IDENTIFIER '(' arguments ')' push_type(T_MANY); for(; e>=0; e--) { - push_finished_type(local_variables->variable[e].type); + push_finished_type(compiler_frame->variable[e].type); if($1 & ID_VARARGS) { push_type(T_VOID); @@ -532,40 +553,39 @@ def: modifiers type_or_error optional_stars F_IDENTIFIER '(' arguments ')' push_type(T_FUNCTION); $<string>$=pop_type(); - define_function($4, - $<string>$, - $1, - IDENTIFIER_PIKE_FUNCTION, - 0); + + if(compiler_pass==1) + { + define_function($4, + $<string>$, + $1, + IDENTIFIER_PIKE_FUNCTION, + 0); + } } block_or_semi { int e; - if($9) + if($10) { - for(e=0; e<$6; e++) + for(e=0; e<$7; e++) { - if(!local_variables->variable[e].name || - !local_variables->variable[e].name->len) - { - my_yyerror("Missing name for argument %d",e); - } + if(!compiler_frame->variable[e].name || + !compiler_frame->variable[e].name->len) + { + my_yyerror("Missing name for argument %d",e); + } } - dooptcode($4, $9, $<string>8, $1); + dooptcode($4, $10, $<string>9, $1); #ifdef DEBUG if(recoveries && sp-evaluator_stack < recoveries->sp) fatal("Stack error (underflow)\n"); #endif } - if(local_variables->current_return_type) - { - free_string(local_variables->current_return_type); - local_variables->current_return_type=0; - } - free_all_local_names(); + pop_compiler_frame(); free_string($4); - free_string($<string>8); + free_string($<string>9); } | modifiers type_or_error name_list ';' {} | inheritance {} @@ -575,11 +595,10 @@ def: modifiers type_or_error optional_stars F_IDENTIFIER '(' arguments ')' | error ';' { yyerrok; } { reset_type_stack(); -/* if(num_parse_error>5) YYACCEPT; */ +/* if(num_parse_error>5) YYACCEPT; */ } ; - optional_dot_dot_dot: F_DOT_DOT_DOT { $$=1; } | /* empty */ { $$=0; } ; @@ -588,7 +607,6 @@ optional_identifier: F_IDENTIFIER | /* empty */ { $$=0; } ; - new_arg_name: type optional_dot_dot_dot optional_identifier { if(varargs) yyerror("Can't define more arguments after ..."); @@ -598,7 +616,9 @@ new_arg_name: type optional_dot_dot_dot optional_identifier push_type(T_ARRAY); varargs=1; } - if(!$3) $3=make_shared_string(""); + if(!$3) + MAKE_CONSTANT_SHARED_STRING($3,""); + if(islocal($3) >= 0) my_yyerror("Variable '%s' appears twice in argument list.", $3->str); @@ -669,9 +689,10 @@ type3: F_INT_ID { push_type(T_INT); } opt_object_type: /* Empty */ { push_type_int(0); } | '(' program_ref ')' { - if(sp[-1].type == T_PROGRAM) + struct program *p=program_from_svalue(sp-1); + if(p) { - push_type_int(sp[-1].u.program->id); + push_type_int(p->id); }else{ yyerror("Not a valid program specifier"); push_type_int(0); @@ -760,7 +781,7 @@ name_list: new_name new_name: optional_stars F_IDENTIFIER { struct pike_string *type; - push_finished_type(local_variables->current_type); + push_finished_type(compiler_frame->current_type); while($1--) push_type(T_ARRAY); type=pop_type(); define_variable($2, type, current_modifiers); @@ -770,7 +791,7 @@ new_name: optional_stars F_IDENTIFIER | optional_stars F_IDENTIFIER '=' { struct pike_string *type; - push_finished_type(local_variables->current_type); + push_finished_type(compiler_frame->current_type); while($1--) push_type(T_ARRAY); type=pop_type(); $<number>$=define_variable($2, type, current_modifiers); @@ -789,14 +810,14 @@ new_name: optional_stars F_IDENTIFIER new_local_name: optional_stars F_IDENTIFIER { - push_finished_type(local_variables->current_type); + push_finished_type(compiler_frame->current_type); while($1--) push_type(T_ARRAY); add_local_name($2, pop_type()); $$=mknode(F_ASSIGN,mkintnode(0), mklocalnode(islocal($2))); } | optional_stars F_IDENTIFIER '=' expr0 { - push_finished_type(local_variables->current_type); + push_finished_type(compiler_frame->current_type); while($1--) push_type(T_ARRAY); add_local_name($2, pop_type()); $$=mknode(F_ASSIGN,$4,mklocalnode(islocal($2))); @@ -806,17 +827,11 @@ new_local_name: optional_stars F_IDENTIFIER block:'{' { - $<number>$=local_variables->current_number_of_locals; + $<number>$=compiler_frame->current_number_of_locals; } statements '}' { - while(local_variables->current_number_of_locals > $<number>2) - { - int e; - e=--(local_variables->current_number_of_locals); - free_string(local_variables->variable[e].name); - free_string(local_variables->variable[e].type); - } + pop_local_variables($<number>2); $$=$3; } ; @@ -861,12 +876,12 @@ continue: F_CONTINUE { $$=mknode(F_CONTINUE,0,0); } ; lambda: F_LAMBDA { - push_locals(); + push_compiler_frame(); $<number>$=comp_stackp; - if(local_variables->current_return_type) - free_string(local_variables->current_return_type); - copy_shared_string(local_variables->current_return_type,any_type_string); + if(compiler_frame->current_return_type) + free_string(compiler_frame->current_return_type); + copy_shared_string(compiler_frame->current_return_type,any_type_string); } func_args failsafe_block { @@ -875,7 +890,6 @@ lambda: F_LAMBDA int f,e; struct pike_string *name; - setup_fake_program(); fix_comp_stack($<number>2); push_type(T_MIXED); @@ -883,7 +897,7 @@ lambda: F_LAMBDA e=$3-1; if(varargs) { - push_finished_type(local_variables->variable[e].type); + push_finished_type(compiler_frame->variable[e].type); e--; varargs=0; pop_type_stack(); @@ -892,28 +906,27 @@ lambda: F_LAMBDA } push_type(T_MANY); for(; e>=0; e--) - push_finished_type(local_variables->variable[e].type); + push_finished_type(compiler_frame->variable[e].type); push_type(T_FUNCTION); type=pop_type(); - - sprintf(buf,"__lambda_%ld", - (long)fake_program.num_identifier_references); - name=make_shared_string(buf); - - f=dooptcode(name, - mknode(F_ARG_LIST,$4,mknode(F_RETURN,mkintnode(0),0)), - type, - 0); -#ifdef DEBUG - if(recoveries && sp-evaluator_stack < recoveries->sp) - fatal("Stack error (underflow)\n"); -#endif + + if(new_program->flags | PROGRAM_PASS_1_DONE) + { + sprintf(buf,"__lambda_%ld", + (long)new_program->num_identifier_references); + name=make_shared_string(buf); + + f=dooptcode(name, + mknode(F_ARG_LIST,$4,mknode(F_RETURN,mkintnode(0),0)), + type, + 0); + } free_string(name); free_string(type); comp_stackp=$<number>2; - pop_locals(); + pop_compiler_frame(); $$=mkidentifiernode(f); } ; @@ -922,41 +935,70 @@ failsafe_program: '{' program '}' | error { yyerrok; } ; -class: modifiers F_CLASS optional_identifier +class: modifiers F_CLASS F_IDENTIFIER { - start_new_program(); - /* write(2, "start\n", 6); */ + if(compiler_pass==1) + { + low_start_new_program(0, $3, $1); + }else{ + int i; + struct program *p; + struct identifier *id; + i=isidentifier($3); + if(i<0) + { + low_start_new_program(new_program,0,0); + yyerror("Pass 2: program not defined!"); + }else{ + id=ID_FROM_INT(new_program, i); + if(IDENTIFIER_IS_CONSTANT(id->identifier_flags)) + { + struct svalue *s; + s=PROG_FROM_INT(new_program,i)->constants+id->func.offset; + if(s->type==T_PROGRAM) + { + low_start_new_program(s->u.program, $3, $1); + }else{ + yyerror("Pass 2: constant redefined!"); + low_start_new_program(new_program, 0,0); + } + }else{ + yyerror("Pass 2: class constant no longer constant!"); + low_start_new_program(new_program, 0,0); + } + } + } } failsafe_program { - struct svalue s; - /* write(2, "end\n", 4); */ - s.u.program=end_program(); - if(!s.u.program) - { + struct program *p; + if(compiler_pass == 1) + p=end_first_pass(0); + else + p=end_program(); + + $$=mkidentifiernode(isidentifier($3)); + + if(!p) yyerror("Class definition failed."); - s.type=T_INT; - s.subtype=0; - } else { - s.type=T_PROGRAM; - s.subtype=0; - } - if($3) - { - add_constant($3, &s, $1); - free_string($3); - } - $$=mksvaluenode(&s); - free_svalue(&s); + else + free_program(p); + + free_string($3); } ; -cond: F_IF '(' comma_expr ')' statement optional_else_part +cond: F_IF + { + $<number>$=compiler_frame->current_number_of_locals; + } + '(' comma_expr ')' statement optional_else_part { - $$=mknode('?',$3,mknode(':',$5,$6)); + $$=mknode('?',$4,mknode(':',$6,$7)); $$->line_number=$1; $$=mkcastnode(void_type_string,$$); $$->line_number=$1; + pop_local_variables($<number>2); } ; @@ -964,10 +1006,15 @@ optional_else_part: { $$=0; } | F_ELSE statement { $$=$2; } ; -foreach: F_FOREACH '(' expr0 ',' lvalue ')' statement +foreach: F_FOREACH + { + $<number>$=compiler_frame->current_number_of_locals; + } + '(' expr0 ',' lvalue ')' statement { - $$=mknode(F_FOREACH,mknode(F_VAL_LVAL,$3,$5),$7); + $$=mknode(F_FOREACH, mknode(F_VAL_LVAL,$4,$6),$8); $$->line_number=$1; + pop_local_variables($<number>2); } ; @@ -978,22 +1025,32 @@ do: F_DO statement F_WHILE '(' comma_expr ')' ';' } ; -for: F_FOR '(' unused ';' for_expr ';' unused ')' statement +for: F_FOR { - int i=current_line; - current_line=$1; - $$=mknode(F_ARG_LIST,mkcastnode(void_type_string,$3),mknode(F_FOR,$5,mknode(':',$9,$7))); - current_line=i; + $<number>$=compiler_frame->current_number_of_locals; + } + '(' unused ';' for_expr ';' unused ')' statement + { + int i=lex.current_line; + lex.current_line=$1; + $$=mknode(F_ARG_LIST,mkcastnode(void_type_string,$4),mknode(F_FOR,$6,mknode(':',$10,$8))); + lex.current_line=i; + pop_local_variables($<number>2); } ; -while: F_WHILE '(' comma_expr ')' statement +while: F_WHILE + { + $<number>$=compiler_frame->current_number_of_locals; + } + '(' comma_expr ')' statement { - int i=current_line; - current_line=$1; - $$=mknode(F_FOR,$3,mknode(':',$5,NULL)); - current_line=i; + int i=lex.current_line; + lex.current_line=$1; + $$=mknode(F_FOR,$4,mknode(':',$6,NULL)); + lex.current_line=i; + pop_local_variables($<number>2); } ; @@ -1001,10 +1058,15 @@ for_expr: /* EMPTY */ { $$=mkintnode(1); } | comma_expr ; -switch: F_SWITCH '(' comma_expr ')' statement +switch: F_SWITCH + { + $<number>$=compiler_frame->current_number_of_locals; + } + '(' comma_expr ')' statement { - $$=mknode(F_SWITCH,$3,$5); + $$=mknode(F_SWITCH,$4,$6); $$->line_number=$1; + pop_local_variables($<number>2); } ; @@ -1014,13 +1076,13 @@ case: F_CASE comma_expr ':' } | F_CASE comma_expr F_DOT_DOT optional_comma_expr ':' { - $$=mknode(F_CASE,$4?$2:0,$4?$4:$2); + $$=mknode(F_CASE,$4?$2:0,$4?$4:$2); } ; return: F_RETURN { - if(!match_types(local_variables->current_return_type, + if(!match_types(compiler_frame->current_return_type, void_type_string)) { yyerror("Must return a value for a non-void function."); @@ -1046,9 +1108,9 @@ optional_comma_expr: { $$=0; } comma_expr: comma_expr2 | type2 { - if(local_variables->current_type) - free_string(local_variables->current_type); - local_variables->current_type=pop_type(); + if(compiler_frame->current_type) + free_string(compiler_frame->current_type); + compiler_frame->current_type=pop_type(); } local_name_list { $$=$3; } ; @@ -1197,35 +1259,36 @@ low_idents: F_IDENTIFIER $$=mklocalnode(i); }else if((i=isidentifier($1))>=0){ $$=mkidentifiernode(i); - }else if(find_module_identifier($1)){ - $$=mkconstantsvaluenode(sp-1); - pop_stack(); - }else{ + }else if(!($$=find_module_identifier($1))){ $$=0; if(!num_parse_error) { - if( get_master() ) - { - reference_shared_string($1); - push_string($1); - reference_shared_string(current_file); - push_string(current_file); - SAFE_APPLY_MASTER("resolv", 2); - - if(throw_value.type == T_STRING) - { - my_yyerror("%s",throw_value.u.string->str); - } - else if(IS_ZERO(sp-1) && sp[-1].subtype==1) - { - my_yyerror("'%s' undefined.", $1->str); - }else{ - $$=mkconstantsvaluenode(sp-1); - } - pop_stack(); - }else{ - my_yyerror("'%s' undefined.", $1->str); - } + if(get_master()) + { + reference_shared_string($1); + push_string($1); + ref_push_string(lex.current_file); + SAFE_APPLY_MASTER("resolv", 2); + + if(throw_value.type == T_STRING) + { + my_yyerror("%s",throw_value.u.string->str); + } + else if(IS_ZERO(sp-1) && sp[-1].subtype==1) + { + my_yyerror("'%s' undefined.", $1->str); + }else{ + $$=mkconstantsvaluenode(sp-1); + } + pop_stack(); + }else{ + if(compiler_pass==2) + { + my_yyerror("'%s' undefined.", $1->str); + }else{ + $$=mknode(F_UNDEFINED,0,0); + } + } } } free_string($1); @@ -1249,10 +1312,9 @@ low_idents: F_IDENTIFIER int f; struct reference *idp; - setup_fake_program(); f=reference_inherited_identifier($1,$3); - idp=fake_program.identifier_references+f; - if (f<0 || ID_FROM_PTR(&fake_program,idp)->func.offset == -1) + idp=new_program->identifier_references+f; + if (f<0) { my_yyerror("Undefined identifier %s::%s", $1->str,$3->str); $$=mkintnode(0); @@ -1268,10 +1330,9 @@ low_idents: F_IDENTIFIER int e,i; $$=0; - setup_fake_program(); - for(e=1;e<(int)fake_program.num_inherits;e++) + for(e=1;e<(int)new_program->num_inherits;e++) { - if(fake_program.inherits[e].inherit_level!=1) continue; + if(new_program->inherits[e].inherit_level!=1) continue; i=low_reference_inherited_identifier(e,$2); if(i==-1) continue; if($$) @@ -1358,9 +1419,7 @@ lvalue_list: /* empty */ { $$ = 0; } low_string: F_STRING | low_string F_STRING { - $$=add_shared_strings($1,$2); - free_string($1); - free_string($2); + $$=add_and_free_shared_strings($1,$2); } ; @@ -1386,24 +1445,20 @@ void yyerror(char *str) if ( get_master() ) { sp->type = T_STRING; - copy_shared_string(sp->u.string, current_file); + copy_shared_string(sp->u.string, lex.current_file); sp++; sp->type = T_INT; - sp->u.integer = current_line; + sp->u.integer = lex.current_line; sp++; sp->type = T_STRING; sp->u.string = make_shared_string(str); sp++; SAFE_APPLY_MASTER("compile_error",3); pop_stack(); -#ifdef DEBUG - if(recoveries && sp-evaluator_stack < recoveries->sp) - fatal("Stack error (underflow)\n"); -#endif }else{ (void)fprintf(stderr, "%s:%ld: %s\n", - current_file->str, - (long)current_line, + lex.current_file->str, + (long)lex.current_line, str); fflush(stderr); } @@ -1413,18 +1468,18 @@ void yyerror(char *str) void add_local_name(struct pike_string *str, struct pike_string *type) { - if (local_variables->current_number_of_locals == MAX_LOCAL) + if (compiler_frame->current_number_of_locals == MAX_LOCAL) { yyerror("Too many local variables"); }else { - local_variables->variable[local_variables->current_number_of_locals].type = type; - local_variables->variable[local_variables->current_number_of_locals].name = str; - local_variables->current_number_of_locals++; - if(local_variables->current_number_of_locals > - local_variables->max_number_of_locals) + compiler_frame->variable[compiler_frame->current_number_of_locals].type = type; + compiler_frame->variable[compiler_frame->current_number_of_locals].name = str; + compiler_frame->current_number_of_locals++; + if(compiler_frame->current_number_of_locals > + compiler_frame->max_number_of_locals) { - local_variables->max_number_of_locals= - local_variables->current_number_of_locals; + compiler_frame->max_number_of_locals= + compiler_frame->current_number_of_locals; } } } @@ -1433,27 +1488,8 @@ void add_local_name(struct pike_string *str, int islocal(struct pike_string *str) { int e; - for(e=local_variables->current_number_of_locals-1;e>=0;e--) - if(local_variables->variable[e].name==str) + for(e=compiler_frame->current_number_of_locals-1;e>=0;e--) + if(compiler_frame->variable[e].name==str) return e; return -1; } - -void free_all_local_names(void) -{ - int e; - - for (e=0; e<local_variables->current_number_of_locals; e++) - { - if(local_variables->variable[e].name) - { - free_string(local_variables->variable[e].name); - free_string(local_variables->variable[e].type); - } - local_variables->variable[e].name=0; - local_variables->variable[e].type=0; - } - local_variables->current_number_of_locals = 0; - local_variables->max_number_of_locals = 0; -} - diff --git a/src/las.c b/src/las.c index 736d579f882df609046032ba8d21f93b019559a9..0f72239e0678908412de61bd4d3203bb63770f5a 100644 --- a/src/las.c +++ b/src/las.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: las.c,v 1.39 1997/10/05 03:39:25 grubba Exp $"); +RCSID("$Id: las.c,v 1.40 1998/01/13 22:56:44 hubbe Exp $"); #include "language.h" #include "interpret.h" @@ -34,7 +34,6 @@ int lasdebug=0; static node *eval(node *); static void optimize(node *n); -dynamic_buffer areas[NUM_AREAS]; node *init_node = 0; int num_parse_error; int cumulative_parse_error=0; @@ -46,6 +45,7 @@ int car_is_node(node *n) { switch(n->token) { + case F_EXTERNAL: case F_IDENTIFIER: case F_CONSTANT: case F_LOCAL: @@ -60,6 +60,7 @@ int cdr_is_node(node *n) { switch(n->token) { + case F_EXTERNAL: case F_IDENTIFIER: case F_CONSTANT: case F_LOCAL: @@ -135,9 +136,9 @@ struct node_chunk static struct node_chunk *node_chunks=0; static node *free_nodes=0; -void free_all_nodes(void) +void free_all_nodes() { - if(!local_variables) + if(!compiler_frame) { node *tmp; struct node_chunk *tmp2; @@ -240,7 +241,7 @@ static node *mkemptynode(void) res=free_nodes; free_nodes=CAR(res); res->token=0; - res->line_number=current_line; + res->line_number=lex.current_line; res->type=0; res->node_info=0; res->tree_info=0; @@ -273,6 +274,10 @@ node *mknode(short token,node *a,node *b) } break; + case F_UNDEFINED: + res->node_info |= OPT_EXTERNAL_DEPEND | OPT_SIDE_EFFECT; + break; + case F_RETURN: res->node_info |= OPT_RETURN; break; @@ -310,7 +315,9 @@ node *mknode(short token,node *a,node *b) if(a) a->parent = res; if(b) b->parent = res; - if(!num_parse_error) optimize(res); + + if(!num_parse_error && compiler_pass==2) + optimize(res); #ifdef DEBUG if(d_flag > 3) @@ -372,13 +379,12 @@ node *mkefuncallnode(char *function, node *args) struct pike_string *name; node *n; name = findstring(function); - if(!name || !find_module_identifier(name)) + if(!name || !(n=find_module_identifier(name))) { my_yyerror("Internally used efun undefined: %s",function); return mkintnode(0); } - n=mkapplynode(mksvaluenode(sp-1), args); - pop_stack(); + n=mkapplynode(n, args); return n; } @@ -394,7 +400,7 @@ node *mklocalnode(int var) { node *res = mkemptynode(); res->token = F_LOCAL; - copy_shared_string(res->type, local_variables->variable[var].type); + copy_shared_string(res->type, compiler_frame->variable[var].type); res->node_info = OPT_NOT_CONST; res->tree_info=res->node_info; #ifdef __CHECKER__ @@ -408,11 +414,10 @@ node *mkidentifiernode(int i) { node *res = mkemptynode(); res->token = F_IDENTIFIER; - setup_fake_program(); - copy_shared_string(res->type, ID_FROM_INT(&fake_program, i)->type); + copy_shared_string(res->type, ID_FROM_INT(new_program, i)->type); /* FIXME */ - if(IDENTIFIER_IS_CONSTANT(ID_FROM_INT(&fake_program, i)->identifier_flags)) + if(IDENTIFIER_IS_CONSTANT(ID_FROM_INT(new_program, i)->identifier_flags)) { res->node_info = OPT_EXTERNAL_DEPEND; }else{ @@ -427,6 +432,27 @@ node *mkidentifiernode(int i) return res; } +node *mkexternalnode(int level, + int i, + struct identifier *id) +{ + node *res = mkemptynode(); + res->token = F_EXTERNAL; + + copy_shared_string(res->type, id->type); + + /* FIXME */ + res->node_info = OPT_NOT_CONST; + res->tree_info=res->node_info; + +#ifdef __CHECKER__ + CDR(res)=0; +#endif + res->u.integer.a = level; + res->u.integer.b = i; + return res; +} + node *mkcastnode(struct pike_string *type,node *n) { node *res; @@ -451,6 +477,9 @@ node *mkcastnode(struct pike_string *type,node *n) void resolv_constant(node *n) { struct identifier *i; + struct program *p; + INT32 numid; + if(!n) { push_int(0); @@ -459,31 +488,49 @@ void resolv_constant(node *n) { case F_CONSTANT: push_svalue(& n->u.sval); - break; + return; - case F_IDENTIFIER: - setup_fake_program(); - i=ID_FROM_INT(& fake_program, n->u.number); - - if(IDENTIFIER_IS_CONSTANT(i->identifier_flags)) + case F_EXTERNAL: + p=parent_compilation(n->u.integer.a); + if(!p) { - push_svalue(PROG_FROM_INT(&fake_program, n->u.number)->constants + - i->func.offset); - }else{ - yyerror("Identifier is not a constant"); + yyerror("Failed to resolv external constant"); push_int(0); + return; } + numid=n->u.integer.b; + break; + + case F_IDENTIFIER: + p=new_program; + numid=n->u.number; break; case F_LOCAL: - yyerror("Expected constant, got local variable"); - push_int(0); - break; + yyerror("Expected constant, got local variable"); + push_int(0); + return; case F_GLOBAL: - yyerror("Expected constant, got global variable"); - push_int(0); - break; + yyerror("Expected constant, got global variable"); + push_int(0); + return; + + default: + yyerror("Expected constant, got something else"); + push_int(0); + return; + } + + i=ID_FROM_INT(p, numid); + + if(IDENTIFIER_IS_CONSTANT(i->identifier_flags)) + { + push_svalue(PROG_FROM_INT(new_program, numid)->constants + + i->func.offset); + }else{ + yyerror("Identifier is not a constant"); + push_int(0); } } } @@ -798,8 +845,7 @@ static void low_print_tree(node *foo,int needlval) case F_IDENTIFIER: if(needlval) putchar('&'); - setup_fake_program(); - printf("%s",ID_FROM_INT(&fake_program, foo->u.number)->name->str); + printf("%s",ID_FROM_INT(new_program, foo->u.number)->name->str); break; case F_ASSIGN: @@ -1235,8 +1281,7 @@ void fix_type_field(node *n) switch(CAR(n)->token) { case F_IDENTIFIER: - setup_fake_program(); - name=ID_FROM_INT(&fake_program, CAR(n)->u.number)->name->str; + name=ID_FROM_INT(new_program, CAR(n)->u.number)->name->str; break; case F_CONSTANT: @@ -1281,11 +1326,11 @@ void fix_type_field(node *n) { yyerror("You cannot return a void expression"); } - if(local_variables && - local_variables->current_return_type && - !match_types(local_variables->current_return_type,CAR(n)->type) && + if(compiler_frame && + compiler_frame->current_return_type && + !match_types(compiler_frame->current_return_type,CAR(n)->type) && !( - local_variables->current_return_type==void_type_string && + compiler_frame->current_return_type==void_type_string && CAR(n)->token == F_CONSTANT && IS_ZERO(& CAR(n)->u.sval) ) @@ -1364,7 +1409,7 @@ static void zapp_try_optimize(node *n) static void optimize(node *n) { node *tmp1, *tmp2, *tmp3; - INT32 save_line = current_line; + INT32 save_line = lex.current_line; do { if(car_is_node(n) && !(CAR(n)->node_info & OPT_OPTIMIZED)) @@ -1377,7 +1422,7 @@ static void optimize(node *n) n=CDR(n); continue; } - current_line = n->line_number; + lex.current_line = n->line_number; n->tree_info = n->node_info; @@ -1807,7 +1852,7 @@ static void optimize(node *n) n->node_info |= OPT_OPTIMIZED; n=n->parent; }while(n); - current_line = save_line; + lex.current_line = save_line; } struct timer_oflo @@ -1842,10 +1887,9 @@ int eval_low(node *n) #endif if(num_parse_error) return -1; - setup_fake_program(); - num_strings=fake_program.num_strings; - num_constants=fake_program.num_constants; + num_strings=new_program->num_strings; + num_constants=new_program->num_constants; jump=PC; store_linenumbers=0; @@ -1853,7 +1897,6 @@ int eval_low(node *n) ins_f_byte(F_DUMB_RETURN); store_linenumbers=1; - setup_fake_program(); ret=-1; if(!num_parse_error) { @@ -1896,21 +1939,19 @@ int eval_low(node *n) remove_callback(tmp_callback); } - while(fake_program.num_strings > num_strings) + while(new_program->num_strings > num_strings) { - fake_program.num_strings--; - free_string(fake_program.strings[fake_program.num_strings]); - areas[A_STRINGS].s.len-=sizeof(struct pike_string *); + new_program->num_strings--; + free_string(new_program->strings[new_program->num_strings]); } - while(fake_program.num_constants > num_constants) + while(new_program->num_constants > num_constants) { - fake_program.num_constants--; - free_svalue(fake_program.constants + fake_program.num_constants); - areas[A_CONSTANTS].s.len-=sizeof(struct svalue); + new_program->num_constants--; + free_svalue(new_program->constants + new_program->num_constants); } - areas[A_PROGRAM].s.len=jump; + new_program->num_program=jump; return ret; } @@ -2036,16 +2077,10 @@ int dooptcode(struct pike_string *name, int args, vargs, ret; struct svalue *foo; -#ifdef DEBUG - if(recoveries && sp-evaluator_stack < recoveries->sp) - fatal("Stack error before dooptcode (underflow)\n"); -#endif - #ifdef DEBUG if(a_flag > 1) fprintf(stderr,"Doing function '%s' at %x\n",name->str,PC); #endif - last_function_opt_info=OPT_SIDE_EFFECT; args=count_arguments(type); if(args < 0) @@ -2055,44 +2090,44 @@ int dooptcode(struct pike_string *name, }else{ vargs=0; } - n=mknode(F_ARG_LIST,n,0); - - if((foo=is_stupid_func(n, args, vargs))) + if(compiler_pass==1) { - if(foo->type == T_FUNCTION && foo->subtype==FUNCTION_BUILTIN) + tmp.offset=-1; + }else{ + n=mknode(F_ARG_LIST,n,0); + + if((foo=is_stupid_func(n, args, vargs))) { - tmp.c_fun=foo->u.efun->function; - ret=define_function(name, - type, - modifiers, - IDENTIFIER_C_FUNCTION | vargs, - &tmp); - free_node(n); - return ret; + if(foo->type == T_FUNCTION && foo->subtype==FUNCTION_BUILTIN) + { + tmp.c_fun=foo->u.efun->function; + ret=define_function(name, + type, + modifiers, + IDENTIFIER_C_FUNCTION | vargs, + &tmp); + free_node(n); + return ret; + } } - } - - tmp.offset=PC; - ins_byte(local_variables->max_number_of_locals, A_PROGRAM); - ins_byte(args, A_PROGRAM); + + tmp.offset=PC; + add_to_program(compiler_frame->max_number_of_locals); + add_to_program(args); #ifdef DEBUG - if(a_flag > 2) - { - fprintf(stderr,"Coding: "); - print_tree(n); - } + if(a_flag > 2) + { + fprintf(stderr,"Coding: "); + print_tree(n); + } #endif - if(!num_parse_error) - { - do_code_block(n); + if(!num_parse_error) + { + do_code_block(n); + } } -#ifdef DEBUG - if(recoveries && sp-evaluator_stack < recoveries->sp) - fatal("Stack error after do_code_block (underflow)\n"); -#endif - ret=define_function(name, type, modifiers, @@ -2103,6 +2138,4 @@ int dooptcode(struct pike_string *name, return ret; } -INT32 get_opt_info(void) { return last_function_opt_info; } - diff --git a/src/las.h b/src/las.h index 46fda27e69e6ff861a7f5d64219c9c819ded4bb1..f47fa7916100c9a9d60171ff918ff4f49a8857a7 100644 --- a/src/las.h +++ b/src/las.h @@ -7,21 +7,34 @@ #define LAS_H #include "global.h" +#include "pike_types.h" #include "svalue.h" #include "dynamic_buffer.h" #include "program.h" #define MAX_GLOBAL_VARIABLES 1000 + +void yyerror(char *s); +int islocal(struct pike_string *str); +int verify_declared(struct pike_string *str); + + +extern node *init_node; +extern int num_parse_error; +extern int cumulative_parse_error; +extern struct compiler_frame *compiler_frame; + struct local_variable { struct pike_string *name; struct pike_string *type; }; -struct locals +struct compiler_frame { - struct locals *next; + struct compiler_frame *previous; + struct pike_string *current_type; struct pike_string *current_return_type; int current_number_of_locals; @@ -29,36 +42,6 @@ struct locals struct local_variable variable[MAX_LOCAL]; }; -void yyerror(char *s); -int islocal(struct pike_string *str); -int verify_declared(struct pike_string *str); - -struct node_s -{ - unsigned INT16 token; - INT16 line_number; - INT16 node_info; - INT16 tree_info; - struct pike_string *type; - struct node_s *parent; - union - { - int number; - struct svalue sval; - struct - { - struct node_s *a,*b; - } node; - } u; -}; - -typedef struct node_s node; - -extern struct locals *local_variables; -extern node *init_node; -extern int num_parse_error; -extern int cumulative_parse_error; - #define OPT_OPTIMIZED 0x1 /* has been processed by optimize(), * only used in node_info */ @@ -79,7 +62,7 @@ int car_is_node(node *n); int cdr_is_node(node *n); INT32 count_args(node *n); struct node_chunk; -void free_all_nodes(void); +void free_all_nodes(); void free_node(node *n); node *mknode(short token,node *a,node *b); node *mkstrnode(struct pike_string *str); @@ -90,6 +73,9 @@ node *mkefuncallnode(char *function, node *args); node *mkopernode(char *oper_id, node *arg1, node *arg2); node *mklocalnode(int var); node *mkidentifiernode(int i); +node *mkexternalnode(int level, + int i, + struct identifier *id); node *mkcastnode(struct pike_string *type,node *n); void resolv_constant(node *n); node *index_node(node *n, struct pike_string * id); @@ -113,7 +99,6 @@ int dooptcode(struct pike_string *name, node *n, struct pike_string *type, int modifiers); -INT32 get_opt_info(void); /* Prototypes end here */ #define CAR(n) ((n)->u.node.a) @@ -125,20 +110,9 @@ INT32 get_opt_info(void); #define GAUGE_RUSAGE_INDEX 0 -#define A_PROGRAM 0 -#define A_STRINGS 1 -#define A_INHERITS 2 -#define A_IDENTIFIERS 3 -#define A_IDENTIFIER_REFERENCES 4 -#define A_CONSTANTS 5 -#define A_LINENUMBERS 6 -#define NUM_AREAS 7 - #define add_to_mem_block(N,Data,Size) low_my_binary_strcat(Data,Size,areas+N) -#define IDENTIFIERP(i) (((struct reference *)areas[A_IDENTIFIER_REFERENCES].s.str)+i) -#define INHERIT(i) (((struct inherit *)areas[A_INHERITS].s.str)+i) -#define PC (areas[A_PROGRAM].s.len) - -extern dynamic_buffer areas[NUM_AREAS]; +#define IDENTIFIERP(i) (new_program->identifier_references+(i)) +#define INHERIT(i) (new_program->inherits+(i)) +#define PC (new_program->num_program) #endif diff --git a/src/lex.c b/src/lex.c index 859bbfabdd133828f48600d9604d14803fefbda1..5fb4368e3896aa655864a696eedf458c4c1e40a8 100644 --- a/src/lex.c +++ b/src/lex.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: lex.c,v 1.36 1998/01/02 01:05:47 hubbe Exp $"); +RCSID("$Id: lex.c,v 1.37 1998/01/13 22:56:45 hubbe Exp $"); #include "language.h" #include "array.h" #include "lex.h" @@ -25,9 +25,11 @@ RCSID("$Id: lex.c,v 1.36 1998/01/02 01:05:47 hubbe Exp $"); #include "mapping.h" #include "pike_macros.h" + #ifdef HAVE_SYS_PARAM_H #include <sys/param.h> #endif + #include <ctype.h> #include <math.h> #include <fcntl.h> @@ -35,27 +37,6 @@ RCSID("$Id: lex.c,v 1.36 1998/01/02 01:05:47 hubbe Exp $"); #include "time_stuff.h" #define LEXDEBUG 0 -#define EXPANDMAX 500000 - -struct pike_string *current_file; - -INT32 current_line; -INT32 old_line; -INT32 total_lines; -INT32 nexpands; -int pragma_all_inline; /* inline all possible inlines */ - -struct pike_predef_s -{ - char *name; - char *value; - struct pike_predef_s *next; -}; - -static struct pike_predef_s *pike_predefs=0; - -static int calc(void); -static void calc1(void); void exit_lex(void) { @@ -73,74 +54,8 @@ void exit_lex(void) } } #endif - - - while(local_variables) - { - int e; - struct locals *l; - for(e=0;e<local_variables->current_number_of_locals;e++) - { - free_string(local_variables->variable[e].name); - free_string(local_variables->variable[e].type); - } - if(local_variables->current_type) - free_string(local_variables->current_type); - if(local_variables->current_return_type) - free_string(local_variables->current_return_type); - l=local_variables->next; - free((char *)local_variables); - local_variables=l; - } - - if(current_file) free_string(current_file); - free_reswords(); } -struct keyword reserved_words[] = -{ -{ "array", F_ARRAY_ID, }, -{ "break", F_BREAK, }, -{ "case", F_CASE, }, -{ "catch", F_CATCH, }, -{ "class", F_CLASS, }, -{ "constant", F_CONSTANT, }, -{ "continue", F_CONTINUE, }, -{ "default", F_DEFAULT, }, -{ "do", F_DO, }, -{ "else", F_ELSE, }, -{ "float", F_FLOAT_ID, }, -{ "for", F_FOR, }, -{ "foreach", F_FOREACH, }, -{ "function", F_FUNCTION_ID, }, -{ "gauge", F_GAUGE, }, -{ "if", F_IF, }, -{ "import", F_IMPORT, }, -{ "inherit", F_INHERIT, }, -{ "inline", F_INLINE, }, -{ "int", F_INT_ID, }, -{ "lambda", F_LAMBDA, }, -{ "mapping", F_MAPPING_ID, }, -{ "mixed", F_MIXED_ID, }, -{ "multiset", F_MULTISET_ID, }, -{ "nomask", F_NO_MASK, }, -{ "object", F_OBJECT_ID, }, -{ "predef", F_PREDEF, }, -{ "private", F_PRIVATE, }, -{ "program", F_PROGRAM_ID, }, -{ "protected", F_PROTECTED, }, -{ "public", F_PUBLIC, }, -{ "return", F_RETURN, }, -{ "sscanf", F_SSCANF, }, -{ "static", F_STATIC, }, -{ "string", F_STRING_ID, }, -{ "switch", F_SWITCH, }, -{ "typeof", F_TYPEOF, }, -{ "varargs", F_VARARGS, }, -{ "void", F_VOID_ID, }, -{ "while", F_WHILE, }, -}; - struct keyword instr_names[]= { { "!", F_NOT }, @@ -230,6 +145,9 @@ struct keyword instr_names[]= { "local function call and pop",F_CALL_LFUN_AND_POP, I_HASARG }, { "local function", F_LFUN, I_HASARG }, { "local", F_LOCAL, I_HASARG }, +{ "external", F_EXTERNAL, I_HASARG }, +{ "& external", F_EXTERNAL_LVALUE, I_HASARG }, +{ "LDA", F_LDA, I_HASARG }, { "mark & local", F_MARK_AND_LOCAL, I_HASARG }, { "ltosval2", F_LTOSVAL2 }, { "lvalue to svalue", F_LTOSVAL }, @@ -259,7 +177,7 @@ struct keyword instr_names[]= { "|", F_OR }, { "|=", F_OR_EQ }, { "~", F_COMPL }, -{ "label", F_LABEL,I_HASARG }, +{ "label", F_LABEL,1 }, { "align", F_ALIGN, I_HASARG }, { "call", F_APPLY, I_HASARG }, { "clear local", F_CLEAR_LOCAL, I_HASARG }, @@ -285,7 +203,10 @@ struct keyword instr_names[]= { "add -integer", F_ADD_NEG_INT, I_HASARG }, { "mark & call", F_MARK_APPLY, I_HASARG }, { "mark, call & pop", F_MARK_APPLY_POP, I_HASARG }, -{ "+= and pop", F_ADD_TO_AND_POP }, +{ "apply and return", F_APPLY_AND_RETURN, I_HASARG }, +{ "call lfun & return", F_CALL_LFUN_AND_RETURN, I_HASARG }, +{ "call function", F_CALL_FUNCTION, 0 }, +{ "call function & return", F_CALL_FUNCTION_AND_RETURN, 0 }, }; struct instr instrs[F_MAX_INSTR - F_OFFSET]; @@ -296,9 +217,7 @@ struct reserved int token; }; -struct hash_table *reswords; - -void init_lex(void) +void init_lex() { unsigned int i; for(i=0; i<NELEM(instr_names);i++) @@ -312,24 +231,6 @@ void init_lex(void) instrs[instr_names[i].token - F_OFFSET].name = instr_names[i].word; instrs[instr_names[i].token - F_OFFSET].flags=instr_names[i].flags; } - - reswords=create_hash_table(); - - for(i=0; i<NELEM(reserved_words); i++) - { - struct reserved *r=ALLOC_STRUCT(reserved); - r->token = reserved_words[i].token; - r->link.s = make_shared_string(reserved_words[i].word); - reswords=hash_insert(reswords, &r->link); - } - - /* Enlarge this hashtable heruetically */ - reswords = hash_rehash(reswords, 2<<my_log2(NELEM(reserved_words))); -} - -void free_reswords(void) -{ - free_hashtable(reswords,0); } char *low_get_f_name(int n,struct program *p) @@ -393,1926 +294,576 @@ char *get_token_name(int n) } } -/* foo must be a shared string */ -static int lookup_resword(struct pike_string *s) -{ - struct hash_entry *h; - h=hash_lookup(reswords, s); - if(!h) return -1; - return BASEOF(h, reserved, link)->token; -} - +struct lex lex; +#define LOOK() (*(lex.pos)) +#define GETC() (*(lex.pos++)) +#define GOBBLE(c) (LOOK()==c?(lex.pos++,1):0) +#define SKIPSPACE() do { while(ISSPACE(LOOK()) && LOOK()!='\n') lex.pos++; }while(0) +#define SKIPWHITE() do { while(ISSPACE(LOOK())) lex.pos++; }while(0) +#define SKIPUPTO(X) do { while(LOOK()!=(X) && LOOK()) lex.pos++; }while(0) -/*** input routines ***/ -struct inputstate -{ - struct inputstate *next; - int fd; - unsigned char *data; - INT32 buflen; - INT32 pos; - int dont_free_data; - - int (*my_getc)(void); - int (*gobble)(int); - int (*look)(void); - void (*my_ungetc)(int); - void (*ungetstr)(char *,INT32); -}; - -#define MY_EOF 4711 - -struct inputstate *istate=NULL; - -static void link_inputstate(struct inputstate *i) -{ - i->next=istate; - istate=i; -} - -static void free_inputstate(struct inputstate *i) -{ - if(!i) return; - if(i->fd>=0) - { - retry: - if(close(i->fd)< 0) - if(errno == EINTR) - goto retry; - } - if(i->data && !i->dont_free_data) free(i->data); - free_inputstate(i->next); - free((char *)i); -} - -static struct inputstate *new_inputstate(void); -static struct inputstate *memory_inputstate(INT32 size); - -static int default_gobble(int c) -{ - if(istate->look()==c) - { - istate->my_getc(); - return 1; - }else{ - return 0; - } +#define READBUF(X) { \ + register int C; \ + buf=lex.pos; \ + while((C=LOOK()) && (X)) lex.pos++; \ + len=lex.pos - buf; \ } -static void default_ungetstr(char *s,INT32 len) -{ - link_inputstate(memory_inputstate(len+1000)); - istate->ungetstr(s,len); -} +#define TWO_CHAR(X,Y) ((X)<<8)+(Y) +#define ISWORD(X) (len==(long)strlen(X) && !MEMCMP(buf,X,strlen(X))) -static void default_ungetc(int s) -{ - char c=s; - istate->ungetstr(&c,1); -} +/*** Lexical analyzing ***/ -static int default_look(void) +static int char_const(void) { int c; - c=istate->my_getc(); - istate->my_ungetc(c); - return c; -} - -static struct inputstate *new_inputstate(void) -{ - struct inputstate *i; - i=(struct inputstate *)xalloc(sizeof(struct inputstate)); - i->fd=-1; - i->data=NULL; - i->next=NULL; - i->dont_free_data=0; - i->gobble=default_gobble; - i->ungetstr=default_ungetstr; - i->my_ungetc=default_ungetc; - i->look=default_look; - return i; -} - -/*** end of file input ***/ -static int end_getc(void) { return MY_EOF; } -static int end_gobble(int c) { return c==MY_EOF; } -static void end_ungetc(int c) -{ - if(c==MY_EOF) return; - default_ungetc(c); -} - -static struct inputstate *end_inputstate(void) -{ - struct inputstate *i; - i=new_inputstate(); - i->gobble=end_gobble; - i->look=end_getc; - i->my_getc=end_getc; - i->my_ungetc=end_ungetc; - return i; -} - -/*** MEMORY input ***/ -static void memory_ungetstr(char *s,INT32 len) -{ - INT32 tmp; - tmp=MINIMUM(len,istate->pos); - if(tmp) - { - istate->pos -= tmp; - MEMCPY(istate->data + istate->pos , s+len-tmp , tmp); - len-=tmp; - } - if(len) default_ungetstr(s,len); -} - -static void memory_ungetc(int s) -{ - if(istate->pos) - { - istate->pos --; - istate->data[istate->pos]=s; - }else{ - default_ungetc(s); - } -} - -static int memory_getc(void) -{ - if(istate->pos<istate->buflen) - { -#if LEXDEBUG>9 - fprintf(stderr,"lex: reading from memory '%c' (%d).\n",istate->data[istate->pos],istate->data[istate->pos]); -#endif - return istate->data[(istate->pos)++]; - }else{ - struct inputstate *i; - i=istate; - istate=i->next; - if(!i->dont_free_data) free(i->data); - free((char *)i); - return istate->my_getc(); - } -} - -static int memory_look(void) -{ - if(istate->pos<istate->buflen) + switch(c=GETC()) { - return istate->data[istate->pos]; - }else{ - struct inputstate *i; - i=istate; - istate=i->next; - if(!i->dont_free_data) free(i->data); - free((char *)i); - return istate->look(); + case 0: + lex.pos--; + yyerror("Unexpected end of file\n"); + return 0; + + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + c-='0'; + if(LOOK()<'0' || LOOK()>'8') return c; + c=c*8+(GETC()-'0'); + if(LOOK()<'0' || LOOK()>'8') return c; + c=c*8+(GETC()-'0'); + return c; + + case 'r': return '\r'; + case 'n': return '\n'; + case 't': return '\t'; + case 'b': return '\b'; + + case '\n': + lex.current_line++; + return '\n'; + + + case 'x': + switch(LOOK()) + { + default: return c; + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + case '8': case '9': + c=GETC()-'0'; + break; + + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + c=GETC()-'a'+10; + break; + + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + c=GETC()-'A'+10; + break; + } + switch(LOOK()) + { + default: return c; + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + case '8': case '9': + c=c*16+GETC()-'0'; + break; + + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + c=c*16+GETC()-'a'+10; + break; + + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + c=c*16+GETC()-'a'+10; + break; + } + return c; + } + return c; } -/* allocate an empty memory state */ -static struct inputstate *memory_inputstate(INT32 size) -{ - struct inputstate *i; - if(!size) size=10000; - i=new_inputstate(); - i->data=(unsigned char *)xalloc(size); - i->buflen=size; - i->pos=size; - i->ungetstr=memory_ungetstr; - i->my_getc=memory_getc; - i->look=memory_look; - i->my_ungetc=memory_ungetc; - return i; -} - -static void prot_memory_ungetstr(char *s,INT32 len) +static struct pike_string *readstring(void) { - INT32 tmp; - tmp=MINIMUM(len,istate->pos); - if(tmp) + int c; + dynamic_buffer tmp; + initialize_buf(&tmp); + + while(1) { - if(!MEMCMP(istate->data + istate->pos - tmp, s+len-tmp , tmp)) + switch(c=GETC()) { - istate->pos-=tmp; - len-=tmp; + case 0: + lex.pos--; + yyerror("End of file in string."); + break; + + case '\n': + lex.current_line++; + yyerror("Newline in string."); + break; + + case '\\': + low_my_putchar(char_const(),&tmp); + continue; + + case '"': + break; + + default: + low_my_putchar(c,&tmp); + continue; } + break; } - if(len) default_ungetstr(s,len); + return low_free_buf(&tmp); } -static void prot_memory_ungetc(int s) +int yylex(YYSTYPE *yylval) +#if LEXDEBUG>4 { - if(istate->pos && istate->data[istate->pos-1] == s) + int t; + int yylex2(YYSTYPE *); + t=yylex2(yylval); + if(t<256) { - istate->pos--; + fprintf(stderr,"yylex() -> '%c' (%d)\n",t,t); }else{ - default_ungetc(s); + fprintf(stderr,"yylex() -> %s (%d)\n",get_f_name(t),t); } + return t; } -/* allocate a memory, read-only, inputstate */ -static struct inputstate *prot_memory_inputstate(char *data,INT32 len) +static int yylex2(YYSTYPE *yylval) +#endif { - struct inputstate *i; - i=new_inputstate(); - i->data=(unsigned char *)data; - i->buflen=len; - i->dont_free_data=1; - i->pos=0; - i->my_getc=memory_getc; - i->look=memory_look; - i->ungetstr=prot_memory_ungetstr; - i->my_ungetc=prot_memory_ungetc; - return i; -} + INT32 c,len; + char *buf; -/*** FILE input ***/ +#ifdef __CHECKER__ + MEMSET((char *)yylval,0,sizeof(YYSTYPE)); +#endif +#ifdef MALLOC_DEBUG + check_sfltable(); +#endif -#define READAHEAD 8192 -static int file_getc(void) -{ - unsigned char buf[READAHEAD]; - int got; - do { - got=read(istate->fd, buf, READAHEAD); - if(got > 0) - { - default_ungetstr((char *)buf, got); - return istate->my_getc(); - } - else if(got==0 || errno != EINTR) + while(1) + { + switch(c=GETC()) { - struct inputstate *i; - if(got<0 && errno != EINTR) - my_yyerror("Lex: Read failed with error %d\n",errno); - - i=istate->next; - close(istate->fd); - free((char *)istate); - istate=i; - return istate->my_getc(); - } - }while(1); -} - -static struct inputstate *file_inputstate(int fd) -{ - struct inputstate *i; - i=new_inputstate(); - i->fd=fd; - i->my_getc=file_getc; - return i; -} - -static int GETC(void) -{ - int c; - c=istate->my_getc(); - if(c=='\n') current_line++; - return c; -} + case 0: + lex.pos--; + return 0; -static void UNGETC(int c) -{ - if(c=='\n') current_line--; - istate->my_ungetc(c); -} + case '\n': + lex.current_line++; + continue; -static void UNGETSTR(char *s,INT32 len) -{ - INT32 e; - for(e=0;e<len;e++) if(s[e]=='\n') current_line--; - istate->ungetstr(s,len); -} + case '#': + SKIPSPACE(); + READBUF(C!=' ' && C!='\t' && C!='\n'); -static int GOBBLE(char c) -{ - if(istate->gobble(c)) - { - if(c=='\n') current_line++; - return 1; - }else{ - return 0; - } -} + switch(len>0?buf[0]:0) + { + char *p; + + case 'l': + if(!ISWORD("line")) goto badhash; + READBUF(C!=' ' && C!='\t' && C!='\n'); + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + lex.current_line=atoi(buf)-1; + SKIPSPACE(); + if(GOBBLE('"')) + { + struct pike_string *tmp=readstring(); + free_string(lex.current_file); + lex.current_file=tmp; + } + break; + + case 'e': + if(ISWORD("error")) + { + SKIPSPACE(); + READBUF(C!='\n'); + yyerror(buf); + break; + } + goto badhash; -#define LOOK() (istate->look()) -#define SKIPWHITE() { int c; while(ISSPACE(c=GETC())); UNGETC(c); } -#define SKIPTO(X) { int c; while((c=GETC())!=(X) && (c!=MY_EOF)); } -#define SKIPUPTO(X) { int c; while((c=GETC())!=(X) && (c!=MY_EOF)); UNGETC(c); } -#define READBUF(X) { \ - register unsigned INT32 p; \ - register int C; \ - for(p=0;(C=GETC())!=MY_EOF && p<sizeof(buf) && (X);p++) \ - buf[p]=C; \ - if(p==sizeof(buf)) { \ - yyerror("Internal buffer overflow.\n"); p--; \ - } \ - UNGETC(C); \ - buf[p]=0; \ -} + case 'p': + if(ISWORD("pragma")) + { + SKIPSPACE(); + READBUF(C!='\n'); + if (strcmp(buf, "all_inline") == 0) + { + lex.pragmas |= PRAGMA_ALL_INLINE; + } + break; + } + + badhash: + my_yyerror("Unknown directive #%s.",buf); + SKIPUPTO('\n'); + continue; + } + continue; -static char buf[1024]; + case ' ': + case '\t': + continue; -/*** Define handling ***/ + case '\'': + switch(c=GETC()) + { + case 0: + lex.pos--; + yyerror("Unexpected end of file\n"); + break; -struct define -{ - struct hash_entry link; /* must be first */ - void (*magic)(void); - int args; - struct array *parts; -}; + case '\\': + c=char_const(); + } + if(!GOBBLE('\'')) + yyerror("Unterminated character constant."); + yylval->number=c; + return F_NUMBER; + + case '"': + yylval->string=readstring(); + return F_STRING; + + case ':': + if(GOBBLE(':')) return F_COLON_COLON; + return c; -struct hash_table *defines = 0; - -#define find_define(N) (defines?BASEOF(hash_lookup(defines, N), define, link):0) - -/* argument must be shared string */ -static void undefine(struct pike_string *name) -{ - struct define *d; - - d=find_define(name); - - if(!d) return; - - defines=hash_unlink(defines, & d->link); - free_string(d->link.s); - free_array(d->parts); - free((char *)d); -} - -/* name and as are supposed to be SHARED strings */ -static void add_define(struct pike_string *name, - int args, - int parts_on_stack, - void (*magic)(void)) -{ - struct define *d; - - f_aggregate(parts_on_stack); - if(sp[-1].type != T_ARRAY) - { - yyerror("Define failed for unknown reason.\n"); - free_string(name); - pop_stack(); - return; - } - -#if 0 - if(find_define(name)) - { - my_yyerror("Redefining '%s'",name->str); - free_string(name); - pop_stack(); - return; - } -#else - undefine(name); -#endif - - d=(struct define *)xalloc(sizeof(struct define)); - d->link.s=name; - d->args=args; - d->magic=magic; - d->parts=sp[-1].u.array; - sp--; - - defines=hash_insert(defines, & d->link); -} - -static void simple_add_define(char *name,char *as,void (*magic)(void)) -{ - if(magic) - { - add_define(make_shared_string(name),-1,0,magic); - }else{ - push_string(make_shared_string(as)); - add_define(make_shared_string(name),-1,1,magic); - } -} - -static void free_one_define(struct hash_entry *h) -{ - struct define *d; - d=BASEOF(h, define, link); - if(d->parts) free_array(d->parts); - free((void *)d); -} - -static void free_all_defines(void) -{ - if(defines) - free_hashtable(defines, free_one_define); - defines=0; -} - -static void do_define(void) -{ - int c,e,t,argc; - struct svalue *save_sp=sp; - struct svalue *args_sp; - struct pike_string *s, *s2; - - SKIPWHITE(); - READBUF(isidchar(C)); - - s=make_shared_string(buf); - - if(GOBBLE('(')) - { - argc=0; - - SKIPWHITE(); - READBUF(isidchar(C)); - if(buf[0]) - { - push_string(make_shared_string(buf)); - argc++; - SKIPWHITE(); - while(GOBBLE(',')) + case '.': + if(GOBBLE('.')) { - SKIPWHITE(); - READBUF(isidchar(C)); - push_string(make_shared_string(buf)); - argc++; + if(GOBBLE('.')) return F_DOT_DOT_DOT; + return F_DOT_DOT; } - } - SKIPWHITE(); - - if(!GOBBLE(')')) - yyerror("Missing ')'"); - }else{ - argc=-1; - } - - args_sp=sp; - - init_buf(); - t=0; - sp->type=T_STRING; - sp->u.string=make_shared_string(""); - sp++; - - while(1) - { - int tmp; - - c=GETC(); - if(c=='\\') if(GOBBLE('\n')) continue; - if( (t!=!!isidchar(c) && argc>0) || c=='\n' || c==MY_EOF) + return c; + + case '0': + if(GOBBLE('x') || GOBBLE('X')) + { + yylval->number=STRTOL(lex.pos, &lex.pos, 16); + return F_NUMBER; + } + + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': { - s2=free_buf(); - tmp=0; - for(e=0;e<argc;e++) + char *p1, *p2; + double f; + long l; + lex.pos--; + f=my_strtod(lex.pos, &p1); + l=STRTOL(lex.pos, &p2, 0); + + if(p1>p2) { - if(save_sp[e].u.string==s2) - { - free_string(s2); - push_int(e); - tmp=1; - break; - } + lex.pos=p1; + yylval->fnum=(float)f; + return F_FLOAT; + }else{ + lex.pos=p2; + yylval->number=l; + return F_NUMBER; } - if(!tmp) + + case '-': + if(GOBBLE('=')) return F_SUB_EQ; + if(GOBBLE('>')) return F_ARROW; + if(GOBBLE('-')) return F_DEC; + return '-'; + + case '+': + if(GOBBLE('=')) return F_ADD_EQ; + if(GOBBLE('+')) return F_INC; + return '+'; + + case '&': + if(GOBBLE('=')) return F_AND_EQ; + if(GOBBLE('&')) return F_LAND; + return '&'; + + case '|': + if(GOBBLE('=')) return F_OR_EQ; + if(GOBBLE('|')) return F_LOR; + return '|'; + + case '^': + if(GOBBLE('=')) return F_XOR_EQ; + return '^'; + + case '*': + if(GOBBLE('=')) return F_MULT_EQ; + return '*'; + + case '%': + if(GOBBLE('=')) return F_MOD_EQ; + return '%'; + + case '/': + if(GOBBLE('=')) return F_DIV_EQ; + return '/'; + + case '=': + if(GOBBLE('=')) return F_EQ; + return '='; + + case '<': + if(GOBBLE('<')) { - push_string(s2); - if(sp[-2].type==T_STRING) f_add(2); + if(GOBBLE('=')) return F_LSH_EQ; + return F_LSH; } - if(c=='\n' || c==MY_EOF) + if(GOBBLE('=')) return F_LE; + return '<'; + + case '>': + if(GOBBLE(')')) return F_MULTISET_END; + if(GOBBLE('=')) return F_GE; + if(GOBBLE('>')) { - push_string(make_shared_string(" ")); - if(sp[-2].type==T_STRING) f_add(2); - break; + if(GOBBLE('=')) return F_RSH_EQ; + return F_RSH; } - t=!!isidchar(c); - init_buf(); - } - my_putchar(c); - } - UNGETC(c); - add_define(s,argc,sp-args_sp,0); - while(sp>save_sp) pop_stack(); -} + return '>'; -/* s is a shared string */ -static int expand_define(struct pike_string *s, int save_newline) -{ - struct svalue *save_sp=sp; - struct define *d; - int len,e,tmp,args; - d=find_define(s); - if(!d) return 0; + case '!': + if(GOBBLE('=')) return F_NE; + return F_NOT; - if(nexpands>EXPANDMAX) - { - yyerror("Macro limit exceeded."); - return 0; - } + case '(': + if(GOBBLE('<')) return F_MULTISET_START; + return '('; - if(d->magic) - { - d->magic(); - return 1; - } + case '?': + case ',': + case '~': + case '@': + case ')': + case '[': + case ']': + case '{': + case ';': + case '}': return c; - if(d->args >= 0) - { - if(!save_newline) + case '`': { - SKIPWHITE(); - }else{ - do { e=GETC(); }while(ISSPACE(e) && e!='\n'); - UNGETC(e); - } + char *tmp; + int offset=2; + if(GOBBLE('`')) offset--; + if(GOBBLE('`')) offset--; + + switch(GETC()) + { + case '+': tmp="```+"; break; + case '/': tmp="```/"; break; + case '%': tmp="```%"; break; + case '*': tmp="```*"; break; + case '&': tmp="```&"; break; + case '|': tmp="```|"; break; + case '^': tmp="```^"; break; + case '~': tmp="```~"; break; + case '<': + if(GOBBLE('<')) { tmp="```<<"; break; } + if(GOBBLE('=')) { tmp="```<="; break; } + tmp="```<"; + break; - if(GOBBLE('(')) - { - int parlvl,quote; - int c; - args=0; + case '>': + if(GOBBLE('>')) { tmp="```>>"; break; } + if(GOBBLE('=')) { tmp="```>="; break; } + tmp="```>"; + break; - SKIPWHITE(); - init_buf(); - parlvl=1; - quote=0; - while(parlvl) - { - switch(c=GETC()) + case '!': + if(GOBBLE('=')) { tmp="```!="; break; } + tmp="```!"; + break; + + case '=': + if(GOBBLE('=')) { tmp="```=="; break; } + tmp="```="; + break; + + case '(': + if(GOBBLE(')')) { - case MY_EOF: - yyerror("Unexpected end of file."); - while(sp>save_sp) pop_stack(); - return 0; - case '"': if(!(quote&2)) quote^=1; break; - case '\'': if(!(quote&1)) quote^=2; break; - case '(': if(!quote) parlvl++; break; - case ')': if(!quote) parlvl--; break; - case '\\': my_putchar(c); c=GETC(); break; - case ',': - if(!quote && parlvl==1) - { - push_string(free_buf()); - init_buf(); - args++; - continue; - } + tmp="```()"; + break; } - if(parlvl) my_putchar(c); - } - push_string(free_buf()); - if(args==0 && !d->args && !sp[-1].u.string->len) - { - pop_stack(); - }else{ - args++; - } - }else{ - args=0; - } - } else { - args=-1; - } - - if(args>d->args) - { - my_yyerror("Too many arguments to macro '%s'.\n",s->str); - while(sp>save_sp) pop_stack(); - return 0; - } + yyerror("Illegal ` identifier."); + tmp="``"; + break; + + case '-': + if(GOBBLE('>')) + { + tmp="```->"; + if(GOBBLE('=')) tmp="```->="; + }else{ + tmp="```-"; + } + break; - if(args<d->args) - { - my_yyerror("Too few arguments to macro '%s'.\n",s->str); - while(sp>save_sp) pop_stack(); - return 0; - } - len=0; - for(e=d->parts->size-1;e>=0;e--) - { - switch(ITEM(d->parts)[e].type) - { - case T_STRING: - tmp=ITEM(d->parts)[e].u.string->len; - UNGETSTR(ITEM(d->parts)[e].u.string->str,tmp); - break; + case '[': + if(GOBBLE(']')) + { + tmp="```[]"; + if(GOBBLE('=')) tmp="```[]="; + break; + } - case T_INT: - tmp=save_sp[ITEM(d->parts)[e].u.integer].u.string->len; - UNGETSTR(save_sp[ITEM(d->parts)[e].u.integer].u.string->str,tmp); - break; + default: + yyerror("Illegal ` identifier."); + lex.pos--; + tmp="``"; + break; + } - default: tmp=0; + yylval->string=make_shared_string(tmp+offset); + return F_IDENTIFIER; } - len+=tmp; - } - while(sp>save_sp) pop_stack(); - nexpands+=len; - return 1; -} -/*** Handle include ****/ - -static void handle_include(char *name, int local_include) -{ - int fd; - char buf[400]; - struct pike_string *s; - - s=make_shared_string(name); - push_string(s); - reference_shared_string(s); - push_string(current_file); - reference_shared_string(current_file); - push_int(local_include); - - SAFE_APPLY_MASTER("handle_include",3); - if(sp[-1].type != T_STRING) - { - my_yyerror("Couldn't include file '%s'.",s->str); - return; - } - free_string(s); - - retry: - fd=open(sp[-1].u.string->str,O_RDONLY); - if(fd < 0) - { - if(errno == EINTR) goto retry; - -#ifdef HAVE_STRERROR - my_yyerror("Couldn't open file to include '%s'. (%s)",sp[-1].u.string->str,strerror(errno)); -#else - my_yyerror("Couldn't open file to include '%s'. (ERRNO=%d)",sp[-1].u.string->str,errno); -#endif - return; - } + default: + if(isidchar(c)) + { + struct pike_string *s; + lex.pos--; + READBUF(isidchar(C)); - UNGETSTR("\" 2",3); - UNGETSTR(current_file->str,current_file->len); - sprintf(buf,"\n# %ld \"",(long)current_line+1); - UNGETSTR(buf,strlen(buf)); + yylval->number=lex.current_line; - total_lines+=current_line-old_line; - old_line=current_line=1; - free_string(current_file); - current_file=sp[-1].u.string; - sp--; - link_inputstate(file_inputstate(fd)); - UNGETSTR("\n",1); -} - -/*** Lexical analyzing ***/ - -static int char_const(void) -{ - int c; - switch(c=GETC()) - { - case 'x': - switch(LOOK()) - { - default: return c; - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - case '8': case '9': - c=GETC()-'0'; + if(len>1 && len<10) + { + switch(TWO_CHAR(buf[0],buf[1])) + { + case TWO_CHAR('a','r'): + if(ISWORD("array")) return F_ARRAY_ID; break; - - case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': - c=GETC()-'a'+10; + case TWO_CHAR('b','r'): + if(ISWORD("break")) return F_BREAK; break; - - case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': - c=GETC()-'A'+10; + case TWO_CHAR('c','a'): + if(ISWORD("case")) return F_CASE; + if(ISWORD("catch")) return F_CATCH; break; - } - switch(LOOK()) - { - default: return c; - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - case '8': case '9': - c=c*16+GETC()-'0'; + case TWO_CHAR('c','l'): + if(ISWORD("class")) return F_CLASS; break; - - case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': - c=c*16+GETC()-'a'+10; + case TWO_CHAR('c','o'): + if(ISWORD("constant")) return F_CONSTANT; + if(ISWORD("continue")) return F_CONTINUE; break; - - case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': - c=c*16+GETC()-'a'+10; + case TWO_CHAR('d','e'): + if(ISWORD("default")) return F_DEFAULT; break; - } - return c; - - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - c-='0'; - if(LOOK()<'0' || LOOK()>'8') return c; - c=c*8+(GETC()-'0'); - if(LOOK()<'0' || LOOK()>'8') return c; - c=c*8+(GETC()-'0'); - return c; - - case 'r': return '\r'; - case 'n': return '\n'; - case 't': return '\t'; - case 'b': return '\b'; - } - return c; -} - -#define SKIPTO_ENDIF 1 -#define SKIPTO_ELSE 2 - -static void do_skip(int to) -{ - int lvl; -#if LEXDEBUG>3 - fprintf(stderr,"Skipping from %ld to ",(long)current_line); -#endif - lvl=1; - while(lvl) - { - switch(GETC()) - { - case '/': - if(GOBBLE('*')) - { - do{ - SKIPTO('*'); - if(LOOK()==MY_EOF) - { - yyerror("Unexpected end of file while skipping comment."); - return; - } - }while(!GOBBLE('/')); - } - continue; - - case MY_EOF: - yyerror("Unexpected end of file while skipping."); - return; - - case '\\': - GETC(); - continue; - - case '\n': - if(GOBBLE('#')) - { - SKIPWHITE(); - READBUF(C!=' ' && C!='\t' && C!='\n'); - - switch(buf[0]) - { - case 'l': - if(strcmp("line",buf)) break; - READBUF(C!=' ' && C!='\t' && C!='\n'); - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - SKIPWHITE(); - READBUF(C!='\n'); - if(buf[0]=='"' && - buf[strlen(buf)-1]=='2' && - ISSPACE(buf[strlen(buf)-2])) - { - if(lvl) - { - yyerror("Unterminated '#if' conditional."); - num_parse_error+=1000; - } - } - continue; - - case 'i': - if(!strcmp("include",buf)) continue; - if(!strcmp("if",buf) || !strcmp("ifdef",buf) || !strcmp("ifndef",buf)) - { - lvl++; - continue; - } + case TWO_CHAR('d','o'): + if(ISWORD("do")) return F_DO; break; - - case 'e': - if(!strcmp("endif",buf)) - { - lvl--; - if(lvl<0) - { - yyerror("Unbalanced '#endif'\n"); - lvl=0; - } - continue; - } - if(!strcmp("else",buf)) - { - if(lvl==1 && to==SKIPTO_ELSE) lvl=0; - continue; - } - if(!strcmp("elif",buf) || !strcmp("elseif",buf)) - { - if(lvl==1 && to==SKIPTO_ELSE && calc()) lvl--; - continue; - } - if(!strcmp("error",buf)) continue; + case TWO_CHAR('e','l'): + if(ISWORD("else")) return F_ELSE; break; - - case 'd': - if(!strcmp("define",buf)) continue; + case TWO_CHAR('f','l'): + if(ISWORD("float")) return F_FLOAT_ID; break; - - case 'u': - if(!strcmp("undef",buf)) continue; + case TWO_CHAR('f','o'): + if(ISWORD("for")) return F_FOR; + if(ISWORD("foreach")) return F_FOREACH; break; - - case 'p': - if(!strcmp("pragma",buf)) continue; + case TWO_CHAR('f','u'): + if(ISWORD("function")) return F_FUNCTION_ID; break; - } - - my_yyerror("Unknown directive #%s.",buf); - SKIPUPTO('\n'); - continue; - } - } - } -#if LEXDEBUG>3 - fprintf(stderr,"%ld in %s.\n",(long)current_line,current_file->str); -#endif -} - -static int do_lex(int literal, YYSTYPE *yylval) -#if LEXDEBUG>4 -{ - int t; - int do_lex2(int literal, YYSTYPE *yylval); - t=do_lex2(literal, yylval); - if(t<256) - { - fprintf(stderr,"do_lex(%d) -> '%c' (%d)\n",literal,t,t); - }else{ - fprintf(stderr,"do_lex(%d) -> %s (%d)\n",literal,get_f_name(t),t); - } - return t; -} - -static int do_lex2(int literal, YYSTYPE *yylval) -#endif -{ - int c; -#ifdef MALLOC_DEBUG - check_sfltable(); -#endif - while(1) - { - switch(c=GETC()) - { - case '\n': - if(literal) - { - UNGETC('\n'); - return '\n'; - } - if(GOBBLE('#')) - { - if(GOBBLE('!')) - { - SKIPUPTO('\n'); - continue; - } - - SKIPWHITE(); - READBUF(C!=' ' && C!='\t' && C!='\n'); - - switch(buf[0]) - { - char *p; - - case 'l': - if(strcmp("line",buf)) goto badhash; - READBUF(C!=' ' && C!='\t' && C!='\n'); - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - total_lines+=current_line-old_line; - old_line=current_line=atoi(buf)-1; - SKIPWHITE(); - READBUF(C!='\n'); - - p=buf; - if(*p=='"' && STRCHR(p+1,'"')) - { - char *p2; - p++; - if((p2=STRCHR(p+1,'"'))) - { - *p2=0; - free_string(current_file); - current_file=make_shared_string(p); - } - } + case TWO_CHAR('g','a'): + if(ISWORD("gauge")) return F_GAUGE; break; - - case 'i': - if(!strcmp("include",buf)) - { - SKIPWHITE(); - c=do_lex(1, yylval); - if(c=='<') - { - READBUF(C!='>' && C!='\n'); - if(!GOBBLE('>')) - { - yyerror("Missing `>`"); - SKIPUPTO('\n'); - continue; - } - }else{ - if(c!=F_STRING) - { - yyerror("Couldn't find include filename.\n"); - SKIPUPTO('\n'); - continue; - } - } - handle_include(buf, c==F_STRING); - break; - } - - if(!strcmp("if",buf)) - { - if(!calc()) do_skip(SKIPTO_ELSE); - break; - } - - if(!strcmp("ifdef",buf)) - { - struct pike_string *s; - SKIPWHITE(); - READBUF(isidchar(C)); - s=findstring(buf); - if(!s || !find_define(s)) do_skip(SKIPTO_ELSE); - break; - } - - if(!strcmp("ifndef",buf)) - { - struct pike_string *s; - SKIPWHITE(); - READBUF(isidchar(C)); - s=findstring(buf); - if(s && find_define(s)) do_skip(SKIPTO_ELSE); - break; - } - goto badhash; - - case 'e': - if(!strcmp("endif",buf)) break; - if(!strcmp("else",buf)) - { - SKIPUPTO('\n'); - do_skip(SKIPTO_ENDIF); - break; - } - if(!strcmp("elif",buf) || !strcmp("elseif",buf)) - { - SKIPUPTO('\n'); - do_skip(SKIPTO_ENDIF); - break; - } - if(!strcmp("error",buf)) - { - SKIPWHITE(); - READBUF(C!='\n'); - yyerror(buf); - break; - } - goto badhash; - - case 'u': - if(!strcmp("undef",buf)) - { - struct pike_string *s; - SKIPWHITE(); - READBUF(isidchar(C)); - if((s=findstring(buf))) undefine(s); - break; - } - goto badhash; - - case 'd': - if(!strcmp("define",buf)) - { - do_define(); - break; - } - goto badhash; - - case 'p': - if(!strcmp("pragma",buf)) - { - SKIPWHITE(); - READBUF(C!='\n'); - if (strcmp(buf, "all_inline") == 0) - { - pragma_all_inline = 1; - } + case TWO_CHAR('i','f'): + if(ISWORD("if")) return F_IF; + break; + case TWO_CHAR('i','m'): + if(ISWORD("import")) return F_IMPORT; + break; + case TWO_CHAR('i','n'): + if(ISWORD("int")) return F_INT_ID; + if(ISWORD("inherit")) return F_INHERIT; + if(ISWORD("inline")) return F_INLINE; + break; + case TWO_CHAR('l','a'): + if(ISWORD("lambda")) return F_LAMBDA; + break; + case TWO_CHAR('m','a'): + if(ISWORD("mapping")) return F_MAPPING_ID; + break; + case TWO_CHAR('m','i'): + if(ISWORD("mixed")) return F_MIXED_ID; + break; + case TWO_CHAR('m','u'): + if(ISWORD("multiset")) return F_MULTISET_ID; + break; + case TWO_CHAR('n','o'): + if(ISWORD("nomask")) return F_NO_MASK; + break; + case TWO_CHAR('o','b'): + if(ISWORD("object")) return F_OBJECT_ID; + break; + case TWO_CHAR('p','r'): + if(ISWORD("predef")) return F_PREDEF; + if(ISWORD("program")) return F_PROGRAM_ID; + if(ISWORD("private")) return F_PRIVATE; + if(ISWORD("protected")) return F_PROTECTED; break; - } - - badhash: - my_yyerror("Unknown directive #%s.",buf); - SKIPUPTO('\n'); - continue; - - } - } - continue; - - case ' ': - case '\t': - continue; - - case MY_EOF: - return 0; - - case '\'': - c=GETC(); - if(c=='\\') c=char_const(); - if(GETC()!='\'') - yyerror("Unterminated character constant."); - yylval->number=c; - return F_NUMBER; - - case '"': - init_buf(); - while(1) - { - c=GETC(); - - switch(c) - { - case MY_EOF: - yyerror("End of file in string."); - free(simple_free_buf()); - return 0; - - case '\n': - yyerror("Newline in string."); - free(simple_free_buf()); - return 0; - - case '\\': - my_putchar(char_const()); - continue; - - case '"': break; - - default: - my_putchar(c); - continue; + case TWO_CHAR('p','u'): + if(ISWORD("public")) return F_PUBLIC; + break; + case TWO_CHAR('r','e'): + if(ISWORD("return")) return F_RETURN; + break; + case TWO_CHAR('s','s'): + if(ISWORD("sscanf")) return F_SSCANF; + break; + case TWO_CHAR('s','t'): + if(ISWORD("static")) return F_STATIC; + if(ISWORD("string")) return F_STRING_ID; + break; + case TWO_CHAR('s','w'): + if(ISWORD("switch")) return F_SWITCH; + break; + case TWO_CHAR('t','y'): + if(ISWORD("typeof")) return F_TYPEOF; + break; + case TWO_CHAR('v','a'): + if(ISWORD("varargs")) return F_VARARGS; + break; + case TWO_CHAR('v','o'): + if(ISWORD("void")) return F_VOID_ID; + break; + case TWO_CHAR('w','h'): + if(ISWORD("while")) return F_WHILE; + break; + } } - break; - } - if(literal) - { - strncpy(buf,return_buf(),sizeof(buf)); - buf[sizeof(buf)-1]=0; - yylval->str=buf; + yylval->string=make_shared_binary_string(buf,len); + return F_IDENTIFIER; }else{ - yylval->string=free_buf(); + char buff[100]; + sprintf(buff, "Illegal character (hex %02x) '%c'", c, c); + yyerror(buff); + return ' '; } - return F_STRING; - - case ':': - if(GOBBLE(':')) return F_COLON_COLON; - return c; + } + } + } +} - case '.': - if(GOBBLE('.')) - { - if(GOBBLE('.')) return F_DOT_DOT_DOT; - return F_DOT_DOT; - } - return c; - - case '0': - if(GOBBLE('x')) - { - READBUF(isxdigit(C)); - yylval->number=STRTOL(buf,NULL,16); - return F_NUMBER; - } - - case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - { - char *p, *p2; - int isfloat=0; - double d; - - UNGETC(c); - READBUF(isdigit(C) || C=='.'); - - p=STRCHR(buf,'.'); - - if(p) - { - if(p[1]=='.') - { - UNGETSTR(p,strlen(p)); - *p=0; - p=NULL; - }else if((p=STRCHR(p+1,'.'))) - { - UNGETSTR(p,strlen(p)); - *p=0; - } - - if((p=STRCHR(buf,'.'))) - { - isfloat=1; - } - } - - d=STRTOD(buf, NULL); - - if(GOBBLE('e') || GOBBLE('E')) - { - int neg; - if(GOBBLE('-')) - neg=1; - else if(GOBBLE('+')) - neg=0; - else - neg=0; - - READBUF(isdigit(C)); - if(neg) - d /= pow(10.0,STRTOD(buf,NULL)); - else - d *= pow(10.0,STRTOD(buf,NULL)); - isfloat=1; - } - if(isfloat) - { - yylval->fnum=(float)d; - return F_FLOAT; - } - - if(buf[0]=='0') - yylval->number=STRTOL(buf,NULL,8); - else - yylval->number=STRTOL(buf,NULL,10); - return F_NUMBER; - } - - case '-': - if(GOBBLE('=')) return F_SUB_EQ; - if(GOBBLE('>')) return F_ARROW; - if(GOBBLE('-')) return F_DEC; - return '-'; - - case '+': - if(GOBBLE('=')) return F_ADD_EQ; - if(GOBBLE('+')) return F_INC; - return '+'; - - case '&': - if(GOBBLE('=')) return F_AND_EQ; - if(GOBBLE('&')) return F_LAND; - return '&'; - - case '|': - if(GOBBLE('=')) return F_OR_EQ; - if(GOBBLE('|')) return F_LOR; - return '|'; - - case '^': - if(GOBBLE('=')) return F_XOR_EQ; - return '^'; - - case '*': - if(GOBBLE('=')) return F_MULT_EQ; - return '*'; - - case '%': - if(GOBBLE('=')) return F_MOD_EQ; - return '%'; - - case '/': - if(GOBBLE('*')) - { - do{ - SKIPTO('*'); - if(LOOK()==MY_EOF) - { - yyerror("Unexpected end of file while skipping comment."); - return 0; - } - } while(!GOBBLE('/')); - continue; - }else if(GOBBLE('/')) - { - SKIPUPTO('\n'); - continue; - } - /* Fallthrough */ - if(GOBBLE('=')) return F_DIV_EQ; - return '/'; - - case '=': - if(GOBBLE('=')) return F_EQ; - return '='; - - case '<': - if(GOBBLE('<')) - { - if(GOBBLE('=')) return F_LSH_EQ; - return F_LSH; - } - if(GOBBLE('=')) return F_LE; - return '<'; - - case '>': - if(GOBBLE(')')) return F_MULTISET_END; - if(GOBBLE('=')) return F_GE; - if(GOBBLE('>')) - { - if(GOBBLE('=')) return F_RSH_EQ; - return F_RSH; - } - return '>'; - - case '!': - if(GOBBLE('=')) return F_NE; - return F_NOT; - - case '(': - if(GOBBLE('<')) return F_MULTISET_START; - return '('; - - case '?': - case ',': - case '~': - case '@': - case ')': - case '[': - case ']': - case '{': - case ';': - case '}': return c; - - case '`': - { - char *tmp; - int offset=2; - if(GOBBLE('`')) offset--; - if(GOBBLE('`')) offset--; - - switch(GETC()) - { - case '+': tmp="```+"; break; - case '/': tmp="```/"; break; - case '%': tmp="```%"; break; - case '*': tmp="```*"; break; - case '&': tmp="```&"; break; - case '|': tmp="```|"; break; - case '^': tmp="```^"; break; - case '~': tmp="```~"; break; - case '<': - if(GOBBLE('<')) { tmp="```<<"; break; } - if(GOBBLE('=')) { tmp="```<="; break; } - tmp="```<"; - break; - - case '>': - if(GOBBLE('>')) { tmp="```>>"; break; } - if(GOBBLE('=')) { tmp="```>="; break; } - tmp="```>"; - break; - - case '!': - if(GOBBLE('=')) { tmp="```!="; break; } - tmp="```!"; - break; - - case '=': - if(GOBBLE('=')) { tmp="```=="; break; } - tmp="```="; - break; - - case '(': - if(GOBBLE(')')) - { - tmp="```()"; - break; - } - yyerror("Illegal ` identifier."); - tmp="``"; - break; - - case '-': - if(GOBBLE('>')) - { - tmp="```->"; - if(GOBBLE('=')) tmp="```->="; - }else{ - tmp="```-"; - } - break; - - case '[': - if(GOBBLE(']')) - { - tmp="```[]"; - if(GOBBLE('=')) tmp="```[]="; - break; - } - - default: - yyerror("Illegal ` identifier."); - tmp="``"; - break; - - } - - if(literal) - { - yylval->str=tmp+offset; - }else{ - yylval->string=make_shared_string(tmp+offset); - } - return F_IDENTIFIER; - } - - - default: - if(isidchar(c)) - { - struct pike_string *s; - UNGETC(c); - READBUF(isidchar(C)); - - if(!literal) - { - /* identify identifier, if it is not a shared string, - * then it is neither a define, reserved word, local variable - * or efun, at least not yet. - */ - - s=findstring(buf); - if(s) - { - int i; - if(expand_define(s,0)) continue; - - i=lookup_resword(s); - if(i >= 0) - { - yylval->number=current_line; - return i; - } - - reference_shared_string(s); - }else{ - s=make_shared_string(buf); - } - yylval->string=s; - return F_IDENTIFIER; - } - - yylval->str=buf; - return F_IDENTIFIER; - }else{ - char buff[100]; - sprintf(buff, "Illegal character (hex %02x) '%c'", c, c); - yyerror(buff); - return ' '; - } - } - } -} - -int yylex(YYSTYPE *yylval) -{ -#ifdef __CHECKER__ - MEMSET((char *)yylval,0,sizeof(YYSTYPE)); -#endif - return do_lex(0, yylval); -} - -static YYSTYPE my_yylval; -static int lookahead; - -static void low_lex(void) -{ - while(1) - { - struct pike_string *s; - - lookahead=do_lex(1, &my_yylval); - if(lookahead == F_IDENTIFIER) - { - if(!strcmp("defined",my_yylval.str)) - { - SKIPWHITE(); - if(!GOBBLE('(')) - { - yyerror("Missing '(' in defined.\n"); - return; - } - READBUF(isidchar(C)); - if(!GOBBLE(')')) - { - yyerror("Missing ')' in defined.\n"); - return; - } - s=findstring(buf); - - if(s && find_define(s)) - UNGETSTR(" 1 ",3); - else - UNGETSTR(" 0 ",3); - - continue; - } - - if(!strcmp("efun",my_yylval.str) || !strcmp("constant",my_yylval.str)) - { - int res = 0; - struct svalue *oldsp = sp; - struct svalue *sv; - - SKIPWHITE(); - if (!GOBBLE('(')) { - yyerror("Missing '(' in #if constant().\n"); - return; - } - READBUF(isidchar(C)); - - push_text(buf); - if ((sv = low_mapping_string_lookup(get_builtin_constants(), - sp[-1].u.string))) { - pop_stack(); - push_svalue(sv); - res = 1; - } else if (get_master()) { - current_file->refs++; - push_string(current_file); - - SAFE_APPLY_MASTER("resolv", 2); - - if ((throw_value.type != T_STRING) && - (!(IS_ZERO(sp-1) && sp[-1].subtype == 1))) { - res = 1; - } - } - - while(GOBBLE('.')) { - READBUF(isidchar(C)); - if (res) { - JMP_BUF recovery; - - push_text(buf); - - free_svalue(&throw_value); - throw_value.type = T_INT; - - if (SETJMP(recovery)) { - res = 0; - } else { - f_index(2); - if (IS_ZERO(sp-1) && sp[-1].subtype == 1) { - res = 0; - } - } - UNSETJMP(recovery); - } - } - - if (!GOBBLE(')')) { - yyerror("Missing ')' in #if constant().\n"); - return; - } - - if (sp > oldsp) { - pop_n_elems(sp - oldsp); - } - - if (res) { - UNGETSTR(" 1 ", 3); - } else { - UNGETSTR(" 0 ", 3); - } - continue; - } - - s=findstring(my_yylval.str); - if(!s || !expand_define(s,1)) - UNGETSTR(" 0 ",3); - continue; - } - - break; - } -} - -static void calcC(void) -{ - switch(lookahead) - { - case '(': - low_lex(); - calc1(); - if(lookahead != ')') - error("Missing ')'\n"); - break; - - case F_FLOAT: - push_float(my_yylval.fnum); - break; - - case F_STRING: - push_string(make_shared_string(my_yylval.str)); - break; - - case F_NUMBER: - push_int(my_yylval.number); - break; - - default: - push_int(0); - yyerror("Syntax error in #if."); - return; - } - - low_lex(); - - while(lookahead=='[') - { - low_lex(); - calc1(); - f_index(2); - if(lookahead!=']') - error("Missing ']'\n"); - else - low_lex(); - } -} - -static void calcB(void) -{ - switch(lookahead) - { - case '-': low_lex(); calcB(); o_negate(); break; - case F_NOT: low_lex(); calcB(); o_not(); break; - case '~': low_lex(); calcB(); o_compl(); break; - default: calcC(); - } -} - -static void calcA(void) -{ - calcB(); - while(1) - { - switch(lookahead) - { - case '/': low_lex(); calcB(); o_divide(); continue; - case '*': low_lex(); calcB(); o_multiply(); continue; - case '%': low_lex(); calcB(); o_mod(); continue; - } - break; - } -} - -static void calc9(void) -{ - calcA(); - - while(1) - { - switch(lookahead) - { - case '+': low_lex(); calcA(); f_add(2); continue; - case '-': low_lex(); calcA(); o_subtract(); continue; - } - break; - } -} - -static void calc8(void) -{ - calc9(); - - while(1) - { - switch(lookahead) - { - case F_LSH: low_lex(); calc9(); o_lsh(); continue; - case F_RSH: low_lex(); calc9(); o_rsh(); continue; - } - break; - } -} - -static void calc7b(void) -{ - calc8(); - - while(1) - { - switch(lookahead) - { - case '<': low_lex(); calc8(); f_lt(2); continue; - case '>': low_lex(); calc8(); f_gt(2); continue; - case F_GE: low_lex(); calc8(); f_ge(2); continue; - case F_LE: low_lex(); calc8(); f_le(2); continue; - } - break; - } -} - -static void calc7(void) -{ - calc7b(); - - while(1) - { - switch(lookahead) - { - case F_EQ: low_lex(); calc7b(); f_eq(2); continue; - case F_NE: low_lex(); calc7b(); f_ne(2); continue; - } - break; - } -} - -static void calc6(void) -{ - calc7(); - - while(lookahead=='&') - { - low_lex(); - calc7(); - o_and(); - } -} - -static void calc5(void) -{ - calc6(); - - while(lookahead=='^') - { - low_lex(); - calc6(); - o_xor(); - } -} - -static void calc4(void) -{ - calc5(); - - while(lookahead=='|') - { - low_lex(); - calc5(); - o_or(); - } -} - -static void calc3(void) -{ - calc4(); - - while(lookahead==F_LAND) - { - low_lex(); - check_destructed(sp-1); - if(IS_ZERO(sp-1)) - { - calc4(); - pop_stack(); - }else{ - pop_stack(); - calc4(); - } - } -} - -static void calc2(void) -{ - calc3(); - - while(lookahead==F_LOR) - { - low_lex(); - check_destructed(sp-1); - if(!IS_ZERO(sp-1)) - { - calc3(); - pop_stack(); - }else{ - pop_stack(); - calc3(); - } - } -} - -static void calc1(void) -{ - calc2(); - - if(lookahead=='?') - { - low_lex(); - calc1(); - if(lookahead!=':') - error("Colon expected.\n"); - low_lex(); - calc1(); - - check_destructed(sp-3); - assign_svalue(sp-3,IS_ZERO(sp-3)?sp-1:sp-2); - pop_n_elems(2); - } - -} - -static int calc(void) -{ - JMP_BUF recovery; - int ret; - - ret=0; - if (SETJMP(recovery)) - { - if(throw_value.type == T_ARRAY && throw_value.u.array->size) - { - union anything *a; - a=low_array_get_item_ptr(throw_value.u.array, 0, T_STRING); - if(a) - { - yyerror(a->string->str); - }else{ - yyerror("Nonstandard error format.\n"); - } - }else{ - yyerror("Nonstandard error format.\n"); - } - ret=-1; - }else{ - low_lex(); - calc1(); - if(lookahead!='\n') - { - SKIPUPTO('\n'); - yyerror("Extra characters after #if expression."); - }else{ - UNGETC('\n'); - } - check_destructed(sp-1); - ret=!IS_ZERO(sp-1); - pop_stack(); - } - UNSETJMP(recovery); - - return ret; -} - -/*** Magic defines ***/ -static void insert_current_line(void) -{ - char buf[20]; - sprintf(buf," %ld ",(long)current_line); - UNGETSTR(buf,strlen(buf)); -} - -static void insert_current_file_as_string(void) -{ - UNGETSTR("\"",1); - UNGETSTR(current_file->str, current_file->len); - UNGETSTR("\"",1); -} - -static void insert_current_time_as_string(void) -{ - time_t tmp; - char *buf; - time(&tmp); - buf=ctime(&tmp); - - UNGETSTR("\"",1); - UNGETSTR(buf+11, 8); - UNGETSTR("\"",1); -} - -static void insert_current_date_as_string(void) -{ - time_t tmp; - char *buf; - time(&tmp); - buf=ctime(&tmp); - - UNGETSTR("\"",1); - UNGETSTR(buf+19, 5); - UNGETSTR(buf+4, 6); - UNGETSTR("\"",1); -} - -/*** ***/ - -static void start_new(void) -{ - struct pike_predef_s *tmpf; - - free_all_defines(); - - simple_add_define("__PIKE__", "1",0); - - for (tmpf=pike_predefs; tmpf; tmpf=tmpf->next) - simple_add_define(tmpf->name, tmpf->value,0); - - simple_add_define("__LINE__",0,insert_current_line); - simple_add_define("__FILE__",0,insert_current_file_as_string); - simple_add_define("__DATE__",0,insert_current_date_as_string); - simple_add_define("__TIME__",0,insert_current_time_as_string); - - free_inputstate(istate); - istate=NULL; - link_inputstate(end_inputstate()); - old_line=current_line = 1; - pragma_all_inline=0; - nexpands=0; - if(current_file) free_string(current_file); - current_file=0; -} - -void start_new_file(int fd,struct pike_string *filename) -{ - start_new(); - copy_shared_string(current_file,filename); - - link_inputstate(file_inputstate(fd)); - UNGETSTR("\n",1); -} - -void start_new_string(char *s,INT32 len,struct pike_string *name) -{ - start_new(); - copy_shared_string(current_file,name); - link_inputstate(prot_memory_inputstate(s,len)); - UNGETSTR("\n",1); -} - -void end_new_file(void) -{ - if(current_file) - { - free_string(current_file); - current_file=0; - } - - free_inputstate(istate); - istate=NULL; - free_all_defines(); - total_lines+=current_line-old_line; -} - - -#if 0 -void add_predefine(char *s) -{ - char buffer1[100],buffer2[10000]; - struct pike_predef_s *tmp; - - if(sscanf(s,"%[^=]=%[ -~=]",buffer1,buffer2) ==2) - { - s=buffer1; - }else{ - buffer2[0]='1'; - buffer2[1]=0; - } - tmp=ALLOC_STRUCT(pike_predef_s); - tmp->name=(char *)xalloc(strlen(s)+1); - strcpy(tmp->name,s); - tmp->value=(char *)xalloc(strlen(buffer2)+1); - strcpy(tmp->value,buffer2); - tmp->next=pike_predefs; - pike_predefs=tmp; -} -#endif diff --git a/src/lex.h b/src/lex.h index f26e42c47037e4cde9a3c706e44144fb2e07e099..df6a17815016ce0d110b09b3df3ae9762c3029ac 100644 --- a/src/lex.h +++ b/src/lex.h @@ -44,44 +44,32 @@ struct instr struct hash_entry; #endif -#ifndef STRUCT_INPUTSTATE_DECLARED -#define STRUCT_INPUTSTATE_DECLARED -struct inputstate; -#endif - #ifndef STRUCT_HASH_TABLE_DECLARED #define STRUCT_HASH_TABLE_DECLARED struct hash_table; #endif -extern struct instr instrs[]; -extern struct hash_table *defines; -extern struct pike_string *current_file; -extern INT32 current_line; -extern INT32 old_line; -extern INT32 total_lines; -extern INT32 nexpands; -extern int pragma_all_inline; /* inline all possible inlines */ -extern struct inputstate *istate; +#define PRAGMA_ALL_INLINE 1 -extern struct pike_predef_s * pike_predefs; +struct lex +{ + char *pos; + char *end; + INT32 current_line; + INT32 pragmas; + struct pike_string *current_file; +}; + +extern struct lex lex; +extern struct instr instrs[]; /* Prototypes begin here */ -struct pike_predef_s; void exit_lex(void); struct reserved; -void init_lex(void); -void free_reswords(void); +void init_lex(); char *low_get_f_name(int n,struct program *p); char *get_f_name(int n); char *get_token_name(int n); -struct inputstate; -struct define; -void free_one_define(struct hash_entry *h); -void start_new_file(int fd,struct pike_string *filename); -void start_new_string(char *s,INT32 len,struct pike_string *name); -void end_new_file(void); -void add_predefine(char *s); /* Prototypes end here */ #endif diff --git a/src/main.c b/src/main.c index 079bd693db4fe2800b5ae1b7c6185d12e71d06d8..221df21c688b974cb5f8aee3c88b411c4607f1b3 100644 --- a/src/main.c +++ b/src/main.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: main.c,v 1.31 1998/01/10 21:19:09 hubbe Exp $"); +RCSID("$Id: main.c,v 1.32 1998/01/13 22:56:45 hubbe Exp $"); #include "fdlib.h" #include "backend.h" #include "module.h" @@ -93,6 +93,28 @@ void main(int argc, char **argv) master_file = 0; #ifdef HAVE_GETENV master_file = getenv("PIKE_MASTER"); +#endif +#if __NT__ + { + char buffer[4096]; + DWORD len=sizeof(buffer)-1,type=REG_SZ; + + if(RegQueryValueEx(HKEY_CURRENT_USER, + "SOFTWARE\\Idonex\\Pike\\0.6\\PIKE_MASTER", + 0, + &type, + buffer, + &len)==ERROR_SUCCESS || + RegQueryValueEx(HKEY_CURRENT_USER, + "SOFTWARE\\Idonex\\Pike\\0.6\\PIKE_MASTER", + 0, + &type, + buffer, + &len)==ERROR_SUCCESS) + { + master_file=strdup(buffer); + } + } #endif if(!master_file) master_file = DEFAULT_MASTER; diff --git a/src/modules/Image/blit.c b/src/modules/Image/blit.c index ea5266e003525ed8c589c847cebbbf4ac04d147b..bdb5aafb579bc155a0874ab257e7fe2735ae0cbb 100644 --- a/src/modules/Image/blit.c +++ b/src/modules/Image/blit.c @@ -1,10 +1,10 @@ -/* $Id: blit.c,v 1.25 1997/12/22 23:26:43 hubbe Exp $ */ +/* $Id: blit.c,v 1.26 1998/01/13 22:59:21 hubbe Exp $ */ #include "global.h" /* **! module Image **! note -**! $Id: blit.c,v 1.25 1997/12/22 23:26:43 hubbe Exp $ +**! $Id: blit.c,v 1.26 1998/01/13 22:59:21 hubbe Exp $ **! class image */ @@ -25,6 +25,9 @@ #include "image.h" extern struct program *image_program; +#ifdef THIS +#undef THIS /* Needed for NT */ +#endif #define THIS ((struct image *)(fp->current_storage)) #define THISOBJ (fp->current_object) diff --git a/src/modules/Image/colortable.c b/src/modules/Image/colortable.c index 32735b50a9056cc33318586abd4ca8877e941d98..6c2924cc22237c3fe8720aa51745c2f855a7ddc1 100644 --- a/src/modules/Image/colortable.c +++ b/src/modules/Image/colortable.c @@ -1,11 +1,11 @@ #include <config.h> -/* $Id: colortable.c,v 1.32 1998/01/11 20:50:33 mirar Exp $ */ +/* $Id: colortable.c,v 1.33 1998/01/13 22:59:21 hubbe Exp $ */ /* **! module Image **! note -**! $Id: colortable.c,v 1.32 1998/01/11 20:50:33 mirar Exp $ +**! $Id: colortable.c,v 1.33 1998/01/13 22:59:21 hubbe Exp $ **! class colortable **! **! This object keeps colortable information, @@ -21,7 +21,7 @@ #undef COLORTABLE_REDUCE_DEBUG #include "global.h" -RCSID("$Id: colortable.c,v 1.32 1998/01/11 20:50:33 mirar Exp $"); +RCSID("$Id: colortable.c,v 1.33 1998/01/13 22:59:21 hubbe Exp $"); #include <sys/types.h> #include <sys/stat.h> @@ -78,6 +78,9 @@ extern struct program *image_program; #define SQ(x) ((x)*(x)) static INLINE int sq(int x) { return x*x; } +#ifdef THIS +#undef THIS /* Needed for NT */ +#endif #define THIS ((struct neo_colortable *)(fp->current_storage)) #define THISOBJ (fp->current_object) diff --git a/src/modules/Image/dct.c b/src/modules/Image/dct.c index 6e30807082bd586d6495efdb9b73c989e73bdfd1..b43d0873ee1d4ca944b29416ce2bca68b6f36f19 100644 --- a/src/modules/Image/dct.c +++ b/src/modules/Image/dct.c @@ -1,9 +1,9 @@ -/* $Id: dct.c,v 1.10 1997/12/22 23:26:45 hubbe Exp $ */ +/* $Id: dct.c,v 1.11 1998/01/13 22:59:22 hubbe Exp $ */ /* **! module Image **! note -**! $Id: dct.c,v 1.10 1997/12/22 23:26:45 hubbe Exp $ +**! $Id: dct.c,v 1.11 1998/01/13 22:59:22 hubbe Exp $ **! class image */ @@ -25,6 +25,9 @@ #include "image.h" extern struct program *image_program; +#ifdef THIS +#undef THIS /* Needed for NT */ +#endif #define THIS ((struct image *)(fp->current_storage)) #define THISOBJ (fp->current_object) diff --git a/src/modules/Image/image.c b/src/modules/Image/image.c index 57a35710a0d78838595bd489139b78726e7963cc..88c0e6539896f3bd9848a7c7f579be911d9c9e25 100644 --- a/src/modules/Image/image.c +++ b/src/modules/Image/image.c @@ -1,9 +1,9 @@ -/* $Id: image.c,v 1.72 1998/01/08 18:44:27 mirar Exp $ */ +/* $Id: image.c,v 1.73 1998/01/13 22:59:23 hubbe Exp $ */ /* **! module Image **! note -**! $Id: image.c,v 1.72 1998/01/08 18:44:27 mirar Exp $ +**! $Id: image.c,v 1.73 1998/01/13 22:59:23 hubbe Exp $ **! class image **! **! The main object of the <ref>Image</ref> module, this object @@ -82,7 +82,7 @@ #include "stralloc.h" #include "global.h" -RCSID("$Id: image.c,v 1.72 1998/01/08 18:44:27 mirar Exp $"); +RCSID("$Id: image.c,v 1.73 1998/01/13 22:59:23 hubbe Exp $"); #include "pike_macros.h" #include "object.h" #include "constants.h" @@ -100,6 +100,10 @@ RCSID("$Id: image.c,v 1.72 1998/01/08 18:44:27 mirar Exp $"); struct program *image_program; extern struct program *image_colortable_program; +#ifdef THIS +#undef THIS /* Needed for NT */ +#endif + #define THIS ((struct image *)(fp->current_storage)) #define THISOBJ (fp->current_object) diff --git a/src/modules/Image/matrix.c b/src/modules/Image/matrix.c index 611487c89e41ce811a50b0ddd2aeeb84c239f68c..ae757b1b7e22bf4e0681b63aedf97e51d88e6831 100644 --- a/src/modules/Image/matrix.c +++ b/src/modules/Image/matrix.c @@ -1,9 +1,9 @@ -/* $Id: matrix.c,v 1.12 1998/01/06 21:39:29 mirar Exp $ */ +/* $Id: matrix.c,v 1.13 1998/01/13 22:59:23 hubbe Exp $ */ /* **! module Image **! note -**! $Id: matrix.c,v 1.12 1998/01/06 21:39:29 mirar Exp $ +**! $Id: matrix.c,v 1.13 1998/01/13 22:59:23 hubbe Exp $ **! class image */ @@ -26,6 +26,10 @@ #include "image.h" extern struct program *image_program; +#ifdef THIS +#undef THIS /* Needed for NT */ +#endif + #define THIS ((struct image *)(fp->current_storage)) #define THISOBJ (fp->current_object) diff --git a/src/modules/Image/operator.c b/src/modules/Image/operator.c index e999d68fde6d35c60b51c49242ca6a6bdeac7dd9..c9e3a571424ca06a5de9b3bf05ffc9bbd6b8c9fc 100644 --- a/src/modules/Image/operator.c +++ b/src/modules/Image/operator.c @@ -1,9 +1,9 @@ -/* $Id: operator.c,v 1.10 1997/12/22 23:26:48 hubbe Exp $ */ +/* $Id: operator.c,v 1.11 1998/01/13 22:59:23 hubbe Exp $ */ /* **! module Image **! note -**! $Id: operator.c,v 1.10 1997/12/22 23:26:48 hubbe Exp $ +**! $Id: operator.c,v 1.11 1998/01/13 22:59:23 hubbe Exp $ **! class image */ @@ -26,6 +26,9 @@ #include "image.h" extern struct program *image_program; +#ifdef THIS +#undef THIS +#endif #define THIS ((struct image *)(fp->current_storage)) #define THISOBJ (fp->current_object) diff --git a/src/modules/Image/pattern.c b/src/modules/Image/pattern.c index 8b7ba8f94ba111f270214945455a23db9c6ccee7..07205152f2c464905b9c0f90632e821a04a99aea 100644 --- a/src/modules/Image/pattern.c +++ b/src/modules/Image/pattern.c @@ -1,9 +1,9 @@ -/* $Id: pattern.c,v 1.10 1997/12/22 23:26:49 hubbe Exp $ */ +/* $Id: pattern.c,v 1.11 1998/01/13 22:59:24 hubbe Exp $ */ /* **! module Image **! note -**! $Id: pattern.c,v 1.10 1997/12/22 23:26:49 hubbe Exp $ +**! $Id: pattern.c,v 1.11 1998/01/13 22:59:24 hubbe Exp $ **! class image */ @@ -25,6 +25,10 @@ #include "image.h" extern struct program *image_program; +#ifdef THIS +#undef THIS +#endif + #define THIS ((struct image *)(fp->current_storage)) #define THISOBJ (fp->current_object) diff --git a/src/modules/Image/pnm.c b/src/modules/Image/pnm.c index c93e0574772c811aff35b383626cffd8cd6710a2..febed8a0a13ad8f3ba72203410a26c5db9a0af62 100644 --- a/src/modules/Image/pnm.c +++ b/src/modules/Image/pnm.c @@ -1,9 +1,9 @@ -/* $Id: pnm.c,v 1.8 1997/11/02 03:46:52 mirar Exp $ */ +/* $Id: pnm.c,v 1.9 1998/01/13 22:59:24 hubbe Exp $ */ /* **! module Image **! note -**! $Id: pnm.c,v 1.8 1997/11/02 03:46:52 mirar Exp $ +**! $Id: pnm.c,v 1.9 1998/01/13 22:59:24 hubbe Exp $ **! class image */ @@ -24,6 +24,9 @@ #include "image.h" +#ifdef THIS +#undef THIS +#endif #define THIS ((struct image *)(fp->current_storage)) #define THISOBJ (fp->current_object) diff --git a/src/modules/Image/polyfill.c b/src/modules/Image/polyfill.c index a79d890e66a910fdbea4b2f2d3fcd490025cb922..e278eebedd5b4cc31bfab8dc23119f74c304b91a 100644 --- a/src/modules/Image/polyfill.c +++ b/src/modules/Image/polyfill.c @@ -1,5 +1,5 @@ #include "global.h" -RCSID("$Id: polyfill.c,v 1.17 1998/01/06 21:39:30 mirar Exp $"); +RCSID("$Id: polyfill.c,v 1.18 1998/01/13 22:59:24 hubbe Exp $"); /* Prototypes are needed for these */ extern double floor(double); @@ -21,6 +21,9 @@ extern double floor(double); #include "image.h" +#ifdef THIS +#undef THIS +#endif #define THIS ((struct image *)(fp->current_storage)) #define THISOBJ (fp->current_object) @@ -29,7 +32,7 @@ extern double floor(double); /* **! module Image **! note -**! $Id: polyfill.c,v 1.17 1998/01/06 21:39:30 mirar Exp $ +**! $Id: polyfill.c,v 1.18 1998/01/13 22:59:24 hubbe Exp $ **! class image */ diff --git a/src/modules/Image/togif.c b/src/modules/Image/togif.c index 8c926d198a4fb484e8fe92400280cc89d71ec774..6df4b0a6157b090b7645a302ea0e22626b0fe993 100644 --- a/src/modules/Image/togif.c +++ b/src/modules/Image/togif.c @@ -2,7 +2,7 @@ togif -$Id: togif.c,v 1.28 1997/11/26 15:41:35 mirar Exp $ +$Id: togif.c,v 1.29 1998/01/13 22:59:25 hubbe Exp $ old GIF API compat stuff @@ -11,7 +11,7 @@ old GIF API compat stuff /* **! module Image **! note -**! $Id: togif.c,v 1.28 1997/11/26 15:41:35 mirar Exp $ +**! $Id: togif.c,v 1.29 1998/01/13 22:59:25 hubbe Exp $ **! class image */ @@ -36,6 +36,10 @@ old GIF API compat stuff #include "image.h" #include "colortable.h" +#ifdef THIS +#undef THIS /* Needed for NT */ +#endif + #define THIS ((struct image *)(fp->current_storage)) #define THISOBJ (fp->current_object) diff --git a/src/modules/Image/x.c b/src/modules/Image/x.c index baecb6764f647046a5fa23c328a91dcb4e97dd69..4703b39b8795653baadd7449394ef345081290b8 100644 --- a/src/modules/Image/x.c +++ b/src/modules/Image/x.c @@ -1,4 +1,4 @@ -/* $Id: x.c,v 1.16 1997/11/11 01:26:17 grubba Exp $ */ +/* $Id: x.c,v 1.17 1998/01/13 22:59:25 hubbe Exp $ */ /* **! module Image @@ -12,7 +12,7 @@ #include "stralloc.h" #include "global.h" -RCSID("$Id: x.c,v 1.16 1997/11/11 01:26:17 grubba Exp $"); +RCSID("$Id: x.c,v 1.17 1998/01/13 22:59:25 hubbe Exp $"); #include "pike_macros.h" #include "object.h" #include "constants.h" @@ -29,6 +29,9 @@ RCSID("$Id: x.c,v 1.16 1997/11/11 01:26:17 grubba Exp $"); extern struct program *image_colortable_program; +#ifdef THIS +#undef THIS +#endif #define THIS ((struct image *)(fp->current_storage)) #define THISOBJ (fp->current_object) diff --git a/src/modules/Pipe/pipe.c b/src/modules/Pipe/pipe.c index e5546bbdfe35e0f224b686ec803536d4deea7109..0a380a3e9885d254a246b122ef59e9ca33516f93 100644 --- a/src/modules/Pipe/pipe.c +++ b/src/modules/Pipe/pipe.c @@ -22,7 +22,7 @@ #include <fcntl.h> #include "global.h" -RCSID("$Id: pipe.c,v 1.14 1997/10/10 18:59:47 grubba Exp $"); +RCSID("$Id: pipe.c,v 1.15 1998/01/13 23:00:35 hubbe Exp $"); #include "threads.h" #include "stralloc.h" @@ -71,6 +71,9 @@ RCSID("$Id: pipe.c,v 1.14 1997/10/10 18:59:47 grubba Exp $"); static struct program *pipe_program, *output_program; +#ifdef THIS +#undef THIS +#endif #define THIS ((struct pipe *)(fp->current_storage)) #define THISOBJ (fp->current_object) diff --git a/src/modules/Regexp/glue.c b/src/modules/Regexp/glue.c index d6eda2a4cf1d65b7966502b9e3e5bb0bea36818c..ef48173a29bc87e4644bfdc2fb2c455cbb80d6f0 100644 --- a/src/modules/Regexp/glue.c +++ b/src/modules/Regexp/glue.c @@ -37,6 +37,10 @@ struct regexp_glue #endif /* USE_SYSTEM_REGEXP */ +#ifdef THIS +#undef THIS +#endif + #define THIS ((struct regexp_glue *)(fp->current_storage)) static void do_free(void) diff --git a/src/modules/_Crypto/cbc.c b/src/modules/_Crypto/cbc.c index d3644cdbf40b5580068d01b766b4849b7b53a667..fdbf61bbe3b11edfe0a18b6d5ed98ddbbd3b6902 100644 --- a/src/modules/_Crypto/cbc.c +++ b/src/modules/_Crypto/cbc.c @@ -1,5 +1,5 @@ /* - * $Id: cbc.c,v 1.9 1997/11/16 22:25:39 nisse Exp $ + * $Id: cbc.c,v 1.10 1998/01/13 23:01:10 hubbe Exp $ * * CBC (Cipher Block Chaining Mode) crypto module for Pike. * @@ -35,6 +35,7 @@ struct pike_crypto_cbc { INT32 mode; }; +#undef THIS #define THIS ((struct pike_crypto_cbc *)(fp->current_storage)) /* * Globals diff --git a/src/modules/_Crypto/crypto.c b/src/modules/_Crypto/crypto.c index 8d960e4de8be730cfb9e10c6e3c4baf6436f31db..05cded80b1f81abd3f63c2ef750174e7d67a8824 100644 --- a/src/modules/_Crypto/crypto.c +++ b/src/modules/_Crypto/crypto.c @@ -1,5 +1,5 @@ /* - * $Id: crypto.c,v 1.23 1997/12/22 23:28:30 hubbe Exp $ + * $Id: crypto.c,v 1.24 1998/01/13 23:01:11 hubbe Exp $ * * A pike module for getting access to some common cryptos. * @@ -55,6 +55,7 @@ static const char *crypto_functions[] = { NULL }; +#undef THIS #define THIS ((struct pike_crypto *)(fp->current_storage)) static struct program *pike_crypto_program; diff --git a/src/modules/_Crypto/des.c b/src/modules/_Crypto/des.c index dc53c2b0f883b15ba28f2c2cdb34be54f634539d..f1405408647149682d6b6f45a689f70987d4019b 100644 --- a/src/modules/_Crypto/des.c +++ b/src/modules/_Crypto/des.c @@ -1,5 +1,5 @@ /* - * $Id: des.c,v 1.10 1997/12/22 23:28:31 hubbe Exp $ + * $Id: des.c,v 1.11 1998/01/13 23:01:11 hubbe Exp $ * * A pike module for getting access to some common cryptos. * @@ -43,6 +43,7 @@ struct pike_crypto_des { unsigned INT32 *method, unsigned INT8 *src); }; +#undef THIS #define THIS ((struct pike_crypto_des *) fp->current_storage) /* diff --git a/src/modules/_Crypto/pipe.c b/src/modules/_Crypto/pipe.c index 604534d351804713fafe4e922fcbb8bb2b89982e..883fc79eed23631b1772ab358b99d306df25e4f1 100644 --- a/src/modules/_Crypto/pipe.c +++ b/src/modules/_Crypto/pipe.c @@ -1,5 +1,5 @@ /* - * $Id: pipe.c,v 1.10 1997/11/16 22:25:45 nisse Exp $ + * $Id: pipe.c,v 1.11 1998/01/13 23:01:11 hubbe Exp $ * * PIPE crypto module for Pike. * @@ -35,6 +35,7 @@ struct pike_crypto_pipe { INT32 mode; }; +#undef THIS #define THIS ((struct pike_crypto_pipe *)(fp->current_storage)) /* * Globals diff --git a/src/modules/_Crypto/sha.c b/src/modules/_Crypto/sha.c index e165fe2290c56e1253bb57e3602a2c09af0940dd..6a20b9c93c2deb19f2665d3e56d0bc0fb3876dae 100644 --- a/src/modules/_Crypto/sha.c +++ b/src/modules/_Crypto/sha.c @@ -14,6 +14,7 @@ #include "program.h" #include "error.h" #include "module_support.h" +#include "las.h" #include <sha.h> diff --git a/src/modules/files/socktest.pike b/src/modules/files/socktest.pike index fbca185280b9266d844fd7ece7d8702ebe922b34..0094853eb4bcc3a82c0289eea003212179b1009f 100755 --- a/src/modules/files/socktest.pike +++ b/src/modules/files/socktest.pike @@ -1,6 +1,6 @@ #!/usr/local/bin/pike -/* $Id: socktest.pike,v 1.5 1997/09/16 07:32:16 hubbe Exp $ */ +/* $Id: socktest.pike,v 1.6 1998/01/13 23:01:25 hubbe Exp $ */ import Stdio; import String; @@ -238,7 +238,7 @@ void finish() case 5..26: tests=(_tests-2)*2; werror("Testing "+(tests*2)+" sockets. "); - for(e=0;e<tests;e++) stdtest(); + for(int e=0;e<tests;e++) stdtest(); break; case 27..48: diff --git a/src/modules/system/system.c b/src/modules/system/system.c index 38575d74c8eb5a1adf031c0b0de5a2cab698e283..fcac2124ef2aceee16e5d46f82a663640ccece23 100644 --- a/src/modules/system/system.c +++ b/src/modules/system/system.c @@ -1,5 +1,5 @@ /* - * $Id: system.c,v 1.36 1998/01/11 00:00:19 grubba Exp $ + * $Id: system.c,v 1.37 1998/01/13 23:01:47 hubbe Exp $ * * System-call module for Pike * @@ -14,7 +14,11 @@ #include "system.h" #include "global.h" -RCSID("$Id: system.c,v 1.36 1998/01/11 00:00:19 grubba Exp $"); +RCSID("$Id: system.c,v 1.37 1998/01/13 23:01:47 hubbe Exp $"); +#ifdef HAVE_WINSOCK2_H +#include <winsock2.h> +#endif + #include "module_support.h" #include "las.h" #include "interpret.h" @@ -60,10 +64,6 @@ RCSID("$Id: system.c,v 1.36 1998/01/11 00:00:19 grubba Exp $"); #include <sys/stat.h> #endif /* HAVE_SYS_STAT_H */ -#ifdef HAVE_WINSOCK2_H -#include <winsock2.h> -#endif - /* * Functions */ @@ -778,7 +778,7 @@ static void describe_hostent(struct hostent *hp) for (p = hp->h_addr_list; *p != 0; p++) { struct in_addr in; - memcpy(&in.s_addr, *p, sizeof (in.s_addr)); + MEMCPY(&in.s_addr, *p, sizeof (in.s_addr)); push_text(inet_ntoa(in)); nelem++; } @@ -793,7 +793,7 @@ static void describe_hostent(struct hostent *hp) #else { struct in_addr in; - memcpy(&in.s_addr, ret->h_addr, sizeof (in.s_addr)); + MEMCPY(&in.s_addr, hp->h_addr, sizeof (in.s_addr)); push_text(inet_ntoa(in)); } diff --git a/src/object.c b/src/object.c index fa6d5ef972217ff512d530ee64e43fa3432a74c5..7498e505a86337fdf6fc3cf31507aaf714097a62 100644 --- a/src/object.c +++ b/src/object.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: object.c,v 1.30 1998/01/02 01:05:48 hubbe Exp $"); +RCSID("$Id: object.c,v 1.31 1998/01/13 22:56:46 hubbe Exp $"); #include "object.h" #include "dynamic_buffer.h" #include "interpret.h" @@ -19,6 +19,8 @@ RCSID("$Id: object.c,v 1.30 1998/01/02 01:05:48 hubbe Exp $"); #include "gc.h" #include "backend.h" #include "callback.h" +#include "cpp.h" +#include "builtin_functions.h" struct object *master_object = 0; struct program *master_program =0; @@ -28,7 +30,7 @@ struct object fake_object = { 1 }; /* start with one reference */ void setup_fake_object(void) { - fake_object.prog=&fake_program; + fake_object.prog=new_program; fake_object.next=0; fake_object.refs=0xffffff; } @@ -39,6 +41,9 @@ struct object *low_clone(struct program *p) struct object *o; struct frame frame; + if(!(p->flags & PROGRAM_FINISHED)) + error("Attempting to clone an unfinished program\n"); + #ifdef PROFILING p->num_clones++; #endif /* PROFILING */ @@ -49,12 +54,22 @@ struct object *low_clone(struct program *p) o->prog=p; p->refs++; + o->parent=0; + o->parent_identifier=0; o->next=first_object; o->prev=0; if(first_object) first_object->prev=o; first_object=o; o->refs=1; + return o; +} + +static void call_c_initializers(struct object *o) +{ + int e; + struct frame frame; + struct program *p=o->prog; frame.parent_frame=fp; frame.current_object=o; @@ -103,11 +118,9 @@ struct object *low_clone(struct program *p) free_object(frame.current_object); fp = frame.parent_frame; - - return o; } -static void init_object(struct object *o, int args) +static void call_pike_initializers(struct object *o, int args) { apply_lfun(o,LFUN___INIT,0); pop_stack(); @@ -118,10 +131,26 @@ static void init_object(struct object *o, int args) struct object *clone_object(struct program *p, int args) { struct object *o=low_clone(p); - init_object(o,args); + call_c_initializers(o); + call_pike_initializers(o,args); return o; } +struct object *parent_clone_object(struct program *p, + struct object *parent, + int parent_identifier, + int args) +{ + struct object *o=low_clone(p); + o->parent=parent; + parent->refs++; + o->parent_identifier=parent_identifier; + call_c_initializers(o); + call_pike_initializers(o,args); + return o; +} + + struct object *get_master(void) { extern char *master_file; @@ -143,13 +172,35 @@ struct object *get_master(void) if(!master_program) { - master_name=make_shared_string(master_file); - master_program=compile_file(master_name); - free_string(master_name); - if(!master_program) return 0; + INT32 len; + struct pike_string *s; + + + FILE *f=fopen(master_file,"r"); + fseek(f,0,SEEK_END); + len=ftell(f); + fseek(f,0,SEEK_SET); + s=begin_shared_string(len); + fread(s->str,1,len,f); + fclose(f); + push_string(end_shared_string(s)); + push_text(master_file); + f_cpp(2); + f_compile(1); + + if(sp[-1].type != T_PROGRAM) + { + pop_stack(); + return 0; + } + master_program=sp[-1].u.program; + sp--; } master_object=clone_object(master_program,0); + call_c_initializers(master_object); + call_pike_initializers(master_object,0); + apply_lfun(master_object,LFUN___INIT,0); pop_stack(); apply_lfun(master_object,LFUN_CREATE,0); @@ -181,9 +232,16 @@ void destruct(struct object *o) o->refs++; - if(o->prog->lfuns[LFUN_DESTROY] != -1) + if(o->parent) + { + free_object(o->parent); + o->parent=0; + } + + e=FIND_LFUN(o->prog,LFUN_DESTROY); + if(e != -1) { - safe_apply_low(o, o->prog->lfuns[LFUN_DESTROY], 0); + safe_apply_low(o, e, 0); pop_stack(); } @@ -293,7 +351,7 @@ void destruct_objects_to_destruct(void) void really_free_object(struct object *o) { - if(o->prog && (o->prog->flags & PROG_DESTRUCT_IMMEDIATE)) + if(o->prog && (o->prog->flags & PROGRAM_DESTRUCT_IMMEDIATE)) { o->refs++; destruct(o); @@ -353,8 +411,16 @@ void low_object_index_no_free(struct svalue *to, { struct svalue *s; s=PROG_FROM_INT(p,f)->constants + i->func.offset; - check_destructed(s); - assign_svalue_no_free(to, s); + if(s->type==T_PROGRAM) + { + to->type=T_FUNCTION; + to->subtype=f; + to->u.object=o; + o->refs++; + }else{ + check_destructed(s); + assign_svalue_no_free(to, s); + } break; } @@ -389,10 +455,23 @@ void object_index_no_free2(struct svalue *to, return; /* make gcc happy */ } - if(index->type != T_STRING) + switch(index->type) + { + case T_STRING: + f=find_shared_string_identifier(index->u.string, p); + free_string(index->u.string); + index->type=T_LVALUE; + index->u.integer=f; + break; + + case T_LVALUE: + f=index->u.integer; + break; + + default: error("Lookup on non-string value.\n"); + } - f=find_shared_string_identifier(index->u.string, p); if(f < 0) { to->type=T_INT; @@ -419,7 +498,7 @@ void object_index_no_free(struct svalue *to, } lfun=ARROW_INDEX_P(index) ? LFUN_ARROW : LFUN_INDEX; - if(p->lfuns[lfun] != -1) + if(FIND_LFUN(p, lfun) != -1) { push_svalue(index); apply_lfun(o,lfun,1); @@ -478,10 +557,25 @@ void object_set_index2(struct object *o, return; /* make gcc happy */ } - if(index->type != T_STRING) + switch(index->type) + { + case T_STRING: + f=find_shared_string_identifier(index->u.string, p); + if(f<0) + error("No such variable (%s) in object.\n", index->u.string->str); + free_string(index->u.string); + index->type=T_LVALUE; + index->u.integer=f; + break; + + case T_LVALUE: + f=index->u.integer; + break; + + default: error("Lookup on non-string value.\n"); + } - f=find_shared_string_identifier(index->u.string, p); if(f < 0) { error("No such variable (%s) in object.\n", index->u.string->str); @@ -505,7 +599,7 @@ void object_set_index(struct object *o, lfun=ARROW_INDEX_P(index) ? LFUN_ASSIGN_ARROW : LFUN_ASSIGN_INDEX; - if(p->lfuns[lfun] != -1) + if(FIND_LFUN(p,lfun) != -1) { push_svalue(index); push_svalue(from); @@ -564,13 +658,27 @@ union anything *object_get_item_ptr(struct object *o, } f=ARROW_INDEX_P(index) ? LFUN_ASSIGN_ARROW : LFUN_ASSIGN_INDEX; - if(p->lfuns[f] != -1) + if(FIND_LFUN(p,f) != -1) error("Cannot do incremental operations on overloaded index (yet).\n"); - if(index->type != T_STRING) + switch(index->type) + { + case T_STRING: + f=find_shared_string_identifier(index->u.string, p); + free_string(index->u.string); + index->type=T_LVALUE; + index->u.integer=f; + break; + + case T_LVALUE: + f=index->u.integer; + break; + + default: error("Lookup on non-string value.\n"); + return 0; + } - f=find_shared_string_identifier(index->u.string, p); if(f < 0) { error("No such variable in object.\n"); @@ -733,10 +841,10 @@ struct array *object_indices(struct object *o) if(!p) error("indices() on destructed object.\n"); - if(p->lfuns[LFUN__INDICES]==-1) + if(FIND_LFUN(p,LFUN__INDICES) == -1) { - a=allocate_array_no_init(p->num_identifier_indexes,0); - for(e=0;e<(int)p->num_identifier_indexes;e++) + a=allocate_array_no_init(p->num_identifier_index,0); + for(e=0;e<(int)p->num_identifier_index;e++) { copy_shared_string(ITEM(a)[e].u.string, ID_FROM_INT(p,p->identifier_index[e])->name); @@ -762,10 +870,10 @@ struct array *object_values(struct object *o) if(!p) error("values() on destructed object.\n"); - if(p->lfuns[LFUN__INDICES]==-1) + if(FIND_LFUN(p,LFUN__VALUES)==-1) { - a=allocate_array_no_init(p->num_identifier_indexes,0); - for(e=0;e<(int)p->num_identifier_indexes;e++) + a=allocate_array_no_init(p->num_identifier_index,0); + for(e=0;e<(int)p->num_identifier_index;e++) { low_object_index_no_free(ITEM(a)+e, o, p->identifier_index[e]); } @@ -791,6 +899,9 @@ void gc_mark_object_as_referenced(struct object *o) if(!o || !(p=o->prog)) return; /* Object already destructed */ o->refs++; + if(o->parent) + gc_mark_object_as_referenced(o); + frame.parent_frame=fp; frame.current_object=o; /* refs already updated */ frame.locals=0; @@ -842,6 +953,14 @@ void gc_check_all_objects(void) for(o=first_object;o;o=o->next) { +#ifdef DEBUG + if(o->parent) + if(gc_check(o->parent)==-2) + fprintf(stderr,"(in object at %lx -> parent)\n",(long)o); +#else + if(o->parent) + gc_check(o->parent); +#endif if(o->prog) { INT32 e,d; diff --git a/src/object.h b/src/object.h index 90bf3280e8dd12e4544cab046592d63a104abde2..04aea59f0104e84c8901b0da947cd88fc11cfb71 100644 --- a/src/object.h +++ b/src/object.h @@ -18,6 +18,8 @@ struct object { INT32 refs; /* Reference count, must be first. */ struct program *prog; + struct object *parent; + INT16 parent_identifier; struct object *next; struct object *prev; char storage[1]; @@ -40,6 +42,10 @@ extern struct program *master_program; void setup_fake_object(void); struct object *low_clone(struct program *p); struct object *clone_object(struct program *p, int args); +struct object *parent_clone_object(struct program *p, + struct object *parent, + int parent_identifier, + int args); struct object *get_master(void); struct object *master(void); void destruct(struct object *o); diff --git a/src/opcodes.c b/src/opcodes.c index 6fb18a40e88f0347c0d22ed907b6db3ef90b0c63..28d78548962517d04a1e57db5a394cddc2258d05 100644 --- a/src/opcodes.c +++ b/src/opcodes.c @@ -90,7 +90,7 @@ void cast(struct pike_string *s) push_string(describe_type(s)); if(!sp[-2].u.object->prog) error("Cast called on destructed object.\n"); - if(sp[-2].u.object->prog->lfuns[LFUN_CAST] == -1) + if(FIND_LFUN(sp[-2].u.object->prog,LFUN_CAST) == -1) error("No cast method in object.\n"); apply_lfun(sp[-2].u.object, LFUN_CAST, 1); free_svalue(sp-2); @@ -235,7 +235,7 @@ void f_cast(void) push_string(s); if(!sp[-2].u.object->prog) error("Cast called on destructed object.\n"); - if(sp[-2].u.object->prog->lfuns[LFUN_CAST] == -1) + if(FIND_LFUN(sp[-2].u.object->prog,LFUN_CAST) == -1) error("No cast method in object.\n"); apply_lfun(sp[-2].u.object, LFUN_CAST, 1); free_svalue(sp-2); diff --git a/src/operators.c b/src/operators.c index dbc6eb4b0a19a90ed31873a6657fb87330401c3c..504471bfa0085e6a7f624ec875b6be362d7aafc3 100644 --- a/src/operators.c +++ b/src/operators.c @@ -5,7 +5,7 @@ \*/ #include <math.h> #include "global.h" -RCSID("$Id: operators.c,v 1.21 1997/12/03 22:46:17 hubbe Exp $"); +RCSID("$Id: operators.c,v 1.22 1998/01/13 22:56:47 hubbe Exp $"); #include "interpret.h" #include "svalue.h" #include "multiset.h" @@ -49,7 +49,7 @@ COMPARISON(f_ge,"`>=",!is_lt(sp-2,sp-1)) #define CALL_OPERATOR(OP, args) \ if(!sp[-args].u.object->prog) \ error("Operator %s called in destructed object.\n",lfun_names[OP]); \ - if(sp[-args].u.object->prog->lfuns[OP] == -1) \ + if(FIND_LFUN(sp[-args].u.object->prog,OP) == -1) \ error("No operator %s in object.\n",lfun_names[OP]); \ apply_lfun(sp[-args].u.object, OP, args-1); \ free_svalue(sp-2); \ @@ -76,7 +76,7 @@ void f_add(INT32 args) { if(sp[-args].type == T_OBJECT && sp[-args].u.object->prog && - sp[-args].u.object->prog->lfuns[LFUN_ADD] != -1) + FIND_LFUN(sp[-args].u.object->prog,LFUN_ADD) != -1) { apply_lfun(sp[-args].u.object, LFUN_ADD, args-1); free_svalue(sp-2); @@ -88,7 +88,7 @@ void f_add(INT32 args) { if(sp[e-args].type == T_OBJECT && sp[e-args].u.object->prog && - sp[e-args].u.object->prog->lfuns[LFUN_RADD] != -1) + FIND_LFUN(sp[e-args].u.object->prog,LFUN_RADD) != -1) { struct svalue *tmp=sp+e-args; check_stack(e); @@ -391,7 +391,7 @@ static int call_lfun(int left, int right) { if(sp[-2].type == T_OBJECT && sp[-2].u.object->prog && - sp[-2].u.object->prog->lfuns[left] != -1) + FIND_LFUN(sp[-2].u.object->prog,left) != -1) { apply_lfun(sp[-2].u.object, left, 1); free_svalue(sp-2); @@ -402,7 +402,7 @@ static int call_lfun(int left, int right) if(sp[-1].type == T_OBJECT && sp[-1].u.object->prog && - sp[-1].u.object->prog->lfuns[right] != -1) + FIND_LFUN(sp[-1].u.object->prog,right) != -1) { push_svalue(sp-2); apply_lfun(sp[-2].u.object, right, 1); @@ -1418,6 +1418,21 @@ static int generate_sizeof(node *n) return 1; } +void f_call_function(INT32 args) +{ + mega_apply(APPLY_STACK,args,0,0); +} + +static int generate_call_function(node *n) +{ + node **arg; + emit2(F_MARK); + do_docode(CDR(n),DO_NOT_COPY); + emit2(F_CALL_FUNCTION); + return 1; +} + + void init_operators(void) { add_efun2("`[]",f_index, @@ -1462,4 +1477,9 @@ void init_operators(void) add_efun2("`~",f_compl,"function(object:mixed)|function(int:int)|function(float:float)|function(string:string)",OPT_TRY_OPTIMIZE,0,generate_compl); add_efun2("sizeof", f_sizeof, "function(string|multiset|array|mapping|object:int)",0,0,generate_sizeof); + + add_efun2("`()",f_call_function,"function(mixed,mixed ...:mixed)",OPT_SIDE_EFFECT | OPT_EXTERNAL_DEPEND,0,generate_call_function); + + /* This one should be removed */ + add_efun2("call_function",f_call_function,"function(mixed,mixed ...:mixed)",OPT_SIDE_EFFECT | OPT_EXTERNAL_DEPEND,0,generate_call_function); } diff --git a/src/peep.c b/src/peep.c index 92b620e729845f3cde40e083aea99d790338ef0e..0339a6054714bd67b25b2d2c0b5859a41ca43ee6 100644 --- a/src/peep.c +++ b/src/peep.c @@ -111,7 +111,7 @@ void ins_f_byte(unsigned int b) if(b>255) error("Instruction too big %d\n",b); #endif - ins_byte((unsigned char)b,A_PROGRAM); + add_to_program((unsigned char)b); } static void ins_f_byte_with_arg(unsigned int a,unsigned INT32 b) @@ -127,20 +127,20 @@ static void ins_f_byte_with_arg(unsigned int a,unsigned INT32 b) if( b < 256*256) { ins_f_byte(F_PREFIX_CHARX256); - ins_byte(b>>8, A_PROGRAM); + add_to_program(b>>8); }else if(b < 256*256*256) { ins_f_byte(F_PREFIX_WORDX256); - ins_byte(b >> 16, A_PROGRAM); - ins_byte(b >> 8, A_PROGRAM); + add_to_program(b>>16); + add_to_program(b>>8); }else{ ins_f_byte(F_PREFIX_24BITX256); - ins_byte(b >> 24, A_PROGRAM); - ins_byte(b >> 16, A_PROGRAM); - ins_byte(b >> 8, A_PROGRAM); + add_to_program(b>>24); + add_to_program(b>>16); + add_to_program(b>>8); } } ins_f_byte(a); - ins_byte(b, A_PROGRAM); + add_to_program(b); } void assemble(void) @@ -248,11 +248,11 @@ void assemble(void) { case F_NOP: break; case F_ALIGN: - while(PC % c->arg) ins_byte(0, A_PROGRAM); + while(PC % c->arg) add_to_program(0); break; case F_BYTE: - ins_byte(c->arg, A_PROGRAM); + add_to_program(c->arg); break; case F_LABEL: @@ -276,7 +276,7 @@ void assemble(void) if(c->arg > max_label || c->arg < 0) fatal("Jump to unknown label?\n"); #endif tmp=PC; - ins_int(jumps[c->arg],A_PROGRAM); + ins_int(jumps[c->arg], (void(*)(char))add_to_program); jumps[c->arg]=tmp; break; @@ -352,7 +352,7 @@ int insopt(int f, INT32 b, int cl, struct pike_string *cf) p->opcode=f; p->line=cl; - copy_shared_string(p->file, current_file); + copy_shared_string(p->file, lex.current_file); p->arg=b; return p - (p_instr *)instrbuf.s.str; diff --git a/src/peep.in b/src/peep.in index 95f88f4741222913fad4d88e8a55d22543304a62..93f78ccc7c3690e19d23efe3034120eb2a5eaafb 100644 --- a/src/peep.in +++ b/src/peep.in @@ -150,3 +150,6 @@ NUMBER [$1a < 0] SUBTRACT : ADD_INT (-$1a) LTOSVAL2 ADD ASSIGN_AND_POP : ADD_TO_AND_POP LTOSVAL ADD ASSIGN_AND_POP : ADD_TO_AND_POP + +APPLY RETURN : APPLY_AND_RETURN($1a) +CALL_FUNCTION RETURN : CALL_FUNCTION_AND_RETURN diff --git a/src/pike_types.c b/src/pike_types.c index c474489b4512a45add485efd24b6e1f2c26b3459..005eccad0e5e65d6e1999aae53a882f16f9798bd 100644 --- a/src/pike_types.c +++ b/src/pike_types.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: pike_types.c,v 1.26 1997/09/29 00:57:55 hubbe Exp $"); +RCSID("$Id: pike_types.c,v 1.27 1998/01/13 22:56:48 hubbe Exp $"); #include <ctype.h> #include "svalue.h" #include "pike_types.h" @@ -715,7 +715,7 @@ static char *low_match_types(char *a,char *b, int flags) struct program *p; if((p=id_to_program(EXTRACT_INT(a+1)))) { - int i=p->lfuns[LFUN_CALL]; + int i=FIND_LFUN(p,LFUN_CALL); if(i == -1) return 0; return low_match_types(ID_FROM_INT(p, i)->type->str, b, flags); } @@ -727,7 +727,7 @@ static char *low_match_types(char *a,char *b, int flags) struct program *p; if((p=id_to_program(EXTRACT_INT(b+1)))) { - int i=p->lfuns[LFUN_CALL]; + int i=FIND_LFUN(p,LFUN_CALL); if(i == -1) return 0; return low_match_types(a, ID_FROM_INT(p, i)->type->str, flags); } @@ -927,13 +927,13 @@ static struct pike_string *low_index_type(char *t, node *n) { if(n->token == F_ARROW) { - if(p->lfuns[LFUN_ARROW] != -1 || p->lfuns[LFUN_ASSIGN_ARROW] != -1) + if(FIND_LFUN(p,LFUN_ARROW)!=-1 || FIND_LFUN(p,LFUN_ASSIGN_ARROW)!=-1) { reference_shared_string(mixed_type_string); return mixed_type_string; } }else{ - if(p->lfuns[LFUN_INDEX] != -1 || p->lfuns[LFUN_ASSIGN_INDEX] != -1) + if(FIND_LFUN(p,LFUN_INDEX) != -1 || FIND_LFUN(p,LFUN_ASSIGN_INDEX) != -1) { reference_shared_string(mixed_type_string); return mixed_type_string; @@ -1046,10 +1046,10 @@ static int low_check_indexing(char *type, char *index_type, node *n) { if(n->token == F_ARROW) { - if(p->lfuns[LFUN_ARROW] != -1 || p->lfuns[LFUN_ASSIGN_ARROW] != -1) + if(FIND_LFUN(p,LFUN_ARROW) != -1 || FIND_LFUN(p,LFUN_ASSIGN_ARROW) != -1) return 1; }else{ - if(p->lfuns[LFUN_INDEX] != -1 || p->lfuns[LFUN_ASSIGN_INDEX] != -1) + if(FIND_LFUN(p,LFUN_INDEX) != -1 || FIND_LFUN(p,LFUN_ASSIGN_INDEX) != -1) return 1; } return !!low_match_types(string_type_string->str, index_type,0); @@ -1188,7 +1188,7 @@ struct pike_string *get_type_of_svalue(struct svalue *s) case T_PROGRAM: { char *a; - int id=s->u.program->lfuns[LFUN_CREATE]; + int id=FIND_LFUN(s->u.program,LFUN_CREATE); if(id>=0) { a=ID_FROM_INT(s->u.program, id)->type->str; diff --git a/src/pike_types.h b/src/pike_types.h index 0c407f8c10b288d39b5232c35756a018007ce92e..bf7934a3d1cbde7a36286ac97adbffd86d6402ee 100644 --- a/src/pike_types.h +++ b/src/pike_types.h @@ -6,7 +6,36 @@ #ifndef PIKE_TYPES_H #define PIKE_TYPES_H -#include "las.h" +#include "svalue.h" + +struct node_s +{ + unsigned INT16 token; + INT16 line_number; + INT16 node_info; + INT16 tree_info; + struct pike_string *type; + struct node_s *parent; + union + { + int number; + struct svalue sval; + struct + { + struct node_s *a,*b; + } node; + struct + { + int a,b; + } integer; + } u; +}; + +#ifndef STRUCT_NODE_S_DECLARED +#define STRUCT_NODE_S_DECLARED +#endif + +typedef struct node_s node; extern int max_correct_args; extern struct pike_string *string_type_string; diff --git a/src/program.c b/src/program.c index da209785ff1f849b6237afce33237c2fdf201708..c4d2e1a18bc92e0c24d8d03fd31d5ff40b3b14a0 100644 --- a/src/program.c +++ b/src/program.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: program.c,v 1.47 1998/01/02 01:05:51 hubbe Exp $"); +RCSID("$Id: program.c,v 1.48 1998/01/13 22:56:49 hubbe Exp $"); #include "program.h" #include "object.h" #include "dynamic_buffer.h" @@ -28,25 +28,22 @@ RCSID("$Id: program.c,v 1.47 1998/01/02 01:05:51 hubbe Exp $"); #include <errno.h> #include <fcntl.h> + +#undef ATTRIBUTE +#define ATTRIBUTE(X) + + /* * Define the size of the cache that is used for method lookup. */ #define FIND_FUNCTION_HASHSIZE 4711 -#define FILE_STATE -#define PROGRAM_STATE - #define STRUCT #include "compilation.h" -#undef STRUCT #define DECLARE #include "compilation.h" -#undef DECLARE - -#undef FILE_STATE -#undef PROGRAM_STATE char *lfun_names[] = { @@ -91,17 +88,61 @@ char *lfun_names[] = { }; struct program *first_program = 0; +static int current_program_id=0; -struct program fake_program; +struct program *new_program=0; +struct program *malloc_size_program=0; -static int current_program_id=0; +int compiler_pass; +int compilation_depth; +struct compiler_frame *compiler_frame=0; static INT32 last_line = 0; static INT32 last_pc = 0; static struct pike_string *last_file = 0; -dynamic_buffer inherit_names; dynamic_buffer used_modules; -void free_all_local_names(void); +/* So what if we don't have templates? / Hubbe */ + +#ifdef DEBUG +#define CHECK_FOO(NUMTYPE,TYPE,NAME) \ + if(malloc_size_program-> PIKE_CONCAT(num_,NAME) < new_program-> PIKE_CONCAT(num_,NAME)) \ + fatal("new_program->num_" #NAME " is out of order\n"); \ + if(new_program->flags & PROGRAM_OPTIMIZED) \ + fatal("Tried to reallocate fixed program.\n") + +#else +#define CHECK_FOO(NUMTYPE,TYPE,NAME) +#endif + +#define FOO(NUMTYPE,TYPE,NAME) \ +void PIKE_CONCAT(add_to_,NAME) (TYPE ARG) { \ + CHECK_FOO(NUMTYPE,TYPE,NAME); \ + if(malloc_size_program->PIKE_CONCAT(num_,NAME) == new_program->PIKE_CONCAT(num_,NAME)) { \ + void *tmp; \ + malloc_size_program->PIKE_CONCAT(num_,NAME) *= 2; \ + malloc_size_program->PIKE_CONCAT(num_,NAME)++; \ + tmp=realloc((char *)new_program->NAME, \ + sizeof(TYPE) * \ + malloc_size_program->PIKE_CONCAT(num_,NAME)); \ + if(!tmp) fatal("Out of memory.\n"); \ + new_program->NAME=tmp; \ + } \ + new_program->NAME[new_program->PIKE_CONCAT(num_,NAME)++]=(ARG); \ +} + +#include "program_areas.h" + +void ins_int(INT32 i, void (*func)(char tmp)) +{ + int e; + for(e=0;e<(long)sizeof(i);e++) func(EXTRACT_UCHAR(((char *)&i)+e)); +} + +void ins_short(INT16 i, void (*func)(char tmp)) +{ + int e; + for(e=0;e<(long)sizeof(i);e++) func(EXTRACT_UCHAR(((char *)&i)+e)); +} void use_module(struct svalue *s) { @@ -116,19 +157,18 @@ void use_module(struct svalue *s) } -static int low_find_shared_string_identifier(struct pike_string *name, - struct program *prog); -int find_module_identifier(struct pike_string *ident) +int low_find_shared_string_identifier(struct pike_string *name, + struct program *prog); + + + +struct node_s *find_module_identifier(struct pike_string *ident) { JMP_BUF tmp; + node *ret; -#ifdef DEBUG - if(recoveries && sp-evaluator_stack < recoveries->sp) - fatal("Stack error in compiation (underflow)\n"); -#endif - - if(SETJMP(tmp)) + if(SETJMP(tmp)) { ONERROR tmp; SET_ONERROR(tmp,exit_on_error,"Error in handle_error in master object!"); @@ -152,7 +192,9 @@ int find_module_identifier(struct pike_string *ident) { /* fprintf(stderr,"MOD: %s, %d %d\n",ident->str, current_line, sp[-1].type); */ UNSETJMP(tmp); - return 1; + ret=mksvaluenode(sp-1); + pop_stack(); + return ret; } pop_stack(); } @@ -160,122 +202,240 @@ int find_module_identifier(struct pike_string *ident) UNSETJMP(tmp); { - struct program_state *p; - for(p=previous_program_state;p;p=p->previous) + struct program_state *p=previous_program_state; + int n; + for(n=0;n<compilation_depth;n++,p=p->previous) { - INT32 i; - if(previous_file_state && - previous_file_state->previous_program_state==p->previous) - break; - - i=low_find_shared_string_identifier(ident, &p->fake_program); + int i=low_find_shared_string_identifier(ident, p->new_program); if(i!=-1) { struct identifier *id; - id=ID_FROM_INT(&p->fake_program, i); + id=ID_FROM_INT(p->new_program, i); if(IDENTIFIER_IS_CONSTANT(id->identifier_flags)) { - push_svalue(PROG_FROM_INT(&p->fake_program, i)->constants+ - id->func.offset); - return 1; + ret=mksvaluenode(PROG_FROM_INT(p->new_program, i)->constants+ + id->func.offset); + return ret; }else{ - yyerror("Identifier is not a constant"); - return 0; + return mkexternalnode(n, i, id); } } } } - return 0; } -/* This should be optimized */ +struct program *parent_compilation(int level) +{ + int n; + struct program_state *p=previous_program_state; + for(n=0;n<level;n++) + { + if(n>=compilation_depth) return 0; + p=p->previous; + if(!p) return 0; + } + return p->new_program; +} + +#define ID_TO_PROGRAM_CACHE_SIZE 512 +struct program *id_to_program_cache[ID_TO_PROGRAM_CACHE_SIZE]; + struct program *id_to_program(INT32 id) { struct program *p; + INT32 h; + if(!id) return 0; + h=id & (ID_TO_PROGRAM_CACHE_SIZE-1); + + if((p=id_to_program_cache[h])) + if(p->id==id) return p; + if(id) - for(p=first_program;p;p=p->next) - if(id==p->id) - return p; + { + for(p=first_program;p;p=p->next) + { + if(id==p->id) + { + if(id_to_program_cache[h]) + free_program(id_to_program_cache[h]); + + id_to_program_cache[h]=p; + p->refs++; + return p; + } + } + } return 0; } -#define SETUP(X,Y,TYPE,AREA) \ - fake_program.X=(TYPE *)areas[AREA].s.str; \ - fake_program.Y=areas[AREA].s.len/sizeof(TYPE) +/* Here starts routines which are used to build new programs */ -/* - * This routine sets up the struct fake_program to work almost like a - * normal program, but all pointers points to the program we are currently - * compiling +/* Re-allocate all the memory in the program in one chunk. because: + * 1) The individual blocks are munch bigger than they need to be + * 2) cuts down on malloc overhead (maybe) + * 3) localizes memory access (decreases paging) */ -void setup_fake_program(void) -{ - fake_program.refs=0xffffff; - SETUP(program, program_size, unsigned char, A_PROGRAM); - SETUP(strings, num_strings, struct pike_string *, A_STRINGS); - SETUP(inherits, num_inherits, struct inherit, A_INHERITS); - SETUP(identifiers, num_identifiers, struct identifier, A_IDENTIFIERS); - SETUP(identifier_references, num_identifier_references, struct reference, A_IDENTIFIER_REFERENCES); - SETUP(constants, num_constants, struct svalue, A_CONSTANTS); - SETUP(linenumbers, num_linenumbers, char, A_LINENUMBERS); - - fake_program.inherits[0].prog=&fake_program; - fake_program.next=0; - fake_program.prev=0; - fake_program.flags=0; -/* - fake_program.lfuns=0; - fake_prog.num_lfuns=0; -*/ -#ifdef PROFILING - fake_program.num_clones = 0; -#endif /* PROFILING */ - fake_object.prog=&fake_program; +void optimize_program(struct program *p) +{ + SIZE_T size=0; + char *data; + + /* Already done (shouldn't happen, but who knows?) */ + if(p->flags & PROGRAM_OPTIMIZED) return; + +#define FOO(NUMTYPE,TYPE,NAME) \ + size+=MY_ALIGN(p->PIKE_CONCAT(num_,NAME)*sizeof(p->NAME[0])); +#include "program_areas.h" + + data=malloc(size); + if(!data) return; /* We are out of memory, but we don't care! */ + + size=0; + +#define FOO(NUMTYPE,TYPE,NAME) \ + MEMCPY(data+size,p->NAME,p->PIKE_CONCAT(num_,NAME)*sizeof(p->NAME[0])); \ + free((char *)p->NAME); \ + p->NAME=(TYPE *)(data+size); \ + size+=MY_ALIGN(p->PIKE_CONCAT(num_,NAME)*sizeof(p->NAME[0])); +#include "program_areas.h" + + p->total_size=size + sizeof(struct program); + + p->flags |= PROGRAM_OPTIMIZED; } -/* Here starts routines which are used to build new programs */ +/* internal function to make the index-table */ +static int funcmp(const void *a,const void *b) +{ + return + my_order_strcmp(ID_FROM_INT(new_program, *(unsigned short *)a)->name, + ID_FROM_INT(new_program, *(unsigned short *)b)->name); +} + +void fixate_program(void) +{ + INT32 i,e,t; + if(new_program->flags & PROGRAM_FIXED) return; +#ifdef DEBUG + if(new_program->flags & PROGRAM_OPTIMIZED) + fatal("Cannot fixate optimized program\n"); +#endif + + /* Ok, sort for binsearch */ + for(e=i=0;i<(int)new_program->num_identifier_references;i++) + { + struct reference *funp; + struct identifier *fun; + funp=new_program->identifier_references+i; + if(funp->id_flags & (ID_HIDDEN|ID_STATIC)) continue; + if(funp->id_flags & ID_INHERITED) + { + if(funp->id_flags & ID_PRIVATE) continue; + fun=ID_FROM_PTR(new_program, funp); +/* if(fun->func.offset == -1) continue; * prototype */ + + /* check for multiple definitions */ + for(t=i+1;t>=0 && t<(int)new_program->num_identifier_references;t++) + { + struct reference *funpb; + struct identifier *funb; + + funpb=new_program->identifier_references+t; + if(funpb->id_flags & (ID_HIDDEN|ID_STATIC)) continue; + funb=ID_FROM_PTR(new_program,funpb); + /* if(funb->func.offset == -1) continue; * prototype */ + if(fun->name==funb->name) t=-10; + } + if(t<0) continue; + } + add_to_identifier_index(i); + } + fsort((void *)new_program->identifier_index, + new_program->num_identifier_index, + sizeof(unsigned short),(fsortfun)funcmp); + + + for(i=0;i<NUM_LFUNS;i++) + new_program->lfuns[i]=find_identifier(lfun_names[i],new_program); + + new_program->flags |= PROGRAM_FIXED; +} /* * Start building a new program */ -void start_new_program(void) +void low_start_new_program(struct program *p, + struct pike_string *name, + int flags) { int e; threads_disabled++; - if(local_variables) - setup_fake_program(); -#define PROGRAM_STATE + compilation_depth++; + + if(!p) + { + p=ALLOC_STRUCT(program); + MEMSET(p, 0, sizeof(struct program)); + + p->refs=1; + p->id=++current_program_id; + + if((p->next=first_program)) first_program->prev=p; + first_program=p; + }else{ + p->refs++; + } + + if(name) + { + struct svalue s; + s.type=T_PROGRAM; + s.u.program=p; + add_constant(name, &s, flags); + } + #define PUSH #include "compilation.h" -#undef PUSH -#undef PROGRAM_STATE - - if(previous_program_state->fake_program.num_inherits) - previous_program_state->fake_program.inherits[0].prog= - &previous_program_state->fake_program; init_type_stack(); - for(e=0; e<NUM_AREAS; e++) low_reinit_buf(areas + e); - low_reinit_buf(& inherit_names); low_reinit_buf(& used_modules); - fake_program.id = ++current_program_id; + if(p && (p->flags & PROGRAM_FINISHED)) { - struct inherit inherit; - struct pike_string *name; - - inherit.prog=&fake_program; - inherit.inherit_level=0; - inherit.identifier_level=0; - inherit.storage_offset=0; - add_to_mem_block(A_INHERITS,(char *)&inherit,sizeof inherit); - name=make_shared_string("this"); - low_my_binary_strcat((char *)&name,sizeof(name), &inherit_names); + yyerror("Pass2: Program already done"); + p=0; + } + + malloc_size_program = ALLOC_STRUCT(program); + new_program=p; + + if(new_program->program) + { +#define FOO(NUMTYPE,TYPE,NAME) \ + malloc_size_program->PIKE_CONCAT(num_,NAME)=new_program->PIKE_CONCAT(num_,NAME); +#include "program_areas.h" + }else{ + static struct pike_string *s; + struct inherit i; + +#define START_SIZE 64 +#define FOO(NUMTYPE,TYPE,NAME) \ + malloc_size_program->PIKE_CONCAT(num_,NAME)=START_SIZE; \ + new_program->NAME=(TYPE *)xalloc(sizeof(TYPE) * START_SIZE); +#include "program_areas.h" + + i.prog=new_program; + i.identifier_level=0; + i.storage_offset=0; + i.inherit_level=0; + i.parent=0; + i.parent_identifier=0; + i.name=0; + add_to_inherits(i); } - { struct svalue tmp; @@ -287,18 +447,25 @@ void start_new_program(void) use_module(& tmp); } + init_node=0; num_parse_error=0; - local_variables=ALLOC_STRUCT(locals); - local_variables->next=0; - local_variables->current_number_of_locals=0; - local_variables->max_number_of_locals=0; - local_variables->current_type=0; - local_variables->current_return_type=0; + + push_compiler_frame(); } -static void low_free_program(struct program *p) +void start_new_program(void) +{ + low_start_new_program(0,0,0); +} + + +void really_free_program(struct program *p) { unsigned INT16 e; + + if(id_to_program_cache[p->id & (ID_TO_PROGRAM_CACHE_SIZE-1)]==p) + id_to_program_cache[p->id & (ID_TO_PROGRAM_CACHE_SIZE-1)]=0; + for(e=0; e<p->num_strings; e++) free_string(p->strings[e]); @@ -312,12 +479,11 @@ static void low_free_program(struct program *p) free_svalue(p->constants+e); for(e=1; e<p->num_inherits; e++) + { free_program(p->inherits[e].prog); -} - -void really_free_program(struct program *p) -{ - low_free_program(p); + if(p->inherits[e].parent) + free_object(p->inherits[e].parent); + } if(p->prev) p->prev->next=p->next; @@ -327,13 +493,24 @@ void really_free_program(struct program *p) if(p->next) p->next->prev=p->prev; + if(p->flags & PROGRAM_OPTIMIZED) + { + if(p->program) + free(p->program); +#define FOO(NUMTYPE,TYPE,NAME) p->NAME=0; +#include "program_areas.h" + }else{ +#define FOO(NUMTYPE,TYPE,NAME) \ + if(p->NAME) { free((char *)p->NAME); p->NAME=0; } +#include "program_areas.h" + } + free((char *)p); GC_FREE(); } #ifdef DEBUG - void dump_program_desc(struct program *p) { int e,d,q; @@ -349,93 +526,54 @@ void dump_program_desc(struct program *p) } */ - fprintf(stderr,"All identifiers: (this=%08x)\n",(unsigned int)p); + fprintf(stderr,"All identifiers:\n"); for(e=0;e<(int)p->num_identifier_references;e++) { fprintf(stderr,"%3d:",e); for(d=0;d<INHERIT_FROM_INT(p,e)->inherit_level;d++) fprintf(stderr," "); - fprintf(stderr," (%08x) %s;\t", - (unsigned int)INHERIT_FROM_INT(p,e)->prog, - ID_FROM_INT(p,e)->name->str); - if(p->identifier_references[e].id_flags&ID_HIDDEN) - fprintf(stderr," (hidden)"); - if(p->identifier_references[e].id_flags&ID_INHERITED) - fprintf(stderr," (inherited)"); - fprintf(stderr,"\n"); + fprintf(stderr,"%s;\n",ID_FROM_INT(p,e)->name->str); } fprintf(stderr,"All sorted identifiers:\n"); - for(q=0;q<(int)p->num_identifier_indexes;q++) + for(q=0;q<(int)p->num_identifier_index;q++) { e=p->identifier_index[q]; fprintf(stderr,"%3d (%3d):",e,q); for(d=0;d<INHERIT_FROM_INT(p,e)->inherit_level;d++) fprintf(stderr," "); - fprintf(stderr," (%08x) %s;\t", - (unsigned int)INHERIT_FROM_INT(p,e)->prog, - ID_FROM_INT(p,e)->name->str); - if(p->identifier_references[e].id_flags & ID_HIDDEN) - fprintf(stderr," (hidden)"); - if(p->identifier_references[e].id_flags&ID_INHERITED) - fprintf(stderr," (inherited)"); - fprintf(stderr,"\n"); + fprintf(stderr,"%s;\n", ID_FROM_INT(p,e)->name->str); } } #endif static void toss_compilation_resources(void) { - struct pike_string **names; - struct svalue *modules; - int e; - - for (e=0; e<NUM_AREAS; e++) toss_buffer(areas+e); - - names=(struct pike_string **)inherit_names.s.str; - e=inherit_names.s.len / sizeof(struct pike_string *); - while(--e>=0) if(names[e]) free_string(names[e]); - toss_buffer(& inherit_names); + free_program(new_program); + new_program=0; - modules=(struct svalue *)used_modules.s.str; - e=used_modules.s.len / sizeof(struct svalue); - while(--e>=0) free_svalue(modules+e); - toss_buffer(& used_modules); - - /* Clean up */ - while(local_variables) - { - struct locals *l; - for(e=0;e<local_variables->current_number_of_locals;e++) + if(malloc_size_program) { - free_string(local_variables->variable[e].name); - free_string(local_variables->variable[e].type); + free((char *)malloc_size_program); + malloc_size_program=0; } - if(local_variables->current_type) - free_string(local_variables->current_type); - - if(local_variables->current_return_type) - free_string(local_variables->current_return_type); - - l=local_variables->next; - free((char *)local_variables); - local_variables=l; - } + while(compiler_frame) + pop_compiler_frame(); if(last_file) { free_string(last_file); last_file=0; } -} + + { + struct svalue *modules=(struct svalue *)used_modules.s.str; + INT32 e; -/* - * Something went wrong. - * toss resources of program we were building - */ -void toss_current_program(void) -{ - setup_fake_program(); - low_free_program(&fake_program); - toss_compilation_resources(); + for(e=0;e<(long)(used_modules.s.len / sizeof(struct svalue));e++) + free_svalue(modules+e); + + toss_buffer(&used_modules); + } + } #ifdef DEBUG @@ -465,6 +603,10 @@ void check_program(struct program *p) if(p->storage_needed < 0) fatal("Program->storage_needed < 0.\n"); + if(p->num_identifier_index > p->num_identifier_references) + fatal("Too many identifier index entries in program!\n"); + +#if 0 size=MY_ALIGN(sizeof(struct program)); size+=MY_ALIGN(p->num_linenumbers); size+=MY_ALIGN(p->program_size); @@ -485,8 +627,8 @@ void check_program(struct program *p) if(size < (INT32)p->total_size) fatal("Program size is in error.\n"); - -#define CHECKRANGE(X,Y) if((char *)(p->X) < (char *)p || (char *)(p->X)> ((char *)p)+size) fatal("Program->%s is wrong.\n",Y) +#define CHECKRANGE(X,Y) \ +if((char *)(p->X) < (char *)p || (char *)(p->X)> ((char *)p)+size) fatal("Program->%s is wrong.\n",Y) CHECKRANGE(program,"program"); CHECKRANGE(strings,"strings"); @@ -509,11 +651,10 @@ void check_program(struct program *p) if(p->checksum != checksum) fatal("Someone changed a program!!!\n"); } +#endif for(e=0;e<(int)p->num_constants;e++) - { check_svalue(p->constants + e); - } for(e=0;e<(int)p->num_strings;e++) check_string(p->strings[e]); @@ -534,14 +675,13 @@ void check_program(struct program *p) { if(p->identifier_references[e].inherit_offset > p->num_inherits) fatal("Inherit offset is wrong!\n"); - + if(p->identifier_references[e].identifier_offset > p->inherits[p->identifier_references[e].inherit_offset].prog->num_identifiers) fatal("Identifier offset is wrong!\n"); } - - for(e=0;e<(int)p->num_identifier_indexes;e++) + for(e=0;e<(int)p->num_identifier_index;e++) { if(p->identifier_index[e] > p->num_identifier_references) fatal("Program->identifier_indexes[%ld] is wrong\n",(long)e); @@ -549,189 +689,44 @@ void check_program(struct program *p) for(e=0;e<(int)p->num_inherits;e++) { - struct program *tmp_prog=p->inherits[e].prog; - INT32 d; - if(p->inherits[e].storage_offset < 0) fatal("Inherit->storage_offset is wrong.\n"); - - for(d=0;d<(int)tmp_prog->num_identifiers;d++) - { - struct identifier *id=tmp_prog->identifiers+d; - - if(IDENTIFIER_IS_VARIABLE(id->identifier_flags)) - { - INT32 offset,size,e2; - offset=p->inherits[e].storage_offset + id->func.offset; - size=id->run_time_type == T_MIXED ? sizeof(struct svalue) : sizeof(union anything); - - if(offset < 0 || offset+size > p->storage_needed) - fatal("Variable located outside allocated space.\n"); - - - for(e2=0;e2<(int)p->num_inherits;e2++) - { - struct program *tmp_prog2=p->inherits[e2].prog; - INT32 d2; - - for(d2=0;d2<(int)tmp_prog2->num_identifiers;d2++) - { - struct identifier *id2=tmp_prog2->identifiers+d2; - - if(e==e2 && d==d2) continue; - - if(IDENTIFIER_IS_VARIABLE(id2->identifier_flags)) - { - INT32 offset2,size2; - - offset2=p->inherits[e2].storage_offset + id2->func.offset; - size2=id2->run_time_type == T_MIXED ? sizeof(struct svalue) : sizeof(union anything); - if( (offset > offset2) ? - (offset2+size2 > offset) : - (offset+size > offset2)) - { - fatal("Variable %s (%ld+%ld) and %s (%ld+%ld) overlap.\n", - id->name->str, (long)offset, (long)size, - id2->name->str, (long)offset2, (long)size2); - } - } - } - } - } - } } } #endif -/* internal function to make the index-table */ -static int funcmp(const void *a,const void *b) +struct program *end_first_pass(int finish) { - return - my_order_strcmp(ID_FROM_INT(&fake_program, *(unsigned short *)a)->name, - ID_FROM_INT(&fake_program, *(unsigned short *)b)->name); -} - -/* - * Finish this program, returning the newly built program - */ - -#define INS_BLOCK(PTR,PTRS,TYPE,AREA) \ -prog->PTR=(TYPE *)p; \ -if((prog->PTRS = areas[AREA].s.len/sizeof(TYPE))) \ -{ \ - MEMCPY(p,areas[AREA].s.str, areas[AREA].s.len); \ - p+=MY_ALIGN(areas[AREA].s.len); \ -} - -struct program *end_program(void) -{ - struct pike_string **names; - int size, i,e,t; - char *p; struct program *prog; /* * Define the __INIT function, but only if there was any code * to initialize. */ - if (init_node) + if(init_node) { union idptr tmp; struct pike_string *s; - push_locals(); s=make_shared_string("__INIT"); dooptcode(s, mknode(F_ARG_LIST, init_node,mknode(F_RETURN,mkintnode(0),0)), function_type_string, 0); - pop_locals(); free_string(s); init_node=0; } + pop_compiler_frame(); /* Pop __INIT local variables */ + exit_type_stack(); - if (num_parse_error > 0) + if(num_parse_error > 0) { - toss_current_program(); prog=0; }else{ - setup_fake_program(); - size = MY_ALIGN(sizeof (struct program)); - for (i=0; i<NUM_AREAS; i++) size += MY_ALIGN(areas[i].s.len); - size+=MY_ALIGN(fake_program.num_identifier_references * sizeof(unsigned short)); - - p = (char *)xalloc(size); - prog = (struct program *)p; - *prog = fake_program; - prog->total_size = size; - prog->refs = 1; - prog->flags=0; - p += MY_ALIGN(sizeof (struct program)); - - INS_BLOCK(program,program_size,unsigned char,A_PROGRAM); - INS_BLOCK(linenumbers,num_linenumbers,char,A_LINENUMBERS); - INS_BLOCK(identifiers,num_identifiers,struct identifier,A_IDENTIFIERS); - INS_BLOCK(identifier_references,num_identifier_references,struct reference,A_IDENTIFIER_REFERENCES); - INS_BLOCK(strings,num_strings,struct pike_string *,A_STRINGS); - INS_BLOCK(inherits,num_inherits,struct inherit,A_INHERITS); - INS_BLOCK(constants,num_constants,struct svalue,A_CONSTANTS); - -#ifdef PROFILING - /* There is probably a better place for this, but... */ - for (i=0; i < prog->num_identifiers; i++) { - prog->identifiers[i].num_calls = 0; - } -#endif /* PROFILING */ - - /* Ok, sort for binsearch */ - prog->identifier_index=(unsigned short *)p; - for(e=i=0;i<(int)prog->num_identifier_references;i++) - { - struct reference *funp; - struct identifier *fun; - funp=prog->identifier_references+i; - if(funp->id_flags & (ID_HIDDEN|ID_STATIC)) continue; - - if(funp->id_flags & ID_INHERITED) - { - fun=ID_FROM_PTR(prog, funp); - /* if(fun->func.offset == -1) continue; prototype */ - - /* check for multiple definitions */ - for(t=i+1;t>=0 && t<(int)prog->num_identifier_references;t++) - { - struct reference *funpb; - struct identifier *funb; - - funpb=prog->identifier_references+t; - if(funpb->id_flags & (ID_HIDDEN|ID_STATIC)) continue; - funb=ID_FROM_PTR(prog,funpb); - if(funb->func.offset == -1) continue; /* prototype */ - if(fun->name==funb->name) t=-10; - } - if(t<0) continue; - } - - prog->identifier_index[e]=i; - e++; - } - prog->num_identifier_indexes=e; - fsort((void *)prog->identifier_index, e,sizeof(unsigned short),(fsortfun)funcmp); - - p+=MY_ALIGN(prog->num_identifier_indexes*sizeof(unsigned short)); - - toss_compilation_resources(); - - prog->inherits[0].prog=prog; - prog->prev=0; - if((prog->next=first_program)) - first_program->prev=prog; - first_program=prog; - - for(i=0;i<NUM_LFUNS;i++) - prog->lfuns[i]=find_identifier(lfun_names[i],prog); + prog=new_program; + prog->refs++; #ifdef DEBUG check_program(prog); @@ -739,21 +734,37 @@ struct program *end_program(void) dump_program_desc(prog); #endif + new_program->flags |= PROGRAM_PASS_1_DONE; + + if(finish) + { + fixate_program(); + optimize_program(new_program); + new_program->flags |= PROGRAM_FINISHED; + } + GC_ALLOC(); } + toss_compilation_resources(); -#define PROGRAM_STATE #define POP #include "compilation.h" -#undef POP -#undef PROGRAM_STATE - if(fake_program.num_inherits) - fake_program.inherits[0].prog=&fake_program; + + compilation_depth--; threads_disabled--; free_all_nodes(); return prog; } +/* + * Finish this program, returning the newly built program + */ +struct program *end_program(void) +{ + return end_first_pass(1); +} + + /* * Allocate needed for this program in the object structure. * An offset to the data is returned. @@ -761,9 +772,9 @@ struct program *end_program(void) SIZE_T add_storage(SIZE_T size) { SIZE_T offset; - offset=fake_program.storage_needed; + offset=new_program->storage_needed; size=MY_ALIGN(size); - fake_program.storage_needed += size; + new_program->storage_needed += size; return offset; } @@ -773,7 +784,7 @@ SIZE_T add_storage(SIZE_T size) */ void set_init_callback(void (*init)(struct object *)) { - fake_program.init=init; + new_program->init=init; } /* @@ -782,7 +793,7 @@ void set_init_callback(void (*init)(struct object *)) */ void set_exit_callback(void (*exit)(struct object *)) { - fake_program.exit=exit; + new_program->exit=exit; } /* @@ -791,48 +802,42 @@ void set_exit_callback(void (*exit)(struct object *)) */ void set_gc_mark_callback(void (*m)(struct object *)) { - fake_program.gc_marked=m; + new_program->gc_marked=m; } - -int low_reference_inherited_identifier(int e,struct pike_string *name) +int low_reference_inherited_identifier(int e, + struct pike_string *name) { struct reference funp; struct program *p; int i,d; - p=fake_program.inherits[e].prog; + p=new_program->inherits[e].prog; i=find_shared_string_identifier(name,p); if(i==-1) return i; if(p->identifier_references[i].id_flags & ID_HIDDEN) return -1; - if(ID_FROM_INT(p,i)->func.offset == -1) /* prototype */ - return -1; - funp=p->identifier_references[i]; funp.inherit_offset+=e; funp.id_flags|=ID_HIDDEN; - for(d=0;d<(int)fake_program.num_identifier_references;d++) + for(d=0;d<(int)new_program->num_identifier_references;d++) { struct reference *fp; - fp=fake_program.identifier_references+d; + fp=new_program->identifier_references+d; if(!MEMCMP((char *)fp,(char *)&funp,sizeof funp)) return d; } - add_to_mem_block(A_IDENTIFIER_REFERENCES,(char *)&funp,sizeof funp); - return fake_program.num_identifier_references; + add_to_identifier_references(funp); + return new_program->num_identifier_references -1; } - - int reference_inherited_identifier(struct pike_string *super_name, struct pike_string *function_name) { - struct pike_string **names; int e,i; #ifdef DEBUG @@ -840,24 +845,14 @@ int reference_inherited_identifier(struct pike_string *super_name, fatal("reference_inherited_function on nonshared string.\n"); #endif - names=(struct pike_string **)inherit_names.s.str; - setup_fake_program(); - - for(e=fake_program.num_inherits-1;e>0;e--) + for(e=new_program->num_inherits-1;e>0;e--) { - if(fake_program.inherits[e].inherit_level!=1) continue; - if(!names[e]) continue; + if(new_program->inherits[e].inherit_level!=1) continue; + if(!new_program->inherits[e].name) continue; if(super_name) - { - int l; - l=names[e]->len; - if(l<super_name->len) continue; - if(strncmp(super_name->str, - names[e]->str+l-super_name->len, - super_name->len)) + if(super_name != new_program->inherits[e].name) continue; - } i=low_reference_inherited_identifier(e,function_name); if(i==-1) continue; @@ -868,45 +863,78 @@ int reference_inherited_identifier(struct pike_string *super_name, void rename_last_inherit(struct pike_string *n) { - struct pike_string **names; - int e; - names=(struct pike_string **)inherit_names.s.str; - e=inherit_names.s.len / sizeof(struct pike_string *); - free_string(names[e-1]); - copy_shared_string(names[e-1],n); + if(new_program->inherits[new_program->num_inherits].name) + free_string(new_program->inherits[new_program->num_inherits].name); + copy_shared_string(new_program->inherits[new_program->num_inherits].name, + n); } /* * make this program inherit another program */ -void do_inherit(struct program *p,INT32 flags, struct pike_string *name) +void do_inherit(struct svalue *prog, + INT32 flags, + struct pike_string *name) { int e, inherit_offset, storage_offset; struct inherit inherit; struct pike_string *s; - setup_fake_program(); + struct program *p=program_from_svalue(prog); - inherit_offset = fake_program.num_inherits; + + if(!p) + { + yyerror("Illegal program pointer."); + return; + } - storage_offset=fake_program.storage_needed; + inherit_offset = new_program->num_inherits; + + storage_offset=new_program->storage_needed; add_storage(p->storage_needed); for(e=0; e<(int)p->num_inherits; e++) { inherit=p->inherits[e]; inherit.prog->refs++; - inherit.identifier_level += fake_program.num_identifier_references; + inherit.identifier_level += new_program->num_identifier_references; inherit.storage_offset += storage_offset; inherit.inherit_level ++; - add_to_mem_block(A_INHERITS,(char *)&inherit,sizeof inherit); - - low_my_binary_strcat((char *)&name,sizeof(name),&inherit_names); + if(!e) + { + if(prog->type == T_FUNCTION) + { + inherit.parent=prog->u.object; + inherit.parent_identifier=prog->subtype; + } + } + if(inherit.parent) inherit.parent->refs++; + if(name) { - reference_shared_string(name); - name=0; + if(e==0) + { + inherit.name=name; + reference_shared_string(name); + } + else if(inherit.name) + { + struct pike_string *s; + s=begin_shared_string(inherit.name->len + name->len + 2); + MEMCPY(s->str,name->str,name->len); + MEMCPY(s->str+name->len,"::",2); + MEMCPY(s->str+name->len+2,inherit.name->str,inherit.name->len); + inherit.name=end_shared_string(s); + } + else + { + inherit.name=0; + } + }else{ + inherit.name=0; } + add_to_inherits(inherit); } for (e=0; e < (int)p->num_identifier_references; e++) @@ -923,7 +951,7 @@ void do_inherit(struct program *p,INT32 flags, struct pike_string *name) { int n; n = isidentifier(name); - if (n != -1 && ID_FROM_INT(&fake_program,n)->func.offset != -1) + if (n != -1 && ID_FROM_INT(new_program,n)->func.offset != -1) my_yyerror("Illegal to redefine 'nomask' function/variable \"%s\"",name->str); } @@ -935,7 +963,7 @@ void do_inherit(struct program *p,INT32 flags, struct pike_string *name) fun.id_flags |= flags; fun.id_flags |= ID_INHERITED; - add_to_mem_block(A_IDENTIFIER_REFERENCES, (char *)&fun, sizeof fun); + add_to_identifier_references(fun); } /* Ska det h{r vara s} h{r? */ @@ -953,12 +981,13 @@ void do_inherit(struct program *p,INT32 flags, struct pike_string *name) } } -void simple_do_inherit(struct pike_string *s, INT32 flags,struct pike_string *name) +void simple_do_inherit(struct pike_string *s, + INT32 flags, + struct pike_string *name) { reference_shared_string(s); push_string(s); - reference_shared_string(current_file); - push_string(current_file); + ref_push_string(lex.current_file); SAFE_APPLY_MASTER("handle_inherit", 2); if(sp[-1].type != T_PROGRAM) @@ -973,7 +1002,7 @@ void simple_do_inherit(struct pike_string *s, INT32 flags,struct pike_string *na free_string(s); s=name; } - do_inherit(sp[-1].u.program, flags, s); + do_inherit(sp-1, flags, s); free_string(s); pop_stack(); } @@ -984,17 +1013,17 @@ void simple_do_inherit(struct pike_string *s, INT32 flags,struct pike_string *na int isidentifier(struct pike_string *s) { INT32 e; - setup_fake_program(); - for(e=(int)fake_program.num_identifier_references-1;e>=0;e--) + for(e=new_program->num_identifier_references-1;e>=0;e--) { - if(fake_program.identifier_references[e].id_flags & ID_HIDDEN) continue; + if(new_program->identifier_references[e].id_flags & ID_HIDDEN) continue; - if(ID_FROM_INT(& fake_program, e)->name == s) + if(ID_FROM_INT(new_program, e)->name == s) return e; } return -1; } +/* argument must be a shared string */ int low_define_variable(struct pike_string *name, struct pike_string *type, INT32 flags, @@ -1002,33 +1031,37 @@ int low_define_variable(struct pike_string *name, INT32 run_time_type) { int n; + struct identifier dummy; struct reference ref; - + +#ifdef DEBUG + if(new_program->flags & (PROGRAM_FIXED | PROGRAM_OPTIMIZED)) + fatal("Attempting to add variable to fixed program\n"); +#endif + copy_shared_string(dummy.name, name); copy_shared_string(dummy.type, type); dummy.identifier_flags = 0; dummy.run_time_type=run_time_type; dummy.func.offset=offset; - #ifdef PROFILING - dummy.num_calls = 0; -#endif /* PROFILING */ + dummy.num_calls=0; +#endif ref.id_flags=flags; - ref.identifier_offset=areas[A_IDENTIFIERS].s.len / sizeof dummy; + ref.identifier_offset=new_program->num_identifiers; ref.inherit_offset=0; - - add_to_mem_block(A_IDENTIFIERS, (char *)&dummy, sizeof dummy); - fake_program.num_identifiers ++; - - n=areas[A_IDENTIFIER_REFERENCES].s.len / sizeof ref; - add_to_mem_block(A_IDENTIFIER_REFERENCES, (char *)&ref, sizeof ref); - fake_program.num_identifier_references ++; - + + add_to_identifiers(dummy); + + n=new_program->num_identifier_references; + add_to_identifier_references(ref); + return n; } + int map_variable(char *name, char *type, INT32 flags, @@ -1061,34 +1094,53 @@ int define_variable(struct pike_string *name, if(type == void_type_string) yyerror("Variables can't be of type void"); - setup_fake_program(); n = isidentifier(name); + if(new_program->flags & PROGRAM_PASS_1_DONE) + { + if(n==-1) + yyerror("Pass2: Variable disappeared!"); + else + return n; + } + +#ifdef DEBUG + if(new_program->flags & (PROGRAM_FIXED | PROGRAM_OPTIMIZED)) + fatal("Attempting to add variable to fixed program\n"); +#endif + if(n != -1) { - setup_fake_program(); if (IDENTIFIERP(n)->id_flags & ID_NOMASK) my_yyerror("Illegal to redefine 'nomask' variable/functions \"%s\"", name->str); - if(PROG_FROM_INT(& fake_program, n) == &fake_program) + if(PROG_FROM_INT(new_program, n) == new_program) my_yyerror("Variable '%s' defined twice.",name->str); - if(ID_FROM_INT(& fake_program, n)->type != type) + if(ID_FROM_INT(new_program, n)->type != type) my_yyerror("Illegal to redefine inherited variable with different type."); - if(ID_FROM_INT(& fake_program, n)->identifier_flags != flags) + if(ID_FROM_INT(new_program, n)->identifier_flags != flags) my_yyerror("Illegal to redefine inherited variable with different type."); } else { int run_time_type=compile_type_to_runtime_type(type); - if(run_time_type == T_FUNCTION) run_time_type = T_MIXED; - - n=low_define_variable(name, type, flags, + + switch(run_time_type) + { + case T_FUNCTION: + case T_PROGRAM: + run_time_type = T_MIXED; + } + + n=low_define_variable(name,type,flags, add_storage(run_time_type == T_MIXED ? sizeof(struct svalue) : sizeof(union anything)), run_time_type); + + } return n; @@ -1109,7 +1161,7 @@ int simple_add_variable(char *name, return ret; } - +/* FIXME: add_constant with c==0 means declaration */ int add_constant(struct pike_string *name, struct svalue *c, INT32 flags) @@ -1123,9 +1175,37 @@ int add_constant(struct pike_string *name, fatal("define_constant on nonshared string.\n"); #endif - setup_fake_program(); n = isidentifier(name); + + if(new_program->flags & PROGRAM_PASS_1_DONE) + { + if(n==-1) + { + yyerror("Pass2: Constant disappeared!"); + }else{ +#if 1 + struct identifier *id; + id=ID_FROM_INT(new_program,n); + if(id->func.offset>=0) + { + struct pike_string *s; + struct svalue *c=PROG_FROM_INT(new_program,n)->constants+ + id->func.offset; + s=get_type_of_svalue(c); + free_string(id->type); + id->type=s; + } +#endif + return n; + } + } + +#ifdef DEBUG + if(new_program->flags & (PROGRAM_FIXED | PROGRAM_OPTIMIZED)) + fatal("Attempting to add constant to fixed program\n"); +#endif + copy_shared_string(dummy.name, name); dummy.type = get_type_of_svalue(c); @@ -1134,31 +1214,28 @@ int add_constant(struct pike_string *name, dummy.func.offset=store_constant(c, 0); -#ifdef PROFILING - /* Not strictly necessary, but... */ - dummy.num_calls = 0; -#endif /* PROFILING */ - ref.id_flags=flags; - ref.identifier_offset=fake_program.num_identifiers; + ref.identifier_offset=new_program->num_identifiers; ref.inherit_offset=0; - add_to_mem_block(A_IDENTIFIERS, (char *)&dummy, sizeof dummy); - fake_program.num_identifiers ++; +#ifdef PROFILEING + dummy.num_calls=0; +#endif + + add_to_identifiers(dummy); if(n != -1) { - if (IDENTIFIERP(n)->id_flags & ID_NOMASK) + if(IDENTIFIERP(n)->id_flags & ID_NOMASK) my_yyerror("Illegal to redefine 'nomask' identifier \"%s\"", name->str); - if(PROG_FROM_INT(& fake_program, n) == &fake_program) + if(PROG_FROM_INT(new_program, n) == new_program) my_yyerror("Identifier '%s' defined twice.",name->str); - fake_program.identifier_references[n]=ref; + new_program->identifier_references[n]=ref; } else { - n=areas[A_IDENTIFIER_REFERENCES].s.len / sizeof ref; - add_to_mem_block(A_IDENTIFIER_REFERENCES, (char *)&ref, sizeof ref); - fake_program.num_identifier_references ++; + n=new_program->num_identifier_references; + add_to_identifier_references(ref); } return n; @@ -1270,14 +1347,13 @@ INT32 define_function(struct pike_string *name, i=isidentifier(name); - setup_fake_program(); if(i >= 0) { /* already defined */ - funp=ID_FROM_INT(&fake_program, i); - ref=fake_program.identifier_references[i]; + funp=ID_FROM_INT(new_program, i); + ref=new_program->identifier_references[i]; if(ref.inherit_offset == 0) /* not inherited */ { @@ -1294,11 +1370,7 @@ INT32 define_function(struct pike_string *name, } } - /* it's just another prototype, don't define anything */ - if(!func || func->offset == -1) return i; - - if((ref.id_flags & ID_NOMASK) && - !(funp->func.offset == -1)) + if((ref.id_flags & ID_NOMASK) && !(funp->func.offset == -1)) { my_yyerror("Illegal to redefine 'nomask' function %s.",name->str); } @@ -1326,17 +1398,13 @@ INT32 define_function(struct pike_string *name, else fun.func.offset = -1; -#ifdef PROFILING - fun.num_calls = 0; -#endif /* PROFILING */ - - ref.identifier_offset=fake_program.num_identifiers; - add_to_mem_block(A_IDENTIFIERS, (char *)&fun, sizeof(fun)); + ref.identifier_offset=new_program->num_identifiers; + add_to_identifiers(fun); } ref.inherit_offset = 0; ref.id_flags = flags; - fake_program.identifier_references[i]=ref; + new_program->identifier_references[i]=ref; }else{ /* define it */ @@ -1352,16 +1420,19 @@ INT32 define_function(struct pike_string *name, else fun.func.offset = -1; - i=fake_program.num_identifiers; - add_to_mem_block(A_IDENTIFIERS, (char *)&fun, sizeof(fun)); + i=new_program->num_identifiers; +#ifdef PROFILING + fun.num_calls = 0; +#endif /* PROFILING */ + + add_to_identifiers(fun); ref.id_flags = flags; ref.identifier_offset = i; ref.inherit_offset = 0; - i=fake_program.num_identifier_references; - add_to_mem_block(A_IDENTIFIER_REFERENCES, (char *)&ref, sizeof ref); - + i=new_program->num_identifier_references; + add_to_identifier_references(ref); } return i; } @@ -1371,18 +1442,23 @@ INT32 define_function(struct pike_string *name, * lookup the number of a function in a program given the name in * a shared_string */ -static int low_find_shared_string_identifier(struct pike_string *name, - struct program *prog) +int low_find_shared_string_identifier(struct pike_string *name, + struct program *prog) { int max,min,tst; struct reference *funp; struct identifier *fun; - unsigned short *funindex; - funindex = prog->identifier_index; - if(funindex) + if(prog->flags & PROGRAM_FIXED) { - max = prog->num_identifier_indexes; + unsigned short *funindex = prog->identifier_index; + +#ifdef DEBUG + if(!funindex) + fatal("No funindex in fixed program\n"); +#endif + + max = prog->num_identifier_index; min = 0; while(max != min) { @@ -1401,7 +1477,7 @@ static int low_find_shared_string_identifier(struct pike_string *name, funp = prog->identifier_references + i; if(funp->id_flags & ID_HIDDEN) continue; fun = ID_FROM_PTR(prog, funp); - if(fun->func.offset == -1) continue; /* Prototype */ + /* if(fun->func.offset == -1) continue; * Prototype */ if(!is_same_string(fun->name,name)) continue; if(funp->id_flags & ID_INHERITED) { @@ -1448,7 +1524,7 @@ int find_shared_string_identifier(struct pike_string *name, struct program *prog) { #ifdef FIND_FUNCTION_HASHSIZE - if(prog!=&fake_program) + if(prog -> flags & PROGRAM_FIXED) { unsigned int hashval; hashval=my_hash_string(name); @@ -1483,31 +1559,30 @@ int find_identifier(char *name,struct program *prog) int store_prog_string(struct pike_string *str) { unsigned int i; - struct pike_string **p; - - p = (struct pike_string **)areas[A_STRINGS].s.str; - for (i=0;i<areas[A_STRINGS].s.len / sizeof str;i++) - if (p[i] == str) + for (i=0;i<new_program->num_strings;i++) + if (new_program->strings[i] == str) return i; reference_shared_string(str); - add_to_mem_block(A_STRINGS, (char *)&str, sizeof str); + add_to_strings(str); return i; } int store_constant(struct svalue *foo, int equal) { - struct svalue *s,tmp; + struct svalue tmp; unsigned int e; - s=(struct svalue *)areas[A_CONSTANTS].s.str; - for(e=0;e<areas[A_CONSTANTS].s.len / sizeof(struct svalue);e++) - if(equal ? is_equal(s+e,foo) : is_eq(s+e,foo)) + for(e=0;e<new_program->num_constants;e++) + { + struct svalue *s=new_program->constants + e; + if(equal ? is_equal(s,foo) : is_eq(s,foo)) return e; + } assign_svalue_no_free(&tmp,foo); - add_to_mem_block(A_CONSTANTS,(char *)&tmp,sizeof(struct svalue)); + add_to_constants(tmp); return e; } @@ -1536,21 +1611,25 @@ static int get_small_number(char **q) void start_line_numbering(void) { - if(last_file) { free_string(last_file); last_file=0; } + if(last_file) + { + free_string(last_file); + last_file=0; + } last_pc=last_line=0; } -static void insert_small_number(int a,int area) +static void insert_small_number(INT32 a) { if(a>-127 && a<127) { - ins_byte(a,area); + add_to_linenumbers(a); }else if(a>=-32768 && a<32768){ - ins_signed_byte(-127,area); - ins_short(a,area); + add_to_linenumbers(a); + ins_short(a, add_to_linenumbers); }else{ - ins_signed_byte(-128,area); - ins_int(a,area); + add_to_linenumbers(-128); + ins_int(a, add_to_linenumbers); } } @@ -1562,13 +1641,14 @@ void store_linenumber(INT32 current_line, struct pike_string *current_file) { char *tmp; if(last_file) free_string(last_file); - ins_byte(127,A_LINENUMBERS); - for(tmp=current_file->str; *tmp; tmp++) ins_byte(*tmp,A_LINENUMBERS); - ins_byte(0,A_LINENUMBERS); + add_to_linenumbers(127); + for(tmp=current_file->str; *tmp; tmp++) + add_to_linenumbers(*tmp); + add_to_linenumbers(0); copy_shared_string(last_file, current_file); } - insert_small_number(PC-last_pc,A_LINENUMBERS); - insert_small_number(current_line-last_line,A_LINENUMBERS); + insert_small_number(PC-last_pc); + insert_small_number(current_line-last_line); last_line=current_line; last_pc=PC; } @@ -1589,20 +1669,18 @@ char *get_line(unsigned char *pc,struct program *prog,INT32 *linep) if (prog == 0) return "Unkown program"; offset = pc - prog->program; - if(prog == & fake_program) + if(prog == new_program) { linep[0]=0; return "Optimizer"; } -#ifdef DEBUG - if (offset > (INT32)prog->program_size || offset<0) - fatal("Illegal offset %ld in program.\n", (long)offset); -#endif - cnt=prog->linenumbers; off=line=0; file="Line not found"; + if (offset > (INT32)prog->num_program || offset<0) + return file; + while(cnt < prog->linenumbers + prog->num_linenumbers) { if(*cnt == 127) @@ -1618,10 +1696,10 @@ char *get_line(unsigned char *pc,struct program *prog,INT32 *linep) return file; } -void my_yyerror(char *fmt,...) +void my_yyerror(char *fmt,...) ATTRIBUTE((format(printf,1,2))) { va_list args; - char buf[1000]; + char buf[8192]; va_start(args,fmt); VSPRINTF(buf,fmt,args); @@ -1632,85 +1710,45 @@ void my_yyerror(char *fmt,...) va_end(args); } -/* - * Compile an PIKE file. Input is supposed to be initalized already. - */ -void compile(void) -{ - int yyparse(void); - - start_line_numbering(); - - num_parse_error = 0; - init_node=0; - - yyparse(); /* Parse da program */ -#ifdef DEBUG - if(recoveries && sp-evaluator_stack < recoveries->sp) - fatal("Stack error in compilation (underflow after yyparse)\n"); -#endif - free_all_local_names(); -} - -struct program *compile_file(struct pike_string *file_name) +struct program *compile(struct pike_string *prog) { - int fd; struct program *p; + struct lex save_lex; + int save_depth=compilation_depth; + void yyparse(void); - while(1) - { - fd=open(file_name->str,O_RDONLY); - if(fd >= 0) break; - if(errno != EINTR) - { -#ifdef HAVE_STRERROR - error("Couldn't open file '%s'. (%s)\n",file_name->str,strerror(errno)); -#else - error("Couldn't open file '%s'. (ERRNO=%d)\n",file_name->str,errno); -#endif - } - } + save_lex=lex; -#define FILE_STATE -#define PUSH -#include "compilation.h" -#undef PUSH + lex.end=prog->str+prog->len; + lex.current_line=1; + lex.current_file=make_shared_string("-"); + lex.pragmas=0; - start_new_file(fd,file_name); start_new_program(); - compile(); - p=end_program(); - end_new_file(); + compilation_depth=0; -#define POP -#include "compilation.h" -#undef POP -#undef FILE_STATE + start_line_numbering(); - if(!p) error("Failed to compile %s.\n",file_name->str); - return p; -} + compiler_pass=1; + lex.pos=prog->str; + yyparse(); /* Parse da program */ -struct program *compile_string(struct pike_string *prog, - struct pike_string *name) -{ - struct program *p; + p=end_first_pass(0); + + if(p && !num_parse_error) + { + low_start_new_program(p,0,0); + compiler_pass=2; + lex.pos=prog->str; + yyparse(); /* Parse da program again */ + p=end_program(); + } -#define FILE_STATE -#define PUSH -#include "compilation.h" -#undef PUSH - start_new_string(prog->str,prog->len,name); - start_new_program(); - compile(); - p=end_program(); - end_new_file(); + free_string(lex.current_file); + lex=save_lex; -#define POP -#include "compilation.h" -#undef POP -#undef FILE_STATE + compilation_depth=save_depth; if(!p) error("Compilation failed.\n"); return p; @@ -1786,10 +1824,25 @@ void cleanup_program(void) #endif } +#ifdef GC2 + void gc_mark_program_as_referenced(struct program *p) { if(gc_mark(p)) + { + int e; gc_mark_svalues(p->constants, p->num_constants); + + for(e=0;e<p->num_inherits;e++) + { + if(p->inherits[e].parent) + gc_mark_object_as_referenced(p->inherits[e].parent); + + if(e) + gc_mark_program_as_referenced(p->inherits[e].prog); + } + + } } void gc_check_all_programs(void) @@ -1797,9 +1850,30 @@ void gc_check_all_programs(void) struct program *p; for(p=first_program;p;p=p->next) { - debug_gc_check_svalues(p->constants, p->num_constants, T_PROGRAM, p); + int e; + gc_check_svalues(p->constants, p->num_constants); + for(e=0;e<p->num_inherits;e++) + { + if(p->inherits[e].parent) + { #ifdef DEBUG + if(gc_check(p->inherits[e].parent)==-2) + fprintf(stderr,"(program at 0x%lx -> inherit[%d].parent)\n", + (long)p, + e); +#else + gc_check(p->inherits[e].parent); +#endif + } + + if(d_flag && p->inherits[e].name) + gc_check(p->inherits[e].name); + + if(e) + gc_check(p->inherits[e].prog); + } + if(d_flag) { int e; @@ -1812,7 +1886,6 @@ void gc_check_all_programs(void) gc_check(p->identifiers[e].type); } } -#endif } } @@ -1832,8 +1905,17 @@ void gc_free_all_unreferenced_programs(void) { if(gc_do_free(p)) { + int e; p->refs++; free_svalues(p->constants, p->num_constants, -1); + for(e=0;e<p->num_inherits;e++) + { + if(p->inherits[e].parent) + { + free_object(p->inherits[e].parent); + p->inherits[e].parent=0; + } + } next=p->next; free_program(p); }else{ @@ -1842,6 +1924,8 @@ void gc_free_all_unreferenced_programs(void) } } +#endif /* GC2 */ + void count_memory_in_programs(INT32 *num_, INT32 *size_) { @@ -1855,31 +1939,50 @@ void count_memory_in_programs(INT32 *num_, INT32 *size_) *num_=num; *size_=size; } -void push_locals(void) + +void push_compiler_frame(void) +{ + struct compiler_frame *f; + f=ALLOC_STRUCT(compiler_frame); + f->current_type=0; + f->current_return_type=0; + f->current_number_of_locals=0; + f->max_number_of_locals=0; + f->previous=compiler_frame; + compiler_frame=f; +} + +void pop_local_variables(int level) { - struct locals *l; - l=ALLOC_STRUCT(locals); - l->current_type=0; - l->current_return_type=0; - l->next=local_variables; - l->current_number_of_locals=0; - l->max_number_of_locals=0; - local_variables=l; + while(compiler_frame->current_number_of_locals > level) + { + int e; + e=--(compiler_frame->current_number_of_locals); + free_string(compiler_frame->variable[e].name); + free_string(compiler_frame->variable[e].type); + } } -void pop_locals(void) + +void pop_compiler_frame(void) { - struct locals *l; - free_all_local_names(); - l=local_variables->next; - if(local_variables->current_type) - free_string(local_variables->current_type); - if(local_variables->current_return_type) - free_string(local_variables->current_return_type); - free((char *)local_variables); + struct compiler_frame *f; + int e; + f=compiler_frame; +#ifdef DEBUG + if(!f) + fatal("Popping out of compiler frames\n"); +#endif - local_variables=l; - /* insert check if ( local->next == parent locals ) here */ + pop_local_variables(0); + if(f->current_type) + free_string(f->current_type); + + if(f->current_return_type) + free_string(f->current_return_type); + + compiler_frame=f->previous; + free((char *)f); } @@ -1897,7 +2000,7 @@ char *get_storage(struct object *o, struct program *p) oid=o->prog->id; pid=p->id; hval=oid*9248339 + pid; - hval %= GET_STORAGE_CACHE_SIZE; + hval%=GET_STORAGE_CACHE_SIZE; #ifdef DEBUG if(hval>GET_STORAGE_CACHE_SIZE) fatal("hval>GET_STORAGE_CACHE_SIZE"); @@ -1926,3 +2029,89 @@ char *get_storage(struct object *o, struct program *p) if(offset == -1) return 0; return o->storage + offset; } + +struct program *low_program_from_function(struct program *p, + INT32 i) +{ + struct svalue *f; + struct identifier *id=ID_FROM_INT(p, i); + if(!IDENTIFIER_IS_CONSTANT(id->identifier_flags)) return 0; + if(id->func.offset==-1) return 0; + f=PROG_FROM_INT(p,i)->constants + id->func.offset; + if(f->type!=T_PROGRAM) return 0; + return f->u.program; +} + +struct program *program_from_function(struct svalue *f) +{ + struct identifier *id; + if(f->type != T_FUNCTION) return 0; + if(f->subtype == FUNCTION_BUILTIN) return 0; + if(!f->u.object->prog) return 0; + return low_program_from_function(f->u.object->prog, f->subtype); +} + +struct program *program_from_svalue(struct svalue *s) +{ + switch(s->type) + { + case T_FUNCTION: + return program_from_function(s); + case T_PROGRAM: + return s->u.program; + default: + return 0; + } +} + +#define FIND_CHILD_HASHSIZE 5003 +struct find_child_cache_s +{ + INT32 pid,cid,id; +}; + +static struct find_child_cache_s find_child_cache[FIND_CHILD_HASHSIZE]; + +int find_child(struct program *parent, struct program *child) +{ + INT32 h=(parent->id * 9248339 + child->id) % FIND_CHILD_HASHSIZE; + if(find_child_cache[h].pid == parent->id && + find_child_cache[h].cid == child->id) + { + return find_child_cache[h].id; + }else{ + INT32 i; + for(i=0;i<parent->num_identifier_references;i++) + { + if(low_program_from_function(parent, i)==child) + { + find_child_cache[h].pid=parent->id; + find_child_cache[h].cid=child->id; + find_child_cache[h].id=i; + return i; + } + } + } + return -1; +} + +void yywarning(char *fmt, ...) ATTRIBUTE((format(printf,1,2))) +{ + char buf[4711]; + va_list args; + va_start(args,fmt); + VSPRINTF(buf, fmt, args); + va_end(args); + + if(strlen(buf)>sizeof(buf)) + fatal("Buffer overfloat in yywarning!\n"); + + if(get_master()) + { + ref_push_string(lex.current_file); + push_int(lex.current_line); + push_text(buf); + SAFE_APPLY_MASTER("compile_warning",3); + pop_stack(); + } +} diff --git a/src/program.h b/src/program.h index d545499b18e934e073f2d7d24a28ae5b293673e8..209efcdcd032a007f0532128c1bee9a3025c6a03 100644 --- a/src/program.h +++ b/src/program.h @@ -8,6 +8,8 @@ #include <stdarg.h> #include "global.h" +#include "pike_types.h" +#include "svalue.h" #define LFUN___INIT 0 #define LFUN_CREATE 1 @@ -57,6 +59,11 @@ extern char *lfun_names[]; struct svalue; #endif +#ifndef STRUCT_NODE_S_DECLARED +#define STRUCT_NODE_S_DECLARED +struct node_s; +#endif + #ifndef STRUCT_OBJECT_DECLARED #define STRUCT_OBJECT_DECLARED struct object; @@ -133,35 +140,48 @@ struct reference { unsigned INT16 inherit_offset; unsigned INT16 identifier_offset; - INT16 id_flags; /* ID_* static, private etc.. */ + INT16 id_flags; /* static, private etc.. */ }; + struct inherit { - struct program *prog; INT16 inherit_level; /* really needed? */ INT16 identifier_level; + INT16 parent_identifier; INT32 storage_offset; + struct object *parent; + struct program *prog; + struct pike_string *name; }; -#define PROG_DESTRUCT_IMMEDIATE 1 +/* program parts have been realloced into one block */ +#define PROGRAM_OPTIMIZED 1 + +/* program has gone through pass 1 of compiler, prototypes etc. will + * not change from now on + */ +#define PROGRAM_FIXED 2 + +/* Program is done and can be cloned */ +#define PROGRAM_FINISHED 4 + +/* Program has gone through first compiler pass */ +#define PROGRAM_PASS_1_DONE 8 + +/* Program will be destructed as soon at it runs out of references. */ +#define PROGRAM_DESTRUCT_IMMEDIATE 15 struct program { INT32 refs; INT32 id; /* used to identify program in caches */ + INT32 flags; INT32 storage_needed; /* storage needed in the object struct */ struct program *next; struct program *prev; - unsigned char *program; - struct pike_string **strings; - struct inherit *inherits; - struct reference *identifier_references; - struct identifier *identifiers; - unsigned INT16 *identifier_index; - struct svalue *constants; - char *linenumbers; + void (*init)(struct object *); void (*exit)(struct object *); void (*gc_marked)(struct object *); @@ -173,15 +193,13 @@ struct program #endif /* PROFILING */ SIZE_T total_size; - SIZE_T num_linenumbers; - SIZE_T program_size; - unsigned INT16 flags; - unsigned INT16 num_constants; - unsigned INT16 num_strings; - unsigned INT16 num_identifiers; - unsigned INT16 num_identifier_references; - unsigned INT16 num_identifier_indexes; - unsigned INT16 num_inherits; + +#define FOO(NUMTYPE,TYPE,NAME) TYPE * NAME ; +#include "program_areas.h" + +#define FOO(NUMTYPE,TYPE,NAME) NUMTYPE PIKE_CONCAT(num_,NAME) ; +#include "program_areas.h" + INT16 lfuns[NUM_LFUNS]; }; @@ -192,33 +210,51 @@ struct program #define PROG_FROM_INT(P,X) PROG_FROM_PTR(P,(P)->identifier_references+(X)) #define ID_FROM_INT(P,X) ID_FROM_PTR(P,(P)->identifier_references+(X)) +#define FIND_LFUN(P,N) ((P)->flags & PROGRAM_FIXED?(P)->lfuns[(N)]:find_identifier(lfun_names[(N)],(P))) + #define free_program(p) do{ struct program *_=(p); if(!--_->refs) really_free_program(_); }while(0) extern struct object fake_object; -extern struct program fake_program; +extern struct program *new_program; extern struct program *first_program; +extern int compiler_pass; + +#define FOO(NUMTYPE,TYPE,NAME) void PIKE_CONCAT(add_to_,NAME(TYPE ARG)); +#include "program_areas.h" /* Prototypes begin here */ +void ins_int(INT32 i, void (*func)(char tmp)); +void ins_short(INT16 i, void (*func)(char tmp)); void use_module(struct svalue *s); -int find_module_identifier(struct pike_string *ident); +struct node_s *find_module_identifier(struct pike_string *ident); +struct program *parent_compilation(int level); struct program *id_to_program(INT32 id); -void setup_fake_program(void); +void optimize_program(struct program *p); +void fixate_program(void); +void low_start_new_program(struct program *p, + struct pike_string *name, + int flags); void start_new_program(void); void really_free_program(struct program *p); void dump_program_desc(struct program *p); -void toss_current_program(void); void check_program(struct program *p); +struct program *end_first_pass(int finish); struct program *end_program(void); SIZE_T add_storage(SIZE_T size); void set_init_callback(void (*init)(struct object *)); void set_exit_callback(void (*exit)(struct object *)); void set_gc_mark_callback(void (*m)(struct object *)); -int low_reference_inherited_identifier(int e,struct pike_string *name); +int low_reference_inherited_identifier(int e, + struct pike_string *name); int reference_inherited_identifier(struct pike_string *super_name, struct pike_string *function_name); void rename_last_inherit(struct pike_string *n); -void do_inherit(struct program *p,INT32 flags, struct pike_string *name); -void simple_do_inherit(struct pike_string *s, INT32 flags,struct pike_string *name); +void do_inherit(struct svalue *prog, + INT32 flags, + struct pike_string *name); +void simple_do_inherit(struct pike_string *s, + INT32 flags, + struct pike_string *name); int isidentifier(struct pike_string *s); int low_define_variable(struct pike_string *name, struct pike_string *type, @@ -261,6 +297,8 @@ INT32 define_function(struct pike_string *name, INT16 flags, INT8 function_flags, union idptr *func); +int low_find_shared_string_identifier(struct pike_string *name, + struct program *prog); struct ff_hash; int find_shared_string_identifier(struct pike_string *name, struct program *prog); @@ -270,11 +308,8 @@ int store_constant(struct svalue *foo, int equal); void start_line_numbering(void); void store_linenumber(INT32 current_line, struct pike_string *current_file); char *get_line(unsigned char *pc,struct program *prog,INT32 *linep); -void my_yyerror(char *fmt,...); -void compile(void); -struct program *compile_file(struct pike_string *file_name); -struct program *compile_string(struct pike_string *prog, - struct pike_string *name); +void my_yyerror(char *fmt,...) ATTRIBUTE((format(printf,1,2))); +struct program *compile(struct pike_string *prog); void add_function(char *name,void (*cfun)(INT32),char *type,INT16 flags); void check_all_programs(void); void cleanup_program(void); @@ -283,16 +318,18 @@ void gc_check_all_programs(void); void gc_mark_all_programs(void); void gc_free_all_unreferenced_programs(void); void count_memory_in_programs(INT32 *num_, INT32 *size_); -void push_locals(void); -void pop_locals(void); +void push_compiler_frame(void); +void pop_local_variables(int level); +void pop_compiler_frame(void); char *get_storage(struct object *o, struct program *p); +struct program *low_program_from_function(struct program *p, + INT32 i); +struct program *program_from_function(struct svalue *f); +struct program *program_from_svalue(struct svalue *s); +struct find_child_cache_s; +int find_child(struct program *parent, struct program *child); +void yywarning(char *fmt, ...) ATTRIBUTE((format(printf,1,2))); /* Prototypes end here */ -void my_yyerror(char *fmt,...) ATTRIBUTE((format (printf, 1, 2))); - #endif - - - - diff --git a/src/program_areas.h b/src/program_areas.h new file mode 100644 index 0000000000000000000000000000000000000000..e932bf85bd10c69565581681fd8927e605370700 --- /dev/null +++ b/src/program_areas.h @@ -0,0 +1,14 @@ +/* Who needs templates anyway? / Hubbe */ + +/* Program *must* be first! */ +FOO(SIZE_T,unsigned char,program) +FOO(SIZE_T,char,linenumbers) +FOO(unsigned INT16,struct inherit,inherits) +FOO(unsigned INT16,struct pike_string *,strings) +FOO(unsigned INT16,struct reference,identifier_references) +FOO(unsigned INT16,struct identifier,identifiers) +FOO(unsigned INT16,unsigned INT16,identifier_index) +FOO(unsigned INT16,struct svalue, constants) + +#undef FOO + diff --git a/src/stralloc.c b/src/stralloc.c index 68a80f4517e600b450b62a76c17a651308696ee1..4ab1c7838de35c079560faf371e9ed7ac7d977b1 100644 --- a/src/stralloc.c +++ b/src/stralloc.c @@ -503,6 +503,16 @@ struct pike_string *add_shared_strings(struct pike_string *a, return ret; } +struct pike_string *add_and_free_shared_strings(struct pike_string *a, + struct pike_string *b) +{ + INT32 alen=a->len; + a=realloc_shared_string(a,alen + b->len); + MEMCPY(a->str+alen,b->str,b->len); + free_string(b); + return end_shared_string(a); +} + /*** replace function ***/ struct pike_string *string_replace(struct pike_string *str, struct pike_string *del, diff --git a/src/stralloc.h b/src/stralloc.h index 397c8d639f76cd163cc6a525178f3a1397d6a481..265a551bed4a54de55110d43118bafd032db65b9 100644 --- a/src/stralloc.h +++ b/src/stralloc.h @@ -33,6 +33,11 @@ struct pike_string *debug_findstring(const struct pike_string *foo); #define reference_shared_string(s) (s)->refs++ #define copy_shared_string(to,s) ((to)=(s))->refs++ +#define MAKE_CONSTANT_SHARED_STRING(var, text) \ + do { static struct pike_string *str_; \ + if(!str_) str_=make_shared_string((text)); \ + copy_shared_string((var), str_); \ + }while(0) /* Prototypes begin here */ struct pike_string *binary_findstring(const char *foo, INT32 l); @@ -56,6 +61,8 @@ struct pike_string *realloc_unlinked_string(struct pike_string *a, INT32 size); struct pike_string *realloc_shared_string(struct pike_string *a, INT32 size); struct pike_string *add_shared_strings(struct pike_string *a, struct pike_string *b); +struct pike_string *add_and_free_shared_strings(struct pike_string *a, + struct pike_string *b); struct pike_string *string_replace(struct pike_string *str, struct pike_string *del, struct pike_string *to); diff --git a/src/svalue.c b/src/svalue.c index 940d406be5628d33e7e415b28987d1ae8b968efd..a772c1f9c28fdbd80c9c5cc06bcd61f771fd6c8f 100644 --- a/src/svalue.c +++ b/src/svalue.c @@ -333,9 +333,9 @@ unsigned INT32 hash_svalue(struct svalue *s) break; } - if(s->u.object->prog->lfuns[LFUN___HASH] != -1) + if(FIND_LFUN(s->u.object->prog,LFUN___HASH) != -1) { - safe_apply_low(s->u.object, s->u.object->prog->lfuns[LFUN___HASH], 0); + safe_apply_low(s->u.object, FIND_LFUN(s->u.object->prog,LFUN___HASH), 0); if(sp[-1].type == T_INT) { q=sp[-1].u.integer; @@ -375,9 +375,9 @@ int svalue_is_true(struct svalue *s) case T_OBJECT: if(!s->u.object->prog) return 0; - if(s->u.object->prog->lfuns[LFUN_NOT]!=-1) + if(FIND_LFUN(s->u.object->prog,LFUN_NOT)!=-1) { - safe_apply_low(s->u.object,s->u.object->prog->lfuns[LFUN_NOT],0); + safe_apply_low(s->u.object,FIND_LFUN(s->u.object->prog,LFUN_NOT),0); if(sp[-1].type == T_INT && sp[-1].u.integer == 0) { pop_stack(); @@ -394,6 +394,8 @@ int svalue_is_true(struct svalue *s) } +#define TWO_TYPES(X,Y) (((X)<<8)|(Y)) + int is_eq(struct svalue *a, struct svalue *b) { check_type(a->type); @@ -406,9 +408,24 @@ int is_eq(struct svalue *a, struct svalue *b) if (a->type != b->type) { - if(a->type == T_OBJECT) + switch(TWO_TYPES((1<<a->type),(1<<b->type))) { - if(a->u.object->prog->lfuns[LFUN_EQ] != -1) + case TWO_TYPES(BIT_FUNCTION,BIT_PROGRAM): + return program_from_function(a) == b->u.program; + + case TWO_TYPES(BIT_PROGRAM,BIT_FUNCTION): + return program_from_function(b) == a->u.program; + + case TWO_TYPES(BIT_OBJECT, BIT_ARRAY): + case TWO_TYPES(BIT_OBJECT, BIT_MAPPING): + case TWO_TYPES(BIT_OBJECT, BIT_MULTISET): + case TWO_TYPES(BIT_OBJECT, BIT_OBJECT): + case TWO_TYPES(BIT_OBJECT, BIT_FUNCTION): + case TWO_TYPES(BIT_OBJECT, BIT_PROGRAM): + case TWO_TYPES(BIT_OBJECT, BIT_STRING): + case TWO_TYPES(BIT_OBJECT, BIT_INT): + case TWO_TYPES(BIT_OBJECT, BIT_FLOAT): + if(FIND_LFUN(a->u.object->prog,LFUN_EQ) != -1) { a_is_obj: assign_svalue_no_free(sp, b); @@ -423,11 +440,17 @@ int is_eq(struct svalue *a, struct svalue *b) return 1; } } - } - - if(b->type == T_OBJECT) - { - if(b->u.object->prog->lfuns[LFUN_EQ] != -1) + if(b->type != T_OBJECT) return 0; + + case TWO_TYPES(BIT_ARRAY,BIT_OBJECT): + case TWO_TYPES(BIT_MAPPING,BIT_OBJECT): + case TWO_TYPES(BIT_MULTISET,BIT_OBJECT): + case TWO_TYPES(BIT_FUNCTION,BIT_OBJECT): + case TWO_TYPES(BIT_PROGRAM,BIT_OBJECT): + case TWO_TYPES(BIT_STRING,BIT_OBJECT): + case TWO_TYPES(BIT_INT,BIT_OBJECT): + case TWO_TYPES(BIT_FLOAT,BIT_OBJECT): + if(FIND_LFUN(b->u.object->prog,LFUN_EQ) != -1) { b_is_obj: assign_svalue_no_free(sp, a); @@ -449,10 +472,10 @@ int is_eq(struct svalue *a, struct svalue *b) switch(a->type) { case T_OBJECT: - if(a->u.object->prog->lfuns[LFUN_EQ] != -1) + if(FIND_LFUN(a->u.object->prog,LFUN_EQ) != -1) goto a_is_obj; - if(b->u.object->prog->lfuns[LFUN_EQ] != -1) + if(FIND_LFUN(b->u.object->prog,LFUN_EQ) != -1) goto b_is_obj; case T_MULTISET: @@ -578,7 +601,7 @@ int is_lt(struct svalue *a,struct svalue *b) a_is_object: if(!a->u.object->prog) error("Comparison on destructed object.\n"); - if(a->u.object->prog->lfuns[LFUN_LT] == -1) + if(FIND_LFUN(a->u.object->prog,LFUN_LT) == -1) error("Object lacks '<\n"); assign_svalue_no_free(sp, b); sp++; @@ -597,7 +620,7 @@ int is_lt(struct svalue *a,struct svalue *b) { if(!b->u.object->prog) error("Comparison on destructed object.\n"); - if(b->u.object->prog->lfuns[LFUN_GT] == -1) + if(FIND_LFUN(b->u.object->prog,LFUN_GT) == -1) error("Object lacks '>\n"); assign_svalue_no_free(sp, a); sp++; @@ -878,7 +901,12 @@ TYPE_FIELD gc_check_svalues(struct svalue *s, int num) case T_OBJECT: if(s->u.object->prog) { - gc_check(s->u.object); +#ifdef DEBUG + if(gc_check(s->u.object) == -2) + fprintf(stderr,"(in svalue at %lx, type = %d)\n",(long)s,s->type); +#else + gc_check(s->u.object); +#endif }else{ free_svalue(s); s->type=T_INT; @@ -1030,9 +1058,9 @@ INT32 pike_sizeof(struct svalue *s) case T_OBJECT: if(!s->u.object->prog) error("sizeof() on destructed object.\n"); - if(s->u.object->prog->lfuns[LFUN__SIZEOF] == -1) + if(FIND_LFUN(s->u.object->prog,LFUN__SIZEOF) == -1) { - return s->u.object->prog->num_identifier_indexes; + return s->u.object->prog->num_identifier_index; }else{ apply_lfun(s->u.object, LFUN__SIZEOF, 0); if(sp[-1].type != T_INT) diff --git a/src/testsuite.in b/src/testsuite.in index 0a35be4b6673de8506584b8aadb09627a346a0a4..d25d1e73db21614be3e387192f86223cd85cb20e 100644 --- a/src/testsuite.in +++ b/src/testsuite.in @@ -1,4 +1,4 @@ -test_true([["$Id: testsuite.in,v 1.63 1998/01/03 07:12:11 hubbe Exp $"]]) +test_true([["$Id: testsuite.in,v 1.64 1998/01/13 22:56:51 hubbe Exp $"]]) test_eq(1e1,10.0) test_eq(1E1,10.0) test_eq(1e+1,10.0) @@ -7,8 +7,19 @@ test_eq(1e-1,0.1) test_eq('\x20',32) test_eq("\x20","\040") -test_eq(class { static int foo=17; }()->foo,0) -test_eval_error(class { static int foo=17; }()->foo=18;) + +test_any([[object o=class foo{int c;class bar{void create(){c++;};}}(); o->bar(); return o->c;]],1) +test_do([[add_constant("GURKA2",class foo { int c; class bar{void create() {c+=17;}}}()); ]]) +test_any([[class x { inherit GURKA2.bar; }(); return GURKA2->c;]],17) +test_any([[class x { inherit GURKA2.bar; }(); return GURKA2->c;]],34) + +test_do([[add_constant("GURKA2",class foo { int c; class bar{void create() { class sune { void create() {c+=17;}}(); }}}()); ]]) +test_any([[class x { inherit GURKA2.bar; }(); return GURKA2->c;]],17) +test_any([[class x { inherit GURKA2.bar; }(); return GURKA2->c;]],34) +test_do([[add_constant("GURKA2");]]); + +test_eq(class c { static int foo=17; }()->foo,0) +test_eval_error(class c { static int foo=17; }()->foo=18;) test_equal( [[ ({ (["foo":"bar"]), (<"foo">), ([]) })->foo ]], [[ ({"bar",1,0}) ]]) test_any([[mixed a=({([]),0}); a[1]=a; return a->foo[0];]],0) test_eval_error([[return column(({0}),"foo");]]) @@ -30,7 +41,7 @@ test_compile_error([[void foo() { return destruct(this_object()); }]]) test_any([[class foo { constant x=17; }; class bar { inherit foo; constant x=18; }; return bar()->x;]],18) test_program([[inline string foo(string s){ while(s[0] == ' ' || s[0] == '\t') s = s[1..]; return(s); } string a() { return foo(" bar"); }]]) test_true([[lambda(function f) {return 1;}(object_program(this_object()));]]) -test_eq([[class { int `()(){ return 4711; } }()(); ]],4711) +test_eq([[class c { int `()(){ return 4711; } }()(); ]],4711) teste_eval_error(mixed foo=({}); sort(@foo); ) test_compile_error([[int foo() { return 1} ; constant foo=(["foo":foo]); return foo->foo();]]) test_compile_error([[class T{void p(object e,object f){lambda::create(f);}}]]) @@ -73,13 +84,12 @@ test_any([[float p=2.0; p--; return p;]],1.0); test_any([[float p=2.0; return --p;]],1.0); test_compile_error(int foo() { LJjjjjJJJ ; }) -test_true(clone(class { constant i=1; })->i) -test_true(clone(class { constant i=0; mixed `->(string s) { if(s=="i") return 1; }})->i) -test_true(clone(class { constant i=1; mixed `->(string s) { return 0; }})["i"]) -test_true(clone(class { constant i=0; mixed `[](string s) { if(s=="i") return 1; }})["i"]) -test_eq([[class{mixed `[](int a,int b) { return a+b; }}()[1..4]]],5) -test_true(clone(class { mixed `[]=(mixed a, mixed b) { if(a!=b) throw(1); }})[1]=1) -test_true(clone(class { mixed `->=(mixed a, mixed b) { if(a!=b) throw(1); }})->i="i") +test_true(clone(class c { constant i=1; })->i) +test_true(clone(class c { constant i=0; mixed `->(string s) { if(s=="i") return 1; }})->i) +test_true(clone(class c { constant i=1; mixed `->(string s) { return 0; }})["i"]) +test_true(clone(class c { constant i=0; mixed `[](string s) { if(s=="i") return 1; }})["i"]) +test_true(clone(class c { mixed `[]=(mixed a, mixed b) { if(a!=b) throw(1); }})[1]=1) +test_true(clone(class c { mixed `->=(mixed a, mixed b) { if(a!=b) throw(1); }})->i="i") test_compile(class A {}; class B { inherit A; }) @@ -99,9 +109,9 @@ test_program(inherit test;) test_program(inherit test; int a() { return foo; } ) test_define_program(test,[[class TEST { int a() { return 1; } }]]) test_program(inherit test; inherit TEST; ) -test_compile_error(class { object(Stdio.File) foo; object(Regexp) bar=foo; }) -test_do(class { object foo; object(Regexp) bar=foo; }) -test_do(class { object(Stdio.File) foo; object bar=foo; }) +test_compile_error(class c { object(Stdio.File) foo; object(Regexp) bar=foo; }) +test_do(class c { object foo; object(Regexp) bar=foo; }) +test_do(class c { object(Stdio.File) foo; object bar=foo; }) test_any(if(int i=1) return i; return 0;,1) test_compile(for(int i=0;i<100;i++) return 0;) test_compile(foreach(({}),mixed i){}) @@ -376,20 +386,20 @@ ifefun(gc, [[ test_true(intp(gc())); test_any([[ array a=({0}); a[0]=a; gc(); a=0; return gc() > 0; ]],1); - test_any([[object o=class {object o;}(); o->o=o; gc(); o=0; return gc() > 0; ]],1); - test_any([[object o=class {object o;}(); o->o=o; gc(); o=0; return gc() > 0; ]],1); + test_any([[object o=class c {object o;}(); o->o=o; gc(); o=0; return gc() > 0; ]],1); + test_any([[object o=class c {object o;}(); o->o=o; gc(); o=0; return gc() > 0; ]],1); test_any([[mapping m=([]); m[m]=m; gc(); m=0; return gc() > 0; ]],1); test_any([[multiset m=(<>); m[m]=1; gc(); m=0; return gc() > 0; ]],1); ]]) test_eq("\377"[0],255) -test_do(add_constant("foo",clone(class {int i;}))) +test_do(add_constant("foo",clone(class c {int i;}))) test_eq(foo->i,0) test_do(foo->i=17) test_eq(foo->i,17) test_do(add_constant("foo")); -test_do(add_constant("foo",clone(class {int *i=({0});}))) +test_do(add_constant("foo",clone(class c {int *i=({0});}))) test_eq(foo->i[0],0) test_do(foo->i[0]=17) test_eq(foo->i[0],17) @@ -419,12 +429,12 @@ test_eq(typeof(0.0),"float") test_eq(typeof(all_constants()["all_constants"]),"mixed") // class -test_true(programp(class {})) -test_true(functionp(clone(class { int foo() { return 1; }})->foo)) -test_true(clone(class { int foo() { return 1; }})->foo()) -test_true(clone(class { int i=1; })->i) -test_false(clone(class { int foo() { return 1; }})->bar) -test_eq(clone(clone(class { program foo=class { int i=20; }; })->foo)->i,20) +test_true(programp(class c {})) +test_true(functionp(clone(class c { int foo() { return 1; }})->foo)) +test_true(clone(class c { int foo() { return 1; }})->foo()) +test_true(clone(class c { int i=1; })->i) +test_false(clone(class c { int foo() { return 1; }})->bar) +test_eq(clone(clone(class c { program foo=class c { int i=20; }; })->foo)->i,20) // type checks test_compile_error([[} int foo() { return]]); @@ -969,15 +979,13 @@ test_any(int e;string t=""; for(e=0;e<10;e++) switch(e) { default: t+=e; case 4. test_any([[float e,q; q=0.0; for(e=0.1;e<10.0;e+=1.0) switch(e) { default: q+=e; case 4.0..8.0: } return q]],0.1+1.1+2.1+3.1+8.1+9.1) // testing preprocessor -test_program([[ -#include <simulate.h> -mixed a() { return explode ; } -]]) -test_program([[ -#include "lib/include/simulate.h" -mixed a() { return implode; } -]]) - +test_any(int e; object o=clone(Stdio.File); if(!o->open("conftest.h","wct")) return -1; e=o->write("return 17;\n"); if(!o->close()) return -1; return e,11) +test_any([[ +#include "conftest.h" +]],17) +dnltest_any([[ +dnl#include <conftest.h> +dnl]],17) test_true(intp(__LINE__)) test_true(stringp(__FILE__)) test_true(stringp(__DATE__)) @@ -1702,6 +1710,7 @@ test_search3($1,($1[..strlen($1)-3])) test_search3($1,($1[1..])) ]]) +dnl some m4 doesn't handle 8 bit characters... test_search4("SUNE") test_search4("kapit\344l>") test_search4("-------------------+") @@ -1785,7 +1794,7 @@ test_program(inherit test; inherit test2; mixed a() { setw(20); setb(22); return test_program(inherit test2; inherit test; mixed a() { w=20; b=22; return getw()==20 && getb()==22; }) test_program(inherit test2; inherit test; mixed a() { setw(20); setb(22); return w==20 && b==22; }) -test_eval_error(clone(class{int i;void foo(){ destruct(this_object());i=0;}})->foo()) +test_eval_error(clone(class c{int i;void foo(){ destruct(this_object());i=0;}})->foo()) // Pike modules // LR diff --git a/src/threads.c b/src/threads.c index 6221538f632125e77b9d170618a19675300d81ae..951d67e567071577e894c6c423eccd743ca21198 100644 --- a/src/threads.c +++ b/src/threads.c @@ -1,5 +1,5 @@ #include "global.h" -RCSID("$Id: threads.c,v 1.50 1998/01/03 07:12:12 hubbe Exp $"); +RCSID("$Id: threads.c,v 1.51 1998/01/13 22:56:51 hubbe Exp $"); int num_threads = 1; int threads_disabled = 0; @@ -74,9 +74,10 @@ int co_destroy(COND_T *c) { struct cond_t_queue *t; mt_lock(& c->lock); - n=c->head; - c->head=c->tail=0; - if(t) return EBUSY; + t=c->head; + mt_unlock(& c->lock); + if(t) return -1; + mt_destroy(& c->lock); return 0; } @@ -191,7 +192,9 @@ void f_thread_create(INT32 args) arg->id=clone_object(thread_id_prog,0); ((struct thread_state *)arg->id->storage)->status=THREAD_RUNNING; - tmp=th_create(&dummy,new_thread_func,arg); + tmp=th_create(&((struct thread_state *)arg->id->storage)->id, + new_thread_func, + arg); if(!tmp) { @@ -509,6 +512,7 @@ void init_thread_obj(struct object *o) void exit_thread_obj(struct object *o) { co_destroy(& THIS_THREAD->status_change); + th_destroy(& THIS_THREAD->id); } #ifdef DEBUG @@ -577,7 +581,7 @@ void th_init(void) set_init_callback(init_mutex_key_obj); set_exit_callback(exit_mutex_key_obj); mutex_key=end_program(); - mutex_key->flags|=PROG_DESTRUCT_IMMEDIATE; + mutex_key->flags|=PROGRAM_DESTRUCT_IMMEDIATE; if(!mutex_key) fatal("Failed to initialize mutex_key program!\n"); diff --git a/src/threads.h b/src/threads.h index 70282721e1fd2973b1ae301bdc1a34fa1a74a260..728821091696ab67a85afe6c10e87acff4595cc2 100644 --- a/src/threads.h +++ b/src/threads.h @@ -154,11 +154,12 @@ extern struct object *thread_id; #ifdef NT_THREADS #include <process.h> +#include <windows.h> #define THREAD_T HANDLE #define th_setconcurrency(X) -#define th_create(ID,fun,arg) _beginthreadex(NULL, 2*1024*1024, fun, arg, 0, ID) -#define th_exit(foo) _endthreadex(foo) +#define th_create(ID,fun,arg) (!(*(ID)=_beginthread(fun, 2*1024*1024, arg))) +#define th_exit(foo) _endthread(foo) #define th_self() GetCurrentThread() #define th_destroy(X) CloseHandle(*(X)) #define th_yield() Sleep(0) @@ -189,10 +190,10 @@ struct cond_t_queue EVENT_T event; }; -struct cond_t_s +typedef struct cond_t_s { MUTEX_T lock; - struct cond_t_queue *head, *tail + struct cond_t_queue *head, *tail; } COND_T; #define COND_T struct cond_t_s @@ -221,6 +222,7 @@ struct thread_state { char swapped; char status; COND_T status_change; + THREAD_T id; /* Swapped variables */ struct svalue *sp,*evaluator_stack;