diff options
author | knu <knu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2010-09-10 07:51:58 +0000 |
---|---|---|
committer | knu <knu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2010-09-10 07:51:58 +0000 |
commit | 82abe79b9fa3b5a648f453076a28ed9566d02ec8 (patch) | |
tree | 38c67940337c200adc83b83669049492fb4a3534 /class.c | |
parent | 4f77c495cddcdfcbb15e363ba21d09e5a9ddfd37 (diff) | |
download | ruby-82abe79b9fa3b5a648f453076a28ed9566d02ec8.tar.gz |
* class.c (rb_scan_args): Add support for optional keyword
argument hash.
* README.EXT, README.EXT.ja: Update documentation accordingly.
* dir.c (dir_initialize): Make use of the new rb_scan_args()
feature.
* io.c (rb_io_s_popen, rb_scan_open_args, rb_io_initialize)
(rb_io_s_pipe, open_key_args, io_s_foreach, io_s_readlines)
(rb_io_s_read, rb_io_set_encoding): Ditto.
* transcode.c (str_transcode, econv_args)
(econv_primitive_convert): Ditto.
* ext/zlib/zlib.c (rb_gzreader_initialize): Ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@29214 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'class.c')
-rw-r--r-- | class.c | 29 |
1 files changed, 28 insertions, 1 deletions
@@ -1376,9 +1376,10 @@ rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...) const char *p = fmt; VALUE *var; va_list vargs; - int f_var = 0, f_block = 0; + int f_var = 0, f_hash = 0, f_block = 0; int n_lead = 0, n_opt = 0, n_trail = 0, n_mand; int argi = 0; + VALUE hash = Qnil; if (ISDIGIT(*p)) { n_lead = *p - '0'; @@ -1402,6 +1403,10 @@ rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...) } } block_arg: + if (*p == ':') { + f_hash = 1; + p++; + } if (*p == '&') { f_block = 1; p++; @@ -1416,6 +1421,23 @@ rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...) va_start(vargs, fmt); + /* capture an option hash - phase 1: pop */ + if (f_hash && n_mand < argc) { + VALUE last = argv[argc - 1]; + + if (NIL_P(last)) { + /* nil is taken as an empty option hash only if it is not + ambiguous; i.e. '*' is not specified and arguments are + given more than sufficient */ + if (!f_var && n_mand + n_opt < argc) + argc--; + } + else { + hash = rb_check_convert_type(last, T_HASH, "Hash", "to_hash"); + if (!NIL_P(hash)) + argc--; + } + } /* capture leading mandatory arguments */ for (i = n_lead; i-- > 0; ) { var = va_arg(vargs, VALUE *); @@ -1452,6 +1474,11 @@ rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...) if (var) *var = argv[argi]; argi++; } + /* capture an option hash - phase 2: assignment */ + if (f_hash) { + var = va_arg(vargs, VALUE *); + if (var) *var = hash; + } /* capture iterator block */ if (f_block) { var = va_arg(vargs, VALUE *); |