aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2005-03-09 09:29:52 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2005-03-09 09:29:52 +0000
commitf43cae2b057622e6812e370f2c7cb3efa06f6665 (patch)
treeca48f13383a026a57bb50ae9e0e3751154ff0420
parent9ef561b6e09a6d5768617e20db4d985ca34260e9 (diff)
downloadruby-f43cae2b057622e6812e370f2c7cb3efa06f6665.tar.gz
* 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
-rw-r--r--ChangeLog14
-rw-r--r--ext/socket/socket.c85
-rw-r--r--ext/tk/sample/demos-en/floor.rb4
-rw-r--r--ext/tk/sample/demos-en/floor2.rb4
-rw-r--r--ext/tk/sample/demos-jp/floor.rb4
-rw-r--r--ext/tk/sample/demos-jp/floor2.rb4
-rw-r--r--parse.y177
-rw-r--r--re.c2
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 <matz@ruby-lang.org>
+
+ * 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 <nagai@ai.kyutech.ac.jp>
* ext/tk/sample/tktextio.rb: fix bug of handling 'end' position.
@@ -14,6 +22,12 @@ Tue Mar 8 13:39:25 2005 NAKAMURA Usaku <usa@ruby-lang.org>
* ext/socket/mkconstants.rb: workaround for some of 4.4BSD-Lite
derived OSs.
+Tue Mar 8 12:36:17 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/socket/socket.c: document from Sam Roberts
+ <sroberts@uniserve.com> for getsockopt and setsockopt is merged.
+ [ruby-doc:824]
+
Tue Mar 8 10:48:53 2005 NAKAMURA Usaku <usa@ruby-lang.org>
* 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 <node> mrhs superclass block_call block_command
%type <node> f_arglist f_args f_optarg f_opt f_block_arg opt_f_block_arg
%type <node> assoc_list assocs assoc undef_list backref string_dvar
-%type <node> for_var block_var opt_block_var block_var_def block_par
+%type <node> for_var block_var opt_block_var block_var_def block_param
+%type <node> opt_bv_decl bv_decls bv_decl
%type <node> brace_block cmd_brace_block do_block lhs none fitem
%type <node> mlhs mlhs_head mlhs_basic mlhs_entry mlhs_item mlhs_node
%type <id> fsym variable sym symbol operation operation2 operation3
@@ -1098,7 +1109,9 @@ cmd_brace_block : tLBRACE_ARG
'}'
{
/*%%%*/
- $$ = NEW_ITER($3, 0, dyna_init($5, $<vars>4));
+ $3->nd_body = block_append($3->nd_body,
+ dyna_init($5, $<vars>4));
+ $$ = $3;
nd_set_line($$, $<num>1);
dyna_pop($<vars>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, $<vars>4));
+ $3->nd_body = block_append($3->nd_body,
+ dyna_init($5, $<vars>4));
+ $$ = $3;
nd_set_line($$, $<num>1);
dyna_pop($<vars>2);
/*%
@@ -3253,7 +3319,9 @@ brace_block : '{'
compstmt '}'
{
/*%%%*/
- $$ = NEW_ITER($3, 0, dyna_init($5, $<vars>4));
+ $3->nd_body = block_append($3->nd_body,
+ dyna_init($5, $<vars>4));
+ $$ = $3;
nd_set_line($$, $<num>1);
dyna_pop($<vars>2);
/*%
@@ -3277,7 +3345,9 @@ brace_block : '{'
compstmt kEND
{
/*%%%*/
- $$ = NEW_ITER($3, 0, dyna_init($5, $<vars>4));
+ $3->nd_body = block_append($3->nd_body,
+ dyna_init($5, $<vars>4));
+ $$ = $3;
nd_set_line($$, $<num>1);
dyna_pop($<vars>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; i<lvtbl->dname_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; i<lvtbl->dname_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 <i>options</i> is a <code>Fixnum</code>, it should be one or
* more of the constants <code>Regexp::EXTENDED</code>,
- * <code>Regexp::IGNORECASE</code>, and <code>Regexp::POSIXLINE</code>,
+ * <code>Regexp::IGNORECASE</code>, and <code>Regexp::MULTILINE</code>,
* <em>or</em>-ed together. Otherwise, if <i>options</i> is not
* <code>nil</code>, the regexp will be case insensitive. The <i>lang</i>
* parameter enables multibyte support for the regexp: `n', `N' = none, `e',