summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2010-03-17 19:45:21 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2010-03-17 19:45:21 +0000
commite29fd6006de8d32efcec2f24ab4588792675b5a6 (patch)
tree6db9e94c724f6d2c780038d99ba7f2b2140c78a2
parentd7ce45bc1fbd4b31262b08fae6754739ed790d3c (diff)
downloadruby-e29fd6006de8d32efcec2f24ab4588792675b5a6.tar.gz
* merged from trunk r26939:26967.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/mvm@26968 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--.merged-trunk-revision2
-rw-r--r--ChangeLog135
-rw-r--r--NEWS1
-rw-r--r--compile.c6
-rw-r--r--configure.in4
-rw-r--r--enc/trans/chinese.trans10
-rw-r--r--enc/trans/emoji.trans1
-rw-r--r--enc/trans/single_byte.trans3
-rw-r--r--ext/bigdecimal/bigdecimal.c1
-rw-r--r--ext/tmpdir/extconf.rb6
-rw-r--r--ext/tmpdir/tmpdir.c32
-rw-r--r--file.c31
-rw-r--r--hash.c3
-rw-r--r--include/ruby/encoding.h3
-rw-r--r--include/ruby/ruby.h2
-rw-r--r--iseq.c54
-rw-r--r--lib/tmpdir.rb32
-rw-r--r--lib/uri/common.rb94
-rw-r--r--load.c16
-rw-r--r--parse.y4
-rw-r--r--prelude.rb14
-rw-r--r--ruby.c4
-rw-r--r--test/ruby/test_m17n_comb.rb4
-rw-r--r--test/ruby/test_string.rb9
-rw-r--r--test/uri/test_common.rb26
-rwxr-xr-xtool/transcode-tblgen.rb227
-rw-r--r--util.c38
-rw-r--r--version.h4
-rw-r--r--vm.c4
-rw-r--r--vm_core.h11
-rw-r--r--vm_eval.c10
-rw-r--r--win32/win32.c34
32 files changed, 580 insertions, 245 deletions
diff --git a/.merged-trunk-revision b/.merged-trunk-revision
index b176560f6c..346a1c9cb5 100644
--- a/.merged-trunk-revision
+++ b/.merged-trunk-revision
@@ -1 +1 @@
-26939
+26967
diff --git a/ChangeLog b/ChangeLog
index eb239e6b33..447e012f15 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,132 @@
+Thu Mar 18 04:40:56 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (rb_intern3): get rid of type-punning cast.
+
+Thu Mar 18 02:29:42 2010 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * compile.c (iseq_build_body): add mark to jump table hash of case.
+
+Thu Mar 18 00:58:27 2010 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * util.c (ruby_strtod): Add support for Hexadecimal
+ floating-point expression [ruby-dev:40650] #2969
+
+Thu Mar 18 00:00:58 2010 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * lib/uri/common.rb (URI#{en,de}code_www_form_component):
+ renamed from URI#{en,de}code_www_component. [ruby-dev:40672]
+
+ * lib/uri/common.rb (URI#encode_www_form_component): %-encoded
+ element should have always two hex.
+
+ * lib/uri/common.rb (URI#encode_www_form_component):
+ better treatment for ASCII incompatible encodings and
+ encodings whose lead byte may use 7bit.
+
+ * lib/uri/common.rb (URI#decode_www_form_component): add %20.
+
+ * lib/uri/common.rb (URI#decode_www_form_component): add
+ result's encoding as 2nd argument.
+
+ * lib/uri/common.rb (URI#decode_www_form): added.
+
+Wed Mar 17 16:25:53 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * hash.c (rb_hash_aset): allow recursive key. [ruby-core:24648]
+
+Wed Mar 17 06:39:59 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ruby.h (rb_warning, rb_sys_warning): fixed typo in rdoc.
+ [ruby-core:28696]
+
+Wed Mar 17 02:29:46 2010 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * compile.c, iseq.c, ruby.c, vm.c, vm_core.h, vm_eval.c: add absolute
+ path field into rb_iseq_t. The field contains a string representing
+ a path to corresponding source file. or nil when the iseq is created
+ from -e, stdin, eval, etc. This field is used for require_relative.
+ [ruby-dev:40004]
+
+ * load.c (rb_f_require_relative): add C implementation of
+ require_relative.
+
+ * prelude.rb (require_relative): get rid of Ruby implementation of
+ require_relative.
+
+Wed Mar 17 01:24:01 2010 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * parse.y (rb_intern3): prohibit Symbol with an invalid encoding.
+ [ruby-core:24621]
+
+ * test/ruby/test_m17n_comb.rb: modify a test for above.
+
+Tue Mar 16 22:51:11 2010 Tanaka Akira <akr@fsij.org>
+
+ * tool/transcode-tblgen.rb: specialize for singleton mappings.
+
+Tue Mar 16 20:13:00 2010 Kenta Murata <mrkn@mrkn.jp>
+
+ * enc/trans/emoji.trans: added codepoints leading 0xf4 into
+ nomap_table.
+
+Tue Mar 16 17:33:30 2010 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/bigdecimal/bigdecimal.c (VpCtoV): keep e's sign.
+ When e doesn't over flow e * BASE_FIG but overflow e * 10,
+ e will overflow.
+
+Tue Mar 16 17:18:44 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * include/ruby/encoding.h (rb_str_conv_enc_opts): missing prototype.
+
+Tue Mar 16 15:20:13 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/tmpdir: split from lib/tmpdir.rb.
+
+ * win32/win32.c (rb_w32_system_tmpdir): extracted from init_env.
+
+ * win32/win32.c (rb_w32_getcwd): removed duplicated code.
+
+Tue Mar 16 14:06:13 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * include/ruby/encoding.h (ENC_TO_ENCINDEX): suppress warnings.
+
+Tue Mar 16 14:03:24 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (RSHIFT): parenthesize the argument of cast instead
+ of the result.
+
+Tue Mar 16 11:23:42 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (file_expand_path): ignore dname if it has different
+ drive letter or UNC.
+
+Tue Mar 16 07:16:56 2010 Tanaka Akira <akr@fsij.org>
+
+ * tool/transcode-tblgen.rb: redundant loop removed.
+
+Tue Mar 16 07:01:43 2010 Tanaka Akira <akr@fsij.org>
+
+ * tool/transcode-tblgen.rb: refactored to use tree as memo key.
+
+Tue Mar 16 04:05:13 2010 Tanaka Akira <akr@fsij.org>
+
+ * tool/transcode-tblgen.rb: more info in generating macro names.
+
+Mon Mar 15 21:58:03 2010 Tanaka Akira <akr@fsij.org>
+
+ * tool/transcode-tblgen.rb: ActionMap#each_firstbyte inlined.
+
+Mon Mar 15 21:22:49 2010 Tanaka Akira <akr@fsij.org>
+
+ * tool/transcode-tblgen.rb (transcode_tblgen): add valid_encoding
+ optional argument.
+
+ * enc/trans/single_byte.trans use valid_encoding argument for
+ transcode_tblgen.
+
+ * enc/trans/chinese.trans: ditto.
+
Mon Mar 15 18:33:36 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
* random.c (default_rand): removed initial buffer.
@@ -111,7 +240,7 @@ Sun Mar 14 02:40:38 2010 Tanaka Akira <akr@fsij.org>
* tool/transcode-tblgen.rb: reject ambiguous mapping.
- * enc/trans/single_byte.trans: remove ambiguous maping such as
+ * enc/trans/single_byte.trans: remove ambiguous mapping such as
\xD6 -> U+05F2 and \xD6\xC7 -> U+FB1F in Windows-1255
Sat Mar 13 23:48:27 2010 Yukihiro Matsumoto <matz@ruby-lang.org>
@@ -124,7 +253,7 @@ Sat Mar 13 23:48:27 2010 Yukihiro Matsumoto <matz@ruby-lang.org>
Sat Mar 13 17:48:43 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
- * tool/file2lastrev.rb: refactord. fixed changed revision of git.
+ * tool/file2lastrev.rb: refactored. fixed changed revision of git.
Sat Mar 13 15:44:20 2010 Yukihiro Matsumoto <matz@ruby-lang.org>
@@ -465,7 +594,7 @@ Wed Mar 3 14:28:23 2010 Yukihiro Matsumoto <matz@ruby-lang.org>
Wed Mar 3 06:19:25 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
- * win32/win32.c (signbig): defined.
+ * win32/win32.c (signbit): defined.
* win32/Makefile.sub, symbian/setup (config.h): pack.c requires
SIZEOF_INT*_T now.
diff --git a/NEWS b/NEWS
index 56b4cf6833..0b6a946b74 100644
--- a/NEWS
+++ b/NEWS
@@ -313,6 +313,7 @@ with all sufficient information, see the ChangeLog file.
* \d, \s, and \w are now ASCII only; use POSIX bracket classes and \p{} for
Unicode semantics
* $: no longer includes the current directory, use require_relative
+* Symbol with an invalid encoding is forbidden to exist.
=== Compilation options
diff --git a/compile.c b/compile.c
index 1db4e9c6b8..8b73cbd92f 100644
--- a/compile.c
+++ b/compile.c
@@ -169,6 +169,9 @@ PRINTF_ARGS(void ruby_debug_printf(const char*, ...), 1, 2);
#define iseq_filename(iseq) \
(((rb_iseq_t*)DATA_PTR(iseq))->filename)
+#define iseq_filepath(iseq) \
+ (((rb_iseq_t*)DATA_PTR(iseq))->filepath)
+
#define NEW_ISEQVAL(node, name, type, line_no) \
new_child_iseq(iseq, node, name, 0, type, line_no)
@@ -917,7 +920,7 @@ new_child_iseq(rb_iseq_t *iseq, NODE *node,
VALUE ret;
debugs("[new_child_iseq]> ---------------------------------------\n");
- ret = rb_iseq_new_with_opt(node, name, iseq_filename(iseq->self), INT2FIX(line_no),
+ ret = rb_iseq_new_with_opt(node, name, iseq_filename(iseq->self), iseq_filepath(iseq->self), INT2FIX(line_no),
parent, type, iseq->compile_data->option);
debugs("[new_child_iseq]< ---------------------------------------\n");
iseq_add_mark_object(iseq, ret);
@@ -5287,6 +5290,7 @@ iseq_build_body(rb_iseq_t *iseq, LINK_ANCHOR *anchor,
rb_ary_store(op, i+1, (VALUE)label | 1);
}
argv[j] = op;
+ iseq_add_mark_object_compile_time(iseq, op);
}
break;
default:
diff --git a/configure.in b/configure.in
index b02abe1132..d5f76564e4 100644
--- a/configure.in
+++ b/configure.in
@@ -1349,9 +1349,9 @@ AC_CACHE_CHECK(whether right shift preserve sign bit, rb_cv_rshift_sign,
rb_cv_rshift_sign=yes,
rb_cv_rshift_sign=no)])
if test "$rb_cv_rshift_sign" = yes; then
- AC_DEFINE(RSHIFT(x,y), ((x)>>((int)y)))
+ AC_DEFINE(RSHIFT(x,y), ((x)>>(int)(y)))
else
- AC_DEFINE(RSHIFT(x,y), (((x)<0) ? ~((~(x))>>(y)) : (x)>>(y)))
+ AC_DEFINE(RSHIFT(x,y), (((x)<0) ? ~((~(x))>>(int)(y)) : (x)>>(int)(y)))
fi
test "$rb_cv_fcnt" = "not found" && rb_cv_fcnt="not found (OK if using GNU libc)"
diff --git a/enc/trans/chinese.trans b/enc/trans/chinese.trans
index 1db6565254..3689696018 100644
--- a/enc/trans/chinese.trans
+++ b/enc/trans/chinese.trans
@@ -1,16 +1,18 @@
#include "transcode_data.h"
<%
- set_valid_byte_pattern 'GB2312', 'EUC-KR'
- set_valid_byte_pattern 'GB12345', 'EUC-KR'
+ gb2312_valid_byte_pattern = ValidEncoding['EUC-KR']
+ gb12345_valid_byte_pattern = ValidEncoding['EUC-KR']
transcode_tblgen "GB2312", "UTF-8",
[["{00-7f}", :nomap]] +
- citrus_decode_mapsrc("euc", 0x8080, "GB2312/UCS")
+ citrus_decode_mapsrc("euc", 0x8080, "GB2312/UCS"),
+ gb2312_valid_byte_pattern
transcode_tblgen "GB12345", "UTF-8",
[["{00-7f}", :nomap]] +
- citrus_decode_mapsrc("euc", 0x8080, "GB12345/UCS")
+ citrus_decode_mapsrc("euc", 0x8080, "GB12345/UCS"),
+ gb12345_valid_byte_pattern
transcode_tblgen "UTF-8", "GB2312",
[["{00-7f}", :nomap]] +
diff --git a/enc/trans/emoji.trans b/enc/trans/emoji.trans
index cb930b51c7..91bbaf499a 100644
--- a/enc/trans/emoji.trans
+++ b/enc/trans/emoji.trans
@@ -12,6 +12,7 @@
["{ee-ef}{80-bf}{80-bf}", :nomap0],
["f0{90-bf}{80-bf}{80-bf}", :nomap0],
["{f1-f3}{80-bf}{80-bf}{80-bf}", :nomap0],
+ ["f4{80-8f}{80-bf}{80-bf}", :nomap0],
]
companies = %w(DoCoMo KDDI SoftBank Unicode)
diff --git a/enc/trans/single_byte.trans b/enc/trans/single_byte.trans
index db47074570..55d8430932 100644
--- a/enc/trans/single_byte.trans
+++ b/enc/trans/single_byte.trans
@@ -22,9 +22,8 @@
require(name.downcase + "-tbl")
control1_if_needed = (name =~ /^ISO-8859/) ? CONTROL1_TO_UCS_TBL : []
tbl_to_ucs = control1_if_needed + eval(name.gsub(/-/, '_') + "_TO_UCS_TBL")
- set_valid_byte_pattern(name, '1byte')
code = ''
- code << transcode_tblgen(name, "UTF-8", [["{00-7f}", :nomap], *tbl_to_ucs.reject {|a, b| a.length != 2 }])
+ code << transcode_tblgen(name, "UTF-8", [["{00-7f}", :nomap], *tbl_to_ucs.reject {|a, b| a.length != 2 }], '{00-ff}')
code << "\n"
code << transcode_tblgen("UTF-8", name, [["{00-7f}", :nomap], *tbl_to_ucs.map {|a,b| [b,a] }])
code
diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c
index 667f58128d..189a6c77fb 100644
--- a/ext/bigdecimal/bigdecimal.c
+++ b/ext/bigdecimal/bigdecimal.c
@@ -4045,6 +4045,7 @@ VpCtoV(Real *a, const char *int_chr, U_LONG ni, const char *frac, U_LONG nf, con
e = e * 10 + exp_chr[i] - '0';
if(es>e*((S_INT)BASE_FIG)) {
exponent_overflow = 1;
+ e = es;
break;
}
++i;
diff --git a/ext/tmpdir/extconf.rb b/ext/tmpdir/extconf.rb
new file mode 100644
index 0000000000..a283f851b0
--- /dev/null
+++ b/ext/tmpdir/extconf.rb
@@ -0,0 +1,6 @@
+case
+when have_func("rb_w32_system_tmpdir")
+ ok = true # win32
+else
+end
+create_makefile("tmpdir") if ok
diff --git a/ext/tmpdir/tmpdir.c b/ext/tmpdir/tmpdir.c
new file mode 100644
index 0000000000..f046713b63
--- /dev/null
+++ b/ext/tmpdir/tmpdir.c
@@ -0,0 +1,32 @@
+#include <ruby/ruby.h>
+#include <ruby/encoding.h>
+
+#define numberof(array) (sizeof(array) / sizeof(*array))
+
+#ifdef HAVE_RB_W32_SYSTEM_TMPDIR
+UINT rb_w32_system_tmpdir(WCHAR *path, UINT len);
+VALUE rb_w32_conv_from_wchar(const WCHAR *wstr, rb_encoding *enc);
+#endif
+
+static VALUE
+system_tmpdir(void)
+{
+#ifdef HAVE_RB_W32_SYSTEM_TMPDIR
+ WCHAR path[_MAX_PATH];
+ UINT len = rb_w32_system_tmpdir(path, numberof(path));
+ if (!len) return Qnil;
+ return rb_w32_conv_from_wchar(path, rb_filesystem_encoding());
+#else
+ return rb_filesystem_str_new_cstr("/tmp");
+#endif
+}
+
+/*
+ * sets Dir.@@systmpdir.
+ */
+void
+Init_tmpdir(void)
+{
+ rb_cvar_set(rb_cDir, rb_intern_const("@@systmpdir"),
+ rb_obj_freeze(system_tmpdir()));
+}
diff --git a/file.c b/file.c
index e757f9619f..6a66e3f14f 100644
--- a/file.c
+++ b/file.c
@@ -2566,6 +2566,12 @@ static const char file_alt_separator[] = {FILE_ALT_SEPARATOR, '\0'};
# define CharNext(p) ((p) + 1)
#endif
+#if defined(DOSISH_UNC)
+#define has_unc(buf) (isdirsep((buf)[0]) && isdirsep((buf)[1]))
+#else
+#define has_unc(buf) 0
+#endif
+
#ifdef DOSISH_DRIVE_LETTER
static inline int
has_drive_letter(const char *buf)
@@ -2604,6 +2610,19 @@ getcwdofdrv(int drv)
}
return drvcwd;
}
+
+static inline int
+not_same_drive(VALUE path, int drive)
+{
+ const char *p = RSTRING_PTR(path);
+ if (RSTRING_LEN(path) < 2) return 0;
+ if (has_drive_letter(p)) {
+ return TOLOWER(p[0]) != TOLOWER(drive);
+ }
+ else {
+ return has_unc(p);
+ }
+}
#endif
static inline char *
@@ -2829,7 +2848,7 @@ file_expand_path(VALUE fname, VALUE dname, int abs_mode, VALUE result)
else {
/* specified drive, but not full path */
int same = 0;
- if (!NIL_P(dname)) {
+ if (!NIL_P(dname) || !not_same_drive(dname, s[0])) {
file_expand_path(dname, Qnil, abs_mode, result);
BUFINIT();
if (has_drive_letter(p) && TOLOWER(p[0]) == TOLOWER(s[0])) {
@@ -3217,8 +3236,8 @@ realpath_rec(long *prefixlenp, VALUE *resolvedp, char *unresolved, VALUE loopche
}
}
-static VALUE
-realpath_internal(VALUE basedir, VALUE path, int strict)
+VALUE
+rb_realpath_internal(VALUE basedir, VALUE path, int strict)
{
long prefixlen;
VALUE resolved;
@@ -3306,7 +3325,7 @@ rb_file_s_realpath(int argc, VALUE *argv, VALUE klass)
{
VALUE path, basedir;
rb_scan_args(argc, argv, "11", &path, &basedir);
- return realpath_internal(basedir, path, 1);
+ return rb_realpath_internal(basedir, path, 1);
}
/*
@@ -3326,7 +3345,7 @@ rb_file_s_realdirpath(int argc, VALUE *argv, VALUE klass)
{
VALUE path, basedir;
rb_scan_args(argc, argv, "11", &path, &basedir);
- return realpath_internal(basedir, path, 0);
+ return rb_realpath_internal(basedir, path, 0);
}
static size_t
@@ -3458,7 +3477,7 @@ rb_file_s_basename(int argc, VALUE *argv)
* File.dirname("/home/gumby/work/ruby.rb") #=> "/home/gumby/work"
*/
-static VALUE
+VALUE
rb_file_s_dirname(VALUE klass, VALUE fname)
{
const char *name, *root, *p;
diff --git a/hash.c b/hash.c
index ebd02b95b9..78f62367ee 100644
--- a/hash.c
+++ b/hash.c
@@ -1094,9 +1094,6 @@ rb_hash_aset(VALUE hash, VALUE key, VALUE val)
{
rb_hash_modify(hash);
hash_update(hash, key);
- if (hash == key) {
- rb_raise(rb_eArgError, "recursive key for hash");
- }
if (RHASH(hash)->ntbl->type == &identhash || rb_obj_class(key) != rb_cString) {
st_insert(RHASH(hash)->ntbl, key, val);
}
diff --git a/include/ruby/encoding.h b/include/ruby/encoding.h
index e6234636a1..a4eb161d68 100644
--- a/include/ruby/encoding.h
+++ b/include/ruby/encoding.h
@@ -95,6 +95,7 @@ VALUE rb_enc_str_buf_cat(VALUE str, const char *ptr, long len, rb_encoding *enc)
VALUE rb_external_str_new_with_enc(const char *ptr, long len, rb_encoding *);
VALUE rb_str_export_to_enc(VALUE, rb_encoding *);
VALUE rb_str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to);
+VALUE rb_str_conv_enc_opts(VALUE str, rb_encoding *from, rb_encoding *to, int ecflags, VALUE ecopts);
/* index -> rb_encoding */
rb_encoding* rb_enc_from_index(int idx);
@@ -197,7 +198,7 @@ long rb_memsearch(const void*,long,const void*,long,rb_encoding*);
#define ENC_DUMMY_FLAG (1<<24)
#define ENC_INDEX_MASK (~(~0U<<24))
-#define ENC_TO_ENCINDEX(enc) ((enc)->ruby_encoding_index & ENC_INDEX_MASK)
+#define ENC_TO_ENCINDEX(enc) (int)((enc)->ruby_encoding_index & ENC_INDEX_MASK)
#define ENC_DUMMY_P(enc) ((enc)->ruby_encoding_index & ENC_DUMMY_FLAG)
#define ENC_SET_DUMMY(enc) ((enc)->ruby_encoding_index |= ENC_DUMMY_FLAG)
diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h
index 872f17c24c..16ab52158f 100644
--- a/include/ruby/ruby.h
+++ b/include/ruby/ruby.h
@@ -1104,7 +1104,7 @@ NORETURN(void rb_iter_break(void));
NORETURN(void rb_exit(int));
NORETURN(void rb_notimplement(void));
-/* reports if `-w' specified */
+/* reports if `-W' specified */
PRINTF_ARGS(void rb_warning(const char*, ...), 1, 2);
PRINTF_ARGS(void rb_compile_warning(const char *, int, const char*, ...), 3, 4);
PRINTF_ARGS(void rb_sys_warning(const char*, ...), 1, 2);
diff --git a/iseq.c b/iseq.c
index baf2a5ac02..e8124b4b6e 100644
--- a/iseq.c
+++ b/iseq.c
@@ -96,6 +96,7 @@ iseq_mark(void *ptr)
RUBY_MARK_UNLESS_NULL(iseq->mark_ary);
RUBY_MARK_UNLESS_NULL(iseq->name);
RUBY_MARK_UNLESS_NULL(iseq->filename);
+ RUBY_MARK_UNLESS_NULL(iseq->filepath);
RUBY_MARK_UNLESS_NULL((VALUE)iseq->cref_stack);
RUBY_MARK_UNLESS_NULL(iseq->klass);
RUBY_MARK_UNLESS_NULL(iseq->coverage);
@@ -205,9 +206,11 @@ set_relation(rb_iseq_t *iseq, const VALUE parent)
}
}
+VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict);
+
static VALUE
prepare_iseq_build(rb_iseq_t *iseq,
- VALUE name, VALUE filename, VALUE line_no,
+ VALUE name, VALUE filename, VALUE filepath, VALUE line_no,
VALUE parent, VALUE type, VALUE block_opt,
const rb_compile_option_t *option)
{
@@ -216,6 +219,7 @@ prepare_iseq_build(rb_iseq_t *iseq,
iseq->name = name;
iseq->filename = filename;
+ iseq->filepath = filepath == Qnil ? Qnil : rb_realpath_internal(Qnil, filepath, 1);
iseq->line_no = line_no;
iseq->defined_method_id = 0;
iseq->mark_ary = rb_ary_tmp_new(3);
@@ -359,31 +363,31 @@ make_compile_option_value(rb_compile_option_t *option)
}
VALUE
-rb_iseq_new(NODE *node, VALUE name, VALUE filename,
+rb_iseq_new(NODE *node, VALUE name, VALUE filename, VALUE filepath,
VALUE parent, VALUE type)
{
- return rb_iseq_new_with_opt(node, name, filename, INT2FIX(0), parent, type,
+ return rb_iseq_new_with_opt(node, name, filename, filepath, INT2FIX(0), parent, type,
&COMPILE_OPTION_DEFAULT);
}
VALUE
-rb_iseq_new_top(NODE *node, VALUE name, VALUE filename, VALUE parent)
+rb_iseq_new_top(NODE *node, VALUE name, VALUE filename, VALUE filepath, VALUE parent)
{
- return rb_iseq_new_with_opt(node, name, filename, INT2FIX(0), parent, ISEQ_TYPE_TOP,
+ return rb_iseq_new_with_opt(node, name, filename, filepath, INT2FIX(0), parent, ISEQ_TYPE_TOP,
&COMPILE_OPTION_DEFAULT);
}
VALUE
-rb_iseq_new_main(NODE *node, VALUE filename)
+rb_iseq_new_main(NODE *node, VALUE filename, VALUE filepath)
{
rb_thread_t *th = GET_THREAD();
VALUE parent = th->base_block->iseq->self;
- return rb_iseq_new_with_opt(node, rb_str_new2("<main>"), filename, INT2FIX(0),
+ return rb_iseq_new_with_opt(node, rb_str_new2("<main>"), filename, filepath, INT2FIX(0),
parent, ISEQ_TYPE_MAIN, &COMPILE_OPTION_DEFAULT);
}
static VALUE
-rb_iseq_new_with_bopt_and_opt(NODE *node, VALUE name, VALUE filename, VALUE line_no,
+rb_iseq_new_with_bopt_and_opt(NODE *node, VALUE name, VALUE filename, VALUE filepath, VALUE line_no,
VALUE parent, VALUE type, VALUE bopt,
const rb_compile_option_t *option)
{
@@ -393,28 +397,28 @@ rb_iseq_new_with_bopt_and_opt(NODE *node, VALUE name, VALUE filename, VALUE line
GetISeqPtr(self, iseq);
iseq->self = self;
- prepare_iseq_build(iseq, name, filename, line_no, parent, type, bopt, option);
+ prepare_iseq_build(iseq, name, filename, filepath, line_no, parent, type, bopt, option);
rb_iseq_compile_node(self, node);
cleanup_iseq_build(iseq);
return self;
}
VALUE
-rb_iseq_new_with_opt(NODE *node, VALUE name, VALUE filename, VALUE line_no,
+rb_iseq_new_with_opt(NODE *node, VALUE name, VALUE filename, VALUE filepath, VALUE line_no,
VALUE parent, VALUE type,
const rb_compile_option_t *option)
{
/* TODO: argument check */
- return rb_iseq_new_with_bopt_and_opt(node, name, filename, line_no, parent, type,
+ return rb_iseq_new_with_bopt_and_opt(node, name, filename, filepath, line_no, parent, type,
Qfalse, option);
}
VALUE
-rb_iseq_new_with_bopt(NODE *node, VALUE name, VALUE filename, VALUE line_no,
+rb_iseq_new_with_bopt(NODE *node, VALUE name, VALUE filename, VALUE filepath, VALUE line_no,
VALUE parent, VALUE type, VALUE bopt)
{
/* TODO: argument check */
- return rb_iseq_new_with_bopt_and_opt(node, name, filename, line_no, parent, type,
+ return rb_iseq_new_with_bopt_and_opt(node, name, filename, filepath, line_no, parent, type,
bopt, &COMPILE_OPTION_DEFAULT);
}
@@ -428,7 +432,7 @@ iseq_load(VALUE self, VALUE data, VALUE parent, VALUE opt)
VALUE iseqval = iseq_alloc(self);
VALUE magic, version1, version2, format_type, misc;
- VALUE name, filename, line_no;
+ VALUE name, filename, filepath, line_no;
VALUE type, body, locals, args, exception;
VALUE iseq_type;
@@ -452,6 +456,7 @@ iseq_load(VALUE self, VALUE data, VALUE parent, VALUE opt)
name = CHECK_STRING(rb_ary_entry(data, i++));
filename = CHECK_STRING(rb_ary_entry(data, i++));
+ filepath = CHECK_STRING(rb_ary_entry(data, i++));
line_no = CHECK_INTEGER(rb_ary_entry(data, i++));
type = CHECK_SYMBOL(rb_ary_entry(data, i++));
@@ -494,7 +499,7 @@ iseq_load(VALUE self, VALUE data, VALUE parent, VALUE opt)
}
make_compile_option(&option, opt);
- prepare_iseq_build(iseq, name, filename, line_no,
+ prepare_iseq_build(iseq, name, filename, filepath, line_no,
parent, iseq_type, 0, &option);
rb_iseq_build_from_ary(iseq, locals, args, exception, body);
@@ -531,7 +536,7 @@ parse_string(VALUE str, const char *file, int line)
}
VALUE
-rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE line, VALUE opt)
+rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE filepath, VALUE line, VALUE opt)
{
rb_compile_option_t option;
const char *fn = StringValueCStr(file);
@@ -542,11 +547,11 @@ rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE line, VALUE opt)
if (th->base_block && th->base_block->iseq) {
return rb_iseq_new_with_opt(node, th->base_block->iseq->name,
- file, line, th->base_block->iseq->self,
+ file, filepath, line, th->base_block->iseq->self,
ISEQ_TYPE_EVAL, &option);
}
else {
- return rb_iseq_new_with_opt(node, rb_str_new2("<compiled>"), file, line, Qfalse,
+ return rb_iseq_new_with_opt(node, rb_str_new2("<compiled>"), file, filepath, line, Qfalse,
ISEQ_TYPE_TOP, &option);
}
}
@@ -554,21 +559,21 @@ rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE line, VALUE opt)
VALUE
rb_iseq_compile(VALUE src, VALUE file, VALUE line)
{
- return rb_iseq_compile_with_option(src, file, line, Qnil);
+ return rb_iseq_compile_with_option(src, file, Qnil, line, Qnil);
}
static VALUE
iseq_s_compile(int argc, VALUE *argv, VALUE self)
{
- VALUE src, file = Qnil, line = INT2FIX(1), opt = Qnil;
+ VALUE src, file = Qnil, path = Qnil, line = INT2FIX(1), opt = Qnil;
rb_secure(1);
- rb_scan_args(argc, argv, "13", &src, &file, &line, &opt);
+ rb_scan_args(argc, argv, "13", &src, &file, &path, &line, &opt);
if (NIL_P(file)) file = rb_str_new2("<compiled>");
if (NIL_P(line)) line = INT2FIX(1);
- return rb_iseq_compile_with_option(src, file, line, opt);
+ return rb_iseq_compile_with_option(src, file, path, line, opt);
}
static VALUE
@@ -591,7 +596,7 @@ iseq_s_compile_file(int argc, VALUE *argv, VALUE self)
parser = rb_parser_new();
node = rb_parser_compile_file(parser, fname, f, NUM2INT(line));
make_compile_option(&option, opt);
- return rb_iseq_new_with_opt(node, rb_str_new2("<main>"), file, line, Qfalse,
+ return rb_iseq_new_with_opt(node, rb_str_new2("<main>"), file, file, line, Qfalse,
ISEQ_TYPE_TOP, &option);
}
@@ -1309,7 +1314,7 @@ iseq_data_to_ary(rb_iseq_t *iseq)
/*
* [:magic, :major_version, :minor_version, :format_type, :misc,
- * :name, :filename, :line_no, :type, :locals, :args,
+ * :name, :filename, :filepath, :line_no, :type, :locals, :args,
* :catch_table, :bytecode]
*/
rb_ary_push(val, rb_str_new2("YARVInstructionSequence/SimpleDataFormat"));
@@ -1319,6 +1324,7 @@ iseq_data_to_ary(rb_iseq_t *iseq)
rb_ary_push(val, misc);
rb_ary_push(val, iseq->name);
rb_ary_push(val, iseq->filename);
+ rb_ary_push(val, iseq->filepath);
rb_ary_push(val, iseq->line_no);
rb_ary_push(val, type);
rb_ary_push(val, locals);
diff --git a/lib/tmpdir.rb b/lib/tmpdir.rb
index 32befa3e8a..302c2fb39f 100644
--- a/lib/tmpdir.rb
+++ b/lib/tmpdir.rb
@@ -5,36 +5,14 @@
#
require 'fileutils'
+begin
+ require 'tmpdir.so'
+rescue LoadError
+end
class Dir
- @@systmpdir = '/tmp'
-
- if /mswin|mingw|cygwin/ =~ RUBY_PLATFORM and
- begin
- require 'Win32API'
- true
- rescue LoadError
- end
- CSIDL_LOCAL_APPDATA = 0x001c
- max_pathlen = 260
- windir = "\0"*(max_pathlen+1)
- begin
- getdir = Win32API.new('shell32', 'SHGetFolderPath', 'LLLLP', 'L')
- raise RuntimeError if getdir.call(0, CSIDL_LOCAL_APPDATA, 0, 0, windir) != 0
- windir.rstrip!
- rescue RuntimeError
- begin
- getdir = Win32API.new('kernel32', 'GetSystemWindowsDirectory', 'PL', 'L')
- rescue RuntimeError
- getdir = Win32API.new('kernel32', 'GetWindowsDirectory', 'PL', 'L')
- end
- windir[getdir.call(windir, windir.size)..-1] = ""
- end
- windir.force_encoding(Dir.pwd.encoding)
- temp = File.expand_path('temp', windir.untaint)
- @@systmpdir = temp if File.directory?(temp) and File.writable?(temp)
- end
+ @@systmpdir ||= '/tmp'
##
# Returns the operating system's temporary file path.
diff --git a/lib/uri/common.rb b/lib/uri/common.rb
index b4de6ad40c..d9aa15a4c3 100644
--- a/lib/uri/common.rb
+++ b/lib/uri/common.rb
@@ -729,49 +729,60 @@ module URI
#
# This refers http://www.w3.org/TR/html5/forms.html#url-encoded-form-data
#
- # See URI.decode_www_component(str), URI.encode_www_form(enum)
- def self.encode_www_component(str)
+ # See URI.decode_www_form_component, URI.encode_www_form
+ def self.encode_www_form_component(str)
if TBLENCWWWCOMP_.empty?
256.times do |i|
case i
when 0x20
TBLENCWWWCOMP_[' '] = '+'
- when 0x2A, 0x2D, 0x2E, 0x30..0x39, 0x41..0x5A, 0x5F, 0x61..0x7A
+ # when 0x2A, 0x2D, 0x2E, 0x30..0x39, 0x41..0x5A, 0x5F, 0x61..0x7A
else
- TBLENCWWWCOMP_[i.chr] = '%%%X' % i
+ TBLENCWWWCOMP_[i.chr] = '%%%02X' % i
end
end
TBLENCWWWCOMP_.freeze
end
- str = str.to_s.dup
- enc = str.encoding
- str.force_encoding(Encoding::ASCII_8BIT)
- str.gsub!(/[^*\-.0-9A-Z_a-z]/, TBLENCWWWCOMP_)
- str.force_encoding(enc)
+ str = str.to_s
+ case str.encoding
+ when Encoding::ASCII_8BIT, Encoding::US_ASCII, Encoding::UTF_8
+ str = str.dup.force_encoding(Encoding::ASCII_8BIT)
+ str.gsub!(/[^*\-.0-9A-Z_a-z]/, TBLENCWWWCOMP_)
+ when Encoding::UTF_16BE, Encoding::UTF_16LE, Encoding::UTF_32BE, Encoding::UTF_32LE
+ reg = Regexp.new('[^*\-.0-9A-Z_a-z]+'.encode(str.encoding))
+ str = str.gsub(reg){
+ $&.force_encoding(Encoding::ASCII_8BIT).gsub(/./, TBLENCWWWCOMP_).
+ force_encoding(str.encoding)
+ }
+ else
+ if str.encoding.ascii_compatible?
+ str = str.gsub(/[^*\-.0-9A-Z_a-z]+/){
+ $&.force_encoding(Encoding::ASCII_8BIT).gsub(/./, TBLENCWWWCOMP_)}
+ else
+ str = str.force_encoding(Encoding::ASCII_8BIT).gsub(/./, TBLENCWWWCOMP_)
+ end
+ end
+ str.force_encoding(Encoding::US_ASCII)
end
# Decode given +str+ of URL-encoded form data.
#
# This decods + to SP.
#
- # See URI.encode_www_component(str)
- def self.decode_www_component(str)
+ # See URI.encode_www_form_component, URI.decode_www_form
+ def self.decode_www_form_component(str, enc=Encoding::UTF_8)
if TBLDECWWWCOMP_.empty?
256.times do |i|
- case i
- when 0x20
- TBLDECWWWCOMP_['+'] = ' '
- else
- h, l = i>>4, i&15
- TBLDECWWWCOMP_['%%%X%X' % [h, l]] = i.chr
- TBLDECWWWCOMP_['%%%x%X' % [h, l]] = i.chr
- TBLDECWWWCOMP_['%%%X%x' % [h, l]] = i.chr
- TBLDECWWWCOMP_['%%%x%x' % [h, l]] = i.chr
- end
+ h, l = i>>4, i&15
+ TBLDECWWWCOMP_['%%%X%X' % [h, l]] = i.chr
+ TBLDECWWWCOMP_['%%%x%X' % [h, l]] = i.chr
+ TBLDECWWWCOMP_['%%%X%x' % [h, l]] = i.chr
+ TBLDECWWWCOMP_['%%%x%x' % [h, l]] = i.chr
+ TBLDECWWWCOMP_['+'] = ' ' if i == 0x20
end
TBLDECWWWCOMP_.freeze
end
- str.gsub(/\+|%\h\h/, TBLDECWWWCOMP_)
+ str.gsub(/\+|%\h\h/, TBLDECWWWCOMP_).force_encoding(Encoding::UTF_8)
end
# Generate URL-encoded form data from given +enum+.
@@ -779,7 +790,7 @@ module URI
# This generates application/x-www-form-urlencoded data defined in HTML5
# from given an Enumerable object.
#
- # This internally uses URI.encode_www_component(str).
+ # This internally uses URI.encode_www_form_component(str).
#
# This doesn't convert encodings of give items, so convert them before call
# this method if you want to send data as other than original encoding or
@@ -789,7 +800,7 @@ module URI
#
# This refers http://www.w3.org/TR/html5/forms.html#url-encoded-form-data
#
- # See URI.encode_www_component(str)
+ # See URI.encode_www_form_component, URI.decode_www_form
def self.encode_www_form(enum)
str = nil
enum.each do |k,v|
@@ -798,12 +809,43 @@ module URI
else
str = ''.force_encoding(Encoding::US_ASCII)
end
- str << encode_www_component(k)
+ str << encode_www_form_component(k)
str << '='
- str << encode_www_component(v)
+ str << encode_www_form_component(v)
end
str
end
+
+ # Decode URL-encoded form data from given +str+.
+ #
+ # This decodes application/x-www-form-urlencoded data
+ # and returns array of key-value array.
+ # This internally uses URI.decode_www_form_component.
+ #
+ # _charset_ hack is not supported now because the mapping from given charset
+ # to Ruby's encoding is not clear yet.
+ # see also http://www.w3.org/TR/html5/syntax.html#character-encodings-0
+ #
+ # This refers http://www.w3.org/TR/html5/forms.html#url-encoded-form-data
+ #
+ # ary = URI.decode_www_form("a=1&a=2&b=3")
+ # p ary #=> [['a', '1'], ['a', '2'], ['b', '3']]
+ # p ary.assoc('a').last #=> '1'
+ # p ary.assoc('b').last #=> '3'
+ # p ary.rassoc('a').last #=> '2'
+ # p Hash[ary] # => {"a"=>"2", "b"=>"3"}
+ #
+ # See URI.decode_www_form_component, URI.encode_www_form
+ def self.decode_www_form(str, enc=Encoding::UTF_8)
+ ary = []
+ unless /\A\??(?<query>[^=;&]*=[^;&]*(?:[;&][^=;&]*=[^;&]*)*)\z/ =~ str
+ raise ArgumentError, "invalid data of application/x-www-form-urlencoded (#{str})"
+ end
+ query.scan(/([^=;&]+)=([^;&]*)/) do
+ ary << [decode_www_form_component($1, enc), decode_www_form_component($2, enc)]
+ end
+ ary
+ end
end
module Kernel
diff --git a/load.c b/load.c
index 94c92795e4..5264f3eae4 100644
--- a/load.c
+++ b/load.c
@@ -297,7 +297,7 @@ rb_load_internal(VALUE fname, int wrap)
th->mild_compile_error++;
node = (NODE *)rb_load_file(RSTRING_PTR(fname));
loaded = TRUE;
- iseq = rb_iseq_new_top(node, rb_str_new2("<top (required)>"), fname, Qfalse);
+ iseq = rb_iseq_new_top(node, rb_str_new2("<top (required)>"), fname, fname, Qfalse);
th->mild_compile_error--;
rb_iseq_eval(iseq);
}
@@ -448,6 +448,19 @@ rb_f_require(VALUE obj, VALUE fname)
return rb_require_safe(fname, rb_safe_level());
}
+VALUE
+rb_f_require_relative(VALUE obj, VALUE fname)
+{
+ VALUE rb_current_realfilepath(void);
+ VALUE rb_file_s_dirname(VALUE klass, VALUE fname);
+ VALUE base = rb_current_realfilepath();
+ if (NIL_P(base)) {
+ rb_raise(rb_eLoadError, "cannot infer basepath");
+ }
+ base = rb_file_s_dirname(rb_cFile, base);
+ return rb_require_safe(rb_file_expand_path(fname, base), rb_safe_level());
+}
+
static int
search_required(VALUE fname, volatile VALUE *path, int safe_level)
{
@@ -746,6 +759,7 @@ InitVM_load(void)
rb_define_global_function("load", rb_f_load, -1);
rb_define_global_function("require", rb_f_require, 1);
+ rb_define_global_function("require_relative", rb_f_require_relative, 1);
rb_define_method(rb_cModule, "autoload", rb_mod_autoload, 2);
rb_define_method(rb_cModule, "autoload?", rb_mod_autoload_p, 1);
rb_define_global_function("autoload", rb_f_autoload, 2);
diff --git a/parse.y b/parse.y
index ed0e0c162d..b1c31a6f27 100644
--- a/parse.y
+++ b/parse.y
@@ -9616,6 +9616,10 @@ rb_intern3(const char *name, long len, rb_encoding *enc)
str = (VALUE)&fake_str;
rb_enc_associate(str, enc);
+ if (rb_enc_str_coderange(str) == ENC_CODERANGE_BROKEN) {
+ rb_raise(rb_eEncodingError, "invalid encoding symbol");
+ }
+
if (st_lookup(global_symbols.sym_id, str, &data))
return (ID)data;
diff --git a/prelude.rb b/prelude.rb
index 679e831ca4..1d084dfd8f 100644
--- a/prelude.rb
+++ b/prelude.rb
@@ -22,17 +22,3 @@ class Thread
}
end
end
-
-module Kernel
- module_function
- def require_relative(relative_feature)
- c = caller.first
- e = c.rindex(/:\d+:in /)
- file = $`
- if /\A\((.*)\)/ =~ file # eval, etc.
- raise LoadError, "require_relative is called in #{$1}"
- end
- absolute_feature = File.join(File.dirname(File.realpath(file)), relative_feature)
- require absolute_feature
- end
-end
diff --git a/ruby.c b/ruby.c
index 26be4060c7..bd422f4f61 100644
--- a/ruby.c
+++ b/ruby.c
@@ -1456,7 +1456,9 @@ process_options(rb_vm_t *vm, int argc, char **argv, struct cmdline_options *opt)
}
PREPARE_PARSE_MAIN({
- iseq = rb_iseq_new_main(tree, opt->script_name);
+ VALUE path = Qnil;
+ if (!opt->e_script && strcmp(opt->script, "-")) path = opt->script_name;
+ iseq = rb_iseq_new_main(tree, opt->script_name, path);
});
if (opt->dump & DUMP_BIT(insns)) {
diff --git a/test/ruby/test_m17n_comb.rb b/test/ruby/test_m17n_comb.rb
index ab891363b1..cf80377172 100644
--- a/test/ruby/test_m17n_comb.rb
+++ b/test/ruby/test_m17n_comb.rb
@@ -1040,10 +1040,12 @@ class TestM17NComb < Test::Unit::TestCase
STRINGS.each {|s|
if /\0/ =~ a(s)
assert_raise(ArgumentError) { s.intern }
- else
+ elsif s.valid_encoding?
sym = s.intern
assert_equal(s, sym.to_s, "#{encdump s}.intern.to_s")
assert_equal(sym, s.to_sym)
+ else
+ assert_raise(EncodingError) { s.intern }
end
}
end
diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb
index 64205f6082..5d6d6d7ab8 100644
--- a/test/ruby/test_string.rb
+++ b/test/ruby/test_string.rb
@@ -1385,6 +1385,15 @@ class TestString < Test::Unit::TestCase
assert_equal(5.9742e24, S("5.9742e24").to_f)
assert_equal(98.6, S("98.6 degrees").to_f)
assert_equal(0.0, S("degrees 100.0").to_f)
+ assert_equal([ 0.0].pack('G'), [S(" 0.0").to_f].pack('G'))
+ assert_equal([-0.0].pack('G'), [S("-0.0").to_f].pack('G'))
+ assert_equal([ 0.0].pack('G'), [S(" 0x0p+0").to_f].pack('G'))
+ assert_equal([-0.0].pack('G'), [S("-0x0p+0").to_f].pack('G'))
+ assert_equal(1.0, S("0X1.P+0").to_f)
+ assert_equal(1024.0, S("0x1p+10").to_f)
+ assert_equal(0.0009765625, S("0x1p-10").to_f)
+ assert_equal(2.6881171418161356e+43, S("0x1.3494a9b171bf5p+144").to_f)
+ assert_equal(-3.720075976020836e-44, S("-0x1.a8c1f14e2af5dp-145").to_f)
end
def test_to_i
diff --git a/test/uri/test_common.rb b/test/uri/test_common.rb
index 9a5fd6751f..730210e8b3 100644
--- a/test/uri/test_common.rb
+++ b/test/uri/test_common.rb
@@ -50,16 +50,22 @@ class TestCommon < Test::Unit::TestCase
assert_raise(NoMethodError) { Object.new.URI("http://www.ruby-lang.org/") }
end
- def test_encode_www_component
- assert_equal("+%21%22%23%24%25%26%27%28%29*%2B%2C-.%2F09%3A%3B%3C%3D%3E%3F%40" \
+ def test_encode_www_form_component
+ assert_equal("%00+%21%22%23%24%25%26%27%28%29*%2B%2C-.%2F09%3A%3B%3C%3D%3E%3F%40" \
"AZ%5B%5C%5D%5E_%60az%7B%7C%7D%7E",
- URI.encode_www_component(" !\"\#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~"))
+ URI.encode_www_form_component("\x00 !\"\#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~"))
+ assert_equal("%95%41", URI.encode_www_form_component(
+ "\x95\x41".force_encoding(Encoding::Shift_JIS)))
+ assert_equal("%30%42", URI.encode_www_form_component(
+ "\x30\x42".force_encoding(Encoding::UTF_16BE)))
+ assert_equal("%30%42", URI.encode_www_form_component(
+ "\x30\x42".force_encoding(Encoding::ISO_2022_JP)))
end
- def test_decode_www_component
- assert_equal(" !\"\#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~",
- URI.decode_www_component(
- "+%21%22%23%24%25%26%27%28%29*%2B%2C-.%2F09%3A%3B%3C%3D%3E%3F%40" \
+ def test_decode_www_form_component
+ assert_equal(" !\"\#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~",
+ URI.decode_www_form_component(
+ "%20+%21%22%23%24%25%26%27%28%29*%2B%2C-.%2F09%3A%3B%3C%3D%3E%3F%40" \
"AZ%5B%5C%5D%5E_%60az%7B%7C%7D%7E"))
end
@@ -74,6 +80,12 @@ class TestCommon < Test::Unit::TestCase
assert_equal(expected, URI.encode_www_form([["a", "1"], ["\u3042", "\u6F22"]]))
assert_equal(expected, URI.encode_www_form([[:a, 1], [:"\u3042", "\u6F22"]]))
end
+
+ def test_decode_www_form
+ assert_equal([%w[a 1], %w[a 2]], URI.decode_www_form("a=1&a=2"))
+ assert_equal([%w[a 1], ["\u3042", "\u6F22"]],
+ URI.decode_www_form("a=1&%E3%81%82=%E6%BC%A2"))
+ end
end
diff --git a/tool/transcode-tblgen.rb b/tool/transcode-tblgen.rb
index 48407ac3df..0abb587478 100755
--- a/tool/transcode-tblgen.rb
+++ b/tool/transcode-tblgen.rb
@@ -81,18 +81,31 @@ class Action
alias == eql?
end
-class ActionMap
- def self.parse_to_rects(hash)
- h = {}
- hash.each {|pat, action|
- pat = pat.to_s
- h[pat] = action
- }
- hash = h
+class Branch
+ def initialize(byte_min, byte_max, child_tree)
+ @byte_min = byte_min
+ @byte_max = byte_max
+ @child_tree = child_tree
+ @hash = byte_min.hash ^ byte_max.hash ^ child_tree.hash
+ end
+ attr_reader :byte_min, :byte_max, :child_tree, :hash
+ def eql?(other)
+ self.class == other.class &&
+ @hash == other.hash &&
+ @byte_min == other.byte_min &&
+ @byte_max == other.byte_max &&
+ @child_tree == other.child_tree
+ end
+ alias == eql?
+end
+
+class ActionMap
+ def self.parse_to_rects(mapping)
rects = []
n = 0
- hash.each {|pat, action|
+ mapping.each {|pat, action|
+ pat = pat.to_s
if /\A\s*\(empset\)\s*\z/ =~ pat
next
elsif /\A\s*\(empstr\)\s*\z/ =~ pat
@@ -165,18 +178,18 @@ class ActionMap
end
def self.build_tree(rects)
- expand("", rects) {|actions|
+ expand("", rects) {|prefix, actions|
unambiguous_action(actions)
}
end
- def self.parse(hash)
- rects = parse_to_rects(hash)
+ def self.parse(mapping)
+ rects = parse_to_rects(mapping)
tree = build_tree(rects)
- self.new("", tree)
+ self.new(tree)
end
- def self.merge(*rects_list)
+ def self.merge_rects(*rects_list)
if rects_list.length < 2
raise ArgumentError, "not enough arguments"
end
@@ -186,99 +199,122 @@ class ActionMap
all_rects.concat rects.map {|min, max, action| [min, max, [i, action]] }
}
- tree = expand("", all_rects) {|actions|
+ tree = expand("", all_rects) {|prefix, actions|
args = Array.new(rects_list.length) { [] }
actions.each {|i, action|
args[i] << action
}
- yield(args)
+ yield(prefix, *args)
}
- self.new("", tree)
+ self.new(tree)
+ end
+
+ def self.merge(*mappings, &block)
+ merge_rects(*mappings.map {|m| parse_to_rects(m) }, &block)
end
def self.expand(prefix, rects, &block)
- return [] if rects.empty?
- has_empty = false
- has_nonempty = false
- rects.each {|min, max, action|
- if min.empty?
- has_empty = true
+ #numsing = numreg = 0
+ #rects.each {|min, max, action| if min == max then numsing += 1 else numreg += 1 end }
+ #puts "#{numsing} singleton mappings and #{numreg} region mappings."
+ singleton_rects = []
+ region_rects = []
+ rects.each {|rect|
+ min, max, action = rect
+ if min == max
+ singleton_rects << rect
else
- has_nonempty = true
+ region_rects << rect
end
}
- if has_empty && has_nonempty
- raise ArgumentError, "ambiguous pattern: #{prefix}"
- end
- if has_empty
- actions = rects.map {|min, max, action| action }.uniq
- act = block.call(actions)
+ expand_rec(prefix, singleton_rects, region_rects, &block)
+ end
+
+ def self.expand_rec(prefix, singleton_rects, region_rects, &block)
+ some_mapping = singleton_rects[0] || region_rects[0]
+ return [] if !some_mapping
+ if some_mapping[0].empty?
+ h = {}
+ (singleton_rects + region_rects).each {|min, max, action|
+ raise ArgumentError, "ambiguous pattern: #{prefix}" if !min.empty?
+ h[action] = true
+ }
+ actions = h.keys
+ act = block.call(prefix, actions)
tree = Action.new(act)
else
tree = []
- each_firstbyte_range(prefix, rects) {|byte_min, byte_max, rects2|
- prefix2 = prefix
+ each_firstbyte_range(prefix, singleton_rects, region_rects) {|byte_min, byte_max, s_rects2, r_rects2|
if byte_min == byte_max
- prefix2 += "%02X" % byte_min
+ prefix2 = prefix + "%02X" % byte_min
else
- prefix2 += "{%02X-%02X}" % [byte_min, byte_max]
+ prefix2 = prefix + "{%02X-%02X}" % [byte_min, byte_max]
end
- child_tree = expand(prefix2, rects2, &block)
- tree << [byte_min, byte_max, child_tree]
+ child_tree = expand_rec(prefix2, s_rects2, r_rects2, &block)
+ tree << Branch.new(byte_min, byte_max, child_tree)
}
end
return tree
end
- def self.each_firstbyte_range(prefix, rects)
- a = []
+ def self.each_firstbyte_range(prefix, singleton_rects, region_rects)
index_from = {}
- rects.each {|min, max, action|
- raise ArgumentError, "emptyable pattern" if min.empty?
+
+ singleton_ary = []
+ singleton_rects.each {|seq, _, action|
+ raise ArgumentError, "ambiguous pattern: #{prefix}" if seq.empty?
+ seq_firstbyte = seq[0,2].to_i(16)
+ seq_rest = seq[2..-1]
+ singleton_ary << [seq_firstbyte, [seq_rest, seq_rest, action]]
+ index_from[seq_firstbyte] = true
+ index_from[seq_firstbyte+1] = true
+ }
+
+ region_ary = []
+ region_rects.each {|min, max, action|
+ raise ArgumentError, "ambiguous pattern: #{prefix}" if min.empty?
min_firstbyte = min[0,2].to_i(16)
min_rest = min[2..-1]
max_firstbyte = max[0,2].to_i(16)
max_rest = max[2..-1]
- a << [min_firstbyte, max_firstbyte, [min_rest, max_rest, action]]
+ region_ary << [min_firstbyte, max_firstbyte, [min_rest, max_rest, action]]
index_from[min_firstbyte] = true
index_from[max_firstbyte+1] = true
}
- byte_from = {}
+
+ byte_from = Array.new(index_from.size)
index_from.keys.sort.each_with_index {|byte, i|
index_from[byte] = i
byte_from[i] = byte
}
- rects_hash = {}
- a.each {|min_firstbyte, max_firstbyte, rest_elt|
+
+ singleton_rects_hash = {}
+ singleton_ary.each {|seq_firstbyte, rest_elt|
+ i = index_from[seq_firstbyte]
+ (singleton_rects_hash[i] ||= []) << rest_elt
+ }
+
+ region_rects_hash = {}
+ region_ary.each {|min_firstbyte, max_firstbyte, rest_elt|
index_from[min_firstbyte].upto(index_from[max_firstbyte+1]-1) {|i|
- rects_hash[i] ||= []
- rects_hash[i] << rest_elt
+ (region_rects_hash[i] ||= []) << rest_elt
}
}
+
0.upto(index_from.size-1) {|i|
- rects2 = rects_hash[i]
- yield byte_from[i], byte_from[i+1]-1, rects2 if rects2
+ s_rects = singleton_rects_hash[i]
+ r_rects = region_rects_hash[i]
+ if s_rects || r_rects
+ yield byte_from[i], byte_from[i+1]-1, (s_rects || []), (r_rects || [])
+ end
}
end
- def initialize(prefix, tree)
- @prefix = prefix # just for debug
+ def initialize(tree)
@tree = tree
end
- def hash
- return @hash if defined? @hash
- @hash = @tree.hash
- end
-
- def eql?(other)
- self.class == other.class &&
- @tree == other.instance_eval { @tree }
- end
-
- alias == eql?
-
def inspect
"\#<#{self.class}:" +
@tree.inspect +
@@ -290,8 +326,8 @@ class ActionMap
when Action
0
else
- tree.map {|byte_min, byte_max, child_tree|
- max_input_length_rec(child_tree)
+ tree.map {|branch|
+ max_input_length_rec(branch.child_tree)
}.max + 1
end
end
@@ -308,16 +344,6 @@ class ActionMap
end
end
- def each_firstbyte
- @tree.each {|byte_min, byte_max, child_tree|
- byte_min.upto(byte_max) {|byte|
- prefix = @prefix + ("%02X" % byte)
- am = ActionMap.new(prefix, child_tree)
- yield byte, am
- }
- }
- end
-
OffsetsMemo = {}
InfosMemo = {}
@@ -422,7 +448,9 @@ class ActionMap
code
end
- def generate_lookup_node(bytes_code, words_code, name, table)
+ def generate_lookup_node(name, table)
+ bytes_code = @bytes_code
+ words_code = @words_code
offsets = []
infos = []
infomap = {}
@@ -480,24 +508,29 @@ End
PostMemo = {}
NextName = "a"
- def generate_node(bytes_code, words_code, name_hint=nil)
- if n = PreMemo[self]
+ def generate_node(name_hint=nil)
+ if n = PreMemo[@tree]
return n
end
table = Array.new(0x100, :invalid)
- each_firstbyte {|byte, rest|
+ @tree.each {|branch|
+ byte_min, byte_max, child_tree = branch.byte_min, branch.byte_max, branch.child_tree
+ rest = ActionMap.new(child_tree)
if a = rest.empty_action
- table[byte] = a
+ table.fill(a, byte_min..byte_max)
else
name_hint2 = nil
- name_hint2 = "#{name_hint}_#{'%02X' % byte}" if name_hint
- table[byte] = "/*BYTE_LOOKUP*/" + rest.gennode(bytes_code, words_code, name_hint2)
+ if name_hint
+ name_hint2 = "#{name_hint}_#{byte_min == byte_max ? '%02X' % byte_min : '%02Xto%02X' % [byte_min, byte_max]}"
+ end
+ v = "/*BYTE_LOOKUP*/" + rest.gennode(@bytes_code, @words_code, name_hint2)
+ table.fill(v, byte_min..byte_max)
end
}
if n = PostMemo[table]
- return PreMemo[self] = n
+ return PreMemo[@tree] = n
end
if !name_hint
@@ -505,16 +538,16 @@ End
NextName.succ!
end
- PreMemo[self] = PostMemo[table] = name_hint
+ PreMemo[@tree] = PostMemo[table] = name_hint
- generate_lookup_node(bytes_code, words_code, name_hint, table)
+ generate_lookup_node(name_hint, table)
name_hint
end
def gennode(bytes_code, words_code, name_hint=nil)
@bytes_code = bytes_code
@words_code = words_code
- name = generate_node(bytes_code, words_code, name_hint)
+ name = generate_node(name_hint)
@bytes_code = nil
@words_code = nil
return name
@@ -649,18 +682,20 @@ def encode_utf8(map)
r
end
-def transcode_compile_tree(name, from, map)
+def transcode_compile_tree(name, from, map, valid_encoding=nil)
map = encode_utf8(map)
h = {}
map.each {|k, v|
h[k] = v unless h[k] # use first mapping
}
- if valid_encoding = ValidEncoding[from]
- rects = ActionMap.parse_to_rects(h)
- undef_rects = ActionMap.parse_to_rects(valid_encoding => :undef)
- am = ActionMap.merge(rects, undef_rects) {|a1, a2|
- a1 = a1.empty? ? nil : ActionMap.unambiguous_action(a1)
- a2 = a2.empty? ? nil : ActionMap.unambiguous_action(a2)
+ valid_encoding = ValidEncoding[from] if valid_encoding == nil
+ if valid_encoding
+ am = ActionMap.merge(h, {valid_encoding => :undef}) {|prefix, as1, as2|
+ a1 = as1.empty? ? nil : ActionMap.unambiguous_action(as1)
+ a2 = as2.empty? ? nil : ActionMap.unambiguous_action(as2)
+ if !a2
+ raise "invalid mapping: #{prefix}"
+ end
a1 || a2
}
else
@@ -675,7 +710,7 @@ end
TRANSCODERS = []
TRANSCODE_GENERATED_TRANSCODER_CODE = ''
-def transcode_tbl_only(from, to, map)
+def transcode_tbl_only(from, to, map, valid_encoding=nil)
if VERBOSE_MODE
if from.empty? || to.empty?
STDERR.puts "converter for #{from.empty? ? to : from}"
@@ -692,12 +727,12 @@ def transcode_tbl_only(from, to, map)
else
tree_name = "from_#{id_from}_to_#{id_to}"
end
- real_tree_name, max_input = transcode_compile_tree(tree_name, from, map)
+ real_tree_name, max_input = transcode_compile_tree(tree_name, from, map, valid_encoding)
return map, tree_name, real_tree_name, max_input
end
-def transcode_tblgen(from, to, map)
- map, tree_name, real_tree_name, max_input = transcode_tbl_only(from, to, map)
+def transcode_tblgen(from, to, map, valid_encoding=nil)
+ map, tree_name, real_tree_name, max_input = transcode_tbl_only(from, to, map, valid_encoding)
transcoder_name = "rb_#{tree_name}"
TRANSCODERS << transcoder_name
input_unit_length = UnitLength[from]
diff --git a/util.c b/util.c
index 62cbf761f0..2786ceff22 100644
--- a/util.c
+++ b/util.c
@@ -2106,6 +2106,44 @@ ruby_strtod(const char *s00, char **se)
}
break2:
if (*s == '0') {
+ if (s[1] == 'x' || s[1] == 'X') {
+ static const char hexdigit[] = "0123456789abcdef0123456789ABCDEF";
+ s0 = ++s;
+ adj = 0;
+
+ while (*++s && (s1 = strchr(hexdigit, *s))) {
+ adj *= 16;
+ adj += (s1 - hexdigit) & 15;
+ }
+
+ if (*s == '.') {
+ aadj = 1.;
+ while (*++s && (s1 = strchr(hexdigit, *s))) {
+ aadj /= 16;
+ adj += aadj * ((s1 - hexdigit) & 15);
+ }
+ }
+
+ if (*s != 'P' && *s != 'p') {
+ s = s0;
+ goto ret;
+ }
+
+ dsign = 0x2C - *++s; /* +: 2B, -: 2D */
+ if (abs(dsign) != 1) {
+ s = s0;
+ goto ret;
+ }
+
+ for (nd = 0, s++; (c = *s) >= '0' && c <= '9'; s++) {
+ nd *= 10;
+ nd += c;
+ nd -= '0';
+ }
+
+ dval(rv) = ldexp(adj, nd * dsign);
+ goto ret;
+ }
nz0 = 1;
while (*++s == '0') ;
if (!*s)
diff --git a/version.h b/version.h
index ce4cbab611..a9dc3d47cf 100644
--- a/version.h
+++ b/version.h
@@ -1,5 +1,5 @@
#define RUBY_VERSION "1.9.2"
-#define RUBY_RELEASE_DATE "2010-03-15"
+#define RUBY_RELEASE_DATE "2010-03-18"
#define RUBY_PATCHLEVEL -1
#define RUBY_BRANCH_NAME "mvm"
@@ -8,7 +8,7 @@
#define RUBY_VERSION_TEENY 1
#define RUBY_RELEASE_YEAR 2010
#define RUBY_RELEASE_MONTH 3
-#define RUBY_RELEASE_DAY 15
+#define RUBY_RELEASE_DAY 18
#include "ruby/version.h"
diff --git a/vm.c b/vm.c
index 7f1eec484c..09d0394d9c 100644
--- a/vm.c
+++ b/vm.c
@@ -1435,7 +1435,7 @@ rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg,
{
rb_thread_t *th = GET_THREAD();
const rb_control_frame_t *reg_cfp = th->cfp;
- volatile VALUE iseqval = rb_iseq_new(0, filename, filename, 0, ISEQ_TYPE_TOP);
+ volatile VALUE iseqval = rb_iseq_new(0, filename, filename, filename, 0, ISEQ_TYPE_TOP);
VALUE val;
vm_push_frame(th, DATA_PTR(iseqval), VM_FRAME_MAGIC_TOP,
@@ -2304,7 +2304,7 @@ InitVM_VM(void)
rb_thread_t *th = GET_THREAD();
rb_vm_t *vm = th->vm;
VALUE filename = rb_str_new2("<main>");
- volatile VALUE iseqval = rb_iseq_new(0, filename, filename, 0, ISEQ_TYPE_TOP);
+ volatile VALUE iseqval = rb_iseq_new(0, filename, filename, Qnil, 0, ISEQ_TYPE_TOP);
volatile VALUE th_self;
rb_iseq_t *iseq;
diff --git a/vm_core.h b/vm_core.h
index f0e83eb9bb..f63170f273 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -158,6 +158,7 @@ struct rb_iseq_struct {
VALUE type; /* instruction sequence type */
VALUE name; /* String: iseq name */
VALUE filename; /* file information where this sequence from */
+ VALUE filepath; /* real file path or nil */
VALUE *iseq; /* iseq (insn number and openrads) */
VALUE *iseq_encoded; /* encoded iseq */
unsigned long iseq_size;
@@ -537,11 +538,11 @@ typedef struct rb_thread_struct
} rb_thread_t;
/* iseq.c */
-VALUE rb_iseq_new(NODE*, VALUE, VALUE, VALUE, VALUE);
-VALUE rb_iseq_new_top(NODE *node, VALUE name, VALUE filename, VALUE parent);
-VALUE rb_iseq_new_main(NODE *node, VALUE filename);
-VALUE rb_iseq_new_with_bopt(NODE*, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE);
-VALUE rb_iseq_new_with_opt(NODE*, VALUE, VALUE, VALUE, VALUE, VALUE, const rb_compile_option_t*);
+VALUE rb_iseq_new(NODE*, VALUE, VALUE, VALUE, VALUE, VALUE);
+VALUE rb_iseq_new_top(NODE *node, VALUE name, VALUE filename, VALUE filepath, VALUE parent);
+VALUE rb_iseq_new_main(NODE *node, VALUE filename, VALUE filepath);
+VALUE rb_iseq_new_with_bopt(NODE*, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE);
+VALUE rb_iseq_new_with_opt(NODE*, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, const rb_compile_option_t*);
VALUE rb_iseq_compile(VALUE src, VALUE file, VALUE line);
VALUE rb_iseq_disasm(VALUE self);
int rb_iseq_disasm_insn(VALUE str, VALUE *iseqval, size_t pos, rb_iseq_t *iseq, VALUE child);
diff --git a/vm_eval.c b/vm_eval.c
index d60f4d46a8..0c6fa5a0af 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -1711,6 +1711,16 @@ rb_f_block_given_p(void)
}
}
+VALUE
+rb_current_realfilepath(void)
+{
+ rb_thread_t *th = GET_THREAD();
+ rb_control_frame_t *cfp = th->cfp;
+ cfp = vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
+ if (cfp != 0) return cfp->iseq->filepath;
+ return Qnil;
+}
+
void
Init_vm_eval(void)
{
diff --git a/win32/win32.c b/win32/win32.c
index 46a2ce5016..8216ac9918 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -430,6 +430,22 @@ get_system_directory(WCHAR *path, UINT len)
#define numberof(array) (sizeof(array) / sizeof(*array))
+UINT
+rb_w32_system_tmpdir(WCHAR *path, UINT len)
+{
+ static const WCHAR temp[] = L"temp";
+ WCHAR *p;
+
+ if (!get_special_folder(CSIDL_LOCAL_APPDATA, path)) {
+ if (get_system_directory(path, len)) return 0;
+ }
+ p = translate_wchar(path, L'\\', L'/');
+ if (*(p - 1) != L'/') *p++ = L'/';
+ if (p - path + numberof(temp) >= len) return 0;
+ memcpy(p, temp, sizeof(temp));
+ return p - path + numberof(temp) - 1;
+}
+
static void
init_env(void)
{
@@ -484,15 +500,8 @@ init_env(void)
if (!GetEnvironmentVariableW(TMPDIR, env, numberof(env)) &&
!GetEnvironmentVariableW(L"TMP", env, numberof(env)) &&
!GetEnvironmentVariableW(L"TEMP", env, numberof(env)) &&
- (get_special_folder(CSIDL_LOCAL_APPDATA, env) ||
- get_system_directory(env, numberof(env)))) {
- static const WCHAR temp[] = L"temp";
- WCHAR *p = translate_wchar(env, L'\\', L'/');
- if (*(p - 1) != L'/') *p++ = L'/';
- if (p - env + numberof(temp) < numberof(env)) {
- memcpy(p, temp, sizeof(temp));
- set_env_val(TMPDIR);
- }
+ rb_w32_system_tmpdir(env, numberof(env))) {
+ set_env_val(TMPDIR);
}
#undef env
@@ -3579,7 +3588,6 @@ char *
rb_w32_getcwd(char *buffer, int size)
{
char *p = buffer;
- char *bp;
int len;
len = GetCurrentDirectory(0, NULL);
@@ -3610,11 +3618,7 @@ rb_w32_getcwd(char *buffer, int size)
return NULL;
}
- for (bp = p; *bp != '\0'; bp = CharNext(bp)) {
- if (*bp == '\\') {
- *bp = '/';
- }
- }
+ translate_char(p, '\\', '/');
return p;
}