summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog19
-rw-r--r--eval.c31
-rw-r--r--lib/getoptlong.rb185
-rw-r--r--parse.y11
-rw-r--r--variable.c4
5 files changed, 209 insertions, 41 deletions
diff --git a/ChangeLog b/ChangeLog
index e57443eea7..31fd6c16d0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+Wed Apr 19 11:57:04 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_eval): use ARGSCAT for NODE_OP_ASGN1.
+ [ruby-dev:28585]
+
+ * parse.y (list_concat): revert last change.
+
+ * parse.y (arg): use NODE_ARGSCAT for placeholder.
+
+Wed Apr 19 11:13:17 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/getoptlong.rb (GetoptLong::get): RDoc update patch from
+ mathew <meta at pobox.com>. [ruby-core:07738]
+
+Wed Apr 19 10:13:27 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * variable.c (rb_const_set): raise error when no target klass is
+ supplied. [ruby-dev:28582]
+
Wed Apr 19 09:49:36 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
* parse.y (list_concat): should not modify nodes other than
diff --git a/eval.c b/eval.c
index 70a64443f1..c6d0dd711e 100644
--- a/eval.c
+++ b/eval.c
@@ -1855,12 +1855,13 @@ ev_const_defined(cref, id, self)
while (cbase && cbase->nd_next) {
struct RClass *klass = RCLASS(cbase->nd_clss);
- if (NIL_P(klass)) return rb_const_defined(CLASS_OF(self), id);
- if (klass->iv_tbl && st_lookup(klass->iv_tbl, id, &result)) {
- if (result == Qundef && NIL_P(rb_autoload_p((VALUE)klass, id))) {
- return Qfalse;
+ if (!NIL_P(klass)) {
+ if (klass->iv_tbl && st_lookup(klass->iv_tbl, id, &result)) {
+ if (result == Qundef && NIL_P(rb_autoload_p((VALUE)klass, id))) {
+ return Qfalse;
+ }
+ return Qtrue;
}
- return Qtrue;
}
cbase = cbase->nd_next;
}
@@ -1879,14 +1880,15 @@ ev_const_get(cref, id, self)
while (cbase && cbase->nd_next) {
VALUE klass = cbase->nd_clss;
- if (NIL_P(klass)) return rb_const_get(CLASS_OF(self), id);
- while (RCLASS(klass)->iv_tbl &&
- st_lookup(RCLASS(klass)->iv_tbl, id, &result)) {
- if (result == Qundef) {
- if (!RTEST(rb_autoload_load(klass, id))) break;
- continue;
+ if (!NIL_P(klass)) {
+ while (RCLASS(klass)->iv_tbl &&
+ st_lookup(RCLASS(klass)->iv_tbl, id, &result)) {
+ if (result == Qundef) {
+ if (!RTEST(rb_autoload_load(klass, id))) break;
+ continue;
+ }
+ return result;
}
- return result;
}
cbase = cbase->nd_next;
}
@@ -3538,7 +3540,7 @@ rb_eval(self, n)
recv = rb_eval(self, node->nd_recv);
rval = node->nd_args->nd_head;
- SETUP_ARGS0(node->nd_args->nd_next, node->nd_args->nd_alen-1,1);
+ SETUP_ARGS0(node->nd_args->nd_body, node->nd_args->nd_alen-1,1);
val = rb_funcall3(recv, aref, argc, argv);
switch (node->nd_mid) {
case 0: /* OR */
@@ -3636,9 +3638,6 @@ rb_eval(self, n)
rb_const_set(class_prefix(self, node->nd_else), node->nd_else->nd_mid, result);
}
else {
- if (NIL_P(ruby_cbase)) {
- rb_raise(rb_eTypeError, "no class/module to define constant");
- }
rb_const_set(ruby_cbase, node->nd_vid, result);
}
break;
diff --git a/lib/getoptlong.rb b/lib/getoptlong.rb
index 1a0d669fa3..f6c5374d67 100644
--- a/lib/getoptlong.rb
+++ b/lib/getoptlong.rb
@@ -1,17 +1,94 @@
-# -*- Ruby -*-
-# Copyright (C) 1998, 1999, 2000 Motoyuki Kasahara
#
-# You may redistribute it and/or modify it under the same license
+# GetoptLong for Ruby
+#
+# Copyright (C) 1998, 1999, 2000 Motoyuki Kasahara.
+#
+# You may redistribute and/or modify this library under the same license
# terms as Ruby.
#
+# See GetoptLong for documentation.
+#
+# Additional documents and the latest version of `getoptlong.rb' can be
+# found at http://www.sra.co.jp/people/m-kasahr/ruby/getoptlong/
+# The GetoptLong class allows you to parse command line options similarly to
+# the GNU getopt_long() C library call. Note, however, that GetoptLong is a
+# pure Ruby implementation.
#
-# Documents and latest version of `getoptlong.rb' are found at:
-# http://www.sra.co.jp/people/m-kasahr/ruby/getoptlong/
+# GetoptLong allows for POSIX-style options like <tt>--file</tt> as well
+# as single letter options like <tt>-f</tt>
#
-
+# The empty option <tt>--</tt> (two minus symbols) is used to end option
+# processing. This can be particularly important if options have optional
+# arguments.
#
-# Parse command line options just like GNU getopt_long().
+# Here is a simple example of usage:
+#
+# # == Synopsis
+# #
+# # hello: greets user, demonstrates command line parsing
+# #
+# # == Usage
+# #
+# # hello [OPTION] ... DIR
+# #
+# # -h, --help:
+# # show help
+# #
+# # --repeat x, -n x:
+# # repeat x times
+# #
+# # --name [name]:
+# # greet user by name, if name not supplied default is John
+# #
+# # DIR: The directory in which to issue the greeting.
+#
+# require 'getoptlong'
+# require 'rdoc/usage'
+#
+# opts = GetoptLong.new(
+# [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
+# [ '--repeat', '-n', GetoptLong::REQUIRED_ARGUMENT ],
+# [ '--name', GetoptLong::OPTIONAL_ARGUMENT ]
+# )
+#
+# dir = nil
+# name = nil
+# repetitions = 1
+# opts.each do |opt, arg|
+# case opt
+# when '--help'
+# RDoc::usage
+# when '--repeat'
+# repetitions = arg.to_i
+# when '--name'
+# if arg == ''
+# name = 'John'
+# else
+# name = arg
+# end
+# end
+# end
+#
+# if ARGV.length != 1
+# puts "Missing dir argument (try --help)"
+# exit 0
+# end
+#
+# dir = ARGV.shift
+#
+# Dir.chdir(dir)
+# for i in (1..repetitions)
+# print "Hello"
+# if name
+# print ", #{name}"
+# end
+# puts
+# end
+#
+# Example command line:
+#
+# hello -n 6 --name -- /tmp
#
class GetoptLong
#
@@ -40,7 +117,20 @@ class GetoptLong
class InvalidOption < Error; end
#
- # Initializer.
+ # Set up option processing.
+ #
+ # The options to support are passed to new() as an array of arrays.
+ # Each sub-array contains any number of String option names which carry
+ # the same meaning, and one of the following flags:
+ #
+ # GetoptLong::NO_ARGUMENT :: Option does not take an argument.
+ #
+ # GetoptLong::REQUIRED_ARGUMENT :: Option always takes an argument.
+ #
+ # GetoptLong::OPTIONAL_ARGUMENT :: Option may or may not take an argument.
+ #
+ # The first option name is considered to be the preferred (canonical) name.
+ # Other than that, the elements of each sub-array can be in any order.
#
def initialize(*arguments)
#
@@ -103,7 +193,53 @@ class GetoptLong
end
#
- # Set ordering.
+ # Set the handling of the ordering of options and arguments.
+ # A RuntimeError is raised if option processing has already started.
+ #
+ # The supplied value must be a member of GetoptLong::ORDERINGS. It alters
+ # the processing of options as follows:
+ #
+ # <b>REQUIRE_ORDER</b> :
+ #
+ # Options are required to occur before non-options.
+ #
+ # Processing of options ends as soon as a word is encountered that has not
+ # been preceded by an appropriate option flag.
+ #
+ # For example, if -a and -b are options which do not take arguments,
+ # parsing command line arguments of '-a one -b two' would result in
+ # 'one', '-b', 'two' being left in ARGV, and only ('-a', '') being
+ # processed as an option/arg pair.
+ #
+ # This is the default ordering, if the environment variable
+ # POSIXLY_CORRECT is set. (This is for compatibility with GNU getopt_long.)
+ #
+ # <b>PERMUTE</b> :
+ #
+ # Options can occur anywhere in the command line parsed. This is the
+ # default behavior.
+ #
+ # Every sequence of words which can be interpreted as an option (with or
+ # without argument) is treated as an option; non-option words are skipped.
+ #
+ # For example, if -a does not require an argument and -b optionally takes
+ # an argument, parsing '-a one -b two three' would result in ('-a','') and
+ # ('-b', 'two') being processed as option/arg pairs, and 'one','three'
+ # being left in ARGV.
+ #
+ # If the ordering is set to PERMUTE but the environment variable
+ # POSIXLY_CORRECT is set, REQUIRE_ORDER is used instead. This is for
+ # compatibility with GNU getopt_long.
+ #
+ # <b>RETURN_IN_ORDER</b> :
+ #
+ # All words on the command line are processed as options. Words not
+ # preceded by a short or long option flag are passed as arguments
+ # with an option of '' (empty string).
+ #
+ # For example, if -a requires an argument but -b does not, a command line
+ # of '-a one -b two three' would result in option/arg pairs of ('-a', 'one')
+ # ('-b', ''), ('', 'two'), ('', 'three') being processed.
#
def ordering=(ordering)
#
@@ -134,7 +270,9 @@ class GetoptLong
attr_reader :ordering
#
- # Set options
+ # Set options. Takes the same argument as GetoptLong.new.
+ #
+ # Raises a RuntimeError if option processing has already started.
#
def set_options(*arguments)
#
@@ -223,7 +361,7 @@ class GetoptLong
alias quiet? quiet
#
- # Terminate option processing.
+ # Explicitly terminate option processing.
#
def terminate
return nil if @status == STATUS_TERMINATED
@@ -243,7 +381,7 @@ class GetoptLong
end
#
- # Examine whether option processing is terminated or not.
+ # Returns true if option processing has terminated, false otherwise.
#
def terminated?
return @status == STATUS_TERMINATED
@@ -276,15 +414,23 @@ class GetoptLong
#
alias error? error
- #
- # Return an error message.
+ # Return the appropriate error message in POSIX-defined format.
+ # If no error has occurred, returns nil.
#
def error_message
return @error_message
end
#
- # Get next option name and its argument as an array.
+ # Get next option name and its argument, as an Array of two elements.
+ #
+ # The option name is always converted to the first (preferred)
+ # name given in the original options to GetoptLong.new.
+ #
+ # Example: ['--option', 'value']
+ #
+ # Returns nil if the processing is complete (as determined by
+ # STATUS_TERMINATED).
#
def get
option_name, option_argument = nil, ''
@@ -450,9 +596,16 @@ class GetoptLong
#
alias get_option get
- #
# Iterator version of `get'.
#
+ # The block is called repeatedly with two arguments:
+ # The first is the option name.
+ # The second is the argument which followed it (if any).
+ # Example: ('--opt', 'value')
+ #
+ # The option name is always converted to the first (preferred)
+ # name given in the original options to GetoptLong.new.
+ #
def each
loop do
option_name, option_argument = get_option
diff --git a/parse.y b/parse.y
index d50f06d104..608da7e820 100644
--- a/parse.y
+++ b/parse.y
@@ -542,11 +542,7 @@ stmt : kALIAS fitem {lex_state = EXPR_FNAME;} fitem
NODE *args;
value_expr($6);
- args = NEW_LIST($6);
- if ($3 && nd_type($3) != NODE_ARRAY)
- $3 = NEW_LIST($3);
- $3 = list_append($3, NEW_NIL());
- list_concat(args, $3);
+ args = arg_concat(NEW_LIST($6), $3);
if ($5 == tOROP) {
$5 = 0;
}
@@ -1013,8 +1009,7 @@ arg : lhs '=' arg
NODE *args;
value_expr($6);
- args = NEW_LIST($6);
- list_concat(args, $3);
+ args = arg_concat(NEW_LIST($6), $3);
if ($5 == tOROP) {
$5 = 0;
}
@@ -4665,8 +4660,6 @@ list_concat(head, tail)
{
NODE *last;
- if (nd_type(tail) != NODE_ARRAY)
- return list_append(head, tail);
if (head->nd_next) {
last = head->nd_next->nd_end;
}
diff --git a/variable.c b/variable.c
index 72ef979a9f..0ca978d4b0 100644
--- a/variable.c
+++ b/variable.c
@@ -1670,6 +1670,10 @@ rb_const_set(klass, id, val)
ID id;
VALUE val;
{
+ if (NIL_P(klass)) {
+ rb_raise(rb_eTypeError, "no class/module to define constant %s",
+ rb_id2name(id));
+ }
mod_av_set(klass, id, val, Qtrue);
}