diff --git a/bin/mktestsuite b/bin/mktestsuite index d1a6ed108923dc4dd3b9dd6d5fc79bdc15141f83..0d0cdab03b82e307f220370a1975250d91a3db86 100755 --- a/bin/mktestsuite +++ b/bin/mktestsuite @@ -53,7 +53,7 @@ define(test_eval_error,[[DOTEST(EVAL_ERROR,dnl mixed a() { [[$1]]; })]]) define(test_define_program,[[DOTEST(RUN,dnl -void a() { add_constant("[[$1]]",class { +void a() { add_constant("[[$1]]",class c { [[$2]] });})]]) diff --git a/lib/master.pike b/lib/master.pike index 5aad3438d461d977c42cf596940dbd5bc9035410..25f788cb2d8ab67e4451707c3244c28f0a6c5139 100644 --- a/lib/master.pike +++ b/lib/master.pike @@ -11,6 +11,16 @@ string *pike_program_path=({}); int want_warnings; +program compile_string(string data, void|string name) +{ + return compile(cpp(data,name||"-")); +} + +program compile_file(string file) +{ + return compile(cpp(_static_modules.files()->file(file,"r")->read(),file)); +} + mapping (string:string) environment=([]); varargs mixed getenv(string s) @@ -185,6 +195,8 @@ object new(mixed prog, mixed ... args) void create() { /* make ourselves known */ + add_constant("compile_string",compile_string); + add_constant("compile_file",compile_file); add_constant("add_include_path",add_include_path); add_constant("remove_include_path",remove_include_path); add_constant("add_module_path",add_module_path); @@ -517,6 +529,11 @@ void compile_warning(string file,int line,string err) } } +string read_include(string f) +{ + return _static_modules->files()->file(f,"r")->read(); +} + /* This function is called whenever an #include directive is encountered * it receives the argument for #include and should return the file name * of the file to include diff --git a/src/ChangeLog b/src/ChangeLog index bdb237e4335f182a0a02cb89b0270855c264e2fd..702df0c80c53300850c2d047607fb0a96528c864 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,10 @@ +Wed Jun 25 15:33:23 1997 Fredrik Hubinette <hubbe@cytocin.hubbe.net> + + * Compiler is now two-pass -> no more prototypes + * New efun: cpp() + * you can now access a class name from inside itself + * objects now have parents + Sat May 10 06:20:51 1997 Fredrik Hubinette <hubbe@cytocin.hubbe.net> * fork() now returns an object diff --git a/src/Makefile.in b/src/Makefile.in index fcd4fe18450d751ae6941cd70d78e331670864f4..51d95c13da73fe0fa74c15f2081d00fedc5c391a 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -65,6 +65,7 @@ MAKE_FLAGS = "prefix=$(prefix)" "exec_prefix=$(exec_prefix)" "CC=$(CC)" "OTHERFL # Add ualarm.o if you don't have ualarm() on your machine. # OBJ= \ + cpp.o \ language.o \ constants.o \ array.o \ diff --git a/src/backend.c b/src/backend.c index e0754176b8f284b761f339dca39ab8b990df3cea..842a49ade23c3a8762ccc00502adfdf531273414 100644 --- a/src/backend.c +++ b/src/backend.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: backend.c,v 1.10.2.2 1997/05/19 09:04:55 hubbe Exp $"); +RCSID("$Id: backend.c,v 1.10.2.3 1997/06/25 22:46:34 hubbe Exp $"); #include "backend.h" #include <errno.h> #ifdef HAVE_SYS_TYPES_H @@ -119,6 +119,7 @@ void set_read_callback(int fd,file_callback cb,void *data) if(cb) { + wake_up_backend(); FD_SET(fd, &selectors.read); if(max_fd < fd) max_fd = fd; }else{ @@ -148,6 +149,7 @@ void set_write_callback(int fd,file_callback cb,void *data) if(cb) { + wake_up_backend(); FD_SET(fd, &selectors.write); if(max_fd < fd) max_fd = fd; }else{ diff --git a/src/builtin_functions.c b/src/builtin_functions.c index 2279f3ee24c176fe73f50d674515cf6a94757cca..2b0ce84c7cf4e2e4637430a7e4c4cf8d69ebd46f 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.36 1997/05/07 06:27:32 per Exp $"); +RCSID("$Id: builtin_functions.c,v 1.36.2.1 1997/06/25 22:46:35 hubbe Exp $"); #include "interpret.h" #include "svalue.h" #include "pike_macros.h" @@ -281,6 +281,28 @@ void f_call_function(INT32 args) } } +void f_parent(INT32 args) +{ + struct object *o; + if(!args) + { + o=fp->current_object; + }else{ + if(sp[-args].type!=T_OBJECT) + error("Bad argument 1 to parent()\n"); + o=sp[-args].u.object; + } + o->refs++; + pop_n_elems(args); + if(o->parent) + { + ref_push_object(o->parent); + }else{ + push_int(0); + } + free_object(o); +} + void f_backtrace(INT32 args) { INT32 frames; @@ -364,20 +386,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 */ @@ -839,24 +847,38 @@ 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 i=find_child(o->parent->prog, p); + if(i!=-1) + { + o->refs++; + pop_n_elems(args); + push_object(o->parent); + sp[-1].subtype=i; + 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) @@ -1068,26 +1090,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); } @@ -1206,7 +1219,6 @@ void ID(INT32 args) \ push_int(t); \ } -TYPEP(f_programp, "programp", T_PROGRAM) TYPEP(f_intp, "intpp", T_INT) TYPEP(f_mappingp, "mappingp", T_MAPPING) TYPEP(f_arrayp, "arrayp", T_ARRAY) @@ -1214,6 +1226,31 @@ TYPEP(f_multisetp, "multisetp", T_MULTISET) TYPEP(f_stringp, "stringp", T_STRING) TYPEP(f_floatp, "floatp", T_FLOAT) +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); + } +} + void f_sort(INT32 args) { INT32 e,*order; @@ -1702,8 +1739,7 @@ void init_builtin_efuns() 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); @@ -1768,5 +1804,6 @@ void init_builtin_efuns() add_efun("encode_value", f_encode_value, "function(mixed:string)", OPT_TRY_OPTIMIZE); add_efun("decode_value", f_decode_value, "function(string:mixed)", OPT_TRY_OPTIMIZE); + add_efun("parent", f_parent, "function(object|void:object)", OPT_EXTERNAL_DEPEND); } diff --git a/src/builtin_functions.h b/src/builtin_functions.h index eb2b465b0d8efb4b3e1aa845741ea59d50ae08cf..83f9da886633eeb9e5a34dab0b1fada9e5f2d7d5 100644 --- a/src/builtin_functions.h +++ b/src/builtin_functions.h @@ -57,7 +57,6 @@ 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) TYPEP(f_intp, "intpp", T_INT) TYPEP(f_mappingp, "mappingp", T_MAPPING) TYPEP(f_arrayp, "arrayp", T_ARRAY) 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/cpp.c b/src/cpp.c new file mode 100644 index 0000000000000000000000000000000000000000..0b6f8d0224a9b40a161da3b7b1979960f13631aa --- /dev/null +++ b/src/cpp.c @@ -0,0 +1,1878 @@ +/*\ +||| This file a part of Pike, and is copyright by Fredrik Hubinette +||| Pike is distributed as GPL (General Public License) +||| See the files COPYING and DISCLAIMER for more information. +\*/ +#include "global.h" +#include "dynamic_buffer.h" +#include "lex.h" +#include "language.h" +#include "stralloc.h" +#include "module_support.h" +#include "interpret.h" +#include "svalue.h" +#include "pike_macros.h" +#include "hashtable.h" +#include "program.h" +#include "object.h" +#include "error.h" +#include "array.h" +#include "mapping.h" +#include "builtin_functions.h" +#include "operators.h" +#include "opcodes.h" +#include "constants.h" +#include "time.h" +#include "stuff.h" +#include <ctype.h> + +#define CPP_NO_OUTPUT 1 +#define CPP_EXPECT_ELSE 2 +#define CPP_EXPECT_ENDIF 4 +#define CPP_REALLY_NO_OUTPUT 8 +#define CPP_END_AT_NEWLINE 16 +#define CPP_DO_IF 32 + +#define OUTP() (!(flags & (CPP_NO_OUTPUT | CPP_REALLY_NO_OUTPUT))) +#define PUTNL() low_my_putchar('\n', &this->buf) +#define GOBBLE(X) (data[pos]==(X)?++pos,1:0) +#define PUTC(C) do { \ + int c_=(C); if(OUTP() || c_=='\n') low_my_putchar(c_, &this->buf); }while(0) + +#define STRCAT(STR,LEN) do { \ + INT32 x_,len_=(LEN); \ + char *str_=(STR); \ + if(OUTP()) \ + low_my_binary_strcat(str_,len_, &this->buf); \ + else \ + for(x_=0;x_<len_;x_++) \ + if(str_[x_]=='\n') \ + low_my_putchar('\n',&this->buf); \ +}while(0) + +#define CHECKWORD(X) \ + (!strncmp(X,data+pos,strlen(X)) && !isidchar(data[pos+strlen(X)])) +#define WGOBBLE(X) (CHECKWORD(X) ? (pos+=strlen(X)),1 : 0) +#define GOBBLEOP(X) \ + ((!strncmp(X,data+pos,strlen(X))) ? (pos+=strlen(X)),1 : 0) + +#define MAX_ARGS 255 +#define DEF_ARG_STRINGIFY 0x100000 +#define DEF_ARG_NOPRESPACE 0x200000 +#define DEF_ARG_NOPOSTSPACE 0x400000 +#define DEF_ARG_MASK 0x0fffff + + +struct pike_predef_s +{ + struct pike_predef_s *next; + char *name; + char *value; +}; + +struct pike_predef_s *pike_predefs=0; +struct define_part +{ + int argument; + struct pike_string *postfix; +}; + +struct define_argument { + char *arg; + INT32 len; +}; + + +struct cpp; +struct define; +typedef void (*magic_define_fun)(struct cpp *, + struct define *, + struct define_argument *, + dynamic_buffer *); + + +struct define +{ + struct hash_entry link; /* must be first */ + magic_define_fun magic; + int args; + int num_parts; + int inside; + struct pike_string *first; + struct define_part parts[1]; +}; + +#define find_define(N) \ + (this->defines?BASEOF(hash_lookup(this->defines, N), define, link):0) + +struct cpp +{ + struct hash_table *defines; + INT32 current_line; + INT32 compile_errors; + struct pike_string *current_file; + dynamic_buffer buf; +}; + +struct define *defined_macro =0; +struct define *constant_macro =0; + +static INT32 calc(struct cpp *,char*,INT32,INT32); +static INT32 calc1(struct cpp *,char*,INT32,INT32); + +void cpp_error(struct cpp *this,char *err) +{ + this->compile_errors++; + if(this->compile_errors > 10) return; + if(get_master()) + { + ref_push_string(this->current_file); + push_int(this->current_line); + push_text(err); + SAFE_APPLY_MASTER("compile_error",3); + pop_stack(); + }else{ + (void)fprintf(stderr, "%s:%ld: %s", + this->current_file->str, + (long)this->current_line, + err); + fflush(stderr); + } +} + +/* devours one reference to 'name'! */ +static struct define *alloc_empty_define(struct pike_string *name, INT32 parts) +{ + struct define *def; + def=(struct define *)xalloc(sizeof(struct define)+ + sizeof(struct define_part) * (parts -1)); + def->magic=0; + def->args=-1; + def->inside=0; + def->num_parts=parts; + def->first=0; + def->link.s=name; + return def; +} + +static void undefine(struct cpp *this, + struct pike_string *name) +{ + INT32 e; + struct define *d; + + d=find_define(name); + + if(!d) return; + + this->defines=hash_unlink(this->defines, & d->link); + + for(e=0;e<d->num_parts;e++) + free_string(d->parts[e].postfix); + free_string(d->link.s); + if(d->first) + free_string(d->first); + free((char *)d); +} + +static void do_magic_define(struct cpp *this, + char *name, + magic_define_fun fun) +{ + struct define* def=alloc_empty_define(make_shared_string(name),0); + def->magic=fun; + this->defines=hash_insert(this->defines, & def->link); +} + +static void simple_add_define(struct cpp *this, + char *name, + char *what) +{ + struct define* def=alloc_empty_define(make_shared_string(name),0); + def->first=make_shared_string(what); + this->defines=hash_insert(this->defines, & def->link); +} + + +/* Who needs inline functions anyway? /Hubbe */ + +#define FIND_END_OF_STRING() do { \ + while(1) \ + { \ + if(pos>=len) \ + { \ + cpp_error(this,"End of file in string."); \ + break; \ + } \ + switch(data[pos++]) \ + { \ + case '\n': \ + cpp_error(this,"Newline in string."); \ + this->current_line++; \ + break; \ + case '"': break; \ + case '\\': if(data[++pos]=='\n') this->current_line++; \ + default: continue; \ + } \ + break; \ + } } while(0) + + +#define FIND_END_OF_CHAR() do { \ + int e=0; \ + while(1) \ + { \ + if(pos+1>=len) \ + { \ + cpp_error(this,"End of file in character constant."); \ + break; \ + } \ + \ + if(e++>16) \ + { \ + cpp_error(this,"Too long character constant."); \ + break; \ + } \ + \ + switch(data[pos++]) \ + { \ + case '\n': \ + cpp_error(this,"Newline in char."); \ + this->current_line++; \ + break; \ + case '\'': break; \ + case '\\': if(data[++pos]=='\n') this->current_line++; \ + default: continue; \ + } \ + break; \ + } } while(0) + +#define DUMPPOS(X) \ + fprintf(stderr,"\nPOS(%s):",X); \ + fflush(stderr); \ + write(2,data+pos,20); \ + fprintf(stderr,"\n"); \ + fflush(stderr) + +#define FIND_EOL() do { \ + this->current_line++; \ + while(pos < len && data[pos]!='\n') pos++; \ + } while(0) + +#define SKIPWHITE() do { \ + if(!isspace(data[pos])) break; \ + PUTNL(); \ + pos++; \ + } while(0) + +#define SKIPSPACE() \ + do { while(isspace(data[pos]) && data[pos]!='\n') pos++; }while (0) + +#define SKIPCOMMENT() do{ \ + pos++; \ + while(data[pos]!='*' || data[pos+1]!='/') \ + { \ + if(pos+2>=len) \ + { \ + cpp_error(this,"End of file in comment."); \ + break; \ + } \ + \ + if(data[pos]=='\n') \ + { \ + this->current_line++; \ + PUTNL(); \ + } \ + \ + pos++; \ + } \ + pos+=2; \ + }while(0) + +#define READCHAR(C) do { \ + switch(data[++pos]) \ + { \ + case 'n': C='\n'; break; \ + case 'r': C='\r'; break; \ + case 'b': C='\b'; break; \ + case 't': C='\t'; break; \ + \ + case '0': case '1': case '2': case '3': \ + case '4': case '5': case '6': case '7': \ + C=data[pos]-'0'; \ + if(data[pos+1]>='0' && data[pos+1]<='8') \ + { \ + C*=8; \ + C+=data[++pos]-'0'; \ + \ + if(data[pos+1]>='0' && data[pos+1]<='8') \ + { \ + C*=8; \ + C+=data[++pos]-'0'; \ + } \ + } \ + break; \ + \ + case '\n': \ + this->current_line++; \ + C='\n'; \ + break; \ + \ + default: \ + C=data[pos]; \ + } \ +}while (0) + + +#define READSTRING(nf) \ +while(1) \ +{ \ + pos++; \ + if(pos>=len) \ + { \ + cpp_error(this,"End of file in string."); \ + break; \ + } \ + \ + switch(data[pos]) \ + { \ + case '\n': \ + cpp_error(this,"Newline in string."); \ + this->current_line++; \ + break; \ + case '"': break; \ + case '\\': \ + { \ + int tmp; \ + READCHAR(tmp); \ + low_my_putchar(tmp, &nf); \ + continue; \ + } \ + \ + default: \ + low_my_putchar(data[pos], &nf); \ + continue; \ + } \ + pos++; \ + break; \ +} + +void PUSH_STRING(char *str, + INT32 len, + dynamic_buffer *buf) +{ + INT32 p2; + low_my_putchar('"', buf); + for(p2=0;p2<len;p2++) + { + switch(str[p2]) + { + case '\n': + low_my_putchar('\\', buf); + low_my_putchar('n', buf); + break; + + case '\t': + low_my_putchar('\\', buf); + low_my_putchar('t', buf); + break; + + case '\r': + low_my_putchar('\\', buf); + low_my_putchar('r', buf); + break; + + case '\b': + low_my_putchar('\\', buf); + low_my_putchar('b', buf); + break; + + case '\\': + case '"': + low_my_putchar('\\', buf); + low_my_putchar(str[p2], buf); + break; + + default: + if(isprint(EXTRACT_UCHAR(str+p2))) + { + low_my_putchar(str[p2], buf); + } + else + { + int c=EXTRACT_UCHAR(str+p2); + low_my_putchar('\\', buf); + low_my_putchar(((c>>6)&7)+'0', buf); + low_my_putchar(((c>>3)&7)+'0', buf); + low_my_putchar((c&7)+'0', buf); + } + break; + } + } + low_my_putchar('"', buf); +} + +#define FINDTOK() \ + do { \ + SKIPSPACE(); \ + if(data[pos]=='/') \ + { \ + INT32 tmp; \ + switch(data[pos+1]) \ + { \ + case '/': \ + FIND_EOL(); \ + break; \ + \ + case '*': \ + tmp=pos+2; \ + while(1) \ + { \ + if(data[tmp]=='*') \ + { \ + if(data[tmp+1] == '/') \ + { \ + pos=tmp+2; \ + break; \ + } \ + break; \ + } \ + \ + if(data[tmp]=='\n') \ + break; \ + tmp++; \ + } \ + } \ + } \ + break; \ + }while(1) + +static INLINE int find_end_parenthesis(struct cpp *this, + char *data, + INT32 len, + INT32 pos) /* position of first " */ +{ + while(1) + { + if(pos+1>=len) + { + cpp_error(this,"End of file while looking for end parenthesis."); + return pos; + } + + switch(data[pos++]) + { + case '\n': this->current_line++; break; + case '\'': FIND_END_OF_CHAR(); break; + case '"': FIND_END_OF_STRING(); break; + case '(': pos=find_end_parenthesis(this, data, len, pos); break; + case ')': return pos; + } + } +} + +static INT32 low_cpp(struct cpp *this, + char *data, + INT32 len, + int flags) +{ + INT32 pos, tmp, e; + + for(pos=0;pos<len;) + { +/* fprintf(stderr,"%c",data[pos]); + fflush(stderr); */ + + switch(data[pos++]) + { + case '\n': + if(flags & CPP_END_AT_NEWLINE) return pos-1; + +/* fprintf(stderr,"CURRENT LINE: %d\n",this->current_line); */ + this->current_line++; + PUTNL(); + goto do_skipwhite; + + case '\t': + case ' ': + case '\r': + PUTC(' '); + + do_skipwhite: + while(data[pos]==' ' || data[pos]=='\r' || data[pos]=='\t') + pos++; + break; + + /* Minor optimization */ + case '!': case '@': case '$': case '%': case '^': case '&': + case '*': case '(': case ')': case '-': case '=': case '+': + case '{': case '}': case ':': case '?': case '`': case ';': + case '<': case '>': case ',': case '.': case '~': case '[': + case ']': case '|': + PUTC(data[pos-1]); + break; + + default: + if(OUTP() && isidchar(data[pos-1])) + { + struct pike_string *s=0; + struct define *d=0; + tmp=pos-1; + while(isidchar(data[pos])) pos++; + + if(flags & CPP_DO_IF) + { + if(pos-tmp == 7 && !strncmp("defined",data+tmp, 7)) + { + d=defined_macro; + } + else if((pos-tmp == 4 && !strncmp("efun",data+tmp, 4)) || + (pos-tmp == 8 && !strncmp("constant",data+tmp,8))) + { + d=constant_macro; + } + else + { + goto do_find_define; + } + }else{ + do_find_define: + if((s=binary_findstring(data+tmp, pos-tmp))) + { + d=find_define(s); + } + } + + if(d && !d->inside) + { + int arg=0; + dynamic_buffer tmp; + struct define_argument arguments [MAX_ARGS]; + + if(s) s->refs++; + + if(d->args>=0) + { + SKIPWHITE(); + + if(!GOBBLE('(')) + { + cpp_error(this,"Missing '(' in macro call."); + break; + } + + for(arg=0;arg<d->args;arg++) + { + SKIPWHITE(); + arguments[arg].arg=data + pos; + if(data[pos]==')') + { + cpp_error(this,"Too few arguments to macro."); + break; + } + + while(1) + { + if(pos+1>len) + { + cpp_error(this,"End of file in macro call."); + break; + } + + switch(data[pos++]) + { + case '\n': + this->current_line++; + PUTNL(); + default: continue; + + case '"': + FIND_END_OF_STRING(); + continue; + + case '\'': + FIND_END_OF_CHAR(); + continue; + + case '(': + pos=find_end_parenthesis(this, data, len, pos); + continue; + + case ')': pos--; + case ',': + break; + } + break; + } + arguments[arg].len=data+pos-arguments[arg].arg; + } + SKIPWHITE(); + if(!GOBBLE(')')) + cpp_error(this,"Missing ) in macro call."); + } + + if(d->args >= 0 && arg != d->args) + cpp_error(this,"Wrong number of arguments to macro."); + + initialize_buf(&tmp); + if(d->magic) + { + d->magic(this, d, arguments, &tmp); + }else{ + low_my_binary_strcat(d->first->str, d->first->len, &tmp); + for(e=0;e<d->num_parts;e++) + { + char *a; + INT32 l; + + if((d->parts[e].argument & DEF_ARG_MASK) < 0 || + (d->parts[e].argument & DEF_ARG_MASK) >= arg) + { + cpp_error(this,"Macro not expanded correctly."); + continue; + } + + a=arguments[d->parts[e].argument&DEF_ARG_MASK].arg; + l=arguments[d->parts[e].argument&DEF_ARG_MASK].len; + + if(!(d->parts[e].argument & DEF_ARG_NOPRESPACE)) + low_my_putchar(' ', &tmp); + + if(d->parts[e].argument & DEF_ARG_STRINGIFY) + { + PUSH_STRING(a,l,&tmp); + }else{ + low_my_binary_strcat(a, l, &tmp); + } + + if(!(d->parts[e].argument & DEF_ARG_NOPOSTSPACE)) + low_my_putchar(' ', &tmp); + + low_my_binary_strcat(d->parts[e].postfix->str, + d->parts[e].postfix->len, + &tmp); + } + } + + /* FIXME */ + for(e=0;e<(long)tmp.s.len;e++) + if(tmp.s.str[e]=='\n') + tmp.s.str[e]=' '; + + if(s) d->inside=1; + + low_my_putchar(0, &tmp); + tmp.s.len--; + + low_cpp(this, tmp.s.str, tmp.s.len, + flags & ~(CPP_EXPECT_ENDIF | CPP_EXPECT_ELSE)); + + if(s) + { + if((d=find_define(s))) + d->inside=0; + + free_string(s); + } + + toss_buffer(&tmp); + break; + }else{ + if(flags & CPP_DO_IF) + { + STRCAT(" 0 ", 3); + }else{ + STRCAT(data+tmp, pos-tmp); + } + } + }else{ + PUTC(data[pos-1]); + } + break; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + PUTC(data[pos-1]); + while(data[pos]>='0' && data[pos]<='9') PUTC(data[pos++]); + break; + + case '"': + tmp=pos-1; + FIND_END_OF_STRING(); + STRCAT(data+tmp, pos-tmp); + break; + + case '\'': + tmp=pos-1; + FIND_END_OF_CHAR(); + STRCAT(data+tmp, pos-tmp); + break; + + case '/': + if(data[pos]=='/') + { + FIND_EOL(); + break; + } + + if(data[pos]=='*') + { + PUTC(' '); + SKIPCOMMENT(); + break; + } + + PUTC(data[pos-1]); + break; + + case '#': + if(GOBBLE('!')) + { + FIND_EOL(); + break; + } + SKIPSPACE(); + + switch(data[pos]) + { + case 'l': + if(WGOBBLE("line")) + { + while(data[pos]==' ' || data[pos]=='\t') pos++; + }else{ + goto unknown_preprocessor_directive; + } + /* Fall through */ + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + { + char *foo=data+pos; + this->current_line=STRTOL(foo, &foo, 10)-1; + pos=foo-data; + SKIPSPACE(); + + if(data[pos]=='"') + { + dynamic_buffer nf; + initialize_buf(&nf); + + READSTRING(nf); + + free_string(this->current_file); + this->current_file=low_free_buf(&nf); + } + + FIND_EOL(); + break; + } + + case 'i': /* include, if, ifdef */ + if(WGOBBLE("include")) + { + struct svalue *save_sp=sp; + SKIPSPACE(); + + check_stack(3); + + switch(data[pos++]) + { + case '"': + { + dynamic_buffer nf; + initialize_buf(&nf); + pos--; + READSTRING(nf); + push_string(low_free_buf(&nf)); + ref_push_string(this->current_file); + push_int(1); + break; + } + + case '<': + { + INT32 tmp=pos; + while(data[pos]!='>') + { + if(data[pos]=='\n') + { + cpp_error(this,"Expecting '>' in include."); + break; + } + + pos++; + } + push_string(make_shared_binary_string(data+tmp, pos-tmp)); + ref_push_string(this->current_file); + pos++; + push_int(0); + break; + } + + default: + cpp_error(this,"Expected file to include."); + break; + } + + if(sp==save_sp) break; + + if(OUTP()) + { + struct pike_string *new_file; + + SAFE_APPLY_MASTER("handle_include",3); + + if(sp[-1].type != T_STRING) + { + cpp_error(this,"Couldn't include file."); + pop_n_elems(sp-save_sp); + break; + } + + new_file=sp[-1].u.string; + + assign_svalue_no_free(sp,sp-1); + sp++; + + SAFE_APPLY_MASTER("read_include",1); + + if(sp[-1].type != T_STRING) + { + cpp_error(this,"Couldn't read include file."); + pop_n_elems(sp-save_sp); + break; + } + + + { + char buffer[47]; + struct pike_string *save_current_file; + INT32 save_current_line; + + save_current_file=this->current_file; + save_current_line=this->current_line; + copy_shared_string(this->current_file,new_file); + + low_my_binary_strcat("# 1 ",4,&this->buf); + PUSH_STRING(new_file->str,new_file->len, & this->buf); + low_my_putchar('\n',&this->buf); + + + low_cpp(this, + sp[-1].u.string->str, + sp[-1].u.string->len, + flags&~(CPP_EXPECT_ENDIF | CPP_EXPECT_ELSE)); + + free_string(this->current_file); + this->current_file=save_current_file; + this->current_line=save_current_line; + + sprintf(buffer,"# %d ",this->current_line); + low_my_binary_strcat(buffer,strlen(buffer),&this->buf); + PUSH_STRING(this->current_file->str,this->current_file->len,& this->buf); + low_my_putchar('\n',&this->buf); + } + } + + pop_n_elems(sp-save_sp); + + break; + } + + if(WGOBBLE("if")) + { + dynamic_buffer save,tmp; + INT32 nflags=CPP_EXPECT_ELSE | CPP_EXPECT_ENDIF; + + if(!OUTP()) + nflags|=CPP_REALLY_NO_OUTPUT; + + save=this->buf; + initialize_buf(& this->buf); + pos+=low_cpp(this,data+pos,len-pos,CPP_END_AT_NEWLINE|CPP_DO_IF); + tmp=this->buf; + this->buf=save; + + low_my_putchar(0, &tmp); + tmp.s.len--; + + calc(this,tmp.s.str,tmp.s.len,0); + toss_buffer(&tmp); + if(IS_ZERO(sp-1)) nflags|=CPP_NO_OUTPUT; + pop_stack(); + pos+=low_cpp(this,data+pos,len-pos,nflags); + break; + } + + if(WGOBBLE("ifdef")) + { + INT32 namestart,nflags; + struct pike_string *s; + SKIPSPACE(); + + if(!isidchar(data[pos])) + cpp_error(this,"#ifdef what?\n"); + + namestart=pos; + while(isidchar(data[pos])) pos++; + nflags=CPP_EXPECT_ELSE | CPP_EXPECT_ENDIF | CPP_NO_OUTPUT; + + if(!OUTP()) + nflags|=CPP_REALLY_NO_OUTPUT; + + if((s=binary_findstring(data+namestart,pos-namestart))) + if(find_define(s)) + nflags&=~CPP_NO_OUTPUT; + + pos+=low_cpp(this,data+pos,len-pos,nflags); + break; + } + + if(WGOBBLE("ifndef")) + { + INT32 namestart,nflags; + struct pike_string *s; + SKIPSPACE(); + + if(!isidchar(data[pos])) + cpp_error(this,"#ifndef what?"); + + namestart=pos; + while(isidchar(data[pos])) pos++; + nflags=CPP_EXPECT_ELSE | CPP_EXPECT_ENDIF; + + if(!OUTP()) + nflags|=CPP_REALLY_NO_OUTPUT; + + if((s=binary_findstring(data+namestart,pos-namestart))) + if(find_define(s)) + nflags|=CPP_NO_OUTPUT; + + pos+=low_cpp(this,data+pos,len-pos,nflags); + break; + } + + goto unknown_preprocessor_directive; + + case 'e': /* endif, else, elif, error */ + if(WGOBBLE("endif")) + { + if(!(flags & CPP_EXPECT_ENDIF)) + cpp_error(this,"Unmatched #endif"); + + return pos; + } + + if(WGOBBLE("else")) + { + if(!(flags & CPP_EXPECT_ELSE)) + cpp_error(this,"Unmatched #else"); + + flags&=~CPP_EXPECT_ELSE; + flags|=CPP_EXPECT_ENDIF; + + if(flags & CPP_NO_OUTPUT) + flags&=~CPP_NO_OUTPUT; + else + flags|=CPP_NO_OUTPUT; + + break; + } + + if(WGOBBLE("elif") || WGOBBLE("elseif")) + { + if(!(flags & CPP_EXPECT_ELSE)) + cpp_error(this,"Unmatched #elif"); + + flags|=CPP_EXPECT_ENDIF; + + if(flags & CPP_NO_OUTPUT) + { + dynamic_buffer save,tmp; + save=this->buf; + initialize_buf(& this->buf); + pos+=low_cpp(this,data+pos,len-pos,CPP_END_AT_NEWLINE|CPP_DO_IF); + tmp=this->buf; + this->buf=save; + + low_my_putchar(0, &tmp); + tmp.s.len--; + + calc(this,tmp.s.str,tmp.s.len,0); + toss_buffer(&tmp); + if(!IS_ZERO(sp-1)) flags&=~CPP_NO_OUTPUT; + pop_stack(); + }else{ + FIND_EOL(); + flags|= CPP_NO_OUTPUT | CPP_REALLY_NO_OUTPUT; + } + break; + } + + if(WGOBBLE("error")) + { + INT32 foo; + SKIPSPACE(); + foo=pos; + FIND_EOL(); + pos++; + if(OUTP()) + { + push_string(make_shared_binary_string(data+foo,pos-foo)); + cpp_error(this,sp[-1].u.string->str); + } + break; + } + + goto unknown_preprocessor_directive; + + case 'd': /* define */ + if(WGOBBLE("define")) + { + dynamic_buffer str; + INT32 namestart, tmp3, nameend, argno=-1; + struct define *def; + struct svalue *partbase,*argbase=sp; + + SKIPSPACE(); + + namestart=pos; + if(!isidchar(data[pos])) + cpp_error(this,"Define what?"); + + while(isidchar(data[pos])) pos++; + nameend=pos; + + if(GOBBLE('(')) + { + argno=0; + SKIPWHITE(); + + while(data[pos]!=')') + { + INT32 tmp2; + if(argno) + { + if(!GOBBLE(',')) + cpp_error(this,"Expecting comma in macro definition."); + SKIPWHITE(); + } + tmp2=pos; + + if(!isidchar(data[pos])) + { + cpp_error(this,"Expected argument for macro."); + break; + } + + while(isidchar(data[pos])) pos++; + check_stack(1); + push_string(make_shared_binary_string(data+tmp2, pos-tmp2)); + + SKIPWHITE(); + argno++; + if(argno>=MAX_ARGS) + { + cpp_error(this,"Too many arguments in macro definition."); + pop_stack(); + argno--; + } + } + + if(!GOBBLE(')')) + cpp_error(this,"Missing ) in macro definition."); + } + + SKIPSPACE(); + + partbase=sp; + initialize_buf(&str); + + while(1) + { + INT32 extra=0; + +/* fprintf(stderr,"%c",data[pos]); + fflush(stderr); */ + + switch(data[pos++]) + { + case '/': + if(data[pos]=='/') + { + low_my_putchar(' ',&str); + FIND_EOL(); + continue; + } + + if(data[pos]=='*') + { + PUTC(' '); + SKIPCOMMENT(); + continue; + } + + low_my_putchar('/',&str); + continue; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + low_my_putchar(data[pos-1],&str); + while(data[pos]>='0' && data[pos]<='9') + low_my_putchar(data[pos++],&str); + continue; + + case '#': + if(GOBBLE('#')) + { + extra=DEF_ARG_NOPRESPACE; + while(str.s.len && isspace(str.s.str[str.s.len-1])) + str.s.len--; + }else{ + extra=DEF_ARG_STRINGIFY; + } + SKIPSPACE(); + + /* fall through */ + + default: + if(isidchar(data[pos-1])) + { + struct pike_string *s; + tmp3=pos-1; + while(isidchar(data[pos])) pos++; + if(argno>0) + { + if((s=binary_findstring(data+tmp3,pos-tmp3))) + { + for(e=0;e<argno;e++) + { + if(argbase[e].u.string == s) + { + check_stack(2); + push_string(low_free_buf(&str)); + initialize_buf(&str); + push_int(e | extra); + extra=0; + break; + } + } + if(e!=argno) continue; + } + } + low_my_binary_strcat(data+tmp3,pos-tmp3, &str); + }else{ + low_my_putchar(data[pos-1],&str); + } + extra=0; + continue; + + case '"': + tmp3=pos-1; + FIND_END_OF_STRING(); + low_my_binary_strcat(data+tmp3, pos-tmp3, &str); + continue; + + case '\'': + tmp3=pos-1; + FIND_END_OF_CHAR(); + low_my_binary_strcat(data+tmp3, pos-tmp3, &str); + continue; + + case '\\': + if(GOBBLE('\n')) + { + this->current_line++; + PUTNL(); + } + continue; + + case '\n': + PUTNL(); + this->current_line++; + case 0: + break; + } + push_string(low_free_buf(&str)); + break; + } + + if(OUTP()) + { + def=alloc_empty_define(make_shared_binary_string(data+namestart, + nameend-namestart), + (sp-partbase)/2); + copy_shared_string(def->first, partbase->u.string); + def->args=argno; + + for(e=0;e<def->num_parts;e++) + { +#if 1 + if(partbase[e*2+1].type != T_INT) + fatal("Cpp internal error, expected integer!\n"); + + if(partbase[e*2+2].type != T_STRING) + fatal("Cpp internal error, expected string!\n"); +#endif + def->parts[e].argument=partbase[e*2+1].u.integer; + copy_shared_string(def->parts[e].postfix, + partbase[e*2+2].u.string); + } + +#ifdef DEBUG + if(def->num_parts==1 && + (def->parts[0].argument & DEF_ARG_MASK) > MAX_ARGS) + fatal("Internal error in define\n"); +#endif + + this->defines=hash_insert(this->defines, & def->link); + + } + pop_n_elems(sp-argbase); + break; + } + + goto unknown_preprocessor_directive; + + case 'u': /* undefine */ + if(WGOBBLE("undefine") || WGOBBLE("undef")) + { + INT32 tmp; + struct pike_string *s; + + SKIPSPACE(); + + tmp=pos; + if(!isidchar(data[pos])) + cpp_error(this,"Undefine what?"); + + while(isidchar(data[pos])) pos++; + + if(OUTP()) + { + if((s=binary_findstring(data+pos, pos-tmp))) + undefine(this,s); + } + + break; + } + + goto unknown_preprocessor_directive; + + case 'p': /* pragma */ + if(WGOBBLE("pragma")) + { + if(OUTP()) + STRCAT("#pragma", 7); + else + FIND_EOL(); + break; + } + + default: + unknown_preprocessor_directive: + { + char buffer[180]; + int i; + for(i=0;i<(long)sizeof(buffer)-1;i++) + { + if(!isidchar(data[pos])) break; + buffer[i]=data[pos++]; + } + buffer[i]=0; + + cpp_error(this,"Unknown preprocessor directive."); + } + } + } + } + + if(flags & CPP_EXPECT_ENDIF) + error("End of file while searching for #endif\n"); + + return pos; +} + +static INT32 calcC(struct cpp *this,char *data,INT32 len,INT32 pos) +{ + FINDTOK(); + +/* DUMPPOS("calcC"); */ + + switch(data[pos]) + { + case '(': + pos=calc1(this,data,len,pos+1); + FINDTOK(); + if(!GOBBLE(')')) + error("Missing ')'\n"); + break; + + case '0': + if(data[pos+1]=='x' || data[pos+1]=='X') + { + char *p; + push_int(STRTOL(data+pos+2, &p, 16)); + pos=p-data; + break; + } + + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + { + char *p1,*p2; + double f; + long l; + + f=my_strtod(data+pos, &p1); + l=STRTOL(data+pos, &p2, 0); + if(p1 > p2) + { + push_float(f); + pos=p1-data; + }else{ + push_int(l); + pos=p2-data; + } + break; + } + + case '\'': + { + int tmp; + READCHAR(tmp); + pos++; + if(!GOBBLE('\'')) + error("Missing end quote in character constant.\n"); + push_int(tmp); + break; + } + + case '"': + { + dynamic_buffer s; + initialize_buf(&s); + READSTRING(s); + push_string(low_free_buf(&s)); + break; + } + + default: +#ifdef DEBUG + if(isidchar(data[pos])) + error("Syntax error in #if (should not happen)\n"); +#endif + + error("Syntax error in #if.\n"); + } + + + FINDTOK(); + + while(GOBBLE('[')) + { + pos=calc1(this,data,len,pos); + f_index(2); + + FINDTOK(); + if(!GOBBLE(']')) + error("Missing ']'"); + } +/* DUMPPOS("after calcC"); */ + return pos; +} + +static INT32 calcB(struct cpp *this,char *data,INT32 len,INT32 pos) +{ + FINDTOK(); + switch(data[pos]) + { + case '-': pos++; pos=calcB(this,data,len,pos); o_negate(); break; + case '!': pos++; pos=calcB(this,data,len,pos); o_not(); break; + case '~': pos++; pos=calcB(this,data,len,pos); o_compl(); break; + default: pos=calcC(this,data,len,pos); + } +/* DUMPPOS("after calcB"); */ + return pos; +} + +static INT32 calcA(struct cpp *this,char *data,INT32 len,INT32 pos) +{ + pos=calcB(this,data,len,pos); + while(1) + { +/* DUMPPOS("inside calcA"); */ + FINDTOK(); + switch(data[pos]) + { + case '/': + if(data[1]=='/' || data[1]=='*') return pos; + pos++; + pos=calcB(this,data,len,pos); + o_divide(); + continue; + + case '*': + pos++; + pos=calcB(this,data,len,pos); + o_multiply(); + continue; + + case '%': + pos++; + pos=calcB(this,data,len,pos); + o_mod(); + continue; + } + break; + } +/* DUMPPOS("after calcA"); */ + return pos; +} + +static INT32 calc9(struct cpp *this,char *data,INT32 len,INT32 pos) +{ + pos=calcA(this,data,len,pos); + + while(1) + { + FINDTOK(); + switch(data[pos]) + { + case '+': + pos++; + pos=calcA(this,data,len,pos); + f_add(2); + continue; + + case '-': + pos++; + pos=calcA(this,data,len,pos); + o_subtract(); + continue; + } + break; + } + +/* DUMPPOS("after calc9"); */ + return pos; +} + +static INT32 calc8(struct cpp *this,char *data,INT32 len,INT32 pos) +{ + pos=calc9(this,data,len,pos); + + while(1) + { + FINDTOK(); + if(GOBBLEOP("<<")) + { + pos=calc9(this,data,len,pos); + o_lsh(); + break; + } + + if(GOBBLEOP(">>")) + { + pos=calc9(this,data,len,pos); + o_rsh(); + break; + } + + break; + } + return pos; +} + +static INT32 calc7b(struct cpp *this,char *data,INT32 len,INT32 pos) +{ + pos=calc8(this,data,len,pos); + + while(1) + { + FINDTOK(); + + switch(data[pos]) + { + case '<': + if(data[pos]+1 == '<') break; + pos++; + if(GOBBLE('=')) + { + pos=calc8(this,data,len,pos); + f_le(2); + }else{ + pos=calc8(this,data,len,pos); + f_lt(2); + } + continue; + + case '>': + if(data[pos]+1 == '>') break; + pos++; + if(GOBBLE('=')) + { + pos=calc8(this,data,len,pos); + f_ge(2); + }else{ + pos=calc8(this,data,len,pos); + f_gt(2); + } + continue; + } + break; + } + return pos; +} + +static INT32 calc7(struct cpp *this,char *data,INT32 len,INT32 pos) +{ + pos=calc7b(this,data,len,pos); + + while(1) + { + FINDTOK(); + if(GOBBLEOP("==")) + { + pos=calc7b(this,data,len,pos); + f_eq(2); + continue; + } + + if(GOBBLEOP("!=")) + { + pos=calc7b(this,data,len,pos); + f_ne(2); + continue; + } + + break; + } + return pos; +} + +static INT32 calc6(struct cpp *this,char *data,INT32 len,INT32 pos) +{ + pos=calc7(this,data,len,pos); + + FINDTOK(); + while(data[pos] == '&' && data[pos+1]!='&') + { + pos++; + pos=calc7(this,data,len,pos); + o_and(); + } + return pos; +} + +static INT32 calc5(struct cpp *this,char *data,INT32 len,INT32 pos) +{ + pos=calc6(this,data,len,pos); + + FINDTOK(); + while(GOBBLE('^')) + { + pos=calc6(this,data,len,pos); + o_xor(); + } + return pos; +} + +static INT32 calc4(struct cpp *this,char *data,INT32 len,INT32 pos) +{ + pos=calc5(this,data,len,pos); + + FINDTOK(); + while(data[pos] == '|' && data[pos+1]!='|') + { + pos++; + pos=calc5(this,data,len,pos); + o_or(); + } + return pos; +} + +static INT32 calc3(struct cpp *this,char *data,INT32 len,INT32 pos) +{ + pos=calc4(this,data,len,pos); + + FINDTOK(); + while(GOBBLEOP("&&")) + { + check_destructed(sp-1); + if(IS_ZERO(sp-1)) + { + pos=calc4(this,data,len,pos); + pop_stack(); + }else{ + pop_stack(); + pos=calc4(this,data,len,pos); + } + } + return pos; +} + +static INT32 calc2(struct cpp *this,char *data,INT32 len,INT32 pos) +{ + pos=calc3(this,data,len,pos); + + FINDTOK(); + while(GOBBLEOP("||")) + { + check_destructed(sp-1); + if(!IS_ZERO(sp-1)) + { + pos=calc3(this,data,len,pos); + pop_stack(); + }else{ + pop_stack(); + pos=calc3(this,data,len,pos); + } + } + return pos; +} + +static INT32 calc1(struct cpp *this,char *data,INT32 len,INT32 pos) +{ + pos=calc2(this,data,len,pos); + + FINDTOK(); + + if(GOBBLE('?')) + { + pos=calc1(this,data,len,pos); + if(!GOBBLE(':')) + error("Colon expected"); + pos=calc1(this,data,len,pos); + + check_destructed(sp-3); + assign_svalue(sp-3,IS_ZERO(sp-3)?sp-1:sp-2); + pop_n_elems(2); + } + return pos; +} + +static int calc(struct cpp *this,char *data,INT32 len,INT32 tmp) +{ + JMP_BUF recovery; + INT32 pos; + +/* fprintf(stderr,"Calculating\n"); */ + + if (SETJMP(recovery)) + { + pos=tmp; + 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) + { + cpp_error(this,a->string->str); + }else{ + cpp_error(this,"Nonstandard error format."); + } + }else{ + cpp_error(this,"Nonstandard error format."); + } + FIND_EOL(); + push_int(0); + }else{ + pos=calc1(this,data,len,tmp); + check_destructed(sp-1); + } + UNSETJMP(recovery); + +/* fprintf(stderr,"Done\n"); */ + + return pos; +} + +void free_one_define(struct hash_entry *h) +{ + int e; + struct define *d=BASEOF(h, define, link); + + for(e=0;e<d->num_parts;e++) + free_string(d->parts[e].postfix); + if(d->first) + free_string(d->first); + free((char *)d); +} + +/*** Magic defines ***/ +static void insert_current_line(struct cpp *this, + struct define *def, + struct define_argument *args, + dynamic_buffer *tmp) +{ + char buf[20]; + sprintf(buf," %ld ",(long)this->current_line); + low_my_binary_strcat(buf, strlen(buf),tmp); +} + +static void insert_current_file_as_string(struct cpp *this, + struct define *def, + struct define_argument *args, + dynamic_buffer *tmp) +{ + PUSH_STRING(this->current_file->str, this->current_file->len, tmp); +} + +static void insert_current_time_as_string(struct cpp *this, + struct define *def, + struct define_argument *args, + dynamic_buffer *tmp) +{ + time_t tmp2; + char *buf; + time(&tmp2); + buf=ctime(&tmp2); + + PUSH_STRING(buf+11, 8, tmp); +} + +static void insert_current_date_as_string(struct cpp *this, + struct define *def, + struct define_argument *args, + dynamic_buffer *tmp) +{ + time_t tmp2; + char *buf; + time(&tmp2); + buf=ctime(&tmp2); + + PUSH_STRING(buf+19, 5, tmp); + PUSH_STRING(buf+4, 6, tmp); +} + +static void check_defined(struct cpp *this, + struct define *def, + struct define_argument *args, + dynamic_buffer *tmp) +{ + struct pike_string *s; + s=binary_findstring(args[0].arg, args[0].len); + if(s && find_define(s)) + { + low_my_binary_strcat(" 1 ", 3,tmp); + }else{ + low_my_binary_strcat(" 0 ", 3,tmp); + } +} + +static void check_constant(struct cpp *this, + struct define *def, + struct define_argument *args, + dynamic_buffer *tmp) +{ + struct pike_string *s; + s=binary_findstring(args[0].arg, args[0].len); + if(s && low_mapping_string_lookup(get_builtin_constants(), s)) + { + low_my_binary_strcat(" 1 ", 3,tmp); + }else{ + low_my_binary_strcat(" 0 ", 3,tmp); + } +} + + + +void f_cpp(INT32 args) +{ + struct pike_predef_s *tmpf; + struct cpp this; + if(args<1) + error("Too few arguments to cpp()\n"); + + if(sp[-args].type != T_STRING) + error("Bad argument 1 to cpp()\n"); + + if(args>1) + { + if(sp[1-args].type != T_STRING) + error("Bad argument 2 to cpp()\n"); + copy_shared_string(this.current_file, sp[1-args].u.string); + }else{ + this.current_file=make_shared_string("-"); + } + + initialize_buf(&this.buf); + this.current_line=1; + this.compile_errors=0; + this.defines=0; + do_magic_define(&this,"__LINE__",insert_current_line); + do_magic_define(&this,"__FILE__",insert_current_file_as_string); + do_magic_define(&this,"__DATE__",insert_current_date_as_string); + do_magic_define(&this,"__TIME__",insert_current_time_as_string); + simple_add_define(&this,"__PIKE__"," 1 "); + + for (tmpf=pike_predefs; tmpf; tmpf=tmpf->next) + simple_add_define(&this, tmpf->name, tmpf->value); + + low_my_binary_strcat("# 1 ",4,&this.buf); + PUSH_STRING(this.current_file->str,this.current_file->len,&this.buf); + low_my_putchar('\n',&this.buf); + + low_cpp(&this, sp[-args].u.string->str, sp[-args].u.string->len,0); + if(this.defines) + free_hashtable(this.defines, free_one_define); + + if(this.compile_errors) + { + error("Cpp() failed\n"); + }else{ + pop_n_elems(args); + free_string(this.current_file); + push_string(low_free_buf(&this.buf)); + } +} + +void init_cpp() +{ + defined_macro=alloc_empty_define(make_shared_string("defined"),0); + defined_macro->magic=check_defined; + defined_macro->args=1; + + constant_macro=alloc_empty_define(make_shared_string("constant"),0); + constant_macro->magic=check_constant; + constant_macro->args=1; + + add_efun("cpp",f_cpp,"function(string,string|void:string)",OPT_EXTERNAL_DEPEND); +} + + +void add_predefine(char *s) +{ + struct pike_predef_s *tmp=ALLOC_STRUCT(pike_predef_s); + char * pos=STRCHR(s,'='); + if(pos) + { + tmp->name=(char *)xalloc(pos-s+1); + MEMCPY(tmp->name,s,pos-s); + tmp->name[pos-s]=0; + + tmp->value=(char *)xalloc(s+strlen(s)-pos); + MEMCPY(tmp->value,pos+1,s+strlen(s)-pos); + }else{ + tmp->name=(char *)xalloc(strlen(s)+1); + MEMCPY(tmp->name,s,strlen(s)+1); + + tmp->value=(char *)xalloc(4); + MEMCPY(tmp->value," 1 ",4); + } + tmp->next=pike_predefs; + pike_predefs=tmp; +} + +void exit_cpp() +{ + struct pike_predef_s *tmp; + while((tmp=pike_predefs)) + { + free(tmp->name); + free(tmp->value); + pike_predefs=tmp->next; + free((char *)tmp); + } +} diff --git a/src/docode.c b/src/docode.c index c6a3bcb7a92fc76979b30ad1e87996b17c64a906..2d1d1b35243574d36b4866834cb5f8074e808ccc 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.16 1997/04/17 22:47:06 hubbe Exp $"); +RCSID("$Id: docode.c,v 1.16.2.1 1997/06/25 22:46:36 hubbe Exp $"); #include "las.h" #include "program.h" #include "language.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"); } } @@ -294,6 +261,11 @@ static int do_docode2(node *n,int flags) switch(n->token) { + 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); @@ -440,7 +412,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"); @@ -449,7 +421,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)->flags)) + if(!IDENTIFIER_IS_VARIABLE( ID_FROM_INT(new_program, CDR(n)->u.number)->flags)) { yyerror("Cannot assign functions or constants.\n"); }else{ @@ -500,7 +472,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; @@ -702,7 +674,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)->flags)) + IDENTIFIER_IS_FUNCTION(ID_FROM_INT(new_program, CAR(n)->u.number)->flags)) { emit2(F_MARK); do_docode(CDR(n),0); @@ -1034,7 +1006,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) { @@ -1046,7 +1018,7 @@ static int do_docode2(node *n,int flags) } case F_IDENTIFIER: - if(IDENTIFIER_IS_FUNCTION(ID_FROM_INT(& fake_program, n->u.number)->flags)) + if(IDENTIFIER_IS_FUNCTION(ID_FROM_INT(new_program, n->u.number)->flags)) { if(flags & DO_LVALUE) { diff --git a/src/docode.h b/src/docode.h index b197c0cde4dfe53f46689972342448f281a28a67..7eb6130bc6e0c01b16eac47cdf8b8b74d48523a5 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 push_explicit(INT32 address); INT32 pop_address(); +int alloc_label(); +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/interpret.c b/src/interpret.c index 5c6d7a6f3c267d843cb8473afe1ef32da9fc9d9d..28b4730238625e7b8cfc6840f7e4d4c9361a7315 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.42 1997/04/16 03:09:11 hubbe Exp $"); +RCSID("$Id: interpret.c,v 1.42.2.1 1997/06/25 22:46:37 hubbe Exp $"); #include "interpret.h" #include "object.h" #include "program.h" @@ -614,6 +614,7 @@ static void eval_instruction(unsigned char *pc) print_return_value(); break; + CASE(F_MARK_AND_LOCAL); *(mark_sp++)=sp; CASE(F_LOCAL); assign_svalue_no_free(sp++,fp->locals+GET_ARG()); @@ -1340,12 +1341,29 @@ void apply_low(struct object *o, int fun, int args) if(function->func.offset == -1) error("Calling undefined function '%s'.\n",function->name->str); - if(function->flags & IDENTIFIER_C_FUNCTION) + switch(function->flags & (IDENTIFIER_FUNCTION | IDENTIFIER_CONSTANT)) { + case IDENTIFIER_C_FUNCTION: fp->num_args=args; new_frame.num_locals=args; (*function->func.c_fun)(args); - }else{ + 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,args); + push_object(tmp); + }else{ + error("Calling strange value!\n"); + } + break; + } + + case IDENTIFIER_PIKE_FUNCTION: + { int num_args; int num_locals; unsigned char *pc; @@ -1388,6 +1406,9 @@ void apply_low(struct object *o, int fun, int args) if(sp<evaluator_stack) fatal("Stack error (also simple).\n"); #endif + break; + } + } if(sp - new_frame.locals > 1) @@ -1495,7 +1516,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, FIND_LFUN(o->prog,fun), args); } void apply_shared(struct object *o, diff --git a/src/interpret.h b/src/interpret.h index c9a47e19c18d3db1282aabfcca60ac8d03c31cf8..3768ed054655eea924e81a5c968d0f2e2922fc80 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) diff --git a/src/language.yacc b/src/language.yacc index cf53c114e44b0bb4edc6160e44d14e7cdf1de5a5..7c194632eb026a1d546a0f92ff3b7128fcd6e131 100644 --- a/src/language.yacc +++ b/src/language.yacc @@ -129,6 +129,7 @@ %token F_WHILE %token F_XOR_EQ %token F_NOP +%token F_UNDEFINED %token F_ALIGN %token F_POINTER @@ -156,7 +157,7 @@ /* This is the grammar definition of Pike. */ #include "global.h" -RCSID("$Id: language.yacc,v 1.42.2.1 1997/05/10 12:56:55 hubbe Exp $"); +RCSID("$Id: language.yacc,v 1.42.2.2 1997/06/25 22:46:38 hubbe Exp $"); #ifdef HAVE_MEMORY_H #include <memory.h> #endif @@ -176,19 +177,14 @@ RCSID("$Id: language.yacc,v 1.42.2.1 1997/05/10 12:56:55 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 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; @@ -205,16 +201,6 @@ void fix_comp_stack(int sp) } } -void pop_local_variables(int level) -{ - while(local_variables->current_number_of_locals > level) - { - int e; - e=--(local_variables->current_number_of_locals); - free_string(local_variables->variable[e].name); - free_string(local_variables->variable[e].type); - } -} %} @@ -359,9 +345,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 +355,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 +370,60 @@ 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: { + struct program *p=program_from_function(sp-1); + if(p) + { + p->refs++; + pop_stack(); + push_program(p); + 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(sp[-1].type == T_PROGRAM && + !(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); } + if($4) free_string($4); pop_n_elems(2); } ; @@ -441,19 +440,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 +462,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 +485,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 +537,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,36 +547,35 @@ 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); } - 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,7 +589,6 @@ def: modifiers type_or_error optional_stars F_IDENTIFIER '(' arguments ')' } ; - optional_dot_dot_dot: F_DOT_DOT_DOT { $$=1; } | /* empty */ { $$=0; } ; @@ -584,7 +597,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 ..."); @@ -594,7 +606,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); @@ -756,7 +770,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); @@ -766,7 +780,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); @@ -785,14 +799,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))); @@ -802,7 +816,7 @@ new_local_name: optional_stars F_IDENTIFIER block:'{' { - $<number>$=local_variables->current_number_of_locals; + $<number>$=compiler_frame->current_number_of_locals; } statements '}' { @@ -851,12 +865,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 { @@ -865,7 +879,6 @@ lambda: F_LAMBDA int f,e; struct pike_string *name; - setup_fake_program(); fix_comp_stack($<number>2); push_type(T_MIXED); @@ -873,7 +886,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(); @@ -882,24 +895,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); + + 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); } ; @@ -908,16 +924,48 @@ 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->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(compiler_pass == 1) + s.u.program=end_first_pass(0); + else + s.u.program=end_program(); + if(!s.u.program) { yyerror("Class definition failed."); @@ -927,11 +975,8 @@ class: modifiers F_CLASS optional_identifier s.type=T_PROGRAM; s.subtype=0; } - if($3) - { - add_constant($3, &s, $1); - free_string($3); - } + + free_string($3); $$=mksvaluenode(&s); free_svalue(&s); } @@ -939,7 +984,7 @@ class: modifiers F_CLASS optional_identifier cond: F_IF { - $<number>$=local_variables->current_number_of_locals; + $<number>$=compiler_frame->current_number_of_locals; } '(' comma_expr ')' statement optional_else_part { @@ -957,7 +1002,7 @@ optional_else_part: { $$=0; } foreach: F_FOREACH { - $<number>$=local_variables->current_number_of_locals; + $<number>$=compiler_frame->current_number_of_locals; } '(' expr0 ',' lvalue ')' statement { @@ -976,14 +1021,14 @@ do: F_DO statement F_WHILE '(' comma_expr ')' ';' for: F_FOR { - $<number>$=local_variables->current_number_of_locals; + $<number>$=compiler_frame->current_number_of_locals; } '(' unused ';' for_expr ';' unused ')' statement { - int i=current_line; - current_line=$1; + 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))); - current_line=i; + lex.current_line=i; pop_local_variables($<number>2); } ; @@ -991,14 +1036,14 @@ for: F_FOR while: F_WHILE { - $<number>$=local_variables->current_number_of_locals; + $<number>$=compiler_frame->current_number_of_locals; } '(' comma_expr ')' statement { - int i=current_line; - current_line=$1; + int i=lex.current_line; + lex.current_line=$1; $$=mknode(F_FOR,$4,mknode(':',$6,NULL)); - current_line=i; + lex.current_line=i; pop_local_variables($<number>2); } ; @@ -1009,7 +1054,7 @@ for_expr: /* EMPTY */ { $$=mkintnode(1); } switch: F_SWITCH { - $<number>$=local_variables->current_number_of_locals; + $<number>$=compiler_frame->current_number_of_locals; } '(' comma_expr ')' statement { @@ -1031,7 +1076,7 @@ case: F_CASE comma_expr ':' 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."); @@ -1053,9 +1098,9 @@ unused2: comma_expr { $$=mkcastnode(void_type_string,$1); } ; 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; } ; @@ -1213,8 +1258,7 @@ low_idents: F_IDENTIFIER { reference_shared_string($1); push_string($1); - reference_shared_string(current_file); - push_string(current_file); + ref_push_string(lex.current_file); SAFE_APPLY_MASTER("resolv", 2); if(throw_value.type == T_STRING) @@ -1229,7 +1273,12 @@ low_idents: F_IDENTIFIER } pop_stack(); }else{ - my_yyerror("'%s' undefined.", $1->str); + if(compiler_pass==2) + { + my_yyerror("'%s' undefined.", $1->str); + }else{ + $$=mknode(F_UNDEFINED,0,0); + } } } free_string($1); @@ -1253,10 +1302,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 || ID_FROM_PTR(new_program,idp)->func.offset == -1) { my_yyerror("Undefined identifier %s::%s", $1->str,$3->str); $$=mkintnode(0); @@ -1272,10 +1320,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($$) @@ -1357,9 +1404,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); } ; @@ -1380,10 +1425,10 @@ 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); @@ -1392,8 +1437,8 @@ void yyerror(char *str) pop_stack(); }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); } @@ -1403,18 +1448,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; } } } @@ -1423,27 +1468,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() -{ - 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 23c9066cee738b20a39d1cc9fd3bad6b2c080b8d..abf41900f6c514d54a9c2ee3ea20494e6605dd23 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.32 1997/04/18 01:17:40 hubbe Exp $"); +RCSID("$Id: las.c,v 1.32.2.1 1997/06/25 22:46:39 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; @@ -137,7 +136,7 @@ static node *free_nodes=0; void free_all_nodes() { - if(!local_variables) + if(!compiler_frame) { node *tmp; struct node_chunk *tmp2; @@ -240,7 +239,7 @@ static node *mkemptynode() 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 +272,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 +313,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) @@ -394,7 +399,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 +413,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)->flags)) + if(IDENTIFIER_IS_CONSTANT(ID_FROM_INT(new_program, i)->flags)) { res->node_info = OPT_EXTERNAL_DEPEND; }else{ @@ -462,12 +466,11 @@ void resolv_constant(node *n) break; case F_IDENTIFIER: - setup_fake_program(); - i=ID_FROM_INT(& fake_program, n->u.number); + i=ID_FROM_INT(new_program, n->u.number); if(IDENTIFIER_IS_CONSTANT(i->flags)) { - push_svalue(PROG_FROM_INT(&fake_program, n->u.number)->constants + + push_svalue(PROG_FROM_INT(new_program, n->u.number)->constants + i->func.offset); }else{ yyerror("Identifier is not a constant"); @@ -799,8 +802,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: @@ -1236,8 +1238,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: @@ -1278,11 +1279,11 @@ void fix_type_field(node *n) break; case F_RETURN: - 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) ) @@ -1361,7 +1362,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)) @@ -1374,7 +1375,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; @@ -1804,7 +1805,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 @@ -1839,10 +1840,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; @@ -1850,7 +1850,6 @@ int eval_low(node *n) ins_f_byte(F_DUMB_RETURN); store_linenumbers=1; - setup_fake_program(); ret=-1; if(!num_parse_error) { @@ -1893,21 +1892,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; } @@ -2037,7 +2034,6 @@ int dooptcode(struct pike_string *name, 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) @@ -2047,37 +2043,42 @@ 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); + } } ret=define_function(name, @@ -2090,6 +2091,4 @@ int dooptcode(struct pike_string *name, return ret; } -INT32 get_opt_info() { return last_function_opt_info; } - diff --git a/src/las.h b/src/las.h index 078670474766d8fde6c66d094b511c50d5441205..7b750e149a10fba4cd8018547fae8352d0459251 100644 --- a/src/las.h +++ b/src/las.h @@ -14,21 +14,6 @@ #define MAX_GLOBAL_VARIABLES 1000 -struct local_variable -{ - struct pike_string *name; - struct pike_string *type; -}; - -struct locals -{ - struct locals *next; - struct pike_string *current_type; - struct pike_string *current_return_type; - int current_number_of_locals; - int max_number_of_locals; - struct local_variable variable[MAX_LOCAL]; -}; void yyerror(char *s); int islocal(struct pike_string *str); @@ -55,10 +40,27 @@ struct node_s typedef struct node_s node; -extern struct locals *local_variables; 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 compiler_frame +{ + struct compiler_frame *previous; + + struct pike_string *current_type; + struct pike_string *current_return_type; + int current_number_of_locals; + int max_number_of_locals; + struct local_variable variable[MAX_LOCAL]; +}; #define OPT_OPTIMIZED 0x1 /* has been processed by optimize(), * only used in node_info @@ -126,20 +128,9 @@ INT32 get_opt_info(); #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 a5a99a7f3e59e90cbddec3f08575fbe53a1da954..507d5e682c3f1b818f59ecd07c67d3931532a880 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.21.2.1 1997/05/19 09:04:55 hubbe Exp $"); +RCSID("$Id: lex.c,v 1.21.2.2 1997/06/25 22:46:39 hubbe Exp $"); #include "language.h" #include "array.h" #include "lex.h" @@ -33,29 +33,8 @@ RCSID("$Id: lex.c,v 1.21.2.1 1997/05/19 09:04:55 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; -}; - -struct pike_predef_s *pike_predefs=0; - -static int calc(); -static void calc1(); - -void exit_lex() +void exit_lex(void) { #ifdef DEBUG if(p_flag) @@ -71,74 +50,8 @@ void exit_lex() } } #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 }, @@ -293,8 +206,6 @@ struct reserved int token; }; -struct hash_table *reswords; - void init_lex() { unsigned int i; @@ -309,24 +220,6 @@ void init_lex() 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() -{ - free_hashtable(reswords,0); } char *low_get_f_name(int n,struct program *p) @@ -390,1068 +283,210 @@ 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; -} - - - -/*** input routines ***/ -struct inputstate -{ - struct inputstate *next; - int fd; - unsigned char *data; - INT32 buflen; - INT32 pos; - int dont_free_data; - - int (*my_getc)(); - int (*gobble)(int); - int (*look)(); - void (*my_ungetc)(int); - void (*ungetstr)(char *,INT32); -}; - -#define MY_EOF 4711 +struct lex lex; -struct inputstate *istate=NULL; +#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) -static void link_inputstate(struct inputstate *i) -{ - i->next=istate; - istate=i; +#define READBUF(X) { \ + register int C; \ + buf=lex.pos; \ + while((C=LOOK()) && (X)) lex.pos++; \ + len=lex.pos - buf; \ } -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); -} +#define TWO_CHAR(X,Y) ((X)<<8)+(Y) +#define ISWORD(X) (len==(long)strlen(X) && !MEMCMP(buf,X,strlen(X))) -static struct inputstate *new_inputstate(); -static struct inputstate *memory_inputstate(INT32 size); +/*** Lexical analyzing ***/ -static int default_gobble(int c) +static int char_const(void) { - if(istate->look()==c) + int c; + switch(c=GETC()) { - istate->my_getc(); - return 1; - }else{ + 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'; + } -} - -static void default_ungetstr(char *s,INT32 len) -{ - link_inputstate(memory_inputstate(len+1000)); - istate->ungetstr(s,len); -} - -static void default_ungetc(int s) -{ - char c=s; - istate->ungetstr(&c,1); -} - -static int default_look() -{ - int c; - c=istate->my_getc(); - istate->my_ungetc(c); return c; } -static struct inputstate *new_inputstate() -{ - 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() { 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() -{ - 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() -{ - 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() -{ - if(istate->pos<istate->buflen) - { - 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(); - } -} - -/* 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); -} - -static void prot_memory_ungetc(int s) -{ - if(istate->pos && istate->data[istate->pos-1] == s) - { - istate->pos--; - }else{ - default_ungetc(s); - } -} - -/* allocate a memory, read-only, inputstate */ -static struct inputstate *prot_memory_inputstate(char *data,INT32 len) -{ - 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; + return low_free_buf(&tmp); } -/*** FILE input ***/ - -#define READAHEAD 8192 -static int file_getc() -{ - 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) - { - 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() -{ - int c; - c=istate->my_getc(); - if(c=='\n') current_line++; - return c; -} - -static void UNGETC(int c) -{ - if(c=='\n') current_line--; - istate->my_ungetc(c); -} - -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); -} - -static int GOBBLE(char c) +int yylex(YYSTYPE *yylval) +#if LEXDEBUG>4 { - if(istate->gobble(c)) + int t; + int yylex2(YYSTYPE *); + t=yylex2(yylval); + if(t<256) { - if(c=='\n') current_line++; - return 1; + fprintf(stderr,"yylex() -> '%c' (%d)\n",t,t); }else{ - return 0; + fprintf(stderr,"yylex() -> %s (%d)\n",get_f_name(t),t); } + return t; } -#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; \ -} - -static char buf[1024]; - -/*** Define handling ***/ - -struct define -{ - struct hash_entry link; /* must be first */ - void (*magic)(); - int args; - struct array *parts; -}; - -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)()) -{ - 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); +static int yylex2(YYSTYPE *yylval) #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)()) -{ - 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); - } -} - -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() { - if(defines) - free_hashtable(defines, free_one_define); - defines=0; -} - -static void do_define() -{ - int c,e,t,argc; - struct svalue *save_sp=sp; - struct svalue *args_sp; - struct pike_string *s, *s2; - - SKIPWHITE(); - READBUF(isidchar(C)); + INT32 c,len; + char *buf; - s=make_shared_string(buf); +#ifdef __CHECKER__ + MEMSET((char *)yylval,0,sizeof(YYSTYPE)); +#endif +#ifdef MALLOC_DEBUG + check_sfltable(); +#endif - if(GOBBLE('(')) + while(1) { - argc=0; - - SKIPWHITE(); - READBUF(isidchar(C)); - if(buf[0]) + switch(c=GETC()) { - push_string(make_shared_string(buf)); - argc++; - SKIPWHITE(); - while(GOBBLE(',')) - { - SKIPWHITE(); - READBUF(isidchar(C)); - push_string(make_shared_string(buf)); - argc++; - } - } - SKIPWHITE(); - - if(!GOBBLE(')')) - yyerror("Missing ')'"); - }else{ - argc=-1; - } - - args_sp=sp; + case 0: + lex.pos--; + return 0; - init_buf(); - t=0; - sp->type=T_STRING; - sp->u.string=make_shared_string(""); - sp++; + case '\n': + lex.current_line++; + continue; - while(1) - { - int tmp; + case '#': + SKIPSPACE(); + READBUF(C!=' ' && C!='\t' && C!='\n'); - c=GETC(); - if(c=='\\') if(GOBBLE('\n')) continue; - if( (t!=!!isidchar(c) && argc>0) || c=='\n' || c==MY_EOF) - { - s2=free_buf(); - tmp=0; - for(e=0;e<argc;e++) + switch(len>0?buf[0]:0) { - if(save_sp[e].u.string==s2) + 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('"')) { - free_string(s2); - push_int(e); - tmp=1; - break; + struct pike_string *tmp=readstring(); + free_string(lex.current_file); + lex.current_file=tmp; } - } - if(!tmp) - { - push_string(s2); - if(sp[-2].type==T_STRING) f_add(2); - } - if(c=='\n' || c==MY_EOF) - { - push_string(make_shared_string(" ")); - if(sp[-2].type==T_STRING) f_add(2); break; - } - t=!!isidchar(c); - init_buf(); - } - my_putchar(c); - } - UNGETC(c); - add_define(s,argc,sp-args_sp,0); - while(sp>save_sp) pop_stack(); -} - -/* 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; - - if(nexpands>EXPANDMAX) - { - yyerror("Macro limit exceeded."); - return 0; - } - - if(d->magic) - { - d->magic(); - return 1; - } - - if(d->args >= 0) - { - if(!save_newline) - { - SKIPWHITE(); - }else{ - do { e=GETC(); }while(ISSPACE(e) && e!='\n'); - UNGETC(e); - } - - if(GOBBLE('(')) - { - int parlvl,quote; - int c; - args=0; + + case 'e': + if(ISWORD("error")) + { + SKIPSPACE(); + READBUF(C!='\n'); + yyerror(buf); + break; + } + goto badhash; - SKIPWHITE(); - init_buf(); - parlvl=1; - quote=0; - while(parlvl) - { - switch(c=GETC()) + case 'p': + if(ISWORD("pragma")) { - 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) + SKIPSPACE(); + READBUF(C!='\n'); + if (strcmp(buf, "all_inline") == 0) { - push_string(free_buf()); - init_buf(); - args++; - continue; + lex.pragmas |= PRAGMA_ALL_INLINE; } + 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; - } - - 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 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: tmp=0; - } - 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; - } - - UNGETSTR("\" 2",3); - UNGETSTR(current_file->str,current_file->len); - sprintf(buf,"\n# %ld \"",(long)current_line+1); - UNGETSTR(buf,strlen(buf)); - - 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() -{ - int c; - switch(c=GETC()) - { - 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; - } - 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; - break; - - case 'd': - if(!strcmp("define",buf)) continue; - break; - - case 'u': - if(!strcmp("undef",buf)) continue; - break; - - case 'p': - if(!strcmp("pragma",buf)) continue; - break; - } - + badhash: 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); - } - } - 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; - } - 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()!='\'') + switch(c=GETC()) + { + case 0: + lex.pos--; + yyerror("Unexpected end of file\n"); + break; + + case '\\': + c=char_const(); + } + if(!GOBBLE('\'')) 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; - } - break; - } - if(literal) - { - strncpy(buf,return_buf(),sizeof(buf)); - buf[sizeof(buf)-1]=0; - yylval->str=buf; - }else{ - yylval->string=free_buf(); - } + yylval->string=readstring(); return F_STRING; case ':': @@ -1467,75 +502,32 @@ static int do_lex2(int literal, YYSTYPE *yylval) return c; case '0': - if(GOBBLE('x')) + if(GOBBLE('x') || GOBBLE('X')) { - READBUF(isxdigit(C)); - yylval->number=STRTOL(buf,NULL,16); + 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': { - 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')) + char *p1, *p2; + double f; + long l; + lex.pos--; + f=my_strtod(lex.pos, &p1); + l=STRTOL(lex.pos, &p2, 0); + + if(p1>p2) { - 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; + lex.pos=p1; + yylval->fnum=(float)f; return F_FLOAT; + }else{ + lex.pos=p2; + yylval->number=l; + return F_NUMBER; } - - 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; @@ -1571,23 +563,6 @@ static int do_lex2(int literal, YYSTYPE *yylval) 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 '/'; @@ -1698,17 +673,12 @@ static int do_lex2(int literal, YYSTYPE *yylval) default: yyerror("Illegal ` identifier."); - tmp=""; + lex.pos--; + tmp="`"; break; - } - if(literal) - { - yylval->str=buf; - }else{ - yylval->string=make_shared_string(tmp); - } + yylval->string=make_shared_string(tmp); return F_IDENTIFIER; } @@ -1717,38 +687,121 @@ static int do_lex2(int literal, YYSTYPE *yylval) if(isidchar(c)) { struct pike_string *s; - UNGETC(c); + lex.pos--; 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. - */ + yylval->number=lex.current_line; - s=findstring(buf); - if(s) + if(len>1 && len<10) + { + switch(TWO_CHAR(buf[0],buf[1])) { - 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); + case TWO_CHAR('a','r'): + if(ISWORD("array")) return F_ARRAY_ID; + break; + case TWO_CHAR('b','r'): + if(ISWORD("break")) return F_BREAK; + break; + case TWO_CHAR('c','a'): + if(ISWORD("case")) return F_CASE; + if(ISWORD("catch")) return F_CATCH; + break; + case TWO_CHAR('c','l'): + if(ISWORD("class")) return F_CLASS; + break; + case TWO_CHAR('c','o'): + if(ISWORD("constant")) return F_CONSTANT; + if(ISWORD("continue")) return F_CONTINUE; + break; + case TWO_CHAR('d','e'): + if(ISWORD("default")) return F_DEFAULT; + break; + case TWO_CHAR('d','o'): + if(ISWORD("do")) return F_DO; + break; + case TWO_CHAR('e','l'): + if(ISWORD("else")) return F_ELSE; + break; + case TWO_CHAR('f','l'): + if(ISWORD("float")) return F_FLOAT_ID; + break; + case TWO_CHAR('f','o'): + if(ISWORD("for")) return F_FOR; + if(ISWORD("foreach")) return F_FOREACH; + break; + case TWO_CHAR('f','u'): + if(ISWORD("function")) return F_FUNCTION_ID; + break; + case TWO_CHAR('g','a'): + if(ISWORD("gauge")) return F_GAUGE; + break; + 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; + break; + 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; } - yylval->string=s; - return F_IDENTIFIER; } - - yylval->str=buf; + yylval->string=make_shared_binary_string(buf,len); return F_IDENTIFIER; }else{ char buff[100]; @@ -1757,469 +810,7 @@ static int do_lex2(int literal, YYSTYPE *yylval) 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() -{ - 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)) - { - SKIPWHITE(); - if(!GOBBLE('(')) - { - yyerror("Missing '(' in #if constant().\n"); - return; - } - READBUF(isidchar(C)); - if(!GOBBLE(')')) - { - yyerror("Missing ')' in #if constant().\n"); - return; - } - s=findstring(buf); - - if(s && low_mapping_string_lookup(get_builtin_constants(), s)) - 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() -{ - 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: - 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() -{ - 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() -{ - 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() -{ - calcA(); - - while(1) - { - switch(lookahead) - { - case '+': low_lex(); calcA(); f_add(2); continue; - case '-': low_lex(); calcA(); o_subtract(); continue; } - break; } } -static void calc8() -{ - 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() -{ - 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() -{ - 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() -{ - calc7(); - - while(lookahead=='&') - { - low_lex(); - calc7(); - o_and(); - } -} - -static void calc5() -{ - calc6(); - - while(lookahead=='^') - { - low_lex(); - calc6(); - o_xor(); - } -} - -static void calc4() -{ - calc5(); - - while(lookahead=='|') - { - low_lex(); - calc5(); - o_or(); - } -} - -static void calc3() -{ - 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() -{ - 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() -{ - 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() -{ - 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 ***/ -void insert_current_line() -{ - char buf[20]; - sprintf(buf," %ld ",(long)current_line); - UNGETSTR(buf,strlen(buf)); -} - -void insert_current_file_as_string() -{ - UNGETSTR("\"",1); - UNGETSTR(current_file->str, current_file->len); - UNGETSTR("\"",1); -} - -void insert_current_time_as_string() -{ - time_t tmp; - char *buf; - time(&tmp); - buf=ctime(&tmp); - - UNGETSTR("\"",1); - UNGETSTR(buf+11, 8); - UNGETSTR("\"",1); -} - -void insert_current_date_as_string() -{ - 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() -{ - 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() -{ - if(current_file) - { - free_string(current_file); - current_file=0; - } - - free_inputstate(istate); - istate=NULL; - free_all_defines(); - total_lines+=current_line-old_line; -} - - -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; -} diff --git a/src/lex.h b/src/lex.h index e5d0f5ba7649e8436dce6e286e7e02d75ee85454..bf9424d3062d4a46d1de70529832d8c32a2ec84c 100644 --- a/src/lex.h +++ b/src/lex.h @@ -54,38 +54,27 @@ struct inputstate; 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 + +struct lex +{ + char *pos; + char *end; + INT32 current_line; + INT32 pragmas; + struct pike_string *current_file; +}; -extern struct pike_predef_s * pike_predefs; +extern struct lex lex; +extern struct instr instrs[]; /* Prototypes begin here */ -struct pike_predef_s; -void exit_lex(); +void exit_lex(void); struct reserved; void init_lex(); -void free_reswords(); 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 insert_current_line(); -void insert_current_file_as_string(); -void insert_current_time_as_string(); -void insert_current_date_as_string(); -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 add_predefine(char *s); /* Prototypes end here */ #endif diff --git a/src/main.c b/src/main.c index c780f60a94ede77cd1c75b2b7472fc38781d4a77..15b253193a4029969bdc9478e93f47aa061c7100 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.21 1997/04/16 03:09:13 hubbe Exp $"); +RCSID("$Id: main.c,v 1.21.2.1 1997/06/25 22:46:40 hubbe Exp $"); #include "types.h" #include "backend.h" #include "module.h" @@ -259,7 +259,10 @@ void main(int argc, char **argv, char **env) void init_main(void) { + void init_cpp(void); + th_init(); + init_cpp(); init_builtin_efuns(); init_signals(); init_dynamic_load(); diff --git a/src/modules/files/file.c b/src/modules/files/file.c index 9ae0b999862deb9e89b540dd4a134fd4ecaa1b9a..6d763cc3428919a945057c16829f15215befb2a6 100644 --- a/src/modules/files/file.c +++ b/src/modules/files/file.c @@ -6,7 +6,7 @@ #define READ_BUFFER 8192 #include "global.h" -RCSID("$Id: file.c,v 1.37.2.2 1997/05/19 09:07:32 hubbe Exp $"); +RCSID("$Id: file.c,v 1.37.2.3 1997/06/25 22:47:56 hubbe Exp $"); #include "types.h" #include "interpret.h" #include "svalue.h" @@ -785,6 +785,7 @@ static void file_set_nonblocking(INT32 args) case 3: file_set_close_callback(1); case 2: file_set_write_callback(1); case 1: file_set_read_callback(1); + case 0: break; } set_nonblocking(FD,1); THIS->open_mode |= FILE_NONBLOCKING; @@ -1497,7 +1498,7 @@ void pike_module_init() add_function("open_socket",file_open_socket,"function(int|void,string|void:int)",0); add_function("connect",file_connect,"function(string,int:int)",0); add_function("query_address",file_query_address,"function(int|void:string)",0); - add_function("create",file_create,"function(void|string:void)",0); + add_function("create",file_create,"function(void|string,void|string:void)",0); add_function("`<<",file_lsh,"function(mixed:object)",0); set_init_callback(init_file_struct); diff --git a/src/object.c b/src/object.c index af163ae754418492a33e788880e356dcb2b1b0d7..5b9aa08600e7434a577e7d8e7977011f51246301 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.17.2.1 1997/05/10 12:56:56 hubbe Exp $"); +RCSID("$Id: object.c,v 1.17.2.2 1997/06/25 22:46:41 hubbe Exp $"); #include "object.h" #include "dynamic_buffer.h" #include "interpret.h" @@ -28,22 +28,27 @@ struct object fake_object = { 1 }; /* start with one reference */ void setup_fake_object() { - fake_object.prog=&fake_program; + fake_object.prog=new_program; fake_object.next=0; fake_object.refs=0xffffff; } -struct object *low_clone(struct program *p) +struct object *low_clone(struct program *p, + struct object *parent) { int e; struct object *o; struct frame frame; + if(!(p->flags & PROGRAM_FINISHED)) + error("Attempting to clone an unfinished program\n"); + GC_ALLOC(); o=(struct object *)xalloc(sizeof(struct object)-1+p->storage_needed); o->prog=p; + if((o->parent=parent)) parent->refs++; p->refs++; o->next=first_object; o->prev=0; @@ -113,7 +118,16 @@ static void init_object(struct object *o, int args) struct object *clone_object(struct program *p, int args) { - struct object *o=low_clone(p); + struct object *o=low_clone(p,0); + init_object(o,args); + return o; +} + +struct object *parent_clone_object(struct program *p, + struct object *parent, + int args) +{ + struct object *o=low_clone(p,parent); init_object(o,args); return o; } @@ -139,17 +153,33 @@ struct object *get_master() 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); + master_object=low_clone(master_program,0); - apply_lfun(master_object,LFUN___INIT,0); - pop_stack(); - apply_lfun(master_object,LFUN_CREATE,0); - pop_stack(); + init_object(master_object,0); inside = 0; return master_object; @@ -177,6 +207,12 @@ void destruct(struct object *o) o->refs++; + if(o->parent) + { + free_object(o->parent); + o->parent=0; + } + if(o->prog->lfuns[LFUN_DESTROY] != -1) { safe_apply_low(o, o->prog->lfuns[LFUN_DESTROY], 0); @@ -338,8 +374,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; } @@ -715,8 +759,8 @@ struct array *object_indices(struct object *o) if(p->lfuns[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); @@ -744,8 +788,8 @@ struct array *object_values(struct object *o) if(p->lfuns[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++) { low_object_index_no_free(ITEM(a)+e, o, p->identifier_index[e]); } @@ -770,7 +814,7 @@ void gc_mark_object_as_referenced(struct object *o) { INT32 e; - for(e=0;e<(int)o->prog->num_identifier_indexes;e++) + for(e=0;e<(int)o->prog->num_identifier_index;e++) { struct identifier *i; @@ -799,7 +843,7 @@ void gc_check_all_objects() { INT32 e; - for(e=0;e<(int)o->prog->num_identifier_indexes;e++) + for(e=0;e<(int)o->prog->num_identifier_index;e++) { struct identifier *i; diff --git a/src/object.h b/src/object.h index 5ac6bae0121bd5e9d1ae9b5b0e1625b04ef45cb6..4d39c455fd32e47ad87613068ea1ab59d9139923 100644 --- a/src/object.h +++ b/src/object.h @@ -18,6 +18,7 @@ struct object { INT32 refs; /* Reference count, must be first. */ struct program *prog; + struct object *parent; struct object *next; struct object *prev; char storage[1]; @@ -38,8 +39,12 @@ extern struct program *master_program; /* Prototypes begin here */ void setup_fake_object(); -struct object *low_clone(struct program *p); +struct object *low_clone(struct program *p, + struct object *parent); struct object *clone_object(struct program *p, int args); +struct object *parent_clone_object(struct program *p, + struct object *parent, + int args); struct object *get_master(); struct object *master(); void destruct(struct object *o); diff --git a/src/peep.c b/src/peep.c index 49e19ea939253f05c3a322ae526ffa8d75af270b..b8f2643265e6ae36a2e07b216290397bb86e8810 100644 --- a/src/peep.c +++ b/src/peep.c @@ -109,7 +109,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) @@ -125,20 +125,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) @@ -244,11 +244,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: @@ -272,7 +272,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; @@ -348,7 +348,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/pike_types.c b/src/pike_types.c index 92c102e6bffc616153fcf80684721db1c6d8018b..cfba782560a21964803481e946d99a3865aa45a4 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.21 1997/04/16 03:09:15 hubbe Exp $"); +RCSID("$Id: pike_types.c,v 1.21.2.1 1997/06/25 22:46:42 hubbe Exp $"); #include <ctype.h> #include "svalue.h" #include "pike_types.h" @@ -1164,7 +1164,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/program.c b/src/program.c index edb83e8c18e2427bcfa678ce7ae04069ff93afd2..a23b69b9222db6fa229e8ca1f6eeff7084dda4ef 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.33.2.1 1997/05/10 12:56:56 hubbe Exp $"); +RCSID("$Id: program.c,v 1.33.2.2 1997/06/25 22:46:43 hubbe Exp $"); #include "program.h" #include "object.h" #include "dynamic_buffer.h" @@ -39,19 +39,11 @@ RCSID("$Id: program.c,v 1.33.2.1 1997/05/10 12:56:56 hubbe Exp $"); #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[] = { @@ -86,17 +78,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->num_##NAME < new_program->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 add_to_##NAME(TYPE ARG) { \ + CHECK_FOO(NUMTYPE,TYPE,NAME); \ + if(malloc_size_program->num_##NAME == new_program->num_##NAME) { \ + void *tmp; \ + malloc_size_program->num_##NAME *= 2; \ + malloc_size_program->num_##NAME++; \ + tmp=realloc((char *)new_program->NAME, \ + sizeof(TYPE) * \ + malloc_size_program->num_##NAME); \ + if(!tmp) fatal("Out of memory.\n"); \ + new_program->NAME=tmp; \ + } \ + new_program->NAME[new_program->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) { @@ -150,22 +186,18 @@ 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->flags)) { - push_svalue(PROG_FROM_INT(&p->fake_program, i)->constants+ + push_svalue(PROG_FROM_INT(p->new_program, i)->constants+ id->func.offset); return 1; }else{ @@ -179,89 +211,204 @@ int find_module_identifier(struct pike_string *ident) return 0; } -/* This should be optimized */ +#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() -{ - 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.lfuns=0; - fake_prog.num_lfuns=0; -*/ - 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->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->num_##NAME*sizeof(p->NAME[0])); \ + free((char *)p->NAME); \ + p->NAME=(TYPE *)(data+size); \ + size+=MY_ALIGN(p->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->flags & (ID_HIDDEN|ID_STATIC)) continue; + if(funp->flags & ID_INHERITED) + { + if(funp->flags & ID_PRIVATE) continue; + fun=ID_FROM_PTR(new_program, funp); +/* if(fun->func.offset == -1) continue; * prototype */ + + /* check for multiple definitions */ + for(t=0;t>=0 && t<(int)new_program->num_identifier_references;t++) + { + struct reference *funpb; + struct identifier *funb; + + if(t==i) continue; + funpb=new_program->identifier_references+t; + if(funpb->flags & (ID_HIDDEN|ID_STATIC)) continue; + if((funpb->flags & ID_INHERITED) && t<i) 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 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->num_##NAME=new_program->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->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.name=0; + add_to_inherits(i); } - { struct svalue tmp; @@ -273,18 +420,25 @@ void start_new_program() 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]); @@ -299,11 +453,6 @@ static void low_free_program(struct program *p) 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->prev) p->prev->next=p->next; @@ -313,6 +462,18 @@ 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(); @@ -342,7 +503,7 @@ void dump_program_desc(struct program *p) 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); @@ -352,61 +513,36 @@ void dump_program_desc(struct program *p) } #endif -static void toss_compilation_resources() +static void toss_compilation_resources(void) { - struct pike_string **names; - struct svalue *modules; - int e; + free_program(new_program); + new_program=0; - 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); - - 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() -{ - 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 @@ -436,6 +572,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); @@ -456,8 +596,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"); @@ -480,11 +620,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]); @@ -511,7 +650,7 @@ void check_program(struct program *p) 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); @@ -525,128 +664,38 @@ void check_program(struct program *p) } #endif -/* internal function to make the index-table */ -static int funcmp(const void *a,const void *b) -{ - 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() +struct program *end_first_pass(int finish) { - 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; - 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); - - /* 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->flags & (ID_HIDDEN|ID_STATIC)) continue; - if(funp->flags & ID_INHERITED) - { - if(funp->flags & ID_PRIVATE) continue; - fun=ID_FROM_PTR(prog, funp); - if(fun->func.offset == -1) continue; /* prototype */ - - /* check for multiple definitions */ - for(t=0;t>=0 && t<(int)prog->num_identifier_references;t++) - { - struct reference *funpb; - struct identifier *funb; - - if(t==i) continue; - funpb=prog->identifier_references+t; - if(funpb->flags & (ID_HIDDEN|ID_STATIC)) continue; - if((funpb->flags & ID_INHERITED) && t<i) 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); @@ -654,21 +703,37 @@ struct program *end_program() 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. @@ -676,9 +741,9 @@ struct program *end_program() 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; } @@ -688,7 +753,7 @@ SIZE_T add_storage(SIZE_T size) */ void set_init_callback(void (*init)(struct object *)) { - fake_program.init=init; + new_program->init=init; } /* @@ -697,17 +762,18 @@ void set_init_callback(void (*init)(struct object *)) */ void set_exit_callback(void (*exit)(struct object *)) { - fake_program.exit=exit; + new_program->exit=exit; } -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; @@ -721,24 +787,21 @@ int low_reference_inherited_identifier(int e,struct pike_string *name) funp.inherit_offset+=e; funp.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 @@ -746,21 +809,18 @@ 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; + l=new_program->inherits[e].name->len; if(l<super_name->len) continue; if(strncmp(super_name->str, - names[e]->str+l-super_name->len, + new_program->inherits[e].name->str+l-super_name->len, super_name->len)) continue; } @@ -774,12 +834,10 @@ 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); } /* @@ -791,28 +849,44 @@ void do_inherit(struct program *p,INT32 flags, struct pike_string *name) struct inherit inherit; struct pike_string *s; - setup_fake_program(); - - inherit_offset = fake_program.num_inherits; + inherit_offset = new_program->num_inherits; - storage_offset=fake_program.storage_needed; + 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(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++) @@ -829,7 +903,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); } @@ -841,7 +915,7 @@ void do_inherit(struct program *p,INT32 flags, struct pike_string *name) fun.flags |= flags; fun.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? */ @@ -863,8 +937,7 @@ void simple_do_inherit(struct pike_string *s, INT32 flags,struct pike_string *na { 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) @@ -890,12 +963,11 @@ 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=0;e<(int)fake_program.num_identifier_references;e++) + for(e=0;e<(int)new_program->num_identifier_references;e++) { - if(fake_program.identifier_references[e].flags & ID_HIDDEN) continue; + if(new_program->identifier_references[e].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; @@ -916,23 +988,34 @@ 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)->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)->flags != flags) + if(ID_FROM_INT(new_program, n)->flags != flags) my_yyerror("Illegal to redefine inherited variable with different type."); } else { @@ -952,16 +1035,13 @@ int define_variable(struct pike_string *name, sizeof(union anything)); ref.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; @@ -982,6 +1062,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) @@ -995,9 +1076,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); @@ -1007,25 +1116,23 @@ int add_constant(struct pike_string *name, dummy.func.offset=store_constant(c, 0); ref.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 ++; + add_to_identifiers(dummy); if(n != -1) { - if (IDENTIFIERP(n)->flags & ID_NOMASK) + if(IDENTIFIERP(n)->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; @@ -1137,14 +1244,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 */ { @@ -1161,11 +1267,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.flags & ID_NOMASK) && - !(funp->func.offset == -1)) + if((ref.flags & ID_NOMASK) && !(funp->func.offset == -1)) { my_yyerror("Illegal to redefine 'nomask' function %s.",name->str); } @@ -1193,13 +1295,13 @@ INT32 define_function(struct pike_string *name, else fun.func.offset = -1; - 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.flags = flags; - fake_program.identifier_references[i]=ref; + new_program->identifier_references[i]=ref; }else{ /* define it */ @@ -1215,16 +1317,15 @@ 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; + add_to_identifiers(fun); ref.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; } @@ -1240,12 +1341,17 @@ static int low_find_shared_string_identifier(struct pike_string *name, 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) { @@ -1264,17 +1370,23 @@ static int low_find_shared_string_identifier(struct pike_string *name, funp = prog->identifier_references + i; if(funp->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->flags & ID_INHERITED) { if(funp->flags & ID_PRIVATE) continue; for(t=0; t>=0 && t<(int)prog->num_identifier_references; t++) { - if(t == i) continue; - - if(is_same_string(fun->name, ID_FROM_INT(prog, i)->name)) - t=-10; + struct reference *funpb; + struct identifier *funb; + + if(t==i) continue; + funpb=prog->identifier_references+t; + if(funpb->flags & (ID_HIDDEN|ID_STATIC)) continue; + if((funpb->flags & ID_INHERITED) && t<i) 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; } @@ -1305,7 +1417,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); @@ -1340,31 +1452,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; } @@ -1393,21 +1504,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); } } @@ -1419,13 +1534,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; } @@ -1446,20 +1562,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) @@ -1489,81 +1603,45 @@ void my_yyerror(char *fmt,...) ATTRIBUTE((format(printf,1,2))) va_end(args); } -/* - * Compile an PIKE file. Input is supposed to be initalized already. - */ -void compile() +struct program *compile(struct pike_string *prog) { - int yyparse(); - - start_line_numbering(); - - num_parse_error = 0; - init_node=0; - - yyparse(); /* Parse da program */ - free_all_local_names(); -} - -struct program *compile_file(struct pike_string *file_name) -{ - 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; @@ -1597,7 +1675,7 @@ void add_function(char *name,void (*cfun)(INT32),char *type,INT16 flags) } #ifdef DEBUG -void check_all_programs() +void check_all_programs(void) { struct program *p; for(p=first_program;p;p=p->next) @@ -1624,7 +1702,7 @@ void check_all_programs() } #endif -void cleanup_program() +void cleanup_program(void) { #ifdef FIND_FUNCTION_HASHSIZE int e; @@ -1647,7 +1725,7 @@ void gc_mark_program_as_referenced(struct program *p) gc_mark_svalues(p->constants, p->num_constants); } -void gc_check_all_programs() +void gc_check_all_programs(void) { struct program *p; for(p=first_program;p;p=p->next) @@ -1669,7 +1747,7 @@ void gc_check_all_programs() } } -void gc_mark_all_programs() +void gc_mark_all_programs(void) { struct program *p; for(p=first_program;p;p=p->next) @@ -1677,7 +1755,7 @@ void gc_mark_all_programs() gc_mark_program_as_referenced(p); } -void gc_free_all_unreferenced_programs() +void gc_free_all_unreferenced_programs(void) { struct program *p,*next; @@ -1710,31 +1788,50 @@ void count_memory_in_programs(INT32 *num_, INT32 *size_) *num_=num; *size_=size; } -void push_locals() + +void push_compiler_frame(void) { - 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; + 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_locals() +void pop_local_variables(int level) { - 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); + 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); + } +} - local_variables=l; - /* insert check if ( local->next == parent locals ) here */ + +void pop_compiler_frame(void) +{ + struct compiler_frame *f; + int e; + f=compiler_frame; +#ifdef DEBUG + if(!f) + fatal("Popping out of compiler frames\n"); +#endif + + 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); } @@ -1777,6 +1874,58 @@ char *get_storage(struct object *o, struct program *p) 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->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); +} + +#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]; @@ -1790,8 +1939,8 @@ void yywarning(char *fmt, ...) ATTRIBUTE((format(printf,1,2))) if(get_master()) { - ref_push_string(current_file); - push_int(current_line); + 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 6444becb754b6d67d8db8e3fbe2dfc2571d0385a..9eba51d6ea8a8adc864636e82b6789bb4ffbaec6 100644 --- a/src/program.h +++ b/src/program.h @@ -9,6 +9,7 @@ #include <stdarg.h> #include "global.h" #include "types.h" +#include "svalue.h" #define LFUN___INIT 0 #define LFUN_CREATE 1 @@ -127,27 +128,36 @@ struct reference struct inherit { struct program *prog; + struct pike_string *name; INT16 inherit_level; /* really needed? */ INT16 identifier_level; INT32 storage_offset; }; +/* 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 trouh first compiler pass */ +#define PROGRAM_PASS_1_DONE 8 + 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 *); #ifdef DEBUG @@ -155,14 +165,13 @@ struct program #endif SIZE_T total_size; - SIZE_T num_linenumbers; - SIZE_T program_size; - 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 num_##NAME ; +#include "program_areas.h" + INT16 lfuns[NUM_LFUNS]; }; @@ -173,26 +182,39 @@ 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 int compiler_pass; + +#define FOO(NUMTYPE,TYPE,NAME) void 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 program *id_to_program(INT32 id); -void setup_fake_program(); -void start_new_program(); +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 check_program(struct program *p); -struct program *end_program(); +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 *)); -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); @@ -240,27 +262,26 @@ 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,...) ATTRIBUTE((format(printf,1,2))); -void compile(); -struct program *compile_file(struct pike_string *file_name); -struct program *compile_string(struct pike_string *prog, - struct pike_string *name); +struct program *compile(struct pike_string *prog); void add_function(char *name,void (*cfun)(INT32),char *type,INT16 flags); -void check_all_programs(); -void cleanup_program(); +void check_all_programs(void); +void cleanup_program(void); void gc_mark_program_as_referenced(struct program *p); -void gc_check_all_programs(); -void gc_mark_all_programs(); -void gc_free_all_unreferenced_programs(); +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 pop_locals(); +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 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 */ #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 4cbbeafb885ec6443e8b322898405496dc1dc581..ed88e1f98f5a7d5195758ea2e575802157195f37 100644 --- a/src/stralloc.c +++ b/src/stralloc.c @@ -496,9 +496,17 @@ struct pike_string *add_shared_strings(struct pike_string *a, buf=ret->str; MEMCPY(buf,a->str,a->len); MEMCPY(buf+a->len,b->str,b->len); - ret=end_shared_string(ret); + return end_shared_string(ret); +} - 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 ***/ diff --git a/src/stralloc.h b/src/stralloc.h index aeb3b12cf50d4a62c817a3e487b5543ce2c43bfe..d6fa9557f6de5d5831679038be52788780a4ea80 100644 --- a/src/stralloc.h +++ b/src/stralloc.h @@ -33,6 +33,12 @@ 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 +62,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/stuff.c b/src/stuff.c index 26ad4a61c8d0909e51de1a07579e1e904f912cd3..9082e74fb559e8c9057d508bdc1930c31b614f6a 100644 --- a/src/stuff.c +++ b/src/stuff.c @@ -3,7 +3,9 @@ ||| Pike is distributed as GPL (General Public License) ||| See the files COPYING and DISCLAIMER for more information. \*/ +#include "global.h" #include "stuff.h" +#include <stdlib.h> /* same thing as (int)floor(log((double)x) / log(2.0)) */ /* Except a bit quicker :) (hopefully) */ @@ -71,3 +73,14 @@ int is_more_than_one_bit(unsigned INT32 x) ((x & 0xff00ff00UL) && (x & 0x00ff00ffUL)) || ((x & 0xffff0000UL) && (x & 0x0000ffffUL)); } + +double my_strtod(char *nptr, char **endptr) +{ + double tmp=STRTOD(nptr,endptr); + if(*endptr>nptr) + { + if(endptr[0][-1]=='.') + endptr[0]--; + } + return tmp; +} diff --git a/src/stuff.h b/src/stuff.h index fc0fe0dd89d2c5f5fa36a508095e46604a1493e0..a67c07939e2c624275724a8a7d00da20bb3030bf 100644 --- a/src/stuff.h +++ b/src/stuff.h @@ -12,6 +12,7 @@ int my_log2(unsigned INT32 x); int count_bits(unsigned INT32 x); int is_more_than_one_bit(unsigned INT32 x); +double my_strtod(char *nptr, char **endptr); /* Prototypes end here */ #endif diff --git a/src/svalue.c b/src/svalue.c index 2e34b6270f2b17a3936eae4392b185ec3357d2d8..565de67fa9fd87ea0e376d0bf04b4d673fc59816 100644 --- a/src/svalue.c +++ b/src/svalue.c @@ -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,8 +408,23 @@ 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))) { + 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(a->u.object->prog->lfuns[LFUN_EQ] != -1) { a_is_obj: @@ -423,10 +440,16 @@ int is_eq(struct svalue *a, struct svalue *b) return 1; } } - } - - if(b->type == T_OBJECT) - { + 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(b->u.object->prog->lfuns[LFUN_EQ] != -1) { b_is_obj: @@ -443,7 +466,6 @@ int is_eq(struct svalue *a, struct svalue *b) } } } - return 0; } switch(a->type) @@ -993,7 +1015,7 @@ INT32 pike_sizeof(struct svalue *s) error("sizeof() on destructed object.\n"); if(s->u.object->prog->lfuns[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 176e186b97653187e0b3b388f312c298476963dc..d796edd591a4aeaaea3c7505f031b18688eb384b 100644 --- a/src/testsuite.in +++ b/src/testsuite.in @@ -1,13 +1,14 @@ -test_true([["$Id: testsuite.in,v 1.40.2.1 1997/05/19 09:04:56 hubbe Exp $"]]) +test_true([["$Id: testsuite.in,v 1.40.2.2 1997/06/25 22:46:46 hubbe Exp $"]]) test_eq(1e1,10.0) test_eq(1E1,10.0) test_eq(1e+1,10.0) test_eq(1.1e1,11.0) test_eq(1e-1,0.1) +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);}}]]) @@ -43,12 +44,12 @@ test_any([[ int e; for(e=0;e<100000;e+=1+(e>>4)) if(decode_value(encode_value(-e 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_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; }) @@ -68,9 +69,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){}) @@ -338,20 +339,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) @@ -380,12 +381,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]]); @@ -1650,10 +1651,11 @@ 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�l>") +test_search4("kapit\344l>") test_search4("-------------------+") -test_search4("�-------------------") +test_search4("\345-------------------") test_search4(sprintf("%'argel-bargel glop-glyf?'2000n")) // - sizeof @@ -1733,7 +1735,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/version.c b/src/version.c index b46b54042e853799bdef3da79801b164dd958810..767fbc08c53aba2b235f6c14acc84ebf9bd231b8 100644 --- a/src/version.c +++ b/src/version.c @@ -12,5 +12,5 @@ void f_version(INT32 args) { pop_n_elems(args); - push_text("Pike v0.5b6"); + push_text("Pike v0.6a1"); }