diff options
-rw-r--r-- | ChangeLog | 21 | ||||
-rw-r--r-- | ToDo | 8 | ||||
-rw-r--r-- | class.c | 31 | ||||
-rw-r--r-- | config_h.dj | 5 | ||||
-rw-r--r-- | eval.c | 31 | ||||
-rw-r--r-- | io.c | 2 | ||||
-rw-r--r-- | missing/file.h | 11 | ||||
-rw-r--r-- | node.h | 6 | ||||
-rw-r--r-- | parse.y | 48 | ||||
-rw-r--r-- | variable.c | 101 | ||||
-rw-r--r-- | version.h | 4 | ||||
-rw-r--r-- | win32/config.h | 7 | ||||
-rw-r--r-- | win32/win32.c | 15 | ||||
-rw-r--r-- | win32/win32.h | 5 |
14 files changed, 247 insertions, 48 deletions
@@ -1,3 +1,19 @@ +Fri Feb 18 00:27:34 2000 Yukihiro Matsumoto <matz@netlab.co.jp> + + * variable.c (rb_shared_variable_declare): shared variable (aka + class/module variable) introduced. prefix `@@'. experimental. + + * class.c (rb_scan_args): new format char '&'. + +Thu Feb 17 19:09:05 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp> + + * win32/win32.c (mypopen): don't close handle if it is not assigned. + * win32/win32.c (my_open_osfhandle): support O_NOINHERIT flag. + * win32/win32.c (win32_getcwd): rename getcwd to win32_getcwd + in order to avoid using the C/C++ runtime DLL's getcwd. + Use CharNext() to process directory name. + * win32/win32.h: map getcwd to win32_getcwd. + Wed Feb 16 00:32:49 2000 Yukihiro Matsumoto <matz@netlab.co.jp> * eval.c (method_arity): nd_rest is -1 for no rest argument. @@ -10,13 +26,14 @@ Tue Feb 15 01:47:00 2000 Yukihiro Matsumoto <matz@netlab.co.jp> Mon Feb 14 13:59:01 2000 Yukihiro Matsumoto <matz@netlab.co.jp> - * parse.y (yylex): yylex yields wrong token for `:foo=~expr'. + * parse.y (yylex): yylex yields wrong tokens for `:foo=~expr'. * ruby.c (load_file): exit if reading file is empty. Mon Feb 14 03:34:52 2000 Yukihiro Matsumoto <matz@netlab.co.jp> - * parse.y (yylex): `foo.bar=' should be <foo><.><bar><=>. + * parse.y (yylex): `foo.bar=1' should be <foo><.><bar><=><1>, + not <foo><.><bar=><1>. * eval.c (rb_thread_restore_context): process according to RESTORE_* is moved after longjmp(). @@ -19,6 +19,7 @@ Language Spec. * class Foo::Bar<Baz .. end, module Boo::Bar .. end * def Foo::Bar::baz() .. end ?? * I18N (or M17N) script/string/regexp +* Fixnum 0 as false ???? Hacking Interpreter @@ -53,9 +54,8 @@ Standard Libraries ScriptError<Exception, not StandardError. - String's bang methods return string always - Thread::start gives arguments, not a thread object to the block -- regexp: (?>..) -* regexp: \G -* Struct::new([name,]member,...) ?? +- regexp: (?>..), \G +- Struct::new([name,]member,...) * String#scanf(?) * Object#fmt(?) * Integer#{bin,oct,hex,heX} @@ -65,12 +65,14 @@ Standard Libraries * Stream or Port, abstract superclass of IO ? * String#{pred,prev}, String#downto * optional stepsize argument for succ() +* performance tune for String's non-bang methods. Extension Libraries - FastCGI ruby * ptk.rb pTk wrapper that is compatible to tk.rb * Berkeley DB extension +* BitVector Ruby Libraries @@ -598,19 +598,13 @@ rb_scan_args(argc, argv, fmt, va_alist) va_dcl #endif { - int n, i; + int n, i = 0; const char *p = fmt; VALUE *var; va_list vargs; va_init_list(vargs, fmt); - if (*p == '*') { - var = va_arg(vargs, VALUE*); - *var = rb_ary_new4(argc, argv); - return argc; - } - if (ISDIGIT(*p)) { n = *p - '0'; if (n > argc) @@ -643,21 +637,34 @@ rb_scan_args(argc, argv, fmt, va_alist) var = va_arg(vargs, VALUE*); if (argc > i) { if (var) *var = rb_ary_new4(argc-i, argv+i); + i = argc; } else { if (var) *var = rb_ary_new(); } + p++; } - else if (*p == '\0') { - if (argc > i) { - rb_raise(rb_eArgError, "wrong # of arguments(%d for %d)", argc, i); + + if (*p == '&') { + var = va_arg(vargs, VALUE*); + if (rb_iterator_p()) { + *var = rb_f_lambda(); + } + else { + *var = Qnil; } + p++; } - else { + va_end(vargs); + + if (*p != '\0') { goto error; } - va_end(vargs); + if (argc > i) { + rb_raise(rb_eArgError, "wrong # of arguments(%d for %d)", argc, i); + } + return argc; error: diff --git a/config_h.dj b/config_h.dj index 029da840c4..91a8f249c1 100644 --- a/config_h.dj +++ b/config_h.dj @@ -65,7 +65,8 @@ #define FILE_COUNT _cnt #define DLEXT ".o" #define RUBY_LIB "/usr/local/lib/ruby/1.5" -#define RUBY_SITE_LIB "/usr/local/lib/ruby/1.5/site_ruby" +#define RUBY_SITE_LIB "/usr/local/lib/ruby/site_ruby" +#define RUBY_SITE_LIB2 "/usr/local/lib/ruby/site_ruby/1.5" #define RUBY_PLATFORM "i386-djgpp" #define RUBY_ARCHLIB "/usr/local/lib/ruby/1.5/i386-djgpp" -#define RUBY_SITE_ARCHLIB "/usr/local/lib/ruby/1.5/site_ruby/i386-djgpp" +#define RUBY_SITE_ARCHLIB "/usr/local/lib/ruby/site_ruby/1.5/i386-djgpp" @@ -1316,6 +1316,8 @@ superclass(self, node) return val; } +#define ruby_cbase (((NODE*)ruby_frame->cbase)->nd_clss) + static VALUE ev_const_defined(cref, id) NODE *cref; @@ -1400,7 +1402,7 @@ rb_mod_s_constants() cbase = cbase->nd_next; } - rb_mod_const_of(((NODE*)ruby_frame->cbase)->nd_clss, ary); + rb_mod_const_of(ruby_cbase, ary); return ary; } @@ -2510,6 +2512,22 @@ rb_eval(self, node) rb_const_set(ruby_class, node->nd_vid, result); break; + case NODE_SHASGN: + if (NIL_P(ruby_class)) { + rb_raise(rb_eTypeError, "no class/module to define shared variable"); + } + result = rb_eval(self, node->nd_value); + rb_shared_variable_set(ruby_cbase, node->nd_vid, result); + break; + + case NODE_SHDECL: + if (NIL_P(ruby_class)) { + rb_raise(rb_eTypeError, "no class/module to define shared variable"); + } + result = rb_eval(self, node->nd_value); + rb_shared_variable_declare(ruby_class, node->nd_vid, result); + break; + case NODE_LVAR: if (ruby_scope->local_vars == 0) { rb_bug("unexpected local variable"); @@ -2533,6 +2551,10 @@ rb_eval(self, node) result = ev_const_get((NODE*)ruby_frame->cbase, node->nd_vid); break; + case NODE_SHVAR: + result = rb_shared_variable_get(ruby_cbase, node->nd_vid); + break; + case NODE_BLOCK_ARG: if (ruby_scope->local_vars == 0) rb_bug("unexpected block argument"); @@ -3486,6 +3508,11 @@ assign(self, lhs, val, check) rb_const_set(ruby_class, lhs->nd_vid, val); break; + case NODE_SHDECL: + case NODE_SHASGN: + rb_shared_variable_set(ruby_cbase, lhs->nd_vid, val); + break; + case NODE_MASGN: massign(self, lhs, val, check); break; @@ -4433,7 +4460,7 @@ eval(self, src, scope, file, line) } } PUSH_CLASS(); - ruby_class = ((NODE*)ruby_frame->cbase)->nd_clss; + ruby_class = ruby_cbase; ruby_in_eval++; if (TYPE(ruby_class) == T_ICLASS) { @@ -3398,6 +3398,6 @@ Init_IO() rb_file_const("BINARY", INT2FIX(O_BINARY)); #endif #ifdef O_SYNC - rb_file_const("BINARY", INT2FIX(O_SYNC)); + rb_file_const("SYNC", INT2FIX(O_SYNC)); #endif } diff --git a/missing/file.h b/missing/file.h index b6cec8eb05..2d491d0fc1 100644 --- a/missing/file.h +++ b/missing/file.h @@ -12,12 +12,11 @@ # define L_XTND 2 /* seek from end. */ #endif -# ifndef R_OK -# define R_OK 4 /* test whether readable. */ -# define W_OK 2 /* test whether writable. */ -# define X_OK 1 /* test whether execubale. */ -# define F_OK 0 /* test whether exist. */ -# endif +#ifndef R_OK +# define R_OK 4 /* test whether readable. */ +# define W_OK 2 /* test whether writable. */ +# define X_OK 1 /* test whether execubale. */ +# define F_OK 0 /* test whether exist. */ #endif #endif @@ -50,6 +50,8 @@ enum node_type { NODE_IASGN, NODE_CASGN, NODE_CDECL, + NODE_SHASGN, + NODE_SHDECL, NODE_OP_ASGN1, NODE_OP_ASGN2, NODE_OP_ASGN_AND, @@ -69,6 +71,7 @@ enum node_type { NODE_GVAR, NODE_IVAR, NODE_CVAR, + NODE_SHVAR, NODE_NTH_REF, NODE_BACK_REF, NODE_MATCH, @@ -264,6 +267,8 @@ typedef struct RNode { #define NEW_IASGN(v,val) rb_node_newnode(NODE_IASGN,v,val,0) #define NEW_CASGN(v,val) rb_node_newnode(NODE_CASGN,v,val,0) #define NEW_CDECL(v,val) rb_node_newnode(NODE_CDECL,v,val,0) +#define NEW_SHASGN(v,val) rb_node_newnode(NODE_SHASGN,v,val,0) +#define NEW_SHDECL(v,val) rb_node_newnode(NODE_SHDECL,v,val,0) #define NEW_OP_ASGN1(p,id,a) rb_node_newnode(NODE_OP_ASGN1,p,id,a) #define NEW_OP_ASGN2(r,i,o,val) rb_node_newnode(NODE_OP_ASGN2,r,val,NEW_OP_ASGN22(i,o)) #define NEW_OP_ASGN22(i,o) rb_node_newnode(NODE_OP_ASGN2,i,o,rb_id_attrset(i)) @@ -274,6 +279,7 @@ typedef struct RNode { #define NEW_DVAR(v) rb_node_newnode(NODE_DVAR,v,0,0); #define NEW_IVAR(v) rb_node_newnode(NODE_IVAR,v,0,0) #define NEW_CVAR(v) rb_node_newnode(NODE_CVAR,v,0,0) +#define NEW_SHVAR(v) rb_node_newnode(NODE_SHVAR,v,0,0) #define NEW_NTH_REF(n) rb_node_newnode(NODE_NTH_REF,0,n,local_cnt('~')) #define NEW_BACK_REF(n) rb_node_newnode(NODE_BACK_REF,0,n,local_cnt('~')) #define NEW_MATCH(c) rb_node_newnode(NODE_MATCH,c,0,0) @@ -27,6 +27,7 @@ #define ID_GLOBAL 0x03 #define ID_ATTRSET 0x04 #define ID_CONST 0x05 +#define ID_SHARED 0x06 #define is_notop_id(id) ((id)>LAST_TOKEN) #define is_local_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_LOCAL) @@ -34,6 +35,7 @@ #define is_instance_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_INSTANCE) #define is_attrset_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_ATTRSET) #define is_const_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CONST) +#define is_shared_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_SHARED) NODE *ruby_eval_tree_begin = 0; NODE *ruby_eval_tree = 0; @@ -164,7 +166,7 @@ static void top_local_setup(); k__LINE__ k__FILE__ -%token <id> tIDENTIFIER tFID tGVAR tIVAR tCONSTANT +%token <id> tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tSHVAR %token <val> tINTEGER tFLOAT tSTRING tXSTRING tREGEXP %token <node> tDSTRING tDXSTRING tDREGEXP tNTH_REF tBACK_REF @@ -1507,6 +1509,7 @@ variable : tIDENTIFIER | tIVAR | tGVAR | tCONSTANT + | tSHVAR | kNIL {$$ = kNIL;} | kSELF {$$ = kSELF;} | kTRUE {$$ = kTRUE;} @@ -1633,6 +1636,10 @@ f_rest_arg : tSTAR tIDENTIFIER f_block_arg : tAMPER tIDENTIFIER { + if (!is_local_id($2)) + yyerror("block argument must be local variable"); + else if (local_id($2)) + yyerror("duplicate block argument name"); $$ = NEW_BLOCK_ARG($2); } @@ -3342,12 +3349,16 @@ yylex() case '@': c = nextc(); + newtok(); + tokadd('@'); + if (c == '@') { + tokadd('@'); + c = nextc(); + } if (!is_identchar(c)) { pushback(c); return '@'; } - newtok(); - tokadd('@'); break; default: @@ -3390,7 +3401,10 @@ yylex() break; case '@': lex_state = EXPR_END; - result = tIVAR; + if (tok()[1] == '@') + result = tSHVAR; + else + result = tIVAR; break; default: if (lex_state != EXPR_DOT) { @@ -3835,6 +3849,9 @@ gettable(id) else if (is_const_id(id)) { return NEW_CVAR(id); } + else if (is_shared_id(id)) { + return NEW_SHVAR(id); + } rb_bug("invalid id for gettable"); return 0; } @@ -3891,6 +3908,14 @@ assignable(id, val) yyerror("dynamic constant assignment"); lhs = NEW_CDECL(id, val); } + else if (is_shared_id(id)) { + if (cur_mid || in_single) { + lhs = NEW_SHASGN(id, val); + } + else { + lhs = NEW_SHDECL(id, val); + } + } else { rb_bug("bad id for variable"); } @@ -3978,6 +4003,8 @@ node_assign(lhs, rhs) case NODE_MASGN: case NODE_CASGN: case NODE_CDECL: + case NODE_SHASGN: + case NODE_SHDECL: lhs->nd_value = rhs; break; @@ -4588,7 +4615,10 @@ rb_intern(name) id |= ID_GLOBAL; break; case '@': - id |= ID_INSTANCE; + if (name[1] == '@') + id |= ID_SHARED; + else + id |= ID_INSTANCE; break; default: if (name[0] != '_' && !ISALPHA(name[0]) && !ismbchar(name[0])) { @@ -4680,6 +4710,14 @@ rb_is_const_id(id) } int +rb_is_shared_id(id) + ID id; +{ + if (is_shared_id(id)) return Qtrue; + return Qfalse; +} + +int rb_is_instance_id(id) ID id; { diff --git a/variable.c b/variable.c index 4d1ec0644c..c8bcfb0393 100644 --- a/variable.c +++ b/variable.c @@ -1216,24 +1216,34 @@ rb_const_defined(klass, id) return rb_autoload_defined(id); } -void -rb_const_set(klass, id, val) +static void +rb_mod_av_set(klass, id, val, dest) VALUE klass; ID id; VALUE val; + char *dest; { if (!OBJ_TAINTED(klass) && rb_safe_level() >= 4) - rb_raise(rb_eSecurityError, "Insecure: can't set constant"); + rb_raise(rb_eSecurityError, "Insecure: can't set %s", dest); if (OBJ_FROZEN(klass)) rb_error_frozen("class/module"); if (!RCLASS(klass)->iv_tbl) { RCLASS(klass)->iv_tbl = st_init_numtable(); } else if (st_lookup(RCLASS(klass)->iv_tbl, id, 0)) { - rb_warn("already initialized constant %s", rb_id2name(id)); + rb_warn("already initialized %s %s", dest, rb_id2name(id)); } st_insert(RCLASS(klass)->iv_tbl, id, val); } + +void +rb_const_set(klass, id, val) + VALUE klass; + ID id; + VALUE val; +{ + rb_mod_av_set(klass, id, val, "constant"); +} void rb_const_assign(klass, id, val) @@ -1302,6 +1312,89 @@ rb_define_global_const(name, val) rb_define_const(rb_cObject, name, val); } +void +rb_shared_variable_declare(klass, id, val) + VALUE klass; + ID id; + VALUE val; +{ + rb_mod_av_set(klass, id, val, "shared variable"); +} + +void +rb_shared_variable_set(klass, id, val) + VALUE klass; + ID id; + VALUE val; +{ + VALUE value; + VALUE tmp; + + tmp = klass; + while (tmp) { + if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,0)) { + st_insert(RCLASS(tmp)->iv_tbl,id,val); + return; + } + tmp = RCLASS(tmp)->super; + } + + rb_raise(rb_eNameError,"uninitialized shared variable %s",rb_id2name(id)); +} + +VALUE +rb_shared_variable_get(klass, id) + VALUE klass; + ID id; +{ + VALUE value; + VALUE tmp; + + tmp = klass; + while (tmp) { + if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,&value)) { + return value; + } + tmp = RCLASS(tmp)->super; + } + + rb_raise(rb_eNameError,"uninitialized shared variable %s",rb_id2name(id)); + return Qnil; /* not reached */ +} + +int +rb_shared_variable_defined(klass, id) + VALUE klass; + ID id; +{ + VALUE value; + VALUE tmp; + + tmp = klass; + while (tmp) { + if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,0)) { + return Qtrue; + } + tmp = RCLASS(tmp)->super; + } + + return Qfalse; +} + +void +rb_define_shared_variable(klass, name, val) + VALUE klass; + const char *name; + VALUE val; +{ + ID id = rb_intern(name); + + if (!rb_is_shared_id(id)) { + rb_raise(rb_eNameError, "wrong shared variable name %s", name); + } + rb_shared_variable_declare(klass, id, val); +} + VALUE rb_iv_get(obj, name) VALUE obj; @@ -1,4 +1,4 @@ #define RUBY_VERSION "1.5.2" -#define RUBY_RELEASE_DATE "2000-02-17" +#define RUBY_RELEASE_DATE "2000-02-18" #define RUBY_VERSION_CODE 152 -#define RUBY_RELEASE_CODE 20000217 +#define RUBY_RELEASE_CODE 20000218 diff --git a/win32/config.h b/win32/config.h index fe550654c2..b1a2d8d0d9 100644 --- a/win32/config.h +++ b/win32/config.h @@ -40,10 +40,11 @@ #define FILE_COUNT _cnt #define DLEXT ".dll" #define RUBY_LIB "/usr/local/lib/ruby/1.5" -#define RUBY_ARCHLIB "/usr/local/lib/ruby/1.5/i386-mswin32" -#define RUBY_SITE_LIB "/usr/local/lib/ruby/1.5/site_ruby" -#define RUBY_SITE_ARCHLIB "/usr/local/lib/ruby/1.5/site_ruby/i386-mswin32" +#define RUBY_SITE_LIB "/usr/local/lib/ruby/site_ruby" +#define RUBY_SITE_LIB2 "/usr/local/lib/ruby/site_ruby/1.5" #define RUBY_PLATFORM "i386-mswin32" +#define RUBY_ARCHLIB "/usr/local/lib/ruby/1.5/i386-mswin32" +#define RUBY_SITE_ARCHLIB "/usr/local/lib/ruby/site_ruby/1.5/i386-mswin32" #define SIZEOF_INT 4 #define SIZEOF_SHORT 2 diff --git a/win32/win32.c b/win32/win32.c index 877978db58..a1e6d25ff3 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -546,15 +546,14 @@ mypopen (char *cmd, char *mode) if (lpCmd2) free(lpCmd2); - CloseHandle(aProcessInformation.hThread); - if (!fRet) { CloseHandle(hInFile); CloseHandle(hOutFile); - CloseHandle(aProcessInformation.hProcess); return NULL; } + CloseHandle(aProcessInformation.hThread); + if (reading) { fd = _open_osfhandle((long)hInFile, (_O_RDONLY | pipemode)); CloseHandle(hOutFile); @@ -1541,7 +1540,7 @@ typedef struct { #endif /* defined (_MT) && !defined (DLL_FOR_WIN32S) */ } ioinfo; -EXTERN_C ioinfo * __pioinfo[]; +EXTERN_C _CRTIMP ioinfo * __pioinfo[]; #define IOINFO_L2E 5 #define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E) @@ -1549,6 +1548,7 @@ EXTERN_C ioinfo * __pioinfo[]; #define _osfile(i) (_pioinfo(i)->osfile) #define FOPEN 0x01 /* file handle open */ +#define FNOINHERIT 0x10 /* file handle opened O_NOINHERIT */ #define FAPPEND 0x20 /* file handle opened O_APPEND */ #define FDEV 0x40 /* file handle refers to device */ #define FTEXT 0x80 /* file handle is in text mode */ @@ -1568,6 +1568,9 @@ my_open_osfhandle(long osfhandle, int flags) if (flags & O_TEXT) fileflags |= FTEXT; + if (flags & O_NOINHERIT) + fileflags |= FNOINHERIT; + /* attempt to allocate a C Runtime file handle */ if ((fh = _alloc_osfhnd()) == -1) { errno = EMFILE; /* too many open files */ @@ -2203,7 +2206,7 @@ gettimeofday(struct timeval *tv, struct timezone *tz) } char * -getcwd(buffer, size) +win32_getcwd(buffer, size) char *buffer; int size; { @@ -2218,7 +2221,7 @@ getcwd(buffer, size) return NULL; } - for (bp = buffer; *bp != '\0'; bp++) { + for (bp = buffer; *bp != '\0'; bp = CharNext(bp)) { if (*bp == '\\') { *bp = '/'; } diff --git a/win32/win32.h b/win32/win32.h index a55641eada..cbcf4e8117 100644 --- a/win32/win32.h +++ b/win32/win32.h @@ -387,6 +387,11 @@ extern char *mystrerror(int); #endif #define get_osfhandle myget_osfhandle +#ifdef getcwd +#undef getcwd +#endif +#define getcwd win32_getcwd + #ifdef getenv #undef getenv #endif |