From 1d3fd0024d2e8821e863a39c53c38dfea65b6fa6 Mon Sep 17 00:00:00 2001 From: matz Date: Wed, 19 Apr 2006 03:02:03 +0000 Subject: [PATCH] * 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. * lib/getoptlong.rb (GetoptLong::get): RDoc update patch from mathew . [ruby-core:07738] * variable.c (rb_const_set): raise error when no target klass is supplied. [ruby-dev:28582] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@10100 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 19 +++++ eval.c | 31 ++++---- lib/getoptlong.rb | 185 ++++++++++++++++++++++++++++++++++++++++++---- parse.y | 11 +-- variable.c | 4 + 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 + + * 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 + + * lib/getoptlong.rb (GetoptLong::get): RDoc update patch from + mathew . [ruby-core:07738] + +Wed Apr 19 10:13:27 2006 Yukihiro Matsumoto + + * 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 * 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 --file as well +# as single letter options like -f # - +# The empty option -- (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: + # + # REQUIRE_ORDER : + # + # 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.) + # + # PERMUTE : + # + # 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. + # + # RETURN_IN_ORDER : + # + # 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); }