From f43cae2b057622e6812e370f2c7cb3efa06f6665 Mon Sep 17 00:00:00 2001 From: matz Date: Wed, 9 Mar 2005 09:29:52 +0000 Subject: * parse.y (gettable_gen): warns if VCALL name is used as out-of-scope block local variable. [EXPERIMENTAL] * parse.y (opt_bv_decl): add explicit block local variable declaration. raises error for name conflicts. [EXPERIMENTAL] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8128 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 14 ++++ ext/socket/socket.c | 85 +++++++++++++++++++ ext/tk/sample/demos-en/floor.rb | 4 +- ext/tk/sample/demos-en/floor2.rb | 4 +- ext/tk/sample/demos-jp/floor.rb | 4 +- ext/tk/sample/demos-jp/floor2.rb | 4 +- parse.y | 177 +++++++++++++++++++++++++++++++++------ re.c | 2 +- 8 files changed, 261 insertions(+), 33 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4ec756c9d2..0431efc8b7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +Wed Mar 9 18:09:51 2005 Yukihiro Matsumoto + + * parse.y (gettable_gen): warns if VCALL name is used as + out-of-scope block local variable. [EXPERIMENTAL] + + * parse.y (opt_bv_decl): add explicit block local variable + declaration. raises error for name conflicts. [EXPERIMENTAL] + Wed Mar 9 13:37:57 2005 Hidetoshi NAGAI * ext/tk/sample/tktextio.rb: fix bug of handling 'end' position. @@ -14,6 +22,12 @@ Tue Mar 8 13:39:25 2005 NAKAMURA Usaku * ext/socket/mkconstants.rb: workaround for some of 4.4BSD-Lite derived OSs. +Tue Mar 8 12:36:17 2005 Yukihiro Matsumoto + + * ext/socket/socket.c: document from Sam Roberts + for getsockopt and setsockopt is merged. + [ruby-doc:824] + Tue Mar 8 10:48:53 2005 NAKAMURA Usaku * eval.c (rb_exec_recursive): declaration should precede statements diff --git a/ext/socket/socket.c b/ext/socket/socket.c index 230966bae4..9383580bdf 100644 --- a/ext/socket/socket.c +++ b/ext/socket/socket.c @@ -271,6 +271,51 @@ bsock_close_write(sock) return Qnil; } +/* + * Document-method: setsockopt + * call-seq: setsockopt(level, optname, optval) + * + * Sets a socket option. These are protocol and system specific, see your + * local sytem documentation for details. + * + * === Parameters + * * +level+ is an integer, usually one of the SOL_ constants such as + * Socket::SOL_SOCKET, or a protocol level. + * * +optname+ is an integer, usually one of the SO_ constants, such + * as Socket::SO_REUSEADDR. + * * +optval+ is the value of the option, it is passed to the underlying + * setsockopt() as a pointer to a certain number of bytes. How this is + * done depends on the type: + * - Fixnum: value is assigned to an int, and a pointer to the int is + * passed, with length of sizeof(int). + * - true or false: 1 or 0 (respectively) is assigned to an int, and the + * int is passed as for a Fixnum. Note that +false+ must be passed, + * not +nil+. + * - String: the string's data and length is passed to the socket. + * + * === Examples + * + * Some socket options are integers with boolean values, in this case + * #setsockopt could be called like this: + * sock.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true) + * + * Some socket options are integers with numeric values, in this case + * #setsockopt could be called like this: + * sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_TTL, 255) + * + * Option values may be structs. Passing them can be complex as it involves + * examining your system headers to determine the correct definition. An + * example is an +ip_mreq+, which may be defined in your system headers as: + * struct ip_mreq { + * struct in_addr imr_multiaddr; + * struct in_addr imr_interface; + * }; + * + * In this case #setsockopt could be called like this: + * optval = IPAddr.new("224.0.0.251") + Socket::INADDR_ANY + * sock.setsockopt(Socket::IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP, optval) + * +*/ static VALUE bsock_setsockopt(sock, lev, optname, val) VALUE sock, lev, optname, val; @@ -311,6 +356,46 @@ bsock_setsockopt(sock, lev, optname, val) return INT2FIX(0); } +/* + * Document-method: getsockopt + * call-seq: getsockopt(level, optname) + * + * Gets a socket option. These are protocol and system specific, see your + * local sytem documentation for details. The option is returned as + * a String with the data being the binary value of the socket option. + * + * === Parameters + * * +level+ is an integer, usually one of the SOL_ constants such as + * Socket::SOL_SOCKET, or a protocol level. + * * +optname+ is an integer, usually one of the SO_ constants, such + * as Socket::SO_REUSEADDR. + * + * === Examples + * + * Some socket options are integers with boolean values, in this case + * #getsockopt could be called like this: + * optval = sock.getsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR) + * optval = optval.unpack "i" + * reuseaddr = optval[0] == 0 ? false : true + * + * Some socket options are integers with numeric values, in this case + * #getsockopt could be called like this: + * optval = sock.getsockopt(Socket::IPPROTO_IP, Socket::IP_TTL) + * ipttl = optval.unpack("i")[0] + * + * Option values may be structs. Decoding them can be complex as it involves + * examining your system headers to determine the correct definition. An + * example is a +struct linger+, which may be defined in your system headers + * as: + * struct linger { + * int l_onoff; + * int l_linger; + * }; + * + * In this case #getsockopt could be called like this: + * optval = sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER) + * onoff, linger = optval.unpack "ii" +*/ static VALUE bsock_getsockopt(sock, lev, optname) VALUE sock, lev, optname; diff --git a/ext/tk/sample/demos-en/floor.rb b/ext/tk/sample/demos-en/floor.rb index 15c56a154e..9c95770d43 100644 --- a/ext/tk/sample/demos-en/floor.rb +++ b/ext/tk/sample/demos-en/floor.rb @@ -1667,8 +1667,8 @@ else pack('expand'=>'yes', 'fill'=>'both', 'padx'=>1, 'pady'=>1) - v.command(proc{|*args| c.yview(*args)}) - h.command(proc{|*args| c.xview(*args)}) + v.command(proc{|*args| f.yview(*args)}) + h.command(proc{|*args| f.xview(*args)}) } end diff --git a/ext/tk/sample/demos-en/floor2.rb b/ext/tk/sample/demos-en/floor2.rb index ab8659a628..513e02aaaa 100644 --- a/ext/tk/sample/demos-en/floor2.rb +++ b/ext/tk/sample/demos-en/floor2.rb @@ -1667,8 +1667,8 @@ else pack('expand'=>'yes', 'fill'=>'both', 'padx'=>1, 'pady'=>1) - v.command(proc{|*args| c.yview(*args)}) - h.command(proc{|*args| c.xview(*args)}) + v.command(proc{|*args| f.yview(*args)}) + h.command(proc{|*args| f.xview(*args)}) } end diff --git a/ext/tk/sample/demos-jp/floor.rb b/ext/tk/sample/demos-jp/floor.rb index 517600de92..d258bb6486 100644 --- a/ext/tk/sample/demos-jp/floor.rb +++ b/ext/tk/sample/demos-jp/floor.rb @@ -1664,8 +1664,8 @@ else pack('expand'=>'yes', 'fill'=>'both', 'padx'=>1, 'pady'=>1) - v.command(proc{|*args| c.yview(*args)}) - h.command(proc{|*args| c.xview(*args)}) + v.command(proc{|*args| f.yview(*args)}) + h.command(proc{|*args| f.xview(*args)}) } end diff --git a/ext/tk/sample/demos-jp/floor2.rb b/ext/tk/sample/demos-jp/floor2.rb index fcf208b61f..9812240dce 100644 --- a/ext/tk/sample/demos-jp/floor2.rb +++ b/ext/tk/sample/demos-jp/floor2.rb @@ -1664,8 +1664,8 @@ else pack('expand'=>'yes', 'fill'=>'both', 'padx'=>1, 'pady'=>1) - v.command(proc{|*args| c.yview(*args)}) - h.command(proc{|*args| c.xview(*args)}) + v.command(proc{|*args| f.yview(*args)}) + h.command(proc{|*args| f.xview(*args)}) } end diff --git a/parse.y b/parse.y index 906589e958..5c22378672 100644 --- a/parse.y +++ b/parse.y @@ -103,6 +103,8 @@ struct local_vars { int nofree; int cnt; int dlev; + int dname_size; + ID *dnames; struct RVarmap* dyna_vars; struct local_vars *prev; }; @@ -251,6 +253,8 @@ static NODE *gettable_gen _((struct parser_params*,ID)); #define gettable(id) gettable_gen(parser,id) static NODE *assignable_gen _((struct parser_params*,ID,NODE*)); #define assignable(id,node) assignable_gen(parser, id, node) +static NODE *new_bv_gen _((struct parser_params*,ID,NODE*)); +#define new_bv(id,node) new_bv_gen(parser, id, node) static NODE *aryset_gen _((struct parser_params*,NODE*,NODE*)); #define aryset(node1,node2) aryset_gen(parser, node1, node2) static NODE *attrset_gen _((struct parser_params*,NODE*,ID)); @@ -285,6 +289,10 @@ static int dyna_in_block_gen _((struct parser_params*)); #define dyna_in_block() dyna_in_block_gen(parser) static NODE *dyna_init_gen _((struct parser_params*, NODE*, struct RVarmap *)); #define dyna_init(node, pre) dyna_init_gen(parser, node, pre) +static void dyna_var_gen _((struct parser_params*,ID)); +#define dyna_var(id) dyna_var_gen(parser, id) +static void dyna_check_gen _((struct parser_params*,ID)); +#define dyna_check(id) dyna_check_gen(parser, id) static void top_local_init_gen _((struct parser_params*)); #define top_local_init() top_local_init_gen(parser) @@ -365,6 +373,8 @@ static VALUE ripper_id2sym _((ID)); #define method_arg(m,a) dispatch2(method_add_arg,m,a) #define escape_Qundef(x) ((x)==Qundef ? Qnil : (x)) +#define FIXME 0 + #endif /* RIPPER */ #ifndef RIPPER @@ -492,7 +502,8 @@ static void ripper_compile_error _((struct parser_params*, const char *fmt, ...) %type mrhs superclass block_call block_command %type f_arglist f_args f_optarg f_opt f_block_arg opt_f_block_arg %type assoc_list assocs assoc undef_list backref string_dvar -%type for_var block_var opt_block_var block_var_def block_par +%type for_var block_var opt_block_var block_var_def block_param +%type opt_bv_decl bv_decls bv_decl %type brace_block cmd_brace_block do_block lhs none fitem %type mlhs mlhs_head mlhs_basic mlhs_entry mlhs_item mlhs_node %type fsym variable sym symbol operation operation2 operation3 @@ -1098,7 +1109,9 @@ cmd_brace_block : tLBRACE_ARG '}' { /*%%%*/ - $$ = NEW_ITER($3, 0, dyna_init($5, $4)); + $3->nd_body = block_append($3->nd_body, + dyna_init($5, $4)); + $$ = $3; nd_set_line($$, $1); dyna_pop($2); /*% @@ -2963,7 +2976,7 @@ for_var : lhs | mlhs ; -block_par : mlhs_item +block_param : mlhs_item { /*%%%*/ $$ = NEW_LIST($1); @@ -2971,7 +2984,7 @@ block_par : mlhs_item $$ = mlhs_add(mlhs_new(), $1); %*/ } - | block_par ',' mlhs_item + | block_param ',' mlhs_item { /*%%%*/ $$ = list_append($1, $3); @@ -2981,7 +2994,7 @@ block_par : mlhs_item } ; -block_var : block_par +block_var : block_param { /*%%%*/ if ($1->nd_alen == 1) { @@ -2995,7 +3008,7 @@ block_var : block_par $$ = blockvar_new($1); %*/ } - | block_par ',' + | block_param ',' { /*%%%*/ $$ = NEW_MASGN($1, 0); @@ -3003,7 +3016,7 @@ block_var : block_par $$ = blockvar_new($1); %*/ } - | block_par ',' tAMPER lhs + | block_param ',' tAMPER lhs { /*%%%*/ $$ = NEW_BLOCK_VAR($4, NEW_MASGN($1, 0)); @@ -3011,7 +3024,7 @@ block_var : block_par $$ = blockvar_add_block(blockvar_new($1), $4); %*/ } - | block_par ',' tSTAR lhs ',' tAMPER lhs + | block_param ',' tSTAR lhs ',' tAMPER lhs { /*%%%*/ $$ = NEW_BLOCK_VAR($7, NEW_MASGN($1, $4)); @@ -3020,7 +3033,7 @@ block_var : block_par $$ = blockvar_add_block($$, $7); %*/ } - | block_par ',' tSTAR ',' tAMPER lhs + | block_param ',' tSTAR ',' tAMPER lhs { /*%%%*/ $$ = NEW_BLOCK_VAR($6, NEW_MASGN($1, -1)); @@ -3029,7 +3042,7 @@ block_var : block_par $$ = blockvar_add_block($$, $6); %*/ } - | block_par ',' tSTAR lhs + | block_param ',' tSTAR lhs { /*%%%*/ $$ = NEW_MASGN($1, $4); @@ -3037,7 +3050,7 @@ block_var : block_par $$ = blockvar_add_star(blockvar_new($1), $4); %*/ } - | block_par ',' tSTAR + | block_param ',' tSTAR { /*%%%*/ $$ = NEW_MASGN($1, -1); @@ -3090,34 +3103,85 @@ block_var : block_par ; opt_block_var : none - | block_var_def { - $$ = $1; + /*%%%*/ + $$ = NEW_ITER(0, 0, 0); + /*% + %*/ } + | block_var_def ; -block_var_def : '|' /* none */ '|' +block_var_def : '|' opt_bv_decl '|' { /*%%%*/ - $$ = (NODE*)1; + $$ = NEW_ITER((NODE*)1, 0, $2); /*% - $$ = dispatch1(blockvar_new, mlhs_new()); + $$ = blockvar_new(mlhs_new()); %*/ } | tOROP { /*%%%*/ - $$ = (NODE*)1; + $$ = NEW_ITER((NODE*)1, 0, 0); + /*% + $$ = blockvar_new(mlhs_new()); + %*/ + } + | '|' block_var opt_bv_decl '|' + { + /*%%%*/ + $$ = NEW_ITER($2, 0, $3); /*% - $$ = dispatch1(blockvar_new, mlhs_new()); + $$ = blockvar_new($2); %*/ } - | '|' block_var '|' + ; + + +opt_bv_decl : none + | ';' bv_decls { /*%%%*/ $$ = $2; /*% - $$ = dispatch1(blockvar_new, $2); + $$ = FIXME; + %*/ + } + ; + +bv_decls : bv_decl + { + /*%%%*/ + $$ = $1; + /*% + $$ = FIXME; + %*/ + } + | bv_decls ',' bv_decl + { + /*%%%*/ + $$ = block_append($1, $3); + /*% + $$ = FIXME; + %*/ + } + ; + +bv_decl : tIDENTIFIER + { + /*%%%*/ + $$ = new_bv($1, NEW_NIL()); + /*% + $$ = FIXME; + %*/ + } + | tIDENTIFIER '=' primary + { + /*%%%*/ + $$ = new_bv($1, $3); + /*% + $$ = FIXME; %*/ } ; @@ -3139,7 +3203,9 @@ do_block : kDO_BLOCK kEND { /*%%%*/ - $$ = NEW_ITER($3, 0, dyna_init($5, $4)); + $3->nd_body = block_append($3->nd_body, + dyna_init($5, $4)); + $$ = $3; nd_set_line($$, $1); dyna_pop($2); /*% @@ -3253,7 +3319,9 @@ brace_block : '{' compstmt '}' { /*%%%*/ - $$ = NEW_ITER($3, 0, dyna_init($5, $4)); + $3->nd_body = block_append($3->nd_body, + dyna_init($5, $4)); + $$ = $3; nd_set_line($$, $1); dyna_pop($2); /*% @@ -3277,7 +3345,9 @@ brace_block : '{' compstmt kEND { /*%%%*/ - $$ = NEW_ITER($3, 0, dyna_init($5, $4)); + $3->nd_body = block_append($3->nd_body, + dyna_init($5, $4)); + $$ = $3; nd_set_line($$, $1); dyna_pop($2); /*% @@ -6831,6 +6901,7 @@ gettable_gen(parser, id) if (dyna_in_block() && rb_dvar_defined(id)) return NEW_DVAR(id); if (local_id(id)) return NEW_LVAR(id); /* method call without arguments */ + dyna_check(id); return NEW_VCALL(id); } else if (is_global_id(id)) { @@ -6885,7 +6956,7 @@ assignable_gen(parser, id, val) return NEW_LASGN(id, val); } else{ - rb_dvar_push(id, Qnil); + dyna_var(id); return NEW_DASGN_CURR(id, val); } } @@ -6910,6 +6981,22 @@ assignable_gen(parser, id, val) return 0; } +static NODE* +new_bv_gen(parser, name, val) + struct parser_params *parser; + ID name; + NODE *val; +{ + if (is_local_id(name) && !rb_dvar_defined(name) && !local_id(name)) { + dyna_var(name); + return NEW_DASGN_CURR(name, val); + } + else { + compile_error(PARSER_ARG "local variable name conflict - %s", + rb_id2name(name)); + return 0; + } +} static NODE * aryset_gen(parser, recv, idx) struct parser_params *parser; @@ -7629,6 +7716,8 @@ local_push_gen(parser, top) local->cnt = 0; local->tbl = 0; local->dlev = 0; + local->dname_size = 0; + local->dnames = 0; local->dyna_vars = ruby_dyna_vars; lvtbl = local; if (!top) { @@ -7648,6 +7737,9 @@ local_pop_gen(parser) if (!lvtbl->nofree) xfree(lvtbl->tbl); else lvtbl->tbl[0] = lvtbl->cnt; } + if (lvtbl->dnames) { + xfree(lvtbl->dnames); + } ruby_dyna_vars = lvtbl->dyna_vars; xfree(lvtbl); lvtbl = local; @@ -7772,6 +7864,42 @@ top_local_setup_gen(parser) local_pop(); } +static void +dyna_var_gen(parser, id) + struct parser_params *parser; + ID id; +{ + int i; + + rb_dvar_push(id, Qnil); + for (i=0; idname_size; i++) { + if (lvtbl->dnames[i] == id) return; + } + if (lvtbl->dname_size == 0) { + lvtbl->dnames = ALLOC_N(ID, 1); + } + else { + REALLOC_N(lvtbl->dnames, ID, lvtbl->dname_size+1); + } + lvtbl->dnames[lvtbl->dname_size++] = id; +} + +static void +dyna_check_gen(parser, id) + struct parser_params *parser; + ID id; +{ + int i; + + if (in_defined) return; /* no check needed */ + for (i=0; idname_size; i++) { + if (lvtbl->dnames[i] == id) { + rb_warnS("out-of-scope variable - %s", rb_id2name(id)); + return; + } + } +} + static struct RVarmap* dyna_push_gen(parser) struct parser_params *parser; @@ -8819,3 +8947,4 @@ Init_ripper() rb_intern("&&"); } #endif /* RIPPER */ + diff --git a/re.c b/re.c index 15248d76bd..937eac66b4 100644 --- a/re.c +++ b/re.c @@ -1719,7 +1719,7 @@ rb_reg_match_m(argc, argv, re) * options are propagated, and new options may not be specified (a change as of * Ruby 1.8). If options is a Fixnum, it should be one or * more of the constants Regexp::EXTENDED, - * Regexp::IGNORECASE, and Regexp::POSIXLINE, + * Regexp::IGNORECASE, and Regexp::MULTILINE, * or-ed together. Otherwise, if options is not * nil, the regexp will be case insensitive. The lang * parameter enables multibyte support for the regexp: `n', `N' = none, `e', -- cgit v1.2.3