diff --git a/lib/master.pike b/lib/master.pike index 47505abf589883a0862524b4607bc18c747bd9c0..215964e5ef3c92827acb35ab133f845b1909ce75 100644 --- a/lib/master.pike +++ b/lib/master.pike @@ -1,3 +1,4 @@ +#define UNDEFINED (([])[0]) string describe_backtrace(mixed *trace); string pike_library_path; @@ -15,7 +16,7 @@ void putenv(string var, string val) environment[var]=val; } -mapping (string:program) programs=([]); +mapping (string:program) programs=(["/master":object_program(this_object())]); #define capitalize(X) (upper_case((X)[..0])+(X)[1..]) @@ -36,6 +37,36 @@ void add_precompiled_program(string name, program p) } } +static program findprog(string pname) +{ + program ret; + + if(ret=programs[pname]) return ret; + + if(file_stat(pname)) + { + ret=compile_file(pname); + } + else if(file_stat(pname+".pike")) + { + ret=compile_file(pname+".pike"); + } +#if efun(load_module) + else if(file_stat(pname+".so")) + { + load_module(pname+".so"); + ret=programs[pname]; + } +#endif + if(ret) + { + programs[pname]=ret; + return ret; + }else{ + return UNDEFINED; + } +} + /* This function is called when the driver wants to cast a string * to a program, this might be because of an explicit cast, an inherit * or a implict cast. In the future it might receive more arguments, @@ -46,31 +77,6 @@ program cast_to_program(string pname) if(pname[sizeof(pname)-3..sizeof(pname)]==".pike") pname=pname[0..sizeof(pname)-4]; - function findprog=lambda(string pname) - { - program ret; - - if(ret=programs[pname]) return ret; - - if(file_stat(pname)) - { - ret=compile_file(pname); - } - else if(file_stat(pname+".pike")) - { - ret=compile_file(pname+".pike"); - } -#if efun(load_module) - else if(file_stat(pname+".so")) - { - load_module(pname+".so"); - ret=programs[pname]; - } -#endif - if(ret) programs[pname]=ret; - return ret; - }; - if(pname[0]=='/') { return findprog(pname); @@ -163,11 +169,52 @@ object cast_to_object(string oname) return objects[oname]=cast_to_program(oname)(); } +class dirnode +{ + string dirname; + void create(string name) { dirname=name; } + object|program `[](string index) + { + index=dirname+"/"+index; + return + ((object)"/master")->findmodule(index) || (program) index; + } +}; -mixed resolv(string identifier, string file) +object findmodule(string fullname) { - /* Module system goes here */ - throw(sprintf("'%s' is undefined.",identifier)); + mixed *stat; + if(mixed *stat=file_stat(fullname)) + { + if(stat[1]==-2) return dirnode(fullname); + } + program p; + if(p=(program)(fullname+".pmod")) + return (object)(fullname+".pmod"); + return UNDEFINED; +} + +mixed resolv(string identifier, string current_file) +{ + mixed ret; + string *tmp,path; + + tmp=current_file/"/"; + tmp[-1]=identifier; + path=combine_path(getcwd(), tmp*"/"); + if(ret=findmodule(path)) return tmp; + + if(path=getenv("PIKE_MODULE_PATH")) + { + foreach(path/":", path) + { + path=combine_path(path,identifier); + if(ret=findmodule(path)) return ret; + } + } + + path=combine_path(pike_library_path+"/modules",identifier); + return findmodule(path); } /* This function is called when all the driver is done with all setup diff --git a/src/ChangeLog b/src/ChangeLog index 2af827b40341479870e31f4015534d6cf28f07aa..188d3105b5937b83d4f7049c1188092b558b091a 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,7 @@ +Sun Jan 19 01:03:49 1997 Fredrik Hubinette <hubbe@cytocin.hubbe.net> + + * new module system implemented. '.' operator utilized + Sat Jan 18 13:54:23 1997 Fredrik Hubinette <hubbe@cytocin.hubbe.net> * f___version moved from main.c to version.c and renamed to f_version. diff --git a/src/Makefile.in b/src/Makefile.in index d853da01a7956e6698090c44de30ffb186c2d6ae..3c4dc73bdb3aefecde19a657ff602c9efe5101c2 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -132,6 +132,7 @@ install: if [ ! -d "$(prefix)" ]; then mkdir "$(prefix)" ; chmod 755 "$(prefix)" ; else : ; fi if [ ! -d "$(exec_prefix)" ]; then mkdir "$(exec_prefix)" ; chmod 755 "$(exec_prefix)" ; else : ; fi $(INSTALL) ./pike $(exec_prefix) + $(INSTALL) ../bin/hilfe $(exec_prefix) if [ ! -d "$(prefix)/lib" ]; then mkdir "$(prefix)/lib" ; chmod 755 "$(prefix)/lib" ; else : ; fi if [ ! -d "$(lib_prefix)" ]; then mkdir "$(lib_prefix)" ; chmod 755 "$(lib_prefix)" ; else : ; fi if [ ! -d "$(prefix)/include" ]; then mkdir "$(prefix)/include"; chmod 755 "$(prefix)/include"; fi diff --git a/src/builtin_functions.c b/src/builtin_functions.c index 54f2ea6699b053b26cbe5263fbf5fc3499141b38..ee0c21a2a88b22136a95be6e62437c5d13f04f64 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.20 1997/01/18 21:34:32 hubbe Exp $"); +RCSID("$Id: builtin_functions.c,v 1.21 1997/01/19 09:07:59 hubbe Exp $"); #include "interpret.h" #include "svalue.h" #include "macros.h" @@ -1606,7 +1606,7 @@ void init_builtin_efuns() { init_operators(); - add_efun("_refs",f__refs,"function(string|array|mapping|multiset|object|program:int)",OPT_EXTERNAL_DEPEND); + add_efun("_refs",f__refs,"function(function|string|array|mapping|multiset|object|program:int)",OPT_EXTERNAL_DEPEND); add_efun("replace_master",f_replace_master,"function(object:void)",OPT_SIDE_EFFECT); add_efun("add_constant",f_add_constant,"function(string,void|mixed:void)",OPT_SIDE_EFFECT); add_efun("aggregate",f_aggregate,"function(mixed ...:mixed *)",OPT_TRY_OPTIMIZE); diff --git a/src/interpret.h b/src/interpret.h index 3ae421679252c6021c51f126def00f059cd84741..1ca3f0fd53de7d4b41e3d590ca155a55ff1301ab 100644 --- a/src/interpret.h +++ b/src/interpret.h @@ -40,7 +40,7 @@ struct frame #define push_mapping(M) do{ struct mapping *_=(M); sp->u.mapping=_; sp++->type=T_MAPPING; }while(0) #define push_array(A) do{ struct array *_=(A); sp->u.array=_ ;sp++->type=T_ARRAY; }while(0) #define push_multiset(L) do{ struct multiset *_=(L); sp->u.multiset=_; sp++->type=T_MULTISET; }while(0) -#define push_string(S) do{ struct pike_string *_=(S); sp->u.string=_; sp++->type=T_STRING; }while(0) +#define push_string(S) do{ struct pike_string *_=(S); sp->subtype=0; sp->u.string=_; sp++->type=T_STRING; }while(0) #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))) diff --git a/src/language.yacc b/src/language.yacc index 5be58913c23555aaeed459f4f078f65ae678f437..b9e2f54b4548ee5a36aaa8d1bd543a53793a405f 100644 --- a/src/language.yacc +++ b/src/language.yacc @@ -95,6 +95,7 @@ %token F_GAUGE %token F_IDENTIFIER %token F_IF +%token F_IMPORT %token F_INHERIT %token F_INLINE %token F_INT_ID @@ -155,7 +156,7 @@ /* This is the grammar definition of Pike. */ #include "global.h" -RCSID("$Id: language.yacc,v 1.17 1997/01/16 05:00:44 hubbe Exp $"); +RCSID("$Id: language.yacc,v 1.18 1997/01/19 09:08:00 hubbe Exp $"); #ifdef HAVE_MEMORY_H #include <memory.h> #endif @@ -303,6 +304,7 @@ void fix_comp_stack(int sp) %type <n> idents %type <n> lambda %type <n> local_name_list +%type <n> low_idents %type <n> lvalue %type <n> lvalue_list %type <n> m_expr_list @@ -359,41 +361,14 @@ program_ref: string_constant | idents { push_string(make_shared_string("")); - if(!$1) + resolv_constant($1); + if(sp[-1].type != T_PROGRAM) { + yyerror("Illegal program identifier"); + pop_stack(); push_int(0); - }else{ - switch($1->token) - { - case F_CONSTANT: - if($1->u.sval.type == T_PROGRAM) - { - push_svalue(& $1->u.sval); - }else{ - yyerror("Illegal program identifier"); - push_int(0); - } - break; - - case F_IDENTIFIER: - { - struct identifier *i; - setup_fake_program(); - i=ID_FROM_INT(& fake_program, $1->u.number); - - if(IDENTIFIER_IS_CONSTANT(i->flags)) - { - push_svalue(PROG_FROM_INT(&fake_program, $1->u.number)->constants + - i->func.offset); - }else{ - yyerror("Illegal program identifier"); - push_int(0); - } - break; - } - } - free_node($1); } + free_node($1); } ; @@ -411,6 +386,15 @@ inheritance: modifiers F_INHERIT program_ref optional_rename_inherit ';' } ; +import: modifiers F_IMPORT idents ';' + { + resolv_constant($3); + free_node($3); + use_module(sp-1); + sp--; + } + ; + constant_name: F_IDENTIFIER '=' expr0 { int tmp; @@ -555,6 +539,7 @@ def: modifiers type_or_error optional_stars F_IDENTIFIER '(' arguments ')' } | modifiers type_or_error name_list ';' {} | inheritance {} + | import {} | constant {} | class { free_node($1); } | error @@ -1147,7 +1132,16 @@ expr4: string } ; -idents: F_IDENTIFIER +idents: low_idents + | idents '.' F_IDENTIFIER + { + $$=index_node($1, $3); + free_node($1); + free_string($3); + } + ; + +low_idents: F_IDENTIFIER { int i; struct efun *f; @@ -1156,10 +1150,13 @@ 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 if((f=lookup_efun($1))){ $$=mkconstantsvaluenode(&f->function); }else{ - $$=0; + $$=0; if( get_master() ) { reference_shared_string($1); @@ -1171,10 +1168,14 @@ idents: F_IDENTIFIER 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(); } + pop_stack(); }else{ my_yyerror("'%s' undefined.", $1->str); } diff --git a/src/las.c b/src/las.c index d49cf595cb91d26c301c5b745848c41d8f30e144..49a8ab05f381f3f9fc5c76c7de9d625d46097c6b 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.11 1997/01/16 05:00:45 hubbe Exp $"); +RCSID("$Id: las.c,v 1.12 1997/01/19 09:08:00 hubbe Exp $"); #include "language.h" #include "interpret.h" @@ -445,6 +445,71 @@ node *mkcastnode(struct pike_string *type,node *n) return res; } +void resolv_constant(node *n) +{ + struct identifier *i; + if(!n) + { + push_int(0); + }else{ + switch(n->token) + { + case F_CONSTANT: + push_svalue(& n->u.sval); + break; + + case F_IDENTIFIER: + setup_fake_program(); + i=ID_FROM_INT(& fake_program, n->u.number); + + if(IDENTIFIER_IS_CONSTANT(i->flags)) + { + push_svalue(PROG_FROM_INT(&fake_program, n->u.number)->constants + + i->func.offset); + }else{ + yyerror("Identifier is not a constant"); + push_int(0); + } + break; + + case F_LOCAL: + yyerror("Expected constant, got local variable"); + push_int(0); + + case F_GLOBAL: + yyerror("Expected constant, got global variable"); + push_int(0); + } + } +} + +node *index_node(node *n, struct pike_string * id) +{ + node *ret; + JMP_BUF tmp; + if(SETJMP(tmp)) + { + ONERROR tmp; + SET_ONERROR(tmp,exit_on_error,"Error in handle_error in master object!"); + assign_svalue_no_free(sp++, & throw_value); + APPLY_MASTER("handle_error", 1); + pop_stack(); + UNSET_ONERROR(tmp); + + yyerror("Couldn't index module."); + push_svalue(0); + }else{ + resolv_constant(n); + push_string(id); + f_index(2); + } + UNSETJMP(tmp); + ret=mkconstantsvaluenode(sp-1); + pop_stack(); + return ret; +} + + int node_is_eq(node *a,node *b) { if(a == b) return 1; diff --git a/src/las.h b/src/las.h index 6d97e60d7b544b240c4a003d75c7a42615413914..6c85fe750b5b942373cd8a8b3a9762361b63fac2 100644 --- a/src/las.h +++ b/src/las.h @@ -92,6 +92,8 @@ node *mkopernode(char *oper_id, node *arg1, node *arg2); node *mklocalnode(int var); node *mkidentifiernode(int i); node *mkcastnode(struct pike_string *type,node *n); +void resolv_constant(node *n); +node *index_node(node *n, struct pike_string * id); int node_is_eq(node *a,node *b); node *mkconstantsvaluenode(struct svalue *s); node *mkliteralsvaluenode(struct svalue *s); diff --git a/src/lex.c b/src/lex.c index 50b25aa5a5c8ececc7ac2fee9125725c4f56f2e3..e6aa0075cd9d928e7d3707e98eea1b64966d7aec 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.11 1997/01/18 04:43:50 hubbe Exp $"); +RCSID("$Id: lex.c,v 1.12 1997/01/19 09:08:01 hubbe Exp $"); #include "language.h" #include "array.h" #include "lex.h" @@ -101,11 +101,10 @@ struct keyword reserved_words[] = { "case", F_CASE, }, { "catch", F_CATCH, }, { "class", F_CLASS, }, -{ "continue", F_CONTINUE, }, { "constant", F_CONSTANT, }, +{ "continue", F_CONTINUE, }, { "default", F_DEFAULT, }, { "do", F_DO, }, -{ "predef", F_PREDEF, }, { "else", F_ELSE, }, { "float", F_FLOAT_ID, }, { "for", F_FOR, }, @@ -113,15 +112,17 @@ struct keyword reserved_words[] = { "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, }, -{ "multiset", F_MULTISET_ID, }, { "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, }, diff --git a/src/object.c b/src/object.c index a12a3c81f4e8ea823d5dd667e8dfa23b7be6ffb5..07c1a9650b01edb7868ba03c42290a5d90efd40a 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.10 1997/01/18 21:34:33 hubbe Exp $"); +RCSID("$Id: object.c,v 1.11 1997/01/19 09:08:02 hubbe Exp $"); #include "object.h" #include "dynamic_buffer.h" #include "interpret.h" @@ -684,14 +684,11 @@ int object_equal_p(struct object *a, struct object *b, struct processing *p) void cleanup_objects() { struct object *o, *next; - o=first_object; - while(o->next) o=o->next; - - for(;o;o=next) + for(o=first_object;o;o=next) { o->refs++; destruct(o); - next=o->prev; + next=o->next; free_object(o); } destruct_objects_to_destruct(); diff --git a/src/program.c b/src/program.c index 0a70679f0d17f641f5b5fadaf9b62c8e68d782c3..72c2eeda446c95e0df25fbbd90ff79a846010ec2 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.12 1997/01/16 05:00:48 hubbe Exp $"); +RCSID("$Id: program.c,v 1.13 1997/01/19 09:08:03 hubbe Exp $"); #include "program.h" #include "object.h" #include "dynamic_buffer.h" @@ -77,16 +77,47 @@ 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; -#define HASH_ID_IS_LOCAL 1 -#define HASH_ID_IS_GLOBAL 2 -#define HASH_ID_IS_FUNCTION 4 -struct id_hash_entry +void use_module(struct svalue *s) { - struct hash_entry link; - INT16 id; - INT16 flags; -}; + low_my_binary_strcat((char *)s,sizeof(struct svalue *),&used_modules); +} + + +int find_module_identifier(struct pike_string *ident) +{ + JMP_BUF tmp; + + if(SETJMP(tmp)) + { + ONERROR tmp; + SET_ONERROR(tmp,exit_on_error,"Error in handle_error in master object!"); + assign_svalue_no_free(sp++, & throw_value); + APPLY_MASTER("handle_error", 1); + pop_stack(); + UNSET_ONERROR(tmp); + yyerror("Couldn't index module."); + }else{ + struct svalue *modules=(struct svalue *)used_modules.s.str; + int e=used_modules.s.len / sizeof(struct svalue *); + + while(--e>=0) + { + push_svalue(modules+e); + push_string(ident); + f_index(2); + + if(!IS_ZERO(sp-1) || sp[-1].subtype != 1) + { + UNSETJMP(tmp); + return 1; + } + } + } + UNSETJMP(tmp); + return 0; +} #define SETUP(X,Y,TYPE,AREA) \ fake_program.X=(TYPE *)areas[AREA].s.str; \ @@ -138,6 +169,7 @@ void start_new_program() 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; inherit.prog=&fake_program; @@ -146,7 +178,7 @@ void start_new_program() 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); + low_my_binary_strcat((char *)&name,sizeof(name), &inherit_names); num_parse_error=0; local_variables=ALLOC_STRUCT(locals); @@ -227,25 +259,61 @@ void dump_program_desc(struct program *p) } #endif -/* - * Something went wrong. - * toss resources of program we were building - */ -void toss_current_program() +static void toss_compilation_resources() { struct pike_string **names; + struct svalue *modules; int e; - setup_fake_program(); - low_free_program(&fake_program); - - for (e=0; e<NUM_AREAS; e++) - toss_buffer(areas+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 *); - for(e--;e>=0;e--) if(names[e]) free_string(names[e]); + while(--e>=0) if(names[e]) free_string(names[e]); toss_buffer(& inherit_names); + + 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++) + { + 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(last_file) + { + free_string(last_file); + last_file=0; + } +} + +/* + * Something went wrong. + * toss resources of program we were building + */ +void toss_current_program() +{ + setup_fake_program(); + low_free_program(&fake_program); + toss_compilation_resources(); } #ifdef DEBUG @@ -476,15 +544,9 @@ struct program *end_program() p+=MY_ALIGN(prog->num_identifier_indexes*sizeof(unsigned short)); - for (i=0; i<NUM_AREAS; i++) toss_buffer(areas+i); + toss_compilation_resources(); prog->inherits[0].prog=prog; - - names=(struct pike_string **)inherit_names.s.str; - e=inherit_names.s.len / sizeof(struct pike_string *); - for(e--;e>=0;e--) if(names[e]) free_string(names[e]); - toss_buffer(& inherit_names); - prog->prev=0; if(prog->next=first_program) first_program->prev=prog; @@ -502,34 +564,6 @@ struct program *end_program() GC_ALLOC(); } - /* Clean up */ - 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(last_file) - { - free_string(last_file); - last_file=0; - } - #define PROGRAM_STATE #define POP #include "compilation.h" diff --git a/src/program.h b/src/program.h index 93f8f869f0afae026ccd1bb37bafb59b05573612..115911a3155a610e32a45efd3bf8c0b6efc5227c 100644 --- a/src/program.h +++ b/src/program.h @@ -182,7 +182,8 @@ extern struct object fake_object; extern struct program fake_program; /* Prototypes begin here */ -struct id_hash_entry; +void use_module(struct svalue *s); +int find_module_identifier(struct pike_string *ident); void setup_fake_program(); void start_new_program(); void really_free_program(struct program *p); diff --git a/src/version.c b/src/version.c index 907297e4ef923d6e1e39271148cf1afc0a4711be..41fd1f63e4dffe4eb489999f60066c539c829f8e 100644 --- a/src/version.c +++ b/src/version.c @@ -6,5 +6,5 @@ void f_version(INT32 args) { pop_n_elems(args); - push_text("Pike v0.4pl3"); + push_text("Pike v0.4pl4"); }