summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-11-19 01:56:51 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-11-19 01:56:51 +0000
commit64a4c5216da5fe4bcdce23693779a1eecdee8b0b (patch)
tree7cb920684f0ebea1e169d75b2e8297ad8aa86f85
parent6007aa4a6b7229204838ee5bcdf5ad97e90f65ae (diff)
downloadruby-64a4c5216da5fe4bcdce23693779a1eecdee8b0b.tar.gz
* merged from trunk r19258:20281.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/mvm@20282 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--.gdbinit39
-rw-r--r--.merged-trunk-revision2
-rw-r--r--ChangeLog4156
-rw-r--r--LEGAL58
-rw-r--r--Makefile.in6
-rw-r--r--README5
-rw-r--r--README.EXT9
-rw-r--r--README.EXT.ja11
-rw-r--r--README.ja6
-rw-r--r--array.c578
-rw-r--r--benchmark/bm_loop_for.rb3
-rw-r--r--benchmark/bm_loop_times.rb2
-rw-r--r--bignum.c35
-rwxr-xr-xbin/erb15
-rwxr-xr-xbin/ri3
-rwxr-xr-xbin/testrb10
-rw-r--r--blockinlining.c1
-rw-r--r--bootstraptest/test_method.rb15
-rw-r--r--bootstraptest/test_thread.rb6
-rw-r--r--class.c35
-rw-r--r--common.mk411
-rw-r--r--compile.c507
-rw-r--r--compile.h241
-rw-r--r--complex.c499
-rw-r--r--configure.in61
-rw-r--r--cont.c247
-rw-r--r--cygwin/GNUmakefile.in4
-rw-r--r--debug.h6
-rw-r--r--defs/keywords (renamed from keywords)0
-rw-r--r--defs/known_errors.def122
-rw-r--r--defs/lex.c.src (renamed from lex.c.src)0
-rw-r--r--defs/opt_insn_unif.def (renamed from opt_insn_unif.def)0
-rw-r--r--defs/opt_operand.def (renamed from opt_operand.def)0
-rw-r--r--dir.c22
-rw-r--r--distruby.rb59
-rw-r--r--djgpp/GNUmakefile.in3
-rw-r--r--djgpp/README.djgpp21
-rw-r--r--djgpp/config.hin114
-rw-r--r--djgpp/config.sed128
-rwxr-xr-xdjgpp/configure.bat20
-rw-r--r--djgpp/mkver.sed1
-rw-r--r--dln.c146
-rw-r--r--dmyext.c2
-rw-r--r--doc/NEWS2
-rw-r--r--enc/Makefile.in1
-rw-r--r--enc/big5.c4
-rw-r--r--enc/cp949.c4
-rw-r--r--enc/depend12
-rw-r--r--enc/emacs_mule.c5
-rw-r--r--enc/euc_jp.c4
-rw-r--r--enc/euc_kr.c4
-rw-r--r--enc/euc_tw.c4
-rw-r--r--enc/gb18030.c6
-rw-r--r--enc/gbk.c4
-rw-r--r--enc/shift_jis.c4
-rw-r--r--enc/trans/escape.trans16
-rw-r--r--enc/trans/ibm437-tbl.rb130
-rw-r--r--enc/trans/ibm775-tbl.rb130
-rw-r--r--enc/trans/ibm852-tbl.rb130
-rw-r--r--enc/trans/ibm855-tbl.rb130
-rw-r--r--enc/trans/ibm857-tbl.rb127
-rw-r--r--enc/trans/ibm860-tbl.rb130
-rw-r--r--enc/trans/ibm861-tbl.rb130
-rw-r--r--enc/trans/ibm862-tbl.rb130
-rw-r--r--enc/trans/ibm863-tbl.rb130
-rw-r--r--enc/trans/ibm865-tbl.rb130
-rw-r--r--enc/trans/ibm866-tbl.rb130
-rw-r--r--enc/trans/ibm869-tbl.rb121
-rw-r--r--enc/trans/iso-8859-1-tbl.rb98
-rw-r--r--enc/trans/iso2022.trans22
-rw-r--r--enc/trans/japanese.trans8
-rw-r--r--enc/trans/maccroatian-tbl.rb129
-rw-r--r--enc/trans/maccyrillic-tbl.rb130
-rw-r--r--enc/trans/macgreek-tbl.rb129
-rw-r--r--enc/trans/maciceland-tbl.rb129
-rw-r--r--enc/trans/macroman-tbl.rb129
-rw-r--r--enc/trans/macromania-tbl.rb129
-rw-r--r--enc/trans/macturkish-tbl.rb128
-rw-r--r--enc/trans/macukraine-tbl.rb130
-rw-r--r--enc/trans/newline.trans11
-rw-r--r--enc/trans/single_byte.trans92
-rw-r--r--enc/trans/utf_16_32.trans32
-rw-r--r--enc/trans/windows-1250-tbl.rb125
-rw-r--r--enc/trans/windows-1251-tbl.rb129
-rw-r--r--enc/trans/windows-1252-tbl.rb125
-rw-r--r--enc/trans/windows-1253-tbl.rb113
-rw-r--r--enc/trans/windows-1254-tbl.rb123
-rw-r--r--enc/trans/windows-1255-tbl.rb141
-rw-r--r--enc/trans/windows-1256-tbl.rb130
-rw-r--r--enc/trans/windows-1257-tbl.rb118
-rw-r--r--enc/trans/windows-874-tbl.rb99
-rw-r--r--enc/us_ascii.c2
-rw-r--r--enc/utf_16be.c2
-rw-r--r--enc/utf_16le.c2
-rw-r--r--enc/utf_32be.c2
-rw-r--r--enc/utf_32le.c2
-rw-r--r--enc/utf_8.c2
-rw-r--r--encoding.c167
-rw-r--r--enum.c2
-rw-r--r--enumerator.c1
-rw-r--r--error.c421
-rw-r--r--eval.c73
-rw-r--r--eval_intern.h32
-rw-r--r--ext/Setup.dj33
-rw-r--r--ext/Setup.x6833
-rw-r--r--ext/bigdecimal/bigdecimal.c67
-rw-r--r--ext/bigdecimal/lib/bigdecimal/util.rb12
-rw-r--r--ext/curses/curses.c79
-rw-r--r--ext/curses/view.rb2
-rw-r--r--ext/dbm/dbm.c24
-rw-r--r--ext/dl/extconf.rb13
-rw-r--r--ext/etc/etc.c9
-rw-r--r--ext/extmk.rb5
-rw-r--r--ext/gdbm/gdbm.c13
-rw-r--r--ext/iconv/iconv.c11
-rw-r--r--ext/io/wait/extconf.rb3
-rw-r--r--ext/io/wait/wait.c5
-rw-r--r--ext/json/ext/generator/extconf.rb3
-rw-r--r--ext/json/ext/generator/generator.c13
-rw-r--r--ext/json/ext/generator/unicode.c2
-rw-r--r--ext/json/ext/parser/extconf.rb3
-rw-r--r--ext/json/ext/parser/parser.c633
-rw-r--r--ext/json/ext/parser/parser.rl62
-rw-r--r--ext/json/ext/parser/unicode.c4
-rw-r--r--ext/json/lib/json/add/core.rb41
-rw-r--r--ext/json/lib/json/common.rb10
-rw-r--r--ext/json/lib/json/editor.rb1
-rw-r--r--ext/json/lib/json/pure.rb53
-rw-r--r--ext/json/lib/json/pure/generator.rb10
-rw-r--r--ext/json/lib/json/pure/parser.rb33
-rw-r--r--ext/json/lib/json/version.rb2
-rw-r--r--ext/mathn/complex/complex.c7
-rw-r--r--ext/mathn/complex/extconf.rb3
-rw-r--r--ext/mathn/rational/extconf.rb3
-rw-r--r--ext/mathn/rational/rational.c7
-rw-r--r--ext/nkf/nkf-utf8/config.h3
-rw-r--r--ext/nkf/nkf-utf8/nkf.c98
-rw-r--r--ext/nkf/nkf-utf8/nkf.h36
-rw-r--r--ext/nkf/nkf-utf8/utf8tbl.c6
-rw-r--r--ext/nkf/nkf.c6
-rw-r--r--ext/openssl/ossl.h2
-rw-r--r--ext/openssl/ossl_pkey_ec.c11
-rw-r--r--ext/readline/readline.c68
-rw-r--r--ext/ripper/depend7
-rw-r--r--ext/ripper/eventids2.c1
-rw-r--r--ext/sdbm/_sdbm.c6
-rw-r--r--ext/sdbm/init.c72
-rw-r--r--ext/sdbm/sdbm.h2
-rw-r--r--ext/socket/getaddrinfo.c2
-rw-r--r--ext/socket/getnameinfo.c2
-rw-r--r--ext/socket/mkconstants.rb15
-rw-r--r--ext/socket/socket.c50
-rw-r--r--ext/stringio/stringio.c80
-rw-r--r--ext/syck/node.c2
-rw-r--r--ext/syck/syck.c4
-rw-r--r--ext/tk/extconf.rb93
-rw-r--r--ext/tk/lib/tk.rb48
-rw-r--r--ext/tk/lib/tk/autoload.rb2
-rw-r--r--ext/tk/lib/tk/variable.rb2
-rw-r--r--ext/tk/sample/tkextlib/treectrl/demo.rb8
-rw-r--r--ext/tk/stubs.c33
-rw-r--r--ext/tk/tcltklib.c79
-rw-r--r--ext/win32ole/extconf.rb3
-rw-r--r--ext/win32ole/win32ole.c232
-rw-r--r--ext/zlib/zlib.c563
-rw-r--r--file.c35
-rw-r--r--gc.c103
-rw-r--r--gem_prelude.rb163
-rw-r--r--hash.c77
-rw-r--r--id.h131
-rw-r--r--include/ruby.h11
-rw-r--r--include/ruby/backward/rubyio.h6
-rw-r--r--include/ruby/backward/rubysig.h33
-rw-r--r--include/ruby/defines.h20
-rw-r--r--include/ruby/encoding.h57
-rw-r--r--include/ruby/intern.h22
-rw-r--r--include/ruby/io.h15
-rw-r--r--include/ruby/missing.h62
-rw-r--r--include/ruby/node.h514
-rw-r--r--include/ruby/oniguruma.h22
-rw-r--r--include/ruby/public_object.h47
-rw-r--r--include/ruby/ruby.h164
-rw-r--r--include/ruby/util.h6
-rw-r--r--include/ruby/vm.h (renamed from include/ruby/mvm.h)9
-rw-r--r--include/ruby/win32.h9
-rw-r--r--include/rubyio.h1
-rw-r--r--include/rubysig.h1
-rw-r--r--inits.c7
-rw-r--r--insns.def2
-rwxr-xr-xinstruby.rb25
-rw-r--r--io.c902
-rw-r--r--iseq.c22
-rw-r--r--iseq.h94
-rw-r--r--lib/base64.rb91
-rw-r--r--lib/cgi.rb2064
-rw-r--r--lib/cgi/cookie.rb137
-rw-r--r--lib/cgi/core.rb784
-rw-r--r--lib/cgi/html.rb1021
-rw-r--r--lib/cgi/session.rb128
-rw-r--r--lib/cgi/session/pstore.rb50
-rw-r--r--lib/cgi/util.rb181
-rw-r--r--lib/cmath.rb76
-rw-r--r--lib/complex.rb18
-rw-r--r--lib/csv.rb753
-rw-r--r--lib/date.rb15
-rw-r--r--lib/date/format.rb2
-rw-r--r--lib/debug.rb3
-rw-r--r--lib/delegate.rb164
-rw-r--r--lib/drb/drb.rb1
-rw-r--r--lib/fileutils.rb4
-rw-r--r--lib/ipaddr.rb1
-rw-r--r--lib/irb.rb2
-rw-r--r--lib/irb/context.rb1
-rw-r--r--lib/irb/ext/save-history.rb20
-rw-r--r--lib/irb/init.rb4
-rw-r--r--lib/logger.rb4
-rw-r--r--lib/mathn.rb56
-rw-r--r--lib/matrix.rb20
-rw-r--r--lib/minitest/mock.rb37
-rw-r--r--lib/minitest/spec.rb88
-rw-r--r--lib/minitest/unit.rb495
-rw-r--r--lib/mkmf.rb36
-rw-r--r--lib/net/ftp.rb4
-rw-r--r--lib/net/pop.rb2
-rw-r--r--lib/open-uri.rb18
-rw-r--r--lib/optparse.rb42
-rw-r--r--lib/pathname.rb11
-rw-r--r--lib/pp.rb54
-rw-r--r--lib/prettyprint.rb14
-rwxr-xr-xlib/rake.rb643
-rw-r--r--lib/rake/gempackagetask.rb6
-rw-r--r--lib/rake/loaders/makefile.rb23
-rw-r--r--lib/rake/packagetask.rb1
-rw-r--r--lib/rake/rdoctask.rb14
-rw-r--r--lib/rake/tasklib.rb11
-rw-r--r--lib/rake/testtask.rb7
-rw-r--r--lib/rake/win32.rb54
-rw-r--r--lib/rational.rb4
-rw-r--r--lib/rdoc.rb190
-rw-r--r--lib/rdoc/code_objects.rb86
-rw-r--r--lib/rdoc/diagram.rb32
-rw-r--r--lib/rdoc/generator.rb36
-rw-r--r--lib/rdoc/generator/chm/chm.rb2
-rw-r--r--lib/rdoc/generator/html.rb226
-rw-r--r--lib/rdoc/generator/html/common.rb24
-rw-r--r--lib/rdoc/generator/html/frameless.rb759
-rw-r--r--lib/rdoc/generator/html/hefss.rb358
-rw-r--r--lib/rdoc/generator/html/html.rb383
-rw-r--r--lib/rdoc/generator/html/kilmer.rb329
-rw-r--r--lib/rdoc/generator/html/kilmerfactory.rb427
-rw-r--r--lib/rdoc/generator/html/one_page_html.rb11
-rw-r--r--lib/rdoc/generator/texinfo.rb9
-rw-r--r--lib/rdoc/generator/texinfo/class.texinfo.erb4
-rw-r--r--lib/rdoc/generator/xml.rb11
-rw-r--r--lib/rdoc/generator/xml/xml.rb30
-rw-r--r--lib/rdoc/known_classes.rb1
-rw-r--r--lib/rdoc/markup.rb95
-rw-r--r--lib/rdoc/markup/inline.rb2
-rw-r--r--lib/rdoc/markup/to_html.rb15
-rw-r--r--lib/rdoc/markup/to_html_crossref.rb88
-rw-r--r--lib/rdoc/markup/to_texinfo.rb2
-rw-r--r--lib/rdoc/options.rb9
-rw-r--r--lib/rdoc/parser.rb35
-rw-r--r--lib/rdoc/parser/c.rb65
-rw-r--r--lib/rdoc/parser/perl.rb165
-rw-r--r--lib/rdoc/parser/ruby.rb12
-rw-r--r--lib/rdoc/parser/simple.rb2
-rw-r--r--lib/rdoc/rdoc.rb6
-rw-r--r--lib/rdoc/ri/cache.rb11
-rw-r--r--lib/rdoc/ri/descriptions.rb3
-rw-r--r--lib/rdoc/ri/display.rb204
-rw-r--r--lib/rdoc/ri/driver.rb522
-rw-r--r--lib/rdoc/ri/formatter.rb2
-rw-r--r--lib/rdoc/ri/paths.rb13
-rw-r--r--lib/rdoc/ri/reader.rb6
-rw-r--r--lib/rdoc/ri/util.rb2
-rw-r--r--lib/resolv.rb40
-rw-r--r--lib/rexml/attlistdecl.rb100
-rw-r--r--lib/rexml/attribute.rb262
-rw-r--r--lib/rexml/cdata.rb96
-rw-r--r--lib/rexml/child.rb164
-rw-r--r--lib/rexml/comment.rb118
-rw-r--r--lib/rexml/document.rb202
-rw-r--r--lib/rexml/dtd/attlistdecl.rb14
-rw-r--r--lib/rexml/dtd/dtd.rb82
-rw-r--r--lib/rexml/dtd/elementdecl.rb26
-rw-r--r--lib/rexml/dtd/entitydecl.rb98
-rw-r--r--lib/rexml/dtd/notationdecl.rb64
-rw-r--r--lib/rexml/encodings/CP-1252.rb12
-rw-r--r--lib/rexml/encodings/ISO-8859-15.rb6
-rw-r--r--lib/rexml/entity.rb288
-rw-r--r--lib/rexml/formatters/pretty.rb1
-rw-r--r--lib/rexml/instruction.rb98
-rw-r--r--lib/rexml/light/node.rb380
-rw-r--r--lib/rexml/namespace.rb78
-rw-r--r--lib/rexml/node.rb64
-rw-r--r--lib/rexml/output.rb22
-rw-r--r--lib/rexml/parsers/lightparser.rb84
-rw-r--r--lib/rexml/parsers/sax2parser.rb390
-rw-r--r--lib/rexml/parsers/ultralightparser.rb80
-rw-r--r--lib/rexml/parsers/xpathparser.rb76
-rw-r--r--lib/rexml/quickpath.rb490
-rw-r--r--lib/rexml/sax2listener.rb184
-rw-r--r--lib/rexml/streamlistener.rb180
-rw-r--r--lib/rexml/xmldecl.rb116
-rw-r--r--lib/rexml/xmltokens.rb28
-rw-r--r--lib/rexml/xpath.rb106
-rw-r--r--lib/rexml/xpath_parser.rb16
-rw-r--r--lib/rss/converter.rb10
-rw-r--r--lib/rubygems.rb144
-rw-r--r--lib/rubygems/commands/check_command.rb3
-rw-r--r--lib/rubygems/commands/contents_command.rb2
-rw-r--r--lib/rubygems/commands/environment_command.rb40
-rw-r--r--lib/rubygems/commands/help_command.rb4
-rw-r--r--lib/rubygems/commands/install_command.rb15
-rw-r--r--lib/rubygems/commands/lock_command.rb21
-rw-r--r--lib/rubygems/commands/outdated_command.rb2
-rw-r--r--lib/rubygems/commands/pristine_command.rb2
-rw-r--r--lib/rubygems/commands/query_command.rb23
-rw-r--r--lib/rubygems/commands/rdoc_command.rb6
-rw-r--r--lib/rubygems/commands/specification_command.rb4
-rw-r--r--lib/rubygems/commands/unpack_command.rb4
-rw-r--r--lib/rubygems/commands/update_command.rb36
-rw-r--r--lib/rubygems/commands/which_command.rb7
-rw-r--r--lib/rubygems/config_file.rb9
-rwxr-xr-xlib/rubygems/custom_require.rb22
-rw-r--r--lib/rubygems/defaults.rb61
-rw-r--r--lib/rubygems/dependency_installer.rb34
-rw-r--r--lib/rubygems/doc_manager.rb277
-rw-r--r--lib/rubygems/gem_path_searcher.rb54
-rw-r--r--lib/rubygems/installer.rb94
-rw-r--r--lib/rubygems/local_remote_options.rb7
-rw-r--r--lib/rubygems/package/tar_reader.rb14
-rw-r--r--lib/rubygems/platform.rb19
-rw-r--r--lib/rubygems/remote_fetcher.rb25
-rw-r--r--lib/rubygems/rubygems_version.rb2
-rw-r--r--lib/rubygems/source_index.rb28
-rw-r--r--lib/rubygems/source_info_cache.rb9
-rw-r--r--lib/rubygems/spec_fetcher.rb8
-rw-r--r--lib/rubygems/specification.rb795
-rw-r--r--lib/rubygems/test_utilities.rb20
-rw-r--r--[-rwxr-xr-x]lib/rubygems/timer.rb0
-rw-r--r--lib/rubygems/uninstaller.rb86
-rw-r--r--[-rwxr-xr-x]lib/rubygems/validator.rb272
-rw-r--r--lib/sync.rb4
-rw-r--r--lib/tempfile.rb16
-rw-r--r--lib/test/unit.rb437
-rw-r--r--lib/test/unit/assertionfailederror.rb14
-rw-r--r--lib/test/unit/assertions.rb622
-rw-r--r--lib/test/unit/autorunner.rb217
-rw-r--r--lib/test/unit/collector.rb43
-rw-r--r--lib/test/unit/collector/dir.rb113
-rw-r--r--lib/test/unit/collector/objectspace.rb40
-rw-r--r--lib/test/unit/error.rb56
-rw-r--r--lib/test/unit/failure.rb51
-rw-r--r--lib/test/unit/testcase.rb163
-rw-r--r--lib/test/unit/testresult.rb81
-rw-r--r--lib/test/unit/testsuite.rb76
-rw-r--r--lib/test/unit/ui/console/testrunner.rb130
-rw-r--r--lib/test/unit/ui/fox/testrunner.rb268
-rw-r--r--lib/test/unit/ui/gtk/testrunner.rb416
-rw-r--r--lib/test/unit/ui/gtk2/testrunner.rb465
-rw-r--r--lib/test/unit/ui/testrunnermediator.rb68
-rw-r--r--lib/test/unit/ui/testrunnerutilities.rb46
-rw-r--r--lib/test/unit/ui/tk/testrunner.rb260
-rw-r--r--lib/test/unit/util/backtracefilter.rb40
-rw-r--r--lib/test/unit/util/observable.rb90
-rw-r--r--lib/test/unit/util/procwrapper.rb48
-rw-r--r--lib/time.rb88
-rw-r--r--lib/tmpdir.rb2
-rw-r--r--lib/tsort.rb20
-rw-r--r--lib/uri/common.rb530
-rw-r--r--lib/uri/generic.rb48
-rw-r--r--lib/uri/mailto.rb16
-rw-r--r--lib/webrick/httpauth/digestauth.rb4
-rw-r--r--lib/webrick/httpproxy.rb4
-rw-r--r--lib/webrick/httprequest.rb8
-rw-r--r--lib/webrick/httpresponse.rb20
-rw-r--r--lib/webrick/httpservlet/abstract.rb2
-rw-r--r--lib/webrick/httpservlet/cgi_runner.rb2
-rw-r--r--lib/webrick/httpservlet/cgihandler.rb10
-rw-r--r--lib/webrick/httpservlet/filehandler.rb4
-rw-r--r--lib/webrick/utils.rb2
-rw-r--r--lib/xmlrpc/client.rb12
-rw-r--r--lib/xmlrpc/create.rb176
-rw-r--r--lib/xmlrpc/httpserver.rb2
-rw-r--r--lib/xmlrpc/parser.rb354
-rw-r--r--lib/xmlrpc/utils.rb4
-rw-r--r--lib/yaml.rb8
-rw-r--r--lib/yaml/rubytypes.rb38
-rw-r--r--load.c20
-rw-r--r--main.c3
-rw-r--r--man/goruby.139
-rw-r--r--man/irb.1127
-rw-r--r--man/ruby.1 (renamed from ruby.1)115
-rw-r--r--marshal.c61
-rw-r--r--math.c52
-rw-r--r--misc/ruby-mode.el60
-rw-r--r--misc/ruby-style.el10
-rw-r--r--missing/vsnprintf.c2
-rw-r--r--missing/x68.c40
-rwxr-xr-xmkconfig.rb2
-rw-r--r--mvm.c1
-rw-r--r--numeric.c86
-rw-r--r--object.c9
-rw-r--r--pack.c109
-rw-r--r--parse.y154
-rw-r--r--prec.c140
-rw-r--r--proc.c80
-rw-r--r--process.c72
-rw-r--r--range.c31
-rw-r--r--rational.c222
-rw-r--r--re.c57
-rw-r--r--regenc.c27
-rw-r--r--regenc.h2
-rw-r--r--regerror.c2
-rw-r--r--regexec.c97
-rw-r--r--regparse.c11
-rw-r--r--ruby.c412
-rw-r--r--safe.c (renamed from eval_safe.c)31
-rw-r--r--signal.c25
-rw-r--r--spec/default.mspec9
-rw-r--r--sprintf.c56
-rw-r--r--st.c7
-rw-r--r--strftime.c15
-rw-r--r--string.c866
-rw-r--r--struct.c21
-rw-r--r--template/id.h.tmpl117
-rw-r--r--template/known_errors.inc.tmpl14
-rw-r--r--template/public_object.h.tmpl52
-rw-r--r--test/base64/test_base64.rb99
-rw-r--r--test/bigdecimal/test_bigdecimal.rb692
-rw-r--r--[-rwxr-xr-x]test/cgi/test_cgi_cookie.rb0
-rw-r--r--[-rwxr-xr-x]test/cgi/test_cgi_core.rb53
-rw-r--r--[-rwxr-xr-x]test/cgi/test_cgi_header.rb2
-rw-r--r--[-rwxr-xr-x]test/cgi/test_cgi_modruby.rb0
-rw-r--r--[-rwxr-xr-x]test/cgi/test_cgi_multipart.rb57
-rw-r--r--test/cgi/test_cgi_session.rb98
-rw-r--r--[-rwxr-xr-x]test/cgi/test_cgi_tag_helper.rb20
-rw-r--r--[-rwxr-xr-x]test/cgi/testdata/file1.html0
-rw-r--r--[-rwxr-xr-x]test/cgi/testdata/large.pngbin156414 -> 156414 bytes
-rw-r--r--[-rwxr-xr-x]test/cgi/testdata/small.pngbin82 -> 82 bytes
-rw-r--r--test/csv/test_csv_parsing.rb (renamed from test/csv/tc_csv_parsing.rb)36
-rw-r--r--test/csv/test_csv_writing.rb (renamed from test/csv/tc_csv_writing.rb)11
-rw-r--r--test/csv/test_data_converters.rb (renamed from test/csv/tc_data_converters.rb)49
-rw-r--r--test/csv/test_encodings.rb256
-rw-r--r--test/csv/test_features.rb (renamed from test/csv/tc_features.rb)122
-rw-r--r--test/csv/test_headers.rb (renamed from test/csv/tc_headers.rb)93
-rw-r--r--test/csv/test_interface.rb (renamed from test/csv/tc_interface.rb)133
-rw-r--r--test/csv/test_row.rb (renamed from test/csv/tc_row.rb)29
-rw-r--r--test/csv/test_serialization.rb (renamed from test/csv/tc_serialization.rb)5
-rw-r--r--test/csv/test_table.rb (renamed from test/csv/tc_table.rb)20
-rw-r--r--test/csv/ts_all.rb22
-rw-r--r--test/date/test_date.rb144
-rw-r--r--test/date/test_date_arith.rb286
-rw-r--r--test/date/test_date_attr.rb109
-rw-r--r--test/date/test_date_base.rb435
-rw-r--r--test/date/test_date_compat.rb21
-rw-r--r--test/date/test_date_conv.rb130
-rw-r--r--test/date/test_date_marshal.rb29
-rw-r--r--test/date/test_date_new.rb278
-rw-r--r--test/date/test_date_parse.rb973
-rw-r--r--test/date/test_date_strftime.rb370
-rw-r--r--test/date/test_date_strptime.rb469
-rw-r--r--test/dbm/test_dbm.rb17
-rw-r--r--test/drb/drbtest.rb16
-rw-r--r--test/drb/test_drb.rb14
-rw-r--r--test/fileutils/fileasserts.rb4
-rw-r--r--test/fileutils/test_fileutils.rb40
-rw-r--r--test/gdbm/test_gdbm.rb10
-rw-r--r--test/iconv/test_basic.rb7
-rw-r--r--test/json/fixtures/fail18.json2
-rwxr-xr-xtest/json/runner.rb1
-rwxr-xr-xtest/json/test_json.rb143
-rwxr-xr-xtest/json/test_json_addition.rb42
-rwxr-xr-xtest/json/test_json_fixtures.rb2
-rw-r--r--test/json/test_json_generate.rb23
-rw-r--r--test/json/test_json_rails.rb13
-rwxr-xr-xtest/json/test_json_unicode.rb7
-rw-r--r--test/logger/test_logger.rb6
-rw-r--r--test/matrix/test_matrix.rb49
-rw-r--r--test/matrix/test_vector.rb49
-rw-r--r--test/minitest/test_mini_mock.rb83
-rw-r--r--test/minitest/test_mini_spec.rb156
-rw-r--r--test/minitest/test_mini_test.rb866
-rw-r--r--test/net/http/test_httpheader.rb2
-rw-r--r--test/net/pop/test_pop.rb132
-rw-r--r--test/nkf/test_nkf.rb6
-rw-r--r--test/openssl/test_cipher.rb2
-rw-r--r--test/openssl/test_ec.rb2
-rw-r--r--test/openssl/test_ssl.rb23
-rw-r--r--test/openssl/test_x509cert.rb6
-rw-r--r--test/openssl/test_x509store.rb4
-rw-r--r--test/optparse/test_noarg.rb12
-rw-r--r--test/optparse/test_reqarg.rb6
-rw-r--r--test/pathname/test_pathname.rb1
-rw-r--r--test/rdoc/binary.datbin0 -> 1024 bytes
-rw-r--r--test/rdoc/rdoc_markup_to_html_crossref_reference.rb31
-rw-r--r--test/rdoc/test_attribute_manager.rb76
-rw-r--r--test/rdoc/test_rdoc_info_formatting.rb20
-rw-r--r--test/rdoc/test_rdoc_info_sections.rb9
-rw-r--r--test/rdoc/test_rdoc_markup.rb6
-rw-r--r--test/rdoc/test_rdoc_markup_attribute_manager.rb42
-rw-r--r--test/rdoc/test_rdoc_markup_to_html.rb23
-rw-r--r--test/rdoc/test_rdoc_markup_to_html_crossref.rb290
-rw-r--r--test/rdoc/test_rdoc_parser.rb23
-rw-r--r--test/rdoc/test_rdoc_parser_c.rb35
-rw-r--r--test/rdoc/test_rdoc_parser_perl.rb74
-rw-r--r--test/rdoc/test_rdoc_parser_ruby.rb216
-rw-r--r--test/rdoc/test_rdoc_ri_attribute_formatter.rb6
-rw-r--r--test/rdoc/test_rdoc_ri_default_display.rb61
-rw-r--r--test/rdoc/test_rdoc_ri_driver.rb8
-rw-r--r--test/rdoc/test_rdoc_ri_formatter.rb12
-rw-r--r--test/rdoc/test_rdoc_ri_overstrike_formatter.rb6
-rw-r--r--test/readline/test_readline.rb6
-rw-r--r--test/readline/test_readline_history.rb20
-rw-r--r--test/rexml/test_document.rb51
-rw-r--r--test/rinda/test_rinda.rb41
-rw-r--r--test/rss/rss-assertions.rb6
-rw-r--r--test/ruby/enc/test_euc_jp.rb4
-rw-r--r--test/ruby/enc/test_utf16.rb56
-rw-r--r--test/ruby/marshaltestlib.rb22
-rw-r--r--test/ruby/test_argf.rb35
-rw-r--r--test/ruby/test_array.rb71
-rw-r--r--test/ruby/test_beginendblock.rb4
-rw-r--r--test/ruby/test_call.rb4
-rw-r--r--test/ruby/test_clone.rb2
-rw-r--r--test/ruby/test_complex.rb355
-rw-r--r--test/ruby/test_complex2.rb735
-rw-r--r--test/ruby/test_complexrational.rb407
-rw-r--r--test/ruby/test_econv.rb217
-rw-r--r--test/ruby/test_encoding.rb9
-rw-r--r--test/ruby/test_env.rb13
-rw-r--r--test/ruby/test_exception.rb4
-rw-r--r--test/ruby/test_file.rb84
-rw-r--r--test/ruby/test_fixnum.rb9
-rw-r--r--test/ruby/test_float.rb7
-rw-r--r--test/ruby/test_hash.rb1
-rw-r--r--test/ruby/test_integer.rb6
-rw-r--r--test/ruby/test_io.rb170
-rw-r--r--test/ruby/test_io_m17n.rb299
-rw-r--r--test/ruby/test_iterator.rb18
-rw-r--r--test/ruby/test_lambda.rb24
-rw-r--r--test/ruby/test_m17n.rb66
-rw-r--r--test/ruby/test_m17n_comb.rb123
-rw-r--r--test/ruby/test_math.rb1
-rw-r--r--test/ruby/test_mixed_unicode_escapes.rb6
-rw-r--r--test/ruby/test_module.rb32
-rw-r--r--test/ruby/test_numeric.rb4
-rw-r--r--test/ruby/test_object.rb7
-rw-r--r--test/ruby/test_pack.rb46
-rw-r--r--test/ruby/test_path.rb8
-rw-r--r--test/ruby/test_prec.rb21
-rw-r--r--test/ruby/test_proc.rb364
-rw-r--r--test/ruby/test_rational.rb239
-rw-r--r--test/ruby/test_rational2.rb26
-rw-r--r--test/ruby/test_readpartial.rb8
-rw-r--r--test/ruby/test_regexp.rb3
-rw-r--r--test/ruby/test_require.rb14
-rw-r--r--test/ruby/test_rubyoptions.rb8
-rw-r--r--test/ruby/test_settracefunc.rb8
-rw-r--r--test/ruby/test_signal.rb4
-rw-r--r--test/ruby/test_sprintf_comb.rb7
-rw-r--r--test/ruby/test_thread.rb4
-rw-r--r--test/ruby/test_transcode.rb905
-rw-r--r--test/ruby/test_unicode_escape.rb2
-rw-r--r--test/ruby/test_variable.rb3
-rw-r--r--test/ruby/test_yield.rb11
-rw-r--r--test/rubygems/functional.rb8
-rw-r--r--test/rubygems/gem_installer_test_case.rb2
-rw-r--r--test/rubygems/gemutilities.rb57
-rw-r--r--test/rubygems/mockgemui.rb24
-rw-r--r--test/rubygems/test_config.rb2
-rw-r--r--test/rubygems/test_gem.rb156
-rw-r--r--test/rubygems/test_gem_builder.rb1
-rw-r--r--test/rubygems/test_gem_command.rb5
-rw-r--r--test/rubygems/test_gem_command_manager.rb1
-rw-r--r--test/rubygems/test_gem_commands_build_command.rb1
-rw-r--r--test/rubygems/test_gem_commands_cert_command.rb1
-rw-r--r--test/rubygems/test_gem_commands_check_command.rb1
-rw-r--r--test/rubygems/test_gem_commands_contents_command.rb5
-rw-r--r--test/rubygems/test_gem_commands_dependency_command.rb7
-rw-r--r--test/rubygems/test_gem_commands_environment_command.rb3
-rw-r--r--test/rubygems/test_gem_commands_fetch_command.rb1
-rw-r--r--test/rubygems/test_gem_commands_generate_index_command.rb2
-rw-r--r--test/rubygems/test_gem_commands_install_command.rb5
-rw-r--r--test/rubygems/test_gem_commands_list_command.rb36
-rw-r--r--test/rubygems/test_gem_commands_lock_command.rb68
-rw-r--r--test/rubygems/test_gem_commands_mirror_command.rb1
-rw-r--r--test/rubygems/test_gem_commands_outdated_command.rb1
-rw-r--r--test/rubygems/test_gem_commands_pristine_command.rb3
-rw-r--r--test/rubygems/test_gem_commands_query_command.rb52
-rw-r--r--test/rubygems/test_gem_commands_server_command.rb1
-rw-r--r--test/rubygems/test_gem_commands_sources_command.rb1
-rw-r--r--test/rubygems/test_gem_commands_specification_command.rb3
-rw-r--r--test/rubygems/test_gem_commands_stale_command.rb1
-rw-r--r--test/rubygems/test_gem_commands_uninstall_command.rb61
-rw-r--r--test/rubygems/test_gem_commands_unpack_command.rb1
-rw-r--r--test/rubygems/test_gem_commands_update_command.rb1
-rw-r--r--test/rubygems/test_gem_config_file.rb7
-rw-r--r--test/rubygems/test_gem_dependency.rb27
-rw-r--r--test/rubygems/test_gem_dependency_installer.rb9
-rw-r--r--test/rubygems/test_gem_dependency_list.rb3
-rwxr-xr-xtest/rubygems/test_gem_digest.rb22
-rw-r--r--test/rubygems/test_gem_doc_manager.rb3
-rw-r--r--test/rubygems/test_gem_ext_configure_builder.rb8
-rw-r--r--test/rubygems/test_gem_ext_ext_conf_builder.rb5
-rw-r--r--test/rubygems/test_gem_ext_rake_builder.rb13
-rw-r--r--test/rubygems/test_gem_format.rb10
-rw-r--r--test/rubygems/test_gem_gem_path_searcher.rb23
-rw-r--r--test/rubygems/test_gem_gem_runner.rb1
-rw-r--r--test/rubygems/test_gem_indexer.rb5
-rw-r--r--test/rubygems/test_gem_install_update_options.rb7
-rw-r--r--test/rubygems/test_gem_installer.rb83
-rw-r--r--test/rubygems/test_gem_local_remote_options.rb15
-rw-r--r--test/rubygems/test_gem_package_tar_reader_entry.rb10
-rw-r--r--test/rubygems/test_gem_package_tar_writer.rb20
-rw-r--r--test/rubygems/test_gem_platform.rb44
-rw-r--r--test/rubygems/test_gem_remote_fetcher.rb54
-rw-r--r--test/rubygems/test_gem_requirement.rb29
-rw-r--r--test/rubygems/test_gem_server.rb1
-rw-r--r--test/rubygems/test_gem_source_index.rb106
-rw-r--r--test/rubygems/test_gem_source_info_cache.rb15
-rw-r--r--test/rubygems/test_gem_source_info_cache_entry.rb3
-rw-r--r--test/rubygems/test_gem_spec_fetcher.rb15
-rw-r--r--test/rubygems/test_gem_specification.rb43
-rw-r--r--test/rubygems/test_gem_stream_ui.rb1
-rw-r--r--test/rubygems/test_gem_uninstaller.rb21
-rw-r--r--test/rubygems/test_gem_validator.rb9
-rw-r--r--test/rubygems/test_gem_version.rb19
-rw-r--r--test/rubygems/test_gem_version_option.rb1
-rw-r--r--test/rubygems/test_kernel.rb4
-rw-r--r--test/runner.rb24
-rw-r--r--test/scanf/test_scanf.rb4
-rw-r--r--test/sdbm/test_sdbm.rb19
-rw-r--r--test/socket/test_tcp.rb19
-rw-r--r--test/strscan/test_stringscanner.rb4
-rw-r--r--test/test_delegate.rb12
-rw-r--r--test/test_shellwords.rb6
-rw-r--r--test/test_tempfile.rb21
-rw-r--r--test/testunit/collector/test_dir.rb411
-rw-r--r--test/testunit/collector/test_objectspace.rb98
-rw-r--r--test/testunit/test_assertions.rb543
-rw-r--r--test/testunit/test_error.rb26
-rw-r--r--test/testunit/test_failure.rb33
-rw-r--r--test/testunit/test_testcase.rb275
-rw-r--r--test/testunit/test_testresult.rb104
-rw-r--r--test/testunit/test_testsuite.rb129
-rw-r--r--test/testunit/util/test_backtracefilter.rb41
-rw-r--r--test/testunit/util/test_observable.rb102
-rw-r--r--test/testunit/util/test_procwrapper.rb36
-rw-r--r--test/uri/test_ftp.rb2
-rw-r--r--test/uri/test_generic.rb125
-rw-r--r--test/uri/test_http.rb2
-rw-r--r--test/uri/test_ldap.rb2
-rw-r--r--test/uri/test_mailto.rb4
-rw-r--r--test/uri/test_parser.rb41
-rw-r--r--test/webrick/test_cgi.rb36
-rw-r--r--test/webrick/test_filehandler.rb62
-rw-r--r--test/webrick/test_httpauth.rb22
-rw-r--r--test/webrick/test_httpproxy.rb112
-rw-r--r--test/webrick/test_httprequest.rb8
-rw-r--r--test/webrick/test_httpserver.rb26
-rw-r--r--test/webrick/test_httputils.rb36
-rw-r--r--test/webrick/test_server.rb20
-rw-r--r--test/webrick/test_utils.rb12
-rw-r--r--test/webrick/utils.rb13
-rw-r--r--test/win32ole/err_in_callback.rb14
-rw-r--r--test/win32ole/orig_data.csv5
-rw-r--r--test/win32ole/test_err_in_callback.rb42
-rw-r--r--test/win32ole/test_win32ole.rb31
-rw-r--r--test/win32ole/test_win32ole_event.rb569
-rw-r--r--test/win32ole/test_win32ole_method.rb3
-rw-r--r--test/win32ole/test_win32ole_typelib.rb2
-rw-r--r--test/win32ole/test_win32ole_variant.rb6
-rw-r--r--test/win32ole/test_win32ole_variant_outarg.rb69
-rw-r--r--test/win32ole/test_win32ole_variant_with_ie.rb53
-rw-r--r--test/xmlrpc/test_datetime.rb46
-rw-r--r--test/xmlrpc/test_features.rb4
-rw-r--r--test/xmlrpc/test_webrick_server.rb2
-rw-r--r--test/yaml/test_yaml.rb24
-rw-r--r--test/zlib/test_zlib.rb14
-rw-r--r--thread.c248
-rw-r--r--thread_pthread.c74
-rw-r--r--thread_win32.c27
-rw-r--r--tool/compile_prelude.rb2
-rw-r--r--tool/generic_erb.rb34
-rwxr-xr-xtool/ifchange8
-rwxr-xr-xtool/insns2vm.rb2
-rw-r--r--tool/instruction.rb8
-rwxr-xr-xtool/make-snapshot48
-rwxr-xr-xtool/mdoc2man.rb (renamed from mdoc2man.rb)2
-rwxr-xr-xtool/merge_from_trunk.rb2
-rw-r--r--tool/transcode-tblgen.rb48
-rw-r--r--transcode.c1279
-rw-r--r--transcode_data.h14
-rw-r--r--util.c148
-rw-r--r--variable.c146
-rw-r--r--version.h6
-rw-r--r--vm.c91
-rw-r--r--vm_core.h134
-rw-r--r--vm_dump.c25
-rw-r--r--vm_eval.c15
-rw-r--r--vm_exec.c (renamed from vm_evalbody.c)32
-rw-r--r--vm_exec.h (renamed from vm.h)75
-rw-r--r--vm_insnhelper.c274
-rw-r--r--vm_insnhelper.h (renamed from insnhelper.h)62
-rw-r--r--vm_method.c5
-rw-r--r--vms/config.h123
-rw-r--r--vms/vms.h13
-rw-r--r--vms/vmsruby_private.c52
-rw-r--r--vms/vmsruby_private.h7
-rw-r--r--win32/Makefile.sub65
-rwxr-xr-xwin32/configure.bat7
-rwxr-xr-xwin32/ifchange.bat16
-rw-r--r--win32/setup.mak3
-rw-r--r--win32/win32.c72
-rw-r--r--wince/Makefile.sub47
-rw-r--r--wince/README.wince122
-rw-r--r--wince/assert.c11
-rw-r--r--wince/assert.h6
-rwxr-xr-xwince/configure.bat109
-rw-r--r--wince/direct.c54
-rw-r--r--wince/direct.h22
-rw-r--r--wince/errno.c11
-rw-r--r--wince/errno.h55
-rw-r--r--wince/fcntl.h42
-rw-r--r--wince/io.h76
-rw-r--r--wince/io_wce.c230
-rw-r--r--wince/process.h46
-rw-r--r--wince/process_wce.c47
-rw-r--r--wince/setup.mak254
-rw-r--r--wince/signal.h71
-rw-r--r--wince/signal_wce.c26
-rw-r--r--wince/stddef.h5
-rw-r--r--wince/stdio.c36
-rw-r--r--wince/stdlib.c57
-rw-r--r--wince/string_wce.c89
-rw-r--r--wince/sys/stat.c102
-rw-r--r--wince/sys/stat.h68
-rw-r--r--wince/sys/timeb.c25
-rw-r--r--wince/sys/timeb.h26
-rw-r--r--wince/sys/types.h60
-rw-r--r--wince/sys/utime.c44
-rw-r--r--wince/sys/utime.h27
-rw-r--r--wince/time.h63
-rw-r--r--wince/time_wce.c301
-rw-r--r--wince/varargs.h34
-rw-r--r--wince/wince.c583
-rw-r--r--wince/wince.h191
-rw-r--r--wince/wincemain.c18
-rw-r--r--wince/wincon.h7
-rw-r--r--wince/winsock2.c338
-rw-r--r--x68/_dtos18.c250
-rw-r--r--x68/_round.c45
-rw-r--r--x68/fconvert.c81
-rw-r--r--x68/select.c167
757 files changed, 40096 insertions, 27172 deletions
diff --git a/.gdbinit b/.gdbinit
index 8598cf0ab7..c2a8b28d0b 100644
--- a/.gdbinit
+++ b/.gdbinit
@@ -86,11 +86,17 @@ define rp
print (struct RString *)$arg0
else
if ($flags & RUBY_T_MASK) == RUBY_T_REGEXP
+ set $regsrc = ((struct RRegexp*)$arg0)->src
+ set $rsflags = ((struct RBasic*)$regsrc)->flags
printf "T_REGEXP: "
set print address off
- output ((struct RRegexp*)$arg0)->str
+ output (char *)(($rsflags & RUBY_FL_USER1) ? \
+ ((struct RString*)$regsrc)->as.heap.ptr : \
+ ((struct RString*)$regsrc)->as.ary)
set print address on
- printf " len:%ld ", ((struct RRegexp*)$arg0)->len
+ printf " len:%ld ", ($rsflags & RUBY_FL_USER1) ? \
+ ((struct RString*)$regsrc)->as.heap.len : \
+ (($rsflags & (RUBY_FL_USER2|RUBY_FL_USER3|RUBY_FL_USER4|RUBY_FL_USER5|RUBY_FL_USER6)) >> RUBY_FL_USHIFT+2)
if $flags & RUBY_FL_USER6
printf "(none) "
end
@@ -104,9 +110,34 @@ define rp
print (struct RRegexp *)$arg0
else
if ($flags & RUBY_T_MASK) == RUBY_T_ARRAY
- printf "T_ARRAY: len=%ld ", ((struct RArray*)$arg0)->len
+ if ($flags & RUBY_FL_USER1)
+ set $len = (($flags & (RUBY_FL_USER3|RUBY_FL_USER4)) >> (RUBY_FL_USHIFT+3))
+ printf "T_ARRAY: len=%ld ", $len
+ printf "(embed) "
+ if ($len == 0)
+ printf "{(empty)} "
+ else
+ output/x *((VALUE*)((struct RArray*)$arg0)->as.ary) @ $len
+ printf " "
+ end
+ else
+ set $len = ((struct RArray*)$arg0)->as.heap.len
+ printf "T_ARRAY: len=%ld ", $len
+ if ($flags & RUBY_FL_USER2)
+ printf "(shared) shared="
+ output/x ((struct RArray*)$arg0)->as.heap.aux.shared
+ printf " "
+ else
+ printf "(ownership) capa=%ld ", ((struct RArray*)$arg0)->as.heap.aux.capa
+ end
+ if ($len == 0)
+ printf "{(empty)} "
+ else
+ output/x *((VALUE*)((struct RArray*)$arg0)->as.heap.ptr) @ $len
+ printf " "
+ end
+ end
print (struct RArray *)$arg0
- x/xw ((struct RArray*)$arg0)->ptr
else
if ($flags & RUBY_T_MASK) == RUBY_T_FIXNUM
printf "T_FIXNUM: "
diff --git a/.merged-trunk-revision b/.merged-trunk-revision
index 94a0018130..c20f5c10e4 100644
--- a/.merged-trunk-revision
+++ b/.merged-trunk-revision
@@ -1 +1 @@
-19258
+20281
diff --git a/ChangeLog b/ChangeLog
index e3c53d0ac6..625a92aed8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,15 +1,4151 @@
+Wed Nov 19 03:01:04 2008 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * test/rinda/test_rinda.rb: fixed fails occasionally [ruby-dev:37119].
+ thanks, shinichiro.h.
+
+Wed Nov 19 02:39:31 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * error.c (Init_syserr): moved function definition itself from
+ template/known_errors.inc.tmpl.
+
+Wed Nov 19 01:10:52 2008 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/drb/drb.rb (DRbConn::alive?): fixed NoMethodError problem
+ from NaHi [ruby-dev:37110].
+
+Wed Nov 19 01:05:26 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * cont.c (cont_mark, cont_capture, cont_restore_1): speed up
+ continuation by copying only valid YARV stack. [ruby-dev:37106]
+
+Wed Nov 19 00:03:13 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/time.rb: according to RFC2822, -0000 means local time, +0000
+ means UTC. a patch from Chun Wang. [ruby-core:19578]
+
+Tue Nov 18 23:02:23 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * proc.c (proc_eq): equivalence check should not done by pointer
+ comparison, but should be based on iseq contents. [ruby-dev:37101]
+
+Tue Nov 18 20:30:08 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/net/ftp.rb (Net::FTP#open_socket): SOCKSsocket is obsolete.
+ a patch from Alan Johnson <alan.wayne.johnson at gmail.com> in
+ [ruby-core:19982].
+
+Tue Nov 18 16:18:23 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/logger.rb (ProgName): fixed for svn, based on a patch from
+ Nobuhiro IMAI at [ruby-dev:37108].
+
+Tue Nov 18 15:56:55 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/webrick/httprequest.rb (WEBrick::HTTPRequest#read_request_line):
+ use possessive match for path retrieval to avoid huge recursion
+ for insanely long path.
+
+Tue Nov 18 15:50:11 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * re.c (rb_reg_desc): re might be NULL.
+
+ * regerror.c (onig_error_code_to_format): message updated.
+
+Tue Nov 18 09:42:11 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/optparse.rb (OptionParser::make_switch): makes default
+ conversion to splat. [ruby-list:45645]
+
+Mon Nov 17 18:05:16 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * enc/depend (LIBS): fixed for disable-shared. [ruby-dev:37103]
+
+Mon Nov 17 11:12:24 2008 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * bin/erb: remove -K option.
+
+Mon Nov 17 02:19:03 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (LIBRUBYARG_STATIC): fixed for --enable-rpath.
+
+Sat Nov 15 22:46:32 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * re.c (rb_reg_regsub): returns -1 unless ascii as well as
+ rb_enc_ascget(). [ruby-dev:37097]
+
+Sat Nov 15 22:23:45 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (LDSHARED): do not suppress debug info if higher debug
+ level is given, on cygwin and mingw.
+
+Fri Nov 14 20:27:46 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * README.EXT, README.EXT.ja, vm_exec.c, vm_insnhelper.c: update
+ filenames.
+
+Thu Nov 13 11:31:13 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * thread.c (rb_barrier_wait): gets rid of recursive deadlock.
+
+Thu Nov 13 06:08:44 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * thread.c (rb_barrier_{new,wait,release,destroy}): use Mutex so that
+ circular requires fail with deadlock. [ruby-core:19821]
+
+Wed Nov 12 07:16:01 2008 David Flanagan <david@think32>
+
+ * ruby.c (set_internal_encoding_once): fix typo in error string
+
+Wed Nov 12 03:30:59 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * include/ruby/intern.h (rb_{external,locale}_str_new_cstr): optimized
+ versions for literal strings.
+
+Wed Nov 12 03:28:41 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * load.c (rb_require_safe): destroys barrier after successfully
+ loaded, to get rid of loading same library again. [ruby-core:19798]
+
+ * thread.c (rb_barrier_wait): can not wait destroyed barrier.
+
+ * thread.c (rb_barrier_destroy): destroys barrier so that no longer
+ waited.
+
+Tue Nov 11 23:02:27 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * man/ruby.1 (RUBYOPT): wrote which option can appear.
+ (--yydebug): wrote "do not use".
+ (--dump): wrote "do not use".
+
+Tue Nov 11 21:22:28 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/uri/generic.rb (URI::Generic#check_path): REL_PATH should a
+ symbol. [ruby-core:19805]
+
+Tue Nov 11 20:49:29 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * configure.in: fix SEGV on Mac OS X 10.5.3 with pthread.
+ a patch from Wataru Kimura in Bug #193 [ruby-core:17333].
+
+Tue Nov 11 20:39:27 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb (inspect): reverted the previous change.
+
+Tue Nov 11 17:35:25 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (rb_w32_accept): secure fd before accept because if
+ error causes in securing, cannot restore the state of accepted
+ socket.
+ fixed [ruby-core:19728]
+
+Tue Nov 11 14:40:40 2008 Martin Duerst <duerst@it.aoyama.ac.jp>
+
+ * test/ruby/test_transcode.rb: unnecessary setup method
+ (setup_really_needed?) removed
+
+Tue Nov 11 14:25:25 2008 Martin Duerst <duerst@it.aoyama.ac.jp>
+
+ * enc/trans/single_byte.trans, macgreek-tbl.rb, macroman-tbl.rb,
+ macromania-tbl.rb, macturkish-tbl.rb, macukraine-tbl.rb,
+ ibm437-tbl.rb, ibm852-tbl.rb, ibm855-tbl.rb, ibm857-tbl.rb,
+ ibm860-tbl.rb, ibm861-tbl.rb, ibm862-tbl.rb, ibm863-tbl.rb,
+ ibm865-tbl.rb, ibm866-tbl.rb, ibm869-tbl.rb, ibm775-tbl.rb:
+ new single-byte transcodings (from Yoshihiro Kambayashi)
+
+ * test/ruby/test_transcode.rb: added tests for the above
+ (from Yoshihiro Kambayashi)
+
+Tue Nov 11 13:20:23 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/bigdecimal/bigdecimal.c (BigDecimal_to_r): moved from
+ bigdecimal/util, converted into C. [ruby-dev:36805]
+
+Tue Nov 11 07:55:57 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb (inspect): changed the format.
+
+Mon Nov 10 17:34:50 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * test/sdbm/test_sdbm.rb (TestSDBM#test_index): Reflect the method
+ name change from #index to #key and remove a duplicated test
+ method.
+
+Mon Nov 10 10:50:43 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/delegate.rb (Delegator.delegating_block): should not refer
+ DelegateClass specific @delegate_dc_obj. a patch from Erik
+ Hollensbe in [ruby-core:19671].
+
+Mon Nov 10 09:54:21 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (ifs_open_socket): should retry without proto_buffer
+ if cannot find the suitable protocol. a patch from Heesob Park.
+ fixed [ruby-core:19713]
+
+Sun Nov 9 13:04:52 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * struct.c (rb_struct_initialize_m): avoid unnecessary array
+ allocation.
+
+Sun Nov 9 04:10:19 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * vm_dump.c (control_frame_dump): suppresses finished method name.
+
+Sun Nov 9 00:30:52 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * thread_pthread.c (thread_timer): checks working flags again.
+
+Sun Nov 9 00:02:01 2008 Takeyuki FUJIOKA <xibbar@ruby-lang.org>
+
+ * lib/cgi/session/pstore.rb: fix indentation.
+
+Sat Nov 8 23:47:45 2008 Takeyuki FUJIOKA <xibbar@ruby-lang.org>
+
+ * lib/cgi/session.rb (FileStore): use marshalized data.
+
+ * test/cgi/session_dir: add a session directory in test.
+
+ * test/cgi/test_cgi_session.rb: add a test.
+
+Sat Nov 8 21:57:03 2008 Takeyuki FUJIOKA <xibbar@ruby-lang.org>
+
+ * lib/cgi/session.rb: remove debug code.
+
+Sat Nov 8 21:33:53 2008 Takeyuki FUJIOKA <xibbar@ruby-lang.org>
+
+ * lib/cgi/session.rb: fix indentation.
+
+Sat Nov 8 18:11:14 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/webrick/httpproxy.rb (WEBrick::HTTPProxyServer#do_CONNECT):
+ use #bytesize instead of #size. a patch submitted from
+ raspberry lemon in [ruby-core:18571].
+
+ * lib/webrick/httpauth/digestauth.rb, lib/webrick/httpproxy.rb,
+ lib/webrick/httprequest.rb, lib/webrick/httpservlet/cgi_runner.rb,
+ lib/webrick/httpservlet/abstract.rb, lib/webrick/httpresponse.rb,
+ lib/webrick/httpservlet/cgihandler.rb, lib/webrick/utils.rb: ditto.
+
+Sat Nov 8 17:31:41 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/stringio/stringio.c (strio_ungetc): ungetc position should
+ not be changed from 1.8. [ruby-core:19632]
+
+Sat Nov 8 17:15:08 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/optparse.rb (OptionParser#make_switch): 1.9 Symbols respond
+ to :match. a patch from keith cascio, <keith at ucla.edu>.
+ [ruby-core:19730]
+
+Sat Nov 8 12:10:15 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/gdbm/gdbm.c (fgdbm_index): make #index warn like Hash.
+ [ruby-dev:37039]
+
+ * ext/sdbm/init.c (Init_sdbm): typo fixed. [ruby-dev:37039]
+
+Sat Nov 8 07:07:48 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * configure.in: detect stdio buffer pointers for uClibc. a patch
+ from Brian Candler <B.Candler at pobox.com> in [ruby-core:12020].
+ [ruby-core:19713]
+
+Sat Nov 8 06:51:42 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/dbm/dbm.c (fdbm_index): make #index warn like Hash.
+
+ * ext/dbm/dbm.c (fdbm_key): new method.
+
+ * ext/sdbm/init.c: ditto.
+
+Sat Nov 8 06:20:42 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/curses/curses.c: curses encoding should obey locale.
+
+ * ext/curses/curses.c (curses_getch): 1.9 getch should return one
+ character string for single byte string. wchar_t support may
+ follow in the future.
+
+Sat Nov 8 05:46:50 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * include/ruby/io.h (rb_io_t): added write_lock to serialize.
+ [ruby-core:19668]
+
+ * gc.c (gc_mark_children): mark write_lock.
+
+ * gc.c (rb_gc_call_finalizer_at_exit): Mutex also needs to be
+ deferred.
+
+ * io.c (io_fflush, io_binwrite, fptr_finalize): serializes writing.
+
+Sat Nov 8 05:31:25 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * safe.c (safe_setter): add warning for $SAFE=3.
+
+Sat Nov 8 01:48:07 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * thread_pthread.c (rb_thread_create_timer_thread): do not wait never
+ coming signal if failed to create tiemr thread.
+
+ * thread_pthread.c (native_cond_timedwait): returns error code.
+
+ * thread_pthread.c (thread_timer): typo fixed.
+
+Sat Nov 8 01:14:16 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * thread_pthread.c (thread_timer, rb_thread_create_timer_thread):
+ handshakes properly.
+
+Fri Nov 7 22:51:49 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * inits.c (rb_call_inits): do not repeat.
+
+Fri Nov 7 22:46:57 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * thread_pthread.c (thread_timer): initializes mutex each time.
+
+Fri Nov 7 21:23:02 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * thread_win32.c (thread_start_func_1): use already gotten stack info.
+
Fri Nov 7 20:42:47 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
* parse.y (Init_sym): symbol objectspace should not be GCed.
+Fri Nov 7 12:26:00 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/irb.rb (IRB::Irb#eval_input): remove extra @context.prompt_i.
+ [ruby-core:19718]
+
+Fri Nov 7 11:55:30 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * nkf.c: update to r1.188. fixes for 16bit environment.
+
+Fri Nov 7 07:43:27 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * thread.c (thread_timer): pthread_cond_timedwait returns ETIMEDOUT
+ when timed out.
+
+Fri Nov 7 07:32:55 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/yaml/rubytypes.rb: support Rational and Complex as 1.8
+ does. a patch from Hiroshi Moriyama in [ruby-dev:36899].
+
+Fri Nov 7 07:12:06 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * thread_pthread.c (thread_timer): uses pthread_cond_timedwait always
+ instead of pthread_kill.
+
+Fri Nov 7 06:58:59 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (Init_String): remove Symbol#===. [ruby-dev:37026]
+
+Fri Nov 7 04:02:22 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * thread.c (thread_timer): uses timedwait on cygwin.
+
+Fri Nov 7 02:00:12 2008 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/rexml/entity.rb (unnormalized): do not call
+ document.record_entity_expansion if document is nil.
+ see <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=502535>.
+ Thanks, Naohisa Goto.
+
+ * test/rexml/test_document.rb: ditto.
+
+Fri Nov 7 01:24:20 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * tool/make-snapshot: binary encoding spec is no longer needed in 1.9.
+
+Thu Nov 6 22:21:23 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * thread.c (rb_thread_stop_timer_thread): terminates timer thread
+ immediately.
+
+Thu Nov 6 21:21:46 2008 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c (fole_s_connect, fole_initialize,
+ folevariant_initialize): check argument type of WIN32OLE.connect,
+ WIN32OLE.new, WIN32OLE_VARIANT.new.
+
+ * test/win32ole/test_win32ole.rb (test_s_new_exc, test_s_connect_exc):
+ ditto.
+
+ * test/win32ole/test_win32ole_variant.rb (test_s_new_exc): ditto.
+
+ * test/win32ole/test_win32ole_method.rb: add assertion of
+ WIN32OLE_METHOD.new.
+
+Tue Nov 4 13:08:01 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * lib/test/unit.rb (Test::Unit.setup_argv): now can specify ``-xname''
+ instead of ``-x name''.
+
+Tue Nov 4 08:00:00 2008 TAKANO Mitsuhiro (takano32) <tak@no32.tk>
+
+ * test/zlib/test_zlib.rb(test_readchar): compare in same type.
+
+Tue Nov 4 03:28:31 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * array.c (rb_ary_join): do not repeat self in a recursive array.
+ [ruby-dev:37019]
+
+Tue Nov 4 01:56:46 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * include/ruby/intern.h (rb_mutex_synchronize): fixed prototype.
+
+ * thread.c (rb_mutex_synchronize): fixed function name.
+
+Mon Nov 3 16:32:54 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * missing.h: needs RUBY_EXTERN instead of extern for mswin.
+
+Mon Nov 3 13:01:13 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * array.c (rb_ary_take_first_or_last): renamed rb_ary_partial more
+ appropriately.
+ (ary_take_pos_flags): new enum. makes the fourth argument of
+ rb_ary_take_first_or_last more descriptive.
+ (rb_ary_partial): renamed rb_ary_partial0 more appropriately.
+ takes a new parameter klass for what class to instanciate.
+
+ * gem_prelude.rb: Don't require rubygems/defaults.rb.
+
+Fri Oct 31 21:58:50 2008 Kouhei Sutou <kou@cozmixng.org>
+
+ * lib/rss/converter.rb (RSS::Converter): use String#encode.
+
+Fri Oct 31 21:28:14 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * lib/webrick/httpauth/digestauth.rb
+ (WEBrick::HTTPAuth::DigestAuth#initialize): fix typo.
+
+Fri Oct 31 18:51:42 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * test/ruby/test_array.rb (test_array_subclass): test for r20076.
+
+Fri Oct 31 18:42:19 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * array.c (ary_partial0): recovers the mistakenly changed feature at r19723.
+ Array#[m,n] had returned an Array even for an instance of a
+ subclass.
+
+Fri Oct 31 18:05:05 2008 Martin Duerst <duerst@it.aoyama.ac.jp>
+
+ * enc/trans/single_byte.trans, maccroatioan-tbl.rb,
+ maccyrillic-tbl.rb, maciceland-tbl.rb: new single-byte
+ transcodings (from Yoshihiro Kambayashi)
+
+ * test/ruby/test_transcode.rb: added tests for the above
+ (from Yoshihiro Kambayashi)
+
+Fri Oct 31 12:51:25 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * dir.c (dir_globs): need taint check. reported by steve
+ <oksteev at gmail.com>
+
+Fri Oct 31 12:42:45 2008 wanabe <s.wanabe@gmail.com>
+
+ * array.c (rb_ary_decrement_share): fix to work recycling
+ shared-array without the following. [ruby-dev:36991]
+
+ * array.c (ary_make_substitution): don't recycle substitution array.
+
+Fri Oct 31 12:27:52 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * spec/default.mspec: supports that the build directory != srcdir.
+
+Fri Oct 31 11:35:38 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * encoding.c (rb_enc_set_default_internal): no alias "internal" if
+ defalt internal is not set. [ruby-dev:37000]
+
+Fri Oct 31 08:16:14 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ruby.c (process_options): delays setting safe level.
+ [ruby-dev:36997]
+
+Thu Oct 30 21:32:15 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * array.c (rb_ary_permutation): hide temporal array.
+
+Thu Oct 30 14:45:45 2008 Martin Duerst <duerst@it.aoyama.ac.jp>
+
+ * enc/trans/single_byte.trans: refactoring to make it easier
+ to add more transcodings (with Yoshihiro Kambayashi)
+
+ * enc/trans/iso-8859-1-tbl.rb: new file to avoid having to
+ treat ISO-8859-1 as special
+
+Thu Oct 30 14:10:46 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * pack.c (pack_pack): templates a, A, Z should propagate encoding
+ of original strings. templates b, B, h, H brings ASCII-8BIT to
+ the result.
+
+Thu Oct 30 10:34:20 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ruby.c (moreswitches): splits option string and passes arguments.
+
+ * ruby.c (proc_options): checks if allowed in RUBYOPT.
+
+ * ruby.c (process_options): allows long style options in RUBYOPT.
+
+ * ruby.c (load_file_internal): ditto in shebang. [ruby-dev:36979]
+
+Thu Oct 30 09:31:45 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * encoding.c (rb_locale_encoding): makes an alias for locale.
+ [ruby-dev:36976]
+
+ * encoding.c (rb_enc_set_default_external): ditto for external.
+
+ * encoding.c (rb_enc_set_default_internal): ditto for internal.
+
+Thu Oct 30 03:30:25 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ruby.c (load_file_internal): should not set script encoding to
+ ASCII-8BIT.
+
+ * ruby.c (load_file_internal): do not auto convert scripts even
+ when default_internal is set. [ruby-core:19579]
+
+Thu Oct 30 02:20:33 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * array.c (rb_ary_sort_bang): remove SEGV when replacing array with
+ embedded one during sort. [ruby-dev:36983]
+
+ * test/ruby/test_array.rb (test_sort!): add tests for above.
+
+Thu Oct 30 01:44:23 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * test/ruby/test_array.rb: add some tests.
+
+Thu Oct 30 01:32:15 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * array.c (rb_ary_splice): remove redundant check.
+
+Thu Oct 30 01:24:55 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * string.c (rb_str_cmp): fix condition which always returned true
+ because ENCODING_GET returns unsigned long.
+
+Thu Oct 30 01:10:32 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * test/ruby/test_array.rb (test_permutation): add a test that replaces
+ array during permutation.
+
+Wed Oct 29 23:31:34 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_check_dummy_enc): new function to check dummy
+ encoding.
+
+ * string.c (rb_str_upcase_bang): case conversion functions should
+ not be applicable to strings in dummy encoding. [ruby-dev:36985]
+
+Wed Oct 29 23:57:29 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * array.c (rb_ary_sort_bang): replacing array during sort broke
+ invariant of array. [ruby-dev:36983]
+
+Wed Oct 29 21:06:46 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_io_rewind): should reset fptr->readconv if it's
+ available.
+
+ * io.c (more_char): clear readconv at EOF.
+
+ * test/ruby/test_file.rb: should not read after EOF. use rewind
+ instead.
+
+Wed Oct 29 20:45:08 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * test/webrick/utils.rb (start_server): provide a reference to log of
+ webrick.
+
+ * test/webrick/test_httpproxy.rb, test/webrick/test_httpauth.rb,
+ test/webrick/test_cgi.rb, test/webrick/test_httpserver.rb,
+ test/webrick/test_server.rb, test/webrick/test_filehandler.rb: use
+ webrick log as an assertion message.
+
+Wed Oct 29 16:41:17 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * pack.c (pack_pack): set encoding from packing string and UTF-8 for
+ "U". [ruby-core:19590]
+
+Wed Oct 29 15:50:00 2008 TAKANO Mitsuhiro (takano32) <tak@no32.tk>
+
+ * complex.c (imp1, imp2): should declare type.
+ [BUG] at IA-64
+
+Wed Oct 29 14:36:50 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk (revision.h): have to be updated daily or by non-trivial
+ commits.
+
+Wed Oct 29 13:18:02 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * README, README.ja: Update the portability section.
+
+Wed Oct 29 13:02:17 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * configure.in (rb_cv_lib_xpg4_needed): Drop legacy FreeBSD
+ support regarding libxpg4. Those old versions of FreeBSD
+ shipped with the library don't have a working pthread library
+ anyway.
+
+Wed Oct 29 11:50:57 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (dln-a-out): cannot make shared library nor work with
+ ELF. [ruby-core:19571]
+
+Wed Oct 29 11:00:25 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (rb_w32_open): shouldn't seek here.
+
+ * win32/win32.c (rb_w32_write): write to the end of the file when
+ FAPPEND is specified.
+
+Wed Oct 29 09:30:04 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ruby.c (load_file_internal): cache common interned IDs.
+
+Wed Oct 29 00:43:39 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * complex.c: uses macro in declarations.
+
+Wed Oct 29 00:26:00 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (rb_w32_open): need to seek to the end of the file when
+ O_APPEND is specified.
+
+Wed Oct 29 00:08:05 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * math.c (rb_math_{atan2,cos,cosh,hypot,log,sin,sinh,sqrt}): added.
+
+ * complex.c: follows the above change.
+
+Tue Oct 28 23:29:06 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/nkf/nkf-utf8/nkf.c (kanji_convert): output unicode chars.
+ [ruby-dev:36957]
+
+ * ext/nkf/nkf-utf8/nkf.c (numchar_getc): increase buffer size.
+ reported and patched at [ruby-dev:36957] by mame.
+
+Tue Oct 28 23:03:46 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * test/ruby/test_proc.rb: filled all patterns for testing
+ vm_yield_setup_args.
+
+Tue Oct 28 23:05:35 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * complex.c: continues to support canonicalization *unofficially*
+ for an odd library mathn for the time being (only 1.9.x).
+ since grand mathn must be very very special library for us.
+
+ * rational.c: ditto.
+
+ * ext/mathn/*/*: follow the above changes.
+
+Tue Oct 28 21:31:55 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * parse.y (parser_yylex): check EOF explicitly.
+
+Tue Oct 28 20:59:12 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * io.c (extract_binmode): new function to extract binmode/textmode
+ options from hash.
+
+ * io.c (rb_io_extract_modeenc): use above function.
+
+ * io.c (rb_io_s_pipe): recognize binmode/textmode options.
+
+Tue Oct 28 20:15:49 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * io.c (make_readconv): now can specify the size of cbuf.
+
+ * io.c (read_all, appendline, io_getc, rb_io_ungetc): follow above
+ change.
+
+Tue Oct 28 19:00:51 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (rb_w32_pipe_exec): internal fds should be always
+ binmode.
+
+Tue Oct 28 17:21:18 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * tool/make-snapshot.rb: merged from ruby_1_9_1.
+
+Tue Oct 28 16:56:31 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * gem_prelude.rb: merged from ruby_1_9_1 branch.
+ considers --program-suffix and prefix configure options.
+
+ * lib/rubygems/defaults.rb: ditto.
+
+ * test/rubygems/test_gem.rb (@default_dir_re): ditto.
+
+Tue Oct 28 16:13:36 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * tool/make-snapshot: use String#bytesize.
+
+Tue Oct 28 09:51:48 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * bootstraptest/test_thread.rb: ignore some exceptions.
+ [ruby-dev:36951]
+
+Tue Oct 28 09:19:40 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/Makefile.sub (RUNRUBY): now ruby requires something from
+ gem_prelude, so need to set library path.
+
+Mon Oct 27 22:29:11 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * vm_insnhelper.c (vm_yield_setup_args): supports optional parameters.
+ Fixed [ruby-core:19503].
+
+ * vm_insnhelper.c (vm_yield_setup_block_args): a new function. extracted
+ from vm_yield_setup_args.
+
+ * vm_insnhelper.c (vm_yield_setup_block_args_complex): ditto.
+
+ * test/ruby/test_proc.rb: added tests for arguments on a Proc from
+ Kernel#proc called.
+
+Mon Oct 27 20:03:05 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/mathn/complex/complex.c: no need to define rb_cComplex because
+ it's already defined at $(srcdir)/complex.c.
+
+ * ext/mathn/rational/rational.c: no need to define rb_cRational because
+ it's already defined at $(srcdir)/rational.c.
+
+Mon Oct 27 15:58:25 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ruby.c (load_file): preserves $.. [ruby-dev:36937]
+
+ * io.c (argf_init): initial value of $. should be 0.
+ see [ruby-dev:36937].
+
+Mon Oct 27 15:38:38 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * test/minitest/test_mini_test.rb
+ (test_assert_raises_triggered_different): the test failed when a
+ file path in the backtrace contontains something except [\w\/\.],
+ e.g. hyphen, Japanese characters or backslash.
+
+ * test/minitest/test_mini_test.rb
+ (test_assert_raises_triggered_subclass): ditto.
+
+Mon Oct 27 15:32:08 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * test/minitest/test_mini_test.rb: fixed that r19958 made
+ test-all fail when the ruby was built at $(srcdir).
+
+Mon Oct 27 12:04:58 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * test/ruby/envutil.rb: reverted the changeset 19948 because it
+ concealed unexpected behaviours of ruby.
+
+ * test/ruby/test_io.rb: ditto.
+
+Mon Oct 27 12:02:53 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * ext/nkf/nkf.c (rb_nkf_convert): should specify type of variable.
+
+Mon Oct 27 11:34:56 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * test/minitest/test_mini_test.rb (test_filter_backtrace):
+ fixed failure on Ruby built at out of $(srcdir).
+
+ * test/minitest/test_mini_test.rb (test_Filter_backtrace_unit_starts):
+ ditto.
+
+Mon Oct 27 10:02:47 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * io.c (read_all): the 3rd argument maybe Qnil.
+
+Mon Oct 27 01:29:55 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * test/nkf/test_nkf.rb: add a test for [ruby-dev:36909].
+
+Mon Oct 27 01:05:48 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/nkf/nkf.c (rb_nkf_convert): avoid GC.
+ reported in [ruby-dev:36909] and patched [ruby-dev:36941] by mame.
+
+Sun Oct 26 21:28:42 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * test/json/test_json.rb: remove dependency on permutation gem.
+
+Sun Oct 26 19:18:36 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * thread.c (blocking_region_{begin,end}): declared as inline.
+
+ * util.c (freedtoa): used only when MULTIPLE_THREADS is not defined.
+
+ * win32/win32.c (rb_w32_pipe): serial is DWORD.
+
+ * ext/etc/etc.c (sGroup): getgrent may not be available.
+
+Sun Oct 26 18:11:40 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/io/wait/{extconf.rb,wait.c}: needs sys/ioctl.h for fcntl on
+ cygwin.
+
+Sun Oct 26 18:18:39 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * gem_prelude.rb: disables debug and verbose flags to suppress failure
+ messages. interpolation does not occur inside single quotes.
+
+Sun Oct 26 18:42:21 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * test/ruby/envutil.rb (assert_in_out_err): disables builtin rubygems
+ to get rid of the interference.
+
+ * test/ruby/test_io.rb (ruby): ditto.
+
+Sun Oct 26 13:30:28 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * io.c (read_all): use the given buffer to read when needs readconv.
+ based on the patch by wanabe <s.wanabe AT gmail.com> at
+ [ruby-dev:36931].
+
+Sun Oct 26 07:57:35 2008 Eric Hodel <drbrain@segment7.net>
+
+ * lib/rubygems*: Update to RubyGems 1.3.1 r1909.
+
+Sun Oct 26 07:35:56 2008 Ryan Davis <ryand-ruby@zenspider.com>
+
+ * lib/minitest/unit.rb: Imported minitest 1.3.0 r4429.
+ * test/minitest/*: ditto.
+
+Sun Oct 26 02:16:29 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * configure.in ($MANTYPE): followed ruby.1, which had moved.
+
+ * instruby.rb (:man): ditto.
+
+ * mdoc2man.rb: fixed for the case Xr with 2 arguments.
+
+Sun Oct 26 01:42:45 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * man/irb.1: new manual page.
+
+Sun Oct 26 00:11:48 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * man/ruby.1: moved into man/. added some descriptions.
+
+ * man/goruby.1: new file.
+
+ * instruby.rb (:man): followed ruby.1.
+
+Sat Oct 25 20:05:22 2008 Narihiro Nakamura <authorNari@gmail.com>
+
+ * gc.c (gc_profile_result): bug fix. The millisecond is 1/1000.
+
+Sat Oct 25 11:12:40 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * ruby.c (usage): updated the description of -E option.
+
+Sat Oct 25 09:54:10 2008 James Edward Gray II <jeg2@ruby-lang.org>
+
+ * lib/csv.rb: Fixed a bug in read_to_char() that would slurp
+ whole files if the encoding was invalid. It will now read
+ up to 10 bytes ahead to find a valid character boundary or
+ give up. [ruby-core:19465]
+
+ * test/csv/test_features.rb, test/csv/test_table.rb, test/csv/test_row.rb:
+ Loosened some tests to check for a compatible? Encoding instead
+ of an exact Encoding. [ruby-core:19470]
+
+Sat Oct 25 07:42:49 2008 Eric Hodel <drbrain@segment7.net>
+
+ * lib/rdoc*: Update to RDoc 2.2.2 r192.
+
+Sat Oct 25 04:00:31 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * enc/us_ascii.c (us_ascii_mbc_enc_len): made static. a patch by
+ Tadashi Saito <shiba AT mail2.accsnet.ne.jp> at [ruby-dev:36916]
+
+ * signal.c (signal_buff): made static. a patch by Tadashi Saito
+ <shiba AT mail2.accsnet.ne.jp> at [ruby-dev:36915]
+
+ * util.c (freedtoa): made static to get rid of name clash. a patch by
+ Tadashi Saito <shiba AT mail2.accsnet.ne.jp> at [ruby-dev:36913]
+
+ * util.c (ruby_dtoa): added prefix, ditto.
+
+Sat Oct 25 03:43:25 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (lambda): need to adjust lpar_beg for both of the parser and
+ ripper.
+
+Sat Oct 25 01:29:34 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/mathn/rational/rational.c: undef duplicated macro definition
+ first to shut up the warning.
+
+ * ext/mathn/rational/rational.c (rb_rational_new_mathn): specify
+ omitted return value.
+
+Sat Oct 25 00:14:41 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * array.c (rb_ary_sample): fixed sizes and randomness.
+
+Fri Oct 24 23:04:42 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * configure.in (sitedir): considers --program-prefix and
+ --program-suffix.
+ (vendordir): ditto.
+ (rubyhdrdir): ditto.
+
+ * mkconfig.rb (CONFIG["rubylibdir"]): ditto.
+
+ * win32/Makefile.sub: ditto.
+
+ * instruby.rb (:rdoc): ditto.
+
+ * lib/rdoc/ri/paths.rb (RDoc::RI::Paths): ditto.
+
+Fri Oct 24 22:59:27 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * test/ruby/test_array.rb (test_sample): add tests for size of
+ returned array and randomness.
+
+Fri Oct 24 21:50:21 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * id.h, template/id.h.tmpl (enum ruby_method_ids): reordered.
+
+Fri Oct 24 21:19:45 2008 Keiju Ishitsuka <keiju@ruby-lang.org>
+
+ * ext/mathn/rational.c: change several global functions.
+
+Fri Oct 24 21:05:38 2008 Takeyuki FUJIOKA <xibbar@ruby-lang.org>
+
+ * lib/cgi/html.rb: allow symbolized key.
+
+ * test/cgi/test_cgi_tag_helper.rb: add a test.
+
+Fri Oct 24 20:54:53 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk (exts): renamed to get rid of the existent directory.
+
+Fri Oct 24 20:45:41 2008 Keiju Ishitsuka <keiju@ruby-lang.org>
+
+ * ext/mathn/rational.c: change several global functions to static
+ function.
+
+Fri Oct 24 19:57:19 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_dump): should have removed commented out
+ unnecessary code. [ruby-cvs:27131]
+
+Fri Oct 24 19:16:36 2008 URABE Shyouhei <shyouhei@ruby-lang.org>
+
+ * id.h (enum ruby_method_ids): ISO C forbids comma at end of
+ enumerator list.
+
+Fri Oct 24 18:29:00 2008 Keiju Ishitsuka <keiju@ruby-lang.org>
+
+ * lib/mathn.rb: moved into ext/mathn/rational/rational.c and
+ ext/mathn/complex/complex.c.
+ * ext/mathn: new mathn ext-libralies.
+
+Fri Oct 24 18:21:31 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * test/ruby/test_array.rb (TestArray#test_join): should restore
+ global variable after the test. [ruby-dev:36896]
+
+ * test/ruby/test_hash.rb (TestHash#test_to_s): ditto.
+
+Fri Oct 24 17:43:26 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (lambda): need to adjust lpar_beg for ripper as well.
+ [ruby-dev:36702]
+
+Fri Oct 24 16:13:12 2008 Takeyuki FUJIOKA <xibbar@ruby-lang.org>
+
+ * lib/cgi/core.rb (read_multipart): change field value as String
+ from StringIO or Tempfile when multipart parse except file field.
+ add files method that can get uploaded files. [ruby-dev:36547]
+
+ * test/cgi/test_cgi_multipart.rb: fix the test for core.rb.
+
+Fri Oct 24 14:22:48 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk (ext): split out the target for extension library.
+
+ * common.mk (encs): depends on enc and trans.
+
+Fri Oct 24 10:23:24 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * test/ruby/test_signal.rb (TestSignal#test_exit_action): Thread
+ may terminate before sysread. [ruby-dev:36835]
+
+Thu Oct 23 22:06:23 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * distruby.rb: removed. "make dist" uses tool/make-snapshot for the 1.9
+ series. distruby.rb has been no longer used.
+
+Thu Oct 23 17:30:29 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * class.c (rb_class_instance_methods): rdoc fixed. [ruby-core:19458]
+
+Thu Oct 23 16:19:33 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/irb/init.rb (IRB.load_modules): catch LoadError explicitly.
+ a patch from Daniel Berger <Daniel.Berger at qwest.com> in
+ [ruby-core:19451]. fix [ruby-core:19450]
+
+Thu Oct 23 16:16:17 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/socket/socket.c (sock_s_getservbyport): check if the port range.
+ [ruby-core:19460]
+
+Thu Oct 23 14:08:07 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/socket/socket.c (sock_s_getservbyname): unuse unnecessary
+ object.
+
+ * ext/socket/socket.c (sock_s_getservbyport): the port should be
+ converted before the proto so that the #to_int of the former cannot
+ alter the latter.
+
+Thu Oct 23 10:55:08 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_dump): use \u{ff} escape for UTF-8 encoding
+ string.
+
+Thu Oct 23 09:26:22 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * ext/socket/socket.c (sock_s_getservbyport): cast to get rid of
+ warning.
+
+Thu Oct 23 08:06:03 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/socket/socket.c (sock_s_getservbyport): port should be
+ network byte order. a patch from Dave Thomas in [ruby-core:19454].
+
+Thu Oct 23 01:26:25 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_conv_enc_opts): new function to convert with
+ specifying ecflags and ecopts.
+
+ * ext/zlib/zlib.c (gzfile_newstr): specify ecflags and ecopts for
+ conversion using above function.
+
+ * ext/zlib/zlib.c (gzfile_newstr): use own rb_econv_t for dummy
+ encoding to handling stateful encoding (e.g. iso-2022-jp).
+ [ruby-dev:36857]
+
+ * ext/zlib/zlib.c (gzfile_getc): ditto.
+
+Thu Oct 23 01:24:49 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (create_tmpsrc): get rid of side effects.
+
+Thu Oct 23 00:10:01 2008 Koichi Sasada <ko1@atdot.net>
+
+ * cont.c: separate data structure between rb_fiber_t and
+ rb_context_t (rb_fiber_t includes rb_context_t).
+ rb_fiber_t has double linked list of fibers in same threads.
+
+Wed Oct 22 17:25:17 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (pipe_open): remove unnecessary flush before fork.
+ a patch from Kazuhiro NISHIYAMA <zn at mbf.nifty.com>
+ in [ruby-dev:36840].
+
+Wed Oct 22 16:27:57 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * vm_insnhelper.c (vm_yield_setup_args): should not drop arguments
+ corresponding to default paramters.
+
+Wed Oct 22 14:59:30 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (f_larglist): should not allow semicolon separated local
+ variable declarations if formal argument list is not surrounded
+ by parentheses, mostly because semicolon outside of parentheses
+ appears to terminate the expression.
+
+Wed Oct 22 14:52:17 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_external_str_new_with_enc): no implicit strlen call.
+ [ruby-dev:36854]
+
+ * string.c (rb_external_str_new_cstr): new function to create
+ string from external NUL terminated C string.
+
+ * string.c (rb_locale_str_new_cstr): ditto.
+
+ * ext/readline/readline.c: now use rb_locale_str_new_cstr().
+
+ * test/sdbm/test_sdbm.rb (TestSDBM#test_delete_with_block):
+ deleted key to the block may be a copy of specified key.
+
+ * test/dbm/test_dbm.rb (TestDBM#test_delete_with_block): ditto.
+
+Wed Oct 22 13:16:47 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * re.c (unescape_escaped_nonascii): back out the last change on
+ the function. [ruby-dev:36818]
+
+Wed Oct 22 07:09:19 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/zlib/zlib.c (rb_gzreader_ungetc): should be able to unget
+ Fixnum.
+
+ * ext/stringio/stringio.c (strio_ungetc): should convert unget
+ string.
+
+ * ext/stringio/stringio.c (strio_ungetbyte): new method.
+
+Wed Oct 22 05:46:25 2008 Koichi Sasada <ko1@atdot.net>
+
+ * include/ruby/vm.h: write a comment.
+
+ * common.mk: remove vm.h from any rules.
+ vm.h is not needed on this version.
+
+ * vm_core.h: ditto.
+
+Wed Oct 22 05:39:39 2008 Koichi Sasada <ko1@atdot.net>
+
+ * parse.y (arg_concat_gen): concat target node should be NODE_ARRAY.
+ [ruby-core:19413]
+
+ * bootstraptest/test_method.rb: add tests.
+
+Wed Oct 22 00:29:13 2008 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * test/rinda/test_rinda.rb (test_core_03_notify): Fixed test failures
+ [ruby-dev:36837].
+
+Wed Oct 22 00:22:06 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_external_str_new_with_enc): wrong condition to
+ calculate strlen().
+
+ * ext/readline/readline.c: add encoding support.
+
+Tue Oct 21 23:12:24 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/stringio/stringio.c (strio_write): should convert writing
+ string to the encoding of the buffer.
+
+ * hash.c (rb_any_hash): typo fixed.
+
+ * ext/zlib/zlib.c (rb_gzwriter_write): oops, IO string conversion
+ need to be done by to_s.
+
+Tue Oct 21 22:38:58 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (open_key_args): should adjust argc, argv in struct
+ foreach_arg.
+
+Tue Oct 21 21:52:00 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/zlib/zlib.c (rb_gzwriter_write): conversion should be done
+ using to_str, not to_s.
+
+ * ext/zlib/zlib.c (rb_gzwriter_write): need proper conversion
+ according to gz encoding.
+
+ * ext/zlib/zlib.c (rb_gzreader_ungetc): convert string encoding
+ before unget.
+
+Tue Oct 21 21:33:36 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/test/unit.rb (assert_nothing_raised): raise with backtrace.
+
+Tue Oct 21 20:12:19 2008 Tanaka Akira <akr@fsij.org>
+
+ * lib/test/unit.rb (assert_nothing_raised): set backtrace.
+
+Tue Oct 21 18:17:42 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/zlib/zlib.c: remove obsolete prototype macros.
+
+ * ext/zlib/zlib.c (struct gzfile): add encoding field to gzfile
+ structure.
+
+ * ext/zlib/zlib.c (rb_gzreader_getc): now works on characters.
+
+ * ext/zlib/zlib.c (rb_gzreader_getbyte): new method to retrieve
+ single byte.
+
+ * ext/zlib/zlib.c (rb_gzreader_readbyte): ditto.
+
+ * ext/zlib/zlib.c (rb_gzreader_each_byte): renamed from each_char
+
+ * ext/zlib/zlib.c (rb_gzreader_ungetc): allow unget strings.
+
+ * ext/zlib/zlib.c (rb_gzreader_ungetbyte): renamed from ungetc.
+
+Tue Oct 21 13:28:42 2008 Shugo Maeda <shugo@ruby-lang.org>
+
+ * io.c, include/ruby/intern.h (rb_io_ascii8bit_binmode): externed.
+
+ * ext/socket/socket.c (init_sock): use rb_io_ascii8bit_binmode()
+ instead of rb_io_binmode().
+
+Tue Oct 21 13:17:39 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * mdoc2man.rb: moved into tools/.
+
+ * instruby.rb: followed the change of mdoc2man.
+
+Tue Oct 21 11:34:04 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/iconv/iconv.c (strip_glibc_option, map_charset): check if
+ encoding is a string. based on the patch by Hiroshi Moriyama at
+ [ruby-dev:36811].
+
+ * test/iconv/test_basic.rb (test_invalid_arguments): added tests.
+
+Tue Oct 21 10:40:37 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * io.c (rb_file_open_internal): should initialize fmode before using.
+
+Tue Oct 21 08:56:37 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * regparse.c (parse_char_class): CCV_SB is only for single
+ byte. [ruby-dev:36786]
+
+Tue Oct 21 01:49:55 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_io_extract_modeenc): plain rb/wb should set ASCII-8BIT
+ to the external_encoding.
+
+ * io.c (rb_file_open_internal): ditto.
+
+ * io.c (NEED_WRITECONV): no conversion when the external_encoding
+ is ASCII-8BIT.
+
+ * io.c (do_writeconv): skip ASCII-8BIT.
+
+Tue Oct 21 00:51:59 2008 Tanaka Akira <akr@fsij.org>
+
+ * io.c (rb_io_ascii8bit_binmode): renamed from rb_io_binmode.
+ (rb_io_binmode): don't change encoding conversion.
+ (rb_io_binmode_m): call rb_io_ascii8bit_binmode.
+
+Mon Oct 20 21:19:00 2008 Takeyuki FUJIOKA <xibbar@ruby-lang.org>
+
+ * lib/cgi/core.rb (read_multipart): file's encoding is ascii-8bit
+ from file field of multipart form.
+
+Mon Oct 20 20:16:25 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/zlib/zlib.c (Init_zlib): add getbyte as an alias to getc.
+ [ruby-dev:36801]
+
+Mon Oct 20 17:31:17 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * error.c (exc_equal): should not compare recursively.
+ [ruby-dev:36796]
+
+Mon Oct 20 16:48:43 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * include/ruby/ruby.h (ExportStringValue): new macro to convert
+ string in internal encoding to external to export.
+
+ * string.c (rb_str_export): new function to do conversion to
+ external encoding.
+
+ * ext/sdbm/init.c: encoding conversion support.
+
+ * ext/dbm/dbm.c: ditto.
+
+Mon Oct 20 15:42:02 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_locale_str_new): new function to convert string
+ from locale to internal encoding.
+
+Mon Oct 20 09:47:13 2008 Tanaka Akira <akr@fsij.org>
+
+ * test/runner.rb: search srcdir/test/arg at first to find test/ruby
+ directory when "ruby" is specified.
+
+Mon Oct 20 08:20:01 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
+
+ * ext/tk/lib/tk.rb: support Encoding.default_internal.
+
+ * ext/tk/tcltklib.c: ditto.
+
+ * ext/tk/extconf.rb: improve the strategy for searching Tcl/Tk headers.
+
+Mon Oct 20 00:57:04 2008 Tanaka Akira <akr@fsij.org>
+
+ * lib/test/unit.rb (Test::Unit.setup_argv): call given block for
+ filtering files.
+
+ * test/runner.rb: search srcdir/test/arg, srcdir/arg.
+
+ * bin/testrb: show usage if no files given.
+
+Sun Oct 19 21:19:16 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk (srcs): removed ID_H_TARGET.
+
+ * tool/generic_erb.rb: always overwrites if no if-change option.
+ sends the result to stdout if no output option.
+
+ * template/id.h.tmpl: shows which token differs.
+
+Sun Oct 19 18:15:15 2008 Martin Duerst <duerst@it.aoyama.ac.jp>
+
+ * enc/trans/single_byte.trans: adding WINDOWS-wwww encodings
+ (wwww = 874/1250/1251/1253/1254/1255/1256/1257)
+ (contributed by Yoshihiro Kambayashi)
+
+ * enc/trans/windows-wwww-tbl.rb: 8 new files
+ (contributed by Yoshihiro Kambayashi)
+
+ * test/ruby/test_transcode.rb: added test_windows_wwww
+ (contributed by Yoshihiro Kambayashi)
+
+Sun Oct 19 07:37:13 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/cmath.rb (log2,cbrt,frexp,ldexp,hypot,erf,erfc,gamma,lgamma):
+ should be also provided as module function. [ruby-dev:36787]
+
+Sun Oct 19 07:25:08 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * keywords, lex.c.src, opt_insn_unif.def, opt_operand.def: moved rarely changed
+ input files for code generators into defs/ directory.
+
+ * Makefile.in (lex.c): followed keywords and lex.c.src.
+
+ * common.mk (parser.o): followed keywords.
+ (INSNS): followed opt_*.def
+
+ * tools/instruction.rb: followed opt_*.def.
+
+Sun Oct 19 12:28:01 2008 James Edward Gray II <jeg2@ruby-lang.org>
+
+ * test/csv/*: Renamed tc_* files to test_* to fit in within Ruby's
+ testing process.
+
+Sun Oct 19 00:15:03 2008 Tanaka Akira <akr@fsij.org>
+
+ * lib/test/unit.rb (assert_nothing_thrown): don't intern.
+
+Sat Oct 18 14:40:32 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * numeric.c (num_sadded): remove newly defined singleton method
+ that should not exist after exception handling. [ruby-dev:36569]
+
+Sat Oct 18 14:27:49 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (opt_block_arg): allow trailing comma after usual
+ arguments. not after block argument.
+
+Sat Oct 18 13:30:53 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_external_str_new): a new function to convert from
+ external encoding to internal encoding. if something went
+ wrong, it returns a string with the external encoding.
+
+ * string.c (rb_external_str_new_with_enc): same as above besides
+ you can specify the source encoding.
+
+ * ruby.c (ruby_set_argv): use rb_external_str_new()
+
+ * ruby.c (set_arg0, ruby_script): ditto.
+
+Sat Oct 18 04:08:18 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/tempfile.rb (Tempfile#initialize): now Tempfile.new takes
+ keyword arguments to open(). [ruby-dev:36756]
+
+Sat Oct 18 17:10:10 2008 Martin Duerst <duerst@it.aoyama.ac.jp>
+
+ * tool/transcode-tblgen.rb: added set_valid_byte_pattern
+ to reduce coupling between table generation script and
+ specific encodings.
+
+ * enc/trans/single_byte.trans: using set_valid_byte_pattern
+
+Sat Oct 18 16:39:39 2008 Martin Duerst <duerst@it.aoyama.ac.jp>
+
+ * transcode.c: in transcode_search_path, eliminated a warning
+ on cygwin about pathlen potentially not being initialized
+
+Sat Oct 18 13:40:27 2008 Tanaka Akira <akr@fsij.org>
+
+ * lib/test/unit.rb (assert_nothing_thrown): implemented.
+
+Sat Oct 18 01:33:22 2008 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * common.mk: use added options for generic_erb.rb.
+
+Sat Oct 18 00:47:51 2008 wanabe <s.wanabe@gmail.com>
+
+ * array.c: don't recycle shared-array while sort!.
+
+Fri Oct 17 22:04:38 2008 wanabe <s.wanabe@gmail.com>
+
+ * array.c: recycle shared-array when it isn't referenced.
+
+Fri Oct 17 20:29:26 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * re.c (rb_reg_initialize_m): specify ARG_ENCODING_NONE instead of
+ ARG_ENCODING_FIXED for Regexp.new("", nil, "n"). [ruby-dev:36761]
+
+ * test/ruby/test_regexp.rb (TestRegexp#test_initialize): test
+ updated.
+
+Fri Oct 17 19:46:20 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * tool/ifchange, win32/ifchange.bat: --timestamp option added.
+
+ * tool/generic_erb.rb: --timestamp, --output and --if-change options
+ added.
+
+Fri Oct 17 18:33:12 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * array.c (ary_resize_capa): renamed RESIZE_CAPA.
+
+Fri Oct 17 18:16:51 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * test/bigdecimal/test_bigdecimal.rb (TestBigDecimal#test_sqrt_bigdecimal):
+ test updated. a patch from TAKANO Mitsuhiro <takano32 at jus.or.jp> in
+ [ruby-dev:36736].
+
+Fri Oct 17 18:14:57 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * configure.in (uncommon.mk): ignores failures at loading.
+
+ * test/rubygems/gemutilities.rb (RubyGemTestCase#build_rake_in):
+ get rid of interference with other tests.
+
+Fri Oct 17 18:06:39 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * transcode.c (str_transcode0): String#encode without argument now
+ behave as if :undef => :replace, :invalid => :replace specified.
+
+ * transcode.c (rb_econv_prepare_opts): should preserve options in
+ any case.
+
+Fri Oct 17 11:48:18 2008 Shugo Maeda <shugo@ruby-lang.org>
+
+ * ext/socket/socket.c (init_sock): sockets should be binmode.
+
+ * test/socket/test_tcp.rb (test_encoding): ditto.
+
+Fri Oct 17 10:26:13 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * tool/insns2vm.rb: remove -Kn option in shebang line because it's
+ inconsistent with -Ks commandline option in common.mk.
+
+Fri Oct 17 01:26:09 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode.c (transcode_restartable0): in_pos and out_pos never be
+ NULL, now.
+
+Fri Oct 17 00:39:19 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * lib/test/unit.rb: sort the order of executing tests.
+
+Fri Oct 17 00:24:15 2008 Tanaka Akira <akr@fsij.org>
+
+ * io.c (rb_io_binmode): reset encoding conversion.
+
+Fri Oct 17 00:16:08 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * io.c (rb_getc, rb_io_fread, rb_io_fwrite, rb_read_pending):
+ remove deprecated functions which do not work. [ruby-dev:36697]
+
+Thu Oct 16 23:48:34 2008 Tanaka Akira <akr@fsij.org>
+
+ * common.mk (TESTS): removed to re-enable test for minitest.
+
+Thu Oct 16 23:37:11 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * compile.c (iseq_set_sequence): fix memory leak.
+
+Thu Oct 16 23:27:27 2008 Tanaka Akira <akr@fsij.org>
+
+ * lib/test/unit.rb (assert_equal): avoid incompatible character
+ encodings error.
+
+Thu Oct 16 23:23:27 2008 Tanaka Akira <akr@fsij.org>
+
+ * lib/test/unit.rb (assert_equal): failure message changed.
+
+Thu Oct 16 22:52:54 2008 Tanaka Akira <akr@fsij.org>
+
+ * lib/test/unit: removed test/unit.
+
+ * lib/test/unit.rb: new compatibility layer using minitest.
+
+ * bin/testrb: use above.
+
+ * test/runner.rb: ditto.
+
+Thu Oct 16 14:34:16 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk, enc/depend (enc, trans): targets for sources.
+
+Thu Oct 16 14:30:30 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * instruby.rb (lib): installs all files other than README etc.
+
+Thu Oct 16 09:48:03 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * re.c (rb_reg_initialize_m): changed the message to clarify the
+ third option argument is now ignored. [ruby-dev:36753]
+
+Thu Oct 16 08:14:39 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ruby.c (proc_options): no warning when default_external already
+ set by -E.
+
+ * test/ruby/test_rubyoptions.rb (TestRubyOptions#test_rubyopt):
+ put -K after -E to set script encoding.
+
+Thu Oct 16 06:20:36 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * test/ruby/test_transcode.rb (TestTranscode#test_errors):
+ String#encode now works without any argument. [ruby-dev:36740]
+
+Wed Oct 15 23:48:22 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * .gdbinit (rp): REGEXP handling fixed.
+
+ * string.c (rb_str_rindex_m): need not to call rb_enc_check on
+ regexp.
+
+ * re.c (unescape_escaped_nonascii): try ASCII-8BIT encoding for
+ broken strings.
+
+Wed Oct 15 23:11:10 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/delegate.rb (DelegateClass): restored 1.8 behavior for
+ DelegateClass as well. [ruby-dev:36739]
+
+Wed Oct 15 22:19:14 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * array.c (RESIZE_CAPA): check whether len is longer than capacity.
+
+ * array.c (rb_ary_compact_bang): resize ary before changing capacity.
+ fixed [ruby-dev:36704]
+
+Wed Oct 15 16:57:30 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * version.h (RUBY_DESCRIPTION): remove unnecessary space.
+
+Tue Oct 14 23:18:15 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/delegate.rb (Delegator): simplified and restored 1.8
+ behavior. [ruby-dev:35986]
+
+Tue Oct 14 21:50:40 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk (TESTS): skips minitest by default, since it interferes
+ with test/unit.
+
+Tue Oct 14 21:36:29 2008 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c (load_conv_function51932): check
+ having IMultiLanguage2 or IMultiLanguage. [ruby-dev:36716]
+
+ * ext/win32ole/extconf.rb: ditto.
+
+Tue Oct 14 20:45:29 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * io.c (Init_IO): $FILENAME and $* must be read-only. [ruby-dev:36698]
+
+ * variable.c (*_getter, *_setter, *_marker): made public.
+
+ * include/ruby/ruby.h (rb_gvar_*_{getter,setter,marker}): declared.
+
+Tue Oct 14 20:32:09 2008 Tanaka Akira <akr@fsij.org>
+
+ * enc/trans/single_byte.trans (transcode_tblgen_singlebyte): renamed
+ from transcode_tblgen_windows.
+ (transcode_tblgen_iso8859): use transcode_tblgen_singlebyte.
+
+Tue Oct 14 19:32:14 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ruby.c (process_options): -U should be allowed in RUBYOPT
+ environment variable. [ruby-dev:36720]
+
+Tue Oct 14 14:11:17 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ruby.c (proc_options): -U can be followed by other options.
+
+Tue Oct 14 13:30:30 2008 Martin Duerst <duerst@it.aoyama.ac.jp>
+
+ * enc/trans/single_byte.trans: added windows-1252
+
+ * enc/trans/windows-1252-tbl.rb: new file
+ (contributed by Yoshihiro Kambayashi)
+
+ * tool/transcode-tblgen.rb: listed windows-1252 as '1byte'
+
+ * test/ruby/test_transcode.rb: added test_windows_1252
+ (contributed by Yoshihiro Kambayashi)
+
+Tue Oct 14 12:22:32 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * test/ruby/test_variable.rb (TestVariable#test_variable): add
+ a test of [ruby-dev:36698].
+
+Tue Oct 14 11:14:29 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * transcode.c (str_transcode0): should not raise error when
+ default_internal is not set. [ruby-core:19309]
+
+Tue Oct 14 11:14:26 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * lib/net/pop.rb: check for invalid APOP timestamp. (CVE-2007-1558)
+ [ruby-dev:36631]
+
+ * test/net/pop/test_pop.rb: ditto.
+
+Tue Oct 14 09:39:32 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ruby.c (set_internal_encoding_once): check double contradicted
+ specification of the encoding from command line.
+
+ * ruby.c (set_external_encoding_once): ditto.
+
+Tue Oct 14 08:28:31 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (parser_yylex): allow reserved word to be keyword argument.
+
+Mon Oct 13 19:07:52 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * parse.y (token_info_pop): show source filename. [ruby-dev:36710]
+
+Mon Oct 13 08:59:08 2008 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c (load_conv_function51932): support
+ CP51932 on cygwin and mingw32. thanks to arton.
+
+ * test/win32ole/test_win32ole.rb (test_cp51932): ditto.
+
+Mon Oct 13 07:54:00 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ruby.c (proc_options): add -U command line option to specify
+ utf-8 as default_internal.
+
+Mon Oct 13 07:42:57 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * transcode.c (str_transcode0): String#encode() with no encoding
+ specified transcode the string into Encoding.default_internal.
+ inspired by [ruby-core:19298].
+
+Sun Oct 12 18:00:18 2008 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c (set_ole_codepage, ole_cp2encoding,
+ ole_wc2mb, ole_vstr2wc, ole_mb2wc): support CP51932 (only mswin32).
+
+ * test/win32ole/test_win32ole.rb: ditto.
+
+Sun Oct 12 12:03:38 2008 Koichi Sasada <ko1@atdot.net>
+
+ * vm.c, vm_insnhelper.h (ruby_vm_redefined_flag): apply optimization
+ patch proposed by Paul Brannan. [ruby-core:19171]
+
+Sun Oct 12 09:46:36 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * strftime.c (rb_strftime): suppressed warnings on cygwin.
+
+Sat Oct 11 19:49:35 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (parser_prepare): use utf-8 encoding directly.
+
+Sat Oct 11 10:20:17 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb (CLEANINGS): uses escaped form tabs to preventing the
+ confusion. [ruby-talk:317345]
+
+Sat Oct 11 08:51:13 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/rake.rb (Rake::Application#standard_exception_handling): removed
+ unnecessary SystemExit, and exits with false instead of system
+ dependent value. [ruby-talk:317330]
+
+Sat Oct 11 03:54:05 2008 Koichi Sasada <ko1@atdot.net>
+
+ * parse.y: optimize 'for' statement when one variable given.
+
+ * benchmark/bm_loop_for.rb: added.
+
+ * benchmark/bm_loop_times.rb: modified.
+
+Sat Oct 11 12:09:05 2008 James Edward Gray II <jeg2@ruby-lang.org>
+
+ * lib/csv/csv.rb: Added support for Encoding::default_internal.
+ * lib/csv/csv.rb: Switched to new Hash syntax.
+
+Fri Oct 10 22:16:55 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (comment_at_top): needed for ripper too.
+
+Fri Oct 10 22:07:05 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * include/ruby.h: updated macros for headers. [ruby-core:19275]
+
+Fri Oct 10 19:21:50 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (magic_comment_encoding): warns when ignored.
+
+ * parse.y (parser_magic_comment): replaces '-' with '_'.
+
+ * parse.y (parser_yylex): allows magic comments indented and the
+ second line or later.
+
+Fri Oct 10 17:26:50 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/json/ext/parser/parser.c (JSON_parse_string):
+ associate encoding.
+
+Fri Oct 10 10:18:21 2008 Ryan Davis <ryan@wrath.local>
+
+ * lib/test/*: reverted back to test/unit.
+ * test/test/*: ditto
+ * lib/minitest/*: Imported minitest 1.3.0 r4333.
+
+Fri Oct 10 03:41:31 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * sprintf.c (rb_str_format): check if codepoint for %c is valid.
+ [ruby-dev:36691]
+
+Fri Oct 10 01:55:48 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * encoding.c (enc_names): minor improvement.
+
+Fri Oct 10 00:21:39 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/optparse.rb (ParseError.filter_backtrace): removes internal
+ backtrace.
+
+Fri Oct 10 00:11:16 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * transcode.c (rb_econv_add_converter): remove unnecessary NULL check.
+
+Thu Oct 9 23:53:23 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * misc/ruby-style.el (ruby-style-c-mode): buffer may not have file
+ name.
+
+Thu Oct 9 23:30:47 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * process.c (run_exec_dup2): fix resource leak.
+
+Thu Oct 9 23:19:02 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * process.c (rb_run_exec_options): fix resource leak.
+
+Thu Oct 9 22:13:58 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * test/ruby/test_module.rb (test_remove_class_variable): add a test
+ for Class#remove_class_variable.
+
+ * test/ruby/test_object.rb (test_remove_instance_variable): add a test
+ for Object#remove_instance_variable.
+
+Thu Oct 9 22:04:38 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * variable.c (rb_mod_remove_cvar): fix r19711.
+
+Thu Oct 9 21:17:50 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * ext/syck/syck.c (syck_lookup_sym): remove reading uninitialized
+ variable.
+
+Thu Oct 9 16:34:15 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/json/ext/generator/extconf.rb: fix target.
+
+ * ext/json/ext/parser/extconf.rb: ditto.
+
+Thu Oct 9 14:37:59 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * include/ruby/ruby.h: embeds the elements of an array into its
+ struct RArray for # of elements <= 3.
+
+ * array.c: ditto.
+
+ * gc.c (gc_mark_children): following the change of struct RArray.
+
+ * ext/tk/tcltklib.c (ip_ruby_cmp): ditto.
+
+ * parse.y (coverage): ditto.
+
+ * proc.c (curry): ditto.
+
+ * .gdbinit: ditto.
+
+Thu Oct 9 11:29:33 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * encoding.c (Init_Encoding): new instance method Encoding#names,
+ returns its name and alias names.
+
+ * encoding.c (enc_names): defined for Encoding#names.
+
+ * encoding.c (enc_names_i): defined for enc_names.
+
+Thu Oct 9 08:47:38 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * thread.c (rb_thread_wait_fd_rw): should not block by select if
+ there's only one thread living. fixed [ruby-dev:36646].
+
+Wed Oct 8 20:59:52 2008 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c (ole_init_cp): initialize WIN32OLE.codepage
+ according to Encoding.default_internal and
+ Encoding.default_external.
+
+Wed Oct 8 17:02:21 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/json/lib/json/pure/generator.rb (utf8_to_json):
+ process each unpacked Unicode character.
+
+Wed Oct 8 15:00:22 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/json/lib/json/pure/parser.rb
+ (JSON::Pure::Parser#parse_string): force_encoding("UTF-8").
+
+Wed Oct 8 11:56:15 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * lib/test/unit/assertions.rb: assert_nothing_thrown,
+ assert_raise, assert_not_equal, assert_no_match, assert_not_nil,
+ assert_not_same are coming back as alias.
+
+Wed Oct 8 11:18:12 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * variable.c (autoload_delete, autoload_file): should not delete
+ autoload table, since it may be shared with duplicated modules.
+ [ruby-core:19181]
+
+Wed Oct 8 02:38:28 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * encoding.c (rb_default_internal_encoding): merged a patch from
+ Michael Selig <michael.selig at fs.com.au> in [ruby-core:18985].
+
+ * io.c (rb_io_ext_int_to_encs): ditto.
+
+ * ruby.c (proc_options): support default internal encoding in -E
+ option.
+
+Wed Oct 8 00:03:39 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date.rb (today,now): should produce own instances.
+ [ruby-talk:317020]
+
+Tue Oct 7 16:43:51 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/json/lib/json/pure/generator.rb (utf8_to_json):
+ force_encoding before gsub.
+
+Tue Oct 7 16:35:41 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/json/lib/json/pure/generator.rb (utf8_to_json):
+ downcase the result of Unicode escape.
+
+Mon Oct 6 16:44:52 2008 Takeyuki FUJIOKA <xibbar@ruby-lang.org>
+
+ * lib/cgi/core.rb (CGI::QueryExtension::initialize_query): fix the
+ condition.
+
+ * test/cgi/test_cgi_core.rb: bug fix encoding.
+ thanks to TAKANO Mitsuhiro <takano32 at jus.or.jp> .
+
+ * test/cgi/test_cgi_multipart.rb: temporary comment in.
+
+Mon Oct 6 15:22:08 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * gc.c (gc_mark_children): ignores T_ZOMBIE.
+
+Mon Oct 6 12:45:20 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * test/ruby/test_module.rb (TestModule#_wrap_assertion): add
+ definition. is this really needed?
+
+ * test/ruby/test_module.rb (TestModule#test_mod_constants): should
+ not depend on global Module constants.
+
+Mon Oct 6 12:38:36 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/test/unit/assertions.rb (Test::Assertions#assert_nothing_raised):
+ should take optional message argument.
+
+Mon Oct 6 12:18:23 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_comparable): string comparison should be
+ transitive. [ruby-dev:36484]
+
+ * test/ruby/test_m17n_comb.rb (TestM17NComb#test_str_eq): test
+ updated.
+
+Mon Oct 6 09:00:58 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * test/bigdecimal/test_bigdecimal.rb (test_sqrt_bigdecimal): test
+ updated. a patch from TAKANO Mitsuhiro <takano32 at jus.or.jp>
+ in [ruby-dev:36669].
+
+Sun Oct 5 23:34:28 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mkmf.rb ($config_h): now always defines for old libraries.
+
+Sun Oct 5 23:06:55 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * vm_method.c (rb_mod_modfunc): method undefined in included module
+ may not have nd_body. [ruby-core:18738]
+
+Sun Oct 5 21:28:58 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/rational.rb: resolved conflicts of aliases.
+
+ * lib/mathn.rb: avoided some warnings.
+
+Sun Oct 5 18:51:50 2008 Tanaka Akira <akr@fsij.org>
+
+ * lib/open-uri.rb: remove debug code introduced by previous change.
+
+Sun Oct 5 17:49:35 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * lib/open-uri.rb (OpenURI.open_uri): set encoding to strio.
+
+Sun Oct 5 17:39:21 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/stringio/stringio.c (strio_set_encoding): defined for
+ StringIO#set_encoding.
+
+Sun Oct 5 11:24:42 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * eval.c: come back definition of environ.
+
+Sun Oct 5 09:19:49 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/nkf/nkf-utf8/utf8tbl.c: update table.
+
+Sat Oct 4 22:50:14 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * dln.c: Ruby no longer supports VMS.
+
+ * error.c: ditto.
+
+ * eval.c: ditto.
+
+ * eval_intern.h: ditto.
+
+ * include/ruby/defines.h: ditto.
+
+ * include/ruby/ruby.h: ditto.
+
+ * io.c: ditto.
+
+ * process.c: ditto.
+
+ * ruby.c: ditto.
+
+ * vms/config.h: removed.
+
+ * vms/vms.h: ditto.
+
+ * vms/vmsruby_private.c: ditto.
+
+ * vms/vmsruby_private.h: ditto.
+
+Sat Oct 4 22:44:23 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * dln.c: Ruby no longer supports Windows CE.
+
+ * eval.c: ditto.
+
+ * include/ruby/defines.h: ditto.
+
+ * include/ruby/win32.h: ditto.
+
+ * ruby.c: ditto.
+
+ * strftime.c: ditto.
+
+ * win32/Makefile.sub: ditto.
+
+ * win32/win32.c: ditto.
+
+ * ext/tk/extconf.rb: ditto.
+
+ * lib/fileutils.rb: ditto.
+
+ * test/fileutils/test_fileutils.rb: ditto.
+
+ * wince/*: removed.
+
+Sat Oct 4 22:35:06 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * dln.c: Ruby no longer supports MacOS 9 or before.
+
+ * eval.c: ditto.
+
+ * eval_intern.h: ditto.
+
+ * ext/extmk.rb: ditto.
+
+ * ext/tk/sample/tkextlib/treectrl/demo.rb: ditto.
+
+ * ext/tk/stubs.c: ditto.
+
+ * file.c: ditto.
+
+ * hash.c: ditto.
+
+ * include/ruby/defines.h: ditto.
+
+ * ruby.c: ditto.
+
+ * signal.c: ditto.
+
+ * vm_core.h: ditto.
+
+Sat Oct 4 22:30:28 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * dln.c: Ruby no longer supports MS-DOS.
+
+ * ext/sdbm/_sdbm.c: ditto.
+
+ * ext/sdbm/sdbm.h: ditto.
+
+ * gc.c: ditto.
+
+ * hash.c: ditto.
+
+ * include/ruby/defines.h: ditto.
+
+ * include/ruby/util.h: ditto.
+
+ * io.c: ditto.
+
+ * process.c: ditto.
+
+ * ruby.c: ditto.
+
+ * strftime.c: ditto.
+
+ * util.c: ditto.
+
+Sat Oct 4 22:14:15 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * djgpp/GNUmakefile.in: removed. Ruby no longer supports djgpp.
+
+ * djgpp/README.djgpp: ditto.
+
+ * djgpp/config.hin: ditto.
+
+ * djgpp/config.sed: ditto.
+
+ * djgpp/configure.bat: ditto.
+
+ * djgpp/mkver.sed: ditto.
+
+ * ext/Setup.dj: ditto.
+
+ * dln.c: removed djgpp supports.
+
+ * file.c: ditto.
+
+ * gc.c: ditto.
+
+ * io.c: ditto.
+
+ * process.c: ditto.
+
+ * ruby.c: ditto.
+
+ * signal.c: ditto.
+
+ * util.c: ditto.
+
+ * vm_core.h: ditto.
+
+ * lib/fileutils.rb: ditto.
+
+ * lib/mkmf.rb: ditto.
+
+ * ext/socket/socket.c: ditto.
+
+ * test/fileutils/test_fileutils.rb: ditto.
+
+ * test/ruby/test_env.rb: ditto.
+
+ * test/ruby/test_path.rb: ditto.
+
+Sat Oct 4 21:59:39 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * x68/_dtos18.c: removed. Ruby no longer supports human68k.
+
+ * x68/_round.c: ditto.
+
+ * x68/fconvert.c: ditto.
+
+ * x68/select.c: ditto.
+
+ * ext/Setup.x68: ditto.
+
+ * missing/x68.c: ditto.
+
+ * dln.c (dln_find_exe_r): removed human68k supports.
+ (dln_find_1): ditto.
+
+ * lib/mkmf.rb: ditto.
+
+ * ext/extmk.rb (Init_ext): ditto.
+
+ * ext/socket/socket.c (init_sock): ditto.
+
+ * gc.c (GC_MALLOC_LIMIT): ditto.
+ (rb_setjmp, rb_jmpbuf): ditto.
+ (mark_current_machine_context): ditto.
+
+ * include/ruby/defines.h (PATH_ENV): ditto.
+
+ * io.c: ditto.
+
+ * process.c: ditto.
+
+ * ruby.c: ditto.
+
+ * test/ruby/test_env.rb: ditto.
+
+ * test/ruby/test_path.rb: ditto.
+
+ * LEGAL
+
+Sat Oct 4 19:02:36 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/date/format.rb: no need to require the "lib/rational.rb".
+
+Sat Oct 4 19:02:59 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/nkf/nkf.c (rb_nkf_enc_get): don't replicate encoding.
+ [ruby-dev:36575]
+
+Sat Oct 4 18:47:22 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/stringio/stringio.c (strio_external_encoding): defined.
+
+ * ext/stringio/stringio.c (strio_internal_encoding): defined.
+
+ * ext/stringio/stringio.c (Init_stringio): define above.
+
+Sat Oct 4 15:52:17 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * test/mini/test_mini_test.rb: recovered.
+ It had been temporarily removed at r19645.
+
+ * test/mini/test_mini_mock.rb: ditto.
+
+ * test/mini/test_mini_spec.rb: ditto.
+
+ * lib/test/**/*: replaced by miniunit.
+ miniunit had been temporarily reverted at r19643 but
+ now recovered.
+
+Sat Oct 4 15:33:26 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * common.mk (gdb-ruby): new target. it runs ruby under controlled by
+ gdb.
+
+ * common.mk (dist): accepts RELNAME variable as the second argument of
+ make-snapshot.rb.
+
+Sat Oct 4 12:17:46 2008 Keiju Ishitsuka <keiju@ruby-lang.org>
+
+ * lib/irb/irb/ext/save-history.rb: change load_history using File.expand_path. see [ruby-dev:36660]. Thanks Kouhei Sutou.
+ * lib/irb/irb/context.rb: convert string Symbol of instance variable names in IRB:Context#inspect.
+
+Fri Oct 3 22:43:04 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * ext/dl/extconf.rb ($distcleanfiles): added callback-?.c into
+ the distclean list.
+
+Fri Oct 3 19:33:21 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/json/lib/json/pure.rb (module JSON): remove Iconv dependency.
+
+ * ext/json/lib/json/pure/generator.rb (utf8_to_json): process as
+ binary and remove Iconv dependency.
+
+ * ext/json/lib/json/pure/parser.rb (parse_string): ditto.
+
+Fri Oct 3 14:04:05 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/{configure.bat,setup.mak,Makefile.sub): add --program-prefix
+ configure option support.
+
+Thu Oct 2 21:22:43 2008 Takeyuki FUJIOKA <xibbar@ruby-lang.org>
+
+ * lib/cgi/core.rb (CGI::QueryExtension): delete MorphingBody
+ and replace like as 1.8's in multipart reading.
+ see [ruby-dev:36443],
+ reference from CGIAlt http://cgialt.rubyforge.org/
+
+ * test/cgi/test_cgi_multipart.rb : fixed multipart test.
+
+Thu Oct 2 20:46:17 2008 Tanaka Akira <akr@fsij.org>
+
+ * string.c (rb_str_sub_bang): fix coderange.
+
+Wed Oct 1 22:54:09 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * lib/rexml/parsers/lightparser.rb, lib/debug.rb: remove unused when
+ clauses.
+
+Wed Oct 1 22:43:59 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * lib/xmlrpc, lib/rexml, test/ruby/test_array.rb,
+ test/ruby/test_unicode_escape.rb, test/scanf/test_scanf.rb,
+ test/rss/rss-assertions.rb: fix indentation to remove warning.
+
+Wed Oct 1 21:36:35 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * gc.c (rb_gc_call_finalizer_at_exit): finalize deferred IO and Data.
+
+ * gc.c (rb_gc_call_finalizer_at_exit): defers IO finalization.
+ [ruby-dev:36646]
+
+Wed Oct 1 19:11:48 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * marshal.c (marshal_dump): fixed for check_dump_arg.
+
+ * marshal.c (marshal_dump): initializes dump_arg before any funcall.
+ [ruby-dev:36648]
+
+Wed Oct 1 00:54:32 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_split_m): should use rb_str_subseq() which use
+ offset and length by bytes. [ruby-dev:36641]
+
+Wed Oct 1 00:29:48 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * test/ruby/test_settracefunc.rb (test_call, test_class): line number
+ was changed at r19592.
+
+Wed Oct 1 00:20:38 2008 Tanaka Akira <akr@fsij.org>
+
+ * process.c (check_exec_redirect): don't depend on rb_stdout and
+ rb_stderr.
+
+Tue Sep 30 23:06:58 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * test/mini/test_mini_test.rb: removed.
+ Temporarily removed the tests for miniunit because of
+ they depend on the miniunit version of test/unit,
+ where test/unit was temporarily reverted to the state
+ before importing miniunit.
+
+ * test/mini/test_mini_mock.rb: ditto.
+
+ * test/mini/test_mini_spec.rb: ditto.
+
+Tue Sep 30 23:04:30 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * lib/test/**/*: recovered.
+ Temporarily reverts the changes of lib/test/unit/* in
+ r19502 and r19501, in order to release 1.9.0-5.
+
+Tue Sep 30 23:00:05 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * lib/test/unit.rb: removed.
+ Temporarily reverts the changes of lib/test/unit/* in
+ r19543, r19534 and r19503, in order to release 1.9.0-5.
+
+ * lib/test/unit/assertions.rb: ditto.
+
+ * lib/test/unit/deprecate.rb: ditto.
+
+ * lib/test/unit/error.rb: ditto.
+
+ * lib/test/unit/testcase.rb: ditto.
+
+Tue Sep 30 20:17:26 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_io_extract_modeenc): should honor value of the
+ textmode: and binmode: options.
+
+Tue Sep 30 17:04:59 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * test/bigdecimal/test_bigdecimal.rb (test_sqrt_bigdecimal): wrong
+ precision specification. a patch from TAKANO Mitsuhiro
+ <takano32 at jus.or.jp> in [ruby-dev:36634].
+
+Tue Sep 30 16:53:55 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (stmt): returns non zero. [ruby-dev:36633]
+
+Tue Sep 30 16:52:38 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * sprintf.c (rb_str_format): add %<name>s style named argument
+ support. a patch from Yusuke Endoh <mame at tsg.ne.jp>
+ in [ruby-dev:35851].
+
+ * sprintf.c (rb_str_format): add gettext style named format
+ (%{name}) support. inspired by [ruby-dev:35852].
+
+ * sprintf.c (GETNAMEARG): should raise KeyError exception when no
+ named argument found.
+
+ * hash.c (rb_hash_fetch): export fetch function.
+
+Tue Sep 30 13:19:01 2008 Eric Hodel <drbrain@segment7.net>
+
+ * test/rubygems/test_gem_installer.rb: remove extra call to setup to
+ fix ENV['HOME'] pollution.
+
+Tue Sep 30 13:04:11 2008 Ryan Davis <ryand-ruby@zenspider.com>
+
+ * lib/mini/test.rb: Updated to 1.3.0 r4257.
+ * test/mini/*: added from r4257.
+
+Tue Sep 30 07:46:07 2008 Eric Hodel <drbrain@segment7.net>
+
+ * test/rdoc/test_rdoc_markup_attribute_manager.rb: Test with clean
+ SPECIALS.
+ * test/rubygems/gemutilities.rb: Restore ENV['HOME'] after test.
+ * test/runner.rb: Pass -n argument down to miniunit.
+
+Tue Sep 30 01:02:55 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (token_info_push, token_info_pop): do nothing for evaled
+ source.
+
+Tue Sep 30 00:47:43 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/nkf/nkf-utf8/nkf.c: constified.
+
+Mon Sep 29 23:32:25 2008 Tanaka Akira <akr@fsij.org>
+
+ * string.c (rb_str_subseq): don't use rb_str_drop_bytes for short
+ string.
+
+Mon Sep 29 22:54:29 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/mathn.rb: added String#to_[rc]. moved def_canon.
+
+Mon Sep 29 20:41:19 2008 Tanaka Akira <akr@fsij.org>
+
+ * string.c (rb_str_subseq): use rb_str_drop_bytes if possible.
+
+Mon Sep 29 20:22:20 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * test/date/*.rb: imported additional tests and some adjustments.
+
+Mon Sep 29 20:13:05 2008 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c (fev_initialize): initialization
+ handler instance variable.
+
+ * test/win32ole/test_win32ole_typelib.rb (test_s_typelibs):
+ fix the warning of shadowing outer local variable.
+
+Mon Sep 29 19:59:00 2008 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c (rescue_callback): use rb_write_error
+ instead of fprintf.
+
+Mon Sep 29 01:51:54 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * test/rdoc/test_rdoc_info_formatting.rb (teardown): delete tmpdir for
+ test.
+
+Mon Sep 29 00:30:20 2008 Takeyuki Fujioka <xibbar@ruby-lang.org>
+
+ * lib/cgi/html.rb (CGI::HtmlExtension::{radio_group, checkbox_group}):
+ can specify the false as checked or selected value.
+ [ruby-core:18306], [ruby-core:18307]
+
+ * test/cgi/test_cgi_tag_helper.rb: add a test.
+
+Sun Sep 28 23:08:38 2008 Takeyuki Fujioka <xibbar@ruby-lang.org>
+
+ * lib/cgi/html.rb (CGI::HtmlExtension::popup_menu):
+ fix the calls #bytesize on array parameters. [ruby-core:18919]
+
+Sun Sep 28 22:44:26 2008 Takeyuki Fujioka <xibbar@ruby-lang.org>
+
+ * lib/cgi/core.rb (CGI::parse): ignore illegal query params.
+ [ruby-dev:36618]
+
+Sun Sep 28 22:05:07 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * compile.c (iseq_set_sequence): check duplicated when clause.
+ [ruby-dev:36616]
+
+Sun Sep 28 19:04:03 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * test/date/*.rb: imported a date test suite ruby 1.9 limited ed.
+
+Sun Sep 28 18:40:49 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mini/test.rb (MINI_DIR): loaded path is expanded.
+
+ * lib/mini/test.rb (assert_match): get rid of confusion of
+ ruby-mode.el.
+
+Sun Sep 28 12:36:09 2008 Koichi Sasada <ko1@atdot.net>
+
+ * vm_exec.c (vm_exec_core): add an UNLIKELY() hint.
+
+ * vm_insnhelper.h (BASIC_OP_UNREDEFINED_P): add a LIKELY() hint.
+
+Sun Sep 28 12:04:18 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * string.c (str_new): sets empty string to coderange 7bit.
+ [ruby-core:18993]
+
+Sun Sep 28 09:39:48 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/mathn.rb ({Fixnum,Bignum,Float}#**): may produce complex
+ value.
+
+Sun Sep 28 09:05:53 2008 James Edward Gray II <jeg2@ruby-lang.org>
+
+ * lib/csv/csv.rb: Worked around some minor encoding changes in Ruby
+ pointed out by Nobu.
+
+Sun Sep 28 08:37:12 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * lib/mathn.rb: a hack to provide canonicalization. This must be
+ temporary, but this seems to be not bad for the time being.
+
+Sat Sep 27 06:22:18 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/rake.rb (Module#rake_extension, String#ext, String#pathmap): use
+ built-in methods.
+
+ * lib/rake.rb (String#pathmap): fixed typo in rdoc.
+
+Sat Sep 27 04:28:41 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * file.c (rmext): preceding dots are not a part of extension.
+
+ * file.c (rb_file_s_extname): ditto.
+
+Sat Sep 27 03:15:51 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * vm.c (vm_jump_tag_but_local_jump): exc is not used if val is nil.
+
+Sat Sep 27 03:12:40 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ext/socket/socket.c (host_str): numeric address should be unsigned.
+ [ruby-core:18971]
+
+Fri Sep 26 22:46:58 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (primary, brace_block): fix for line number.
+
+ * proc.c (rb_proc_location, rb_method_location): new methods
+ {Proc,Method,UnboundMethod}#source_location. [ruby-core:18452]
+
+Fri Sep 26 21:36:33 2008 Koichi Sasada <ko1@atdot.net>
+
+ * vm_core.h (RUBY_VM_CHECK_INTS_TH): add an UNLIKELY hint.
+
+Fri Sep 26 19:33:36 2008 Tanaka Akira <akr@fsij.org>
+
+ * include/ruby/encoding.h (rb_str_encode): renamed from
+ rb_str_transcode. [ruby-dev:36593]
+ (rb_econv_has_convpath_p): renamed from rb_transcode_convertible.
+
+ * transcode.c: follow the renaming.
+
+ * io.c: ditto.
+
+Fri Sep 26 19:01:47 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * test/bigdecimal/test_bigdecimal.rb (test_inspect): fixed CPU bit
+ size dependent test. pointed out by TAKANO Mitsuhiro <takano32 AT
+ jus.or.jp>.
+
+Fri Sep 26 18:57:33 2008 Akinori MUSHA <knu@iDaemons.org>
+
+ * test/pathname/test_pathname.rb: Fix use of deprecated methods.
+
+Fri Sep 26 18:39:59 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * common.mk (dist): nothing is needed to run BASERUBY.
+
+ * tool/make-snapshot: new option -archname.
+
+Fri Sep 26 18:24:28 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * misc/ruby-mode.el: safe customizable variables.
+
+Fri Sep 26 17:37:18 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * include/ruby/ruby.h (rb_mPrecision): removed.
+ Precision module was temporarily removed at r19430.
+
+Fri Sep 26 17:25:10 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * common.mk (dist): Changed its dependencies and action.
+
+Fri Sep 26 17:07:04 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * error.c (Init_syserr): moved to the template.
+ (errno_missing): removed. fixed [ruby-dev:35958].
+
+ * defs/known_errors.def: added. extracted from Init_syserr.
+
+ * templates/known_errors.inc.tmpl: added. Template for Init_syserr.
+ c.f. [ruby-dev:35958].
+
+ * tools/generic_erb.rb: added. general purpose mapper which maps
+ data+template into source code.
+
+ * common.mk (error.$(OBJEXT), incs, known_errors.inc):
+ Fixed dependencies.
+
+Fri Sep 26 17:02:04 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * thread.c (thlist_signal): clears the woken thread if nothing woke.
+
+ * thread.c (rb_barrier_wait): achieves the lock if no thread was
+ waiting yet.
+
+Fri Sep 26 12:04:07 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/curses/curses.c: should include <ruby/io.h>.
+
+ * ext/io/wait/wait.c: ditto.
+
+ * ext/openssl/ossl.h: ditto.
+
+Fri Sep 26 11:34:08 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * variable.c (rb_define_hooked_variable): cast to get rid of compiler
+ warnings.
+
+Fri Sep 26 11:05:41 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * transcode.c, include/ruby/encoding.c (rb_transcode_convertible):
+ new function. checking the existence of converter.
+
+Fri Sep 26 10:35:50 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * variable.c (global_variable, struct trace_var): made function
+ members more strict.
+
+Fri Sep 26 09:55:06 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * include/ruby{io,sig}.h: moved to include/ruby/backward.
+
+Fri Sep 26 09:47:15 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * include/rubysig.h: old macros for backward compatibility.
+
+ * thread.c (BLOCKING_REGION): rewritten using helper functions.
+
+Fri Sep 26 03:03:32 2008 Tanaka Akira <akr@fsij.org>
+
+ * vm_eval.c (Init_vm_eval): define module_eval, class_eval and eval
+ here for rdoc.
+
+Fri Sep 26 00:40:30 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * range.c (range_inspect): fix SEGV for cyclic range object.
+ [ruby-core:18835]
+
+Thu Sep 25 23:59:56 2008 Tanaka Akira <akr@fsij.org>
+
+ * common.mk: dependency updated.
+
+Thu Sep 25 21:46:48 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode.c (rb_eUndefinedConversionError): renamed from
+ rb_eConversionUndefinedError.
+ (rb_eConverterNotFoundError): renamed from rb_eNoConverterError.
+
+Thu Sep 25 21:23:08 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * pack.c (pack_pack, pack_unpack): 'm0' format (base64) complies with
+ RFC 4648. It adds no line feed when encoding, and raise ArgumentError
+ if the encoded string contains non-alphabet (including CR and LF).
+
+ * lib/base64.rb: added. This provides encoding/decoding method for
+ Base64 in standard RFC 2045, Base64 in standard RFC 4648 and ``Base 64
+ Encoding with URL and Filename SafeAlphabet'' in RFC 4648.
+
+ * test_pack.c, test/base64/test_base64.rb: add tests for above.
+
+Thu Sep 25 21:00:32 2008 Koichi Sasada <ko1@atdot.net>
+
+ * common.mk: fix btest-* rules [ruby-dev:36528].
+ and remove obsolete rules.
+
+Thu Sep 25 20:27:54 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * class.c (rb_make_metaclass): [BUG] Fixed a bus error
+ on the case for metaclass of a class which includes a
+ module.
+
+Thu Sep 25 19:34:33 2008 Eric Hodel <drbrain@segment7.net>
+
+ * test/rubygems/*: Update some new tests to use build_rake_in.
+ * test/rubygems/gemutilities.rb: Fix broken merge of rake detection.
+
+Thu Sep 25 19:13:12 2008 Eric Hodel <drbrain@segment7.net>
+
+ * lib/rubygems*: Update to RubyGems 1.3.0 r1891.
+
+Thu Sep 25 18:40:42 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * class.c (rb_make_metaclass): Made class of class of class
+ from Class into its own eigenclass. Now meta^(n)-class
+ hierarchy regresses infinitely, again.
+ (This feature was decided on developer-meeting-20080922.)
+
+Thu Sep 25 16:01:07 2008 Jim Weirich <jim@tardis.local>
+
+ * lib/rake.rb: Update rake source to version 0.8.3. This
+ version includes some fixes for running Rake on windows.
+ (1) better APPDATA/HOMExxx/USERPROFILE integration for
+ system rakefiles, (2) Better handling of the :ruby command
+ when installed in directory containing spaces.
+
+Thu Sep 25 11:22:51 2008 Eric Hodel <drbrain@segment7.net>
+
+ * lib/rdoc*: Update to RDoc 2.2.1 r185.
+
+Thu Sep 25 02:08:47 2008 Tanaka Akira <akr@fsij.org>
+
+ * io.c (rb_io_mode_enc): make it static.
+
+Thu Sep 25 01:22:39 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/mini/test.rb (Mini::Assertions#assert_raise): fixed typo.
+
+Wed Sep 24 23:39:00 2008 Takeyuki Fujioka <xibbar@ruby-lang.org>
+
+ * test/cgi/test_cgi_multipart.rb : revert last change.
+ ( deprecated is assert_raises. )
+ * test/cgi/test_cgi_core.rb : ditto.
+ * test/cgi/test_cgi_header.rb : ditto.
+
+Wed Sep 24 23:12:49 2008 Takeyuki Fujioka <xibbar@ruby-lang.org>
+
+ * lib/cgi/core.rb (CGI::new, CGI::{accept_charset,accept_charset=}) :
+ accept parameters either in a hash,
+ string as a block. add the encoding validation process.
+ * test/cgi/test_cgi_core.rb : test for query encoding check.
+
+Wed Sep 24 22:58:18 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * string.c (rb_str_rstrip_bang): raise exception when the encoding of
+ the string is dummy.
+
+ * string.c (rb_str_rstrip_bang): remove nul characters even if the
+ encoding of the string is not single byte optimizable.
+ fixed [ruby-core:18844], reported by Michael Selig.
+
+Wed Sep 24 19:01:45 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * string.c (rb_str_rstrip_bang): workaround for VC++8 x64.
+
+Wed Sep 24 17:44:44 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * complex.c (Init_Complex), rational.c (Init_Rational): undefines
+ default #allocate methods which call the allocator.
+
+Wed Sep 24 17:02:14 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * complex.c (Init_Complex), rational.c (Init_Rational): ID_ALLOCATOR
+ differs from :allocate, and invisible in ruby level.
+
+Wed Sep 24 15:58:52 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_rstrip_bang): removing mixed spaces and nuls at
+ the end of strings. [ruby-dev:36497]
+
+Wed Sep 24 15:13:04 2008 Takeyuki Fujioka <xibbar@ruby-lang.org>
+
+ * test/cgi/test_cgi_multipart.rb : test for miniunit.
+ * test/cgi/test_cgi_core.rb : ditto.
+ * test/cgi/test_cgi_header.rb : ditto.
+
+Wed Sep 24 14:38:29 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * lib/tmpdir.rb: setup buffer with nul characters instead of spaces.
+ fixed [ruby-dev:36493]
+
+Wed Sep 24 11:18:33 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_io_s_binread): offset argument was wrongly passed to
+ internal IO#read call. [ruby-core:18810]
+
+Wed Sep 24 07:38:23 2008 URABE Shyouhei <shyouhei@ruby-lang.org>
+
+ * vm_core.h: ruby/ruby.h should be included at the very first
+ place in an entire compilation unit, as it includes
+ ruby/config.h
+
+Wed Sep 24 06:41:24 2008 Ryan Davis <ryand-ruby@zenspider.com>
+
+ * lib/test/*: removed test/unit.
+ * lib/test/*: added miniunit.
+ * lib/mini/*: ditto.
+
+Wed Sep 24 04:45:35 2008 Koichi Sasada <ko1@atdot.net>
+
+ * include/ruby/node.h, node.h: move node.h from include path.
+ This change stop to install node.h because of saving ABI
+ (node.h will be changed. Extensions should not depends on
+ this file).
+
+ * blockinlining.c, class.c, compile.c, debug.h, enum.c,
+ gc.c, iseq.c, parse.y, ruby.c, signal.c, variable.c,
+ vm.c, vm_core.h, vm_dump.c: ditto.
+
+ * ext/ripper/depend: ditto.
+
+Wed Sep 24 04:09:13 2008 Koichi Sasada <ko1@atdot.net>
+
+ * vm_core.h: remove unused frame values.
+
+Wed Sep 24 04:07:07 2008 Koichi Sasada <ko1@atdot.net>
+
+ * signal.c (signal_exec): execute rb_eval_cmd() directly.
+
+Wed Sep 24 03:08:58 2008 Eric Hodel <drbrain@segment7.net>
+
+ * lib/uri/mailto.rb: fix indentation.
+ * lib/uri/generic.rb: ditto.
+ * lib/yaml.rb: ditto.
+ * lib/uri/cgi/core.rb: fix indentation and ambiguous argument warning.
+
+Tue Sep 23 23:39:25 2008 James Edward Gray II <jeg2@ruby-lang.org>
+
+ * lib/csv/csv.rb: Improved the idea of whitespace and word characters used
+ in substitutions during header conversion as suggested by Michael Selig.
+
+Tue Sep 23 21:50:53 2008 Tanaka Akira <akr@fsij.org>
+
+ * io.c (io_binwrite): allocate wbuf if nosync.
+
+Tue Sep 23 21:45:02 2008 Tanaka Akira <akr@fsij.org>
+
+ * io.c (copy_stream_body): use io_binwrite instead of io_fwrite.
+
+Tue Sep 23 21:31:16 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * test/ruby/test_rational2.rb: updated.
+
+ * test/ruby/test_complex2.rb: added.
+
+ * test/ruby/test_complexrational.rb: added.
+
+Tue Sep 23 21:26:32 2008 Tanaka Akira <akr@fsij.org>
+
+ * string.c (rb_str_casecmp): make the ordering consistent with
+ String#<=>.
+
+Tue Sep 23 20:52:25 2008 Tanaka Akira <akr@fsij.org>
+
+ * io.c (io_binwrite): add nosync argument.
+ (do_writeconv): extracted from io_fwrite.
+ (io_fwrite): add nosync argument. use do_writeconv.
+ (io_write): add nosync argument.
+ (io_write_m): new function for IO#write.
+ (rb_p): don't append record separator.
+
+Tue Sep 23 20:24:41 2008 Koichi Sasada <ko1@atdot.net>
+
+ * signal.c (signal_exec): fix to use rb_proc_call().
+
+Tue Sep 23 20:06:46 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/rexml/formatters/pretty.rb (REXML::Formatters::Pretty#wrap):
+ abandon wrapping if the line contains no space. [ruby-dev:36045]
+
+Tue Sep 23 19:38:03 2008 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * win32/win32.c (subtract): check tv_sec. reported by ko1.
+
+Tue Sep 23 19:21:03 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * complex.c (nucomp_s_canonicalize_internal): does no apply
+ canonicalization rule anymore.
+
+ * rational.c (nurat_s_canonicalize_internal(_no_reduce)?): ditto.
+
+ * complex.c: removed class method new! and new.
+
+ * rational.c: ditto.
+
+Tue Sep 23 19:20:59 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_io_s_binread): a new method to read binary chunk from a
+ file. [ruby-core:18674]
+
+ * io.c (open_key_args): wrong permission specified for read-open.
+
+Tue Sep 23 18:24:34 2008 Tanaka Akira <akr@fsij.org>
+
+ * hash.c (rb_obj_is_proc): declaration moved for rdoc.
+
+Tue Sep 23 18:07:55 2008 Koichi Sasada <ko1@atdot.net>
+
+ * common.mk (io.o): remove dependency for vm_core.h.
+
+Tue Sep 23 17:56:44 2008 Koichi Sasada <ko1@atdot.net>
+
+ * thread.c (rb_thread_blocking_region): fix typo in a document.
+
+Tue Sep 23 17:50:35 2008 Koichi Sasada <ko1@atdot.net>
+
+ * thread.c (rb_thread_blocking_region): write a document.
+
+Tue Sep 23 17:14:31 2008 Koichi Sasada <ko1@atdot.net>
+
+ * thread.c, include/ruby/intern.h (rb_thread_interrupted): added.
+
+ * io.c: use VALUE of thead instead of rb_tread_t to check interrupts.
+
+Tue Sep 23 17:05:14 2008 Koichi Sasada <ko1@atdot.net>
+
+ * class.c, vm_core.h: move decl of rb_iseq_clone() to class.c.
+
+Tue Sep 23 17:02:47 2008 Tanaka Akira <akr@fsij.org>
+
+ * debug.h (ruby_set_debug_option): declared.
+
+ * main.c: include debug.h.
+
+ * common.mk (main.$(OBJEXT)): dependency updated.
+
+Tue Sep 23 16:59:45 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * hash.c (ENVMATCH, ENVNMATCH): reduced same code.
+
+Tue Sep 23 16:55:11 2008 Koichi Sasada <ko1@atdot.net>
+
+ * ruby.h: fix comment and rename macro HAVE_RUBY_MVM_H to
+ HAVE_RUBY_VM_H.
+
+Tue Sep 23 16:41:31 2008 Koichi Sasada <ko1@atdot.net>
+
+ * include/ruby/node.h, vm_core.h: move definition of
+ RUBY_VM_METHOD_NODE to node.h.
+
+ * class.c, common.mk: remove useless inclusion.
+
+ * compile.h, iseq.h, vm_core.h: rename compile.h to iseq.h.
+ move some definitions from vm_core.h to iseq.h.
+
+ * compile.c, iseq.c, vm.c: ditto.
+
+ * eval.c, compile.c: move some functions for parser
+ from eval.c to compile.c.
+
+ * eval_intern.h, vm_core.h: move va_init_list() macro to
+ vm_core.h.
+
+ * iseq.c (rb_iseq_new_top, rb_iseq_first_lineno): added.
+
+ * load.c, ruby.c: use rb_iseq_new_top() instead of
+ rb_iseq_new() with ISEQ_TYPE_TOP constant directly.
+
+ * proc.c: use rb_iseq_first_lineno() instead of accessing
+ iseq structure.
+
+Tue Sep 23 16:17:54 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/ripper/eventids2.c (token_to_eventid): supper __ENCODING__
+ keyword. [ruby-dev:36478]
+
+Tue Sep 23 15:30:53 2008 Koichi Sasada <ko1@atdot.net>
+
+ * common.mk, hash.c: remove unused inclusion.
+
+Tue Sep 23 09:52:07 2008 Koichi Sasada <ko1@atdot.net>
+
+ * eval_safe.c, safe.c: rename eval_safe.c to safe.c.
+
+ * common.mk, eval.c, safe.c, inits.c: separate safe.c from eval.c and
+ make Init_safe().
+
+Tue Sep 23 09:20:00 2008 Koichi Sasada <ko1@atdot.net>
+
+ * common.mk: clean up
+ - remove blockinlining.$(OBJEXT) to built
+ - make ENCODING_H_INCLDUES variable (include/ruby/encoding.h)
+ - make VM_CORE_H_INCLUDES variable (vm_core.h)
+ - simplify rules.
+ - make depends rule to output depend status using gcc -MM.
+
+ * include/ruby/mvm.h, include/ruby/vm.h: rename mvm.h to vm.h.
+
+ * include/ruby.h: ditto.
+
+ * load.c: add inclusion explicitly.
+
+ * enumerator.c, object.c, parse.y, thread.c, vm_dump.c:
+ remove useless inclusion.
+
+ * eval_intern.h: cleanup inclusion.
+
+ * vm_core.h: rb_thread_t should be defined in this file.
+
+ * vm_evalbody.c, vm_exec.c: rename vm_evalbody.c to vm_exec.c.
+
+ * vm.h, vm_exec.h: rename vm.h to vm_exec.h.
+
+ * insnhelper.h, vm_insnhelper.h: rename insnhelper.h to vm_insnhelper.h.
+
+ * vm.c, vm_insnhelper.c, vm_insnhelper.h:
+ - rename vm_eval() to vm_exec_core().
+ - rename vm_eval_body() to vm_exec().
+ - cleanup include order.
+
+ * vm_method.c: fix comment.
+
+Tue Sep 23 09:01:15 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * lib/pathname.rb (each_filename): return Enumerator if no block
+ given.
+
+ * test/pathname/test_pathname.rb: add a test for above.
+
+Tue Sep 23 08:25:56 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * hash.c (env_aset): allow nil value to remove an entry.
+ [ruby-dev:36465]
+
+ * test/ruby/test_env.rb (TestEnv#test_aset): test updated.
+
+Tue Sep 23 08:07:07 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * misc/ruby-mode.el (ruby-keyword-end-re): emacs21 support. a
+ patch from Hiroshi Moriyama <hiroshi at kvd.biglobe.ne.jp> in
+ [ruby-dev:36471].
+
+ * misc/ruby-mode.el (ruby-in-ppss-context-p): ditto.
+
+ * misc/ruby-mode.el (ruby-here-doc-end-syntax):
+
+Tue Sep 23 02:07:52 2008 TAKAO Kouji <kouji@takao7.net>
+
+ * test/readline/test_readline_history.rb
+ (Readline::TestHistory#test_each): checked return value.
+
+Tue Sep 23 02:05:34 2008 TAKAO Kouji <kouji@takao7.net>
+
+ * ext/readline/readline.c (Init_readline): used remove_history to
+ check offset of history if unsupported clear_history.
+
+Mon Sep 22 17:39:25 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/tempfile.rb (Tempfile#open): should return a value from the
+ block (if given). [ruby-core:18394]
+
+Mon Sep 22 11:17:51 2008 URABE Shyouhei <shyouhei@ruby-lang.org>
+
+ * include/ruby/encoding.h (enum): ISO C forbids comma at end of
+ enumerator list
+
+Mon Sep 22 10:15:24 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * LEGAL: updated file names removed and added. [ruby-dev:36426]
+
+Mon Sep 22 02:39:05 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * encoding.c (get_default_external): add description.
+
+Sun Sep 21 21:52:41 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * math.c (math_log): should check argc.
+
+Sun Sep 21 21:20:24 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * complex.c: added two macros.
+
+ * rational.c: ditto.
+
+Sun Sep 21 18:06:38 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * complex.c (nucomp_s_convert): checks argc.
+
+ * rational.c (nurat_s_convert): ditto.
+
+Sun Sep 21 10:19:04 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * complex.c (nucomp_s_canonicalize_internal): checks exactness of
+ imag only.
+
+ * rational.c (nurat_s_convert): accepts non real value
+ (Rational(a,b) as a/b).
+
+ * complex.c (nucomp_s_convert): refined.
+
+Sun Sep 21 09:37:57 2008 James Edward Gray II <jeg2@ruby-lang.org>
+
+ * lib/csv/csv.rb: Reworked CSV's parser and generator to be m17n. Data
+ is now parsed in the Encoding it is in without need for translation.
+ * lib/csv/csv.rb: Improved inspect() messages for better IRb support.
+ * lib/csv/csv.rb: Fixed header writing bug reported by Dov Murik.
+ * lib/csv/csv.rb: Use custom separators in parsing header Strings as
+ suggested by Shmulik Regev.
+ * lib/csv/csv.rb: Added a :write_headers option for outputting headers.
+ * lib/csv/csv.rb: Handle open() calls in binary mode whenever we can to
+ workaround a Windows issue where line-ending translation can cause an
+ off-by-one error in seeking back to a non-zero starting position after
+ auto-discovery for :row_sep as suggested by Robert Battle.
+ * lib/csv/csv.rb: Improved the parser to fail faster when fed some forms
+ of invalid CSV that can be detected without reading ahead.
+ * lib/csv/csv.rb: Added a :field_size_limit option to control CSV's
+ lookahead and prevent the parser from biting off more data than
+ it can chew.
+ * lib/csv/csv.rb: Added readers for CSV attributes: col_sep(), row_sep(),
+ quote_char(), field_size_limit(), converters(), unconverted_fields?(),
+ headers(), return_headers?(), write_headers?(), header_converters(),
+ skip_blanks?(), and force_quotes?().
+ * lib/csv/csv.rb: Cleaned up code syntax to be more inline with
+ Ruby 1.9 than 1.8.
+
+Sun Sep 21 07:43:16 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * complex.c: an instance method image has been removed and
+ uses "imag" instead of "image".
+
+ * complex.c: two instance method re and im are removed.
+
+ * rational.c: follows the above changes.
+
+ * include/ruby/ruby.h: ditto.
+
+ * gc.c: ditto.
+
+ * lib/cmath.rb: ditto.
+
+ * lib/mathn.rb: ditto.
+
+ * lib/complex.rb: ditto. and provides some obsolete methods.
+
+Sun Sep 21 02:48:45 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/json/ext/parser/parse.c: use ruby_xfree().
+
+ * ext/json/ext/parser/parse.rl: ditto.
+
+ * ext/json/ext/parser/unicode.c: ditto.
+
+Sun Sep 21 02:40:20 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/json: import JSON v 1.1.3.
+
+Sat Sep 20 11:43:08 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * lib/optparse.rb (summarize): separator "" should output new line.
+
+Sat Sep 20 08:07:34 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * parse.y: strings which contain only US-ASCII don't force to have
+ US-ASCII encoding. [ruby-dev:36400]
+
+Sat Sep 20 07:59:31 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * re.c (rb_reg_desc): Regexps of ASCII Compatible encoding may
+ contain non-ASCII characters. So in that case its encoding
+ must keep original encoding.
+
+Sat Sep 20 07:44:56 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * common.mk: prec.c is removed.
+
+Fri Sep 19 22:37:25 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * complex.c: uses f_(in)?exact_p macro.
+
+ * rational.c: ditto.
+
+ * bignum.c (rb_big_pow): bignum**bignum - should calculate without
+ rational.
+
+ * lib/complex.rb: should override Math module at most once.
+
+ * lib/mathn.rb: requires 'cmath' directly.
+
+Fri Sep 19 20:48:06 2008 Yuki Sonoda <yugui@yugui.jp>
+
+ * prec.c: removed. Precision will be redesigned and be back again.
+ c.f. [ruby-dev:36352].
+
+ * common.mk (COMMON_OBJS): removed prec.o.
+
+ * inits.c (rb_call_inits): removed Init_Precision.
+
+ * numeric.c (Init_Numeric): removed inclusion of Precision.
+ removed #induced_from from each class.
+
+ * rational.c: ditto.
+
+ * ext/bigdecimal/bigdecimal.c: ditto.
+
+ * lib/rdoc/known_classes.rb: removed the entry for Precision.
+
+ * test/ruby/test_prec.rb: removed.
+
+ * test/ruby/test_integer.rb: removed tests for Precision.
+
+ * test/ruby/test_fixnum.rb: ditto.
+
+ * test/ruby/test_float.rb: ditto.
+
+ * test/ruby/test_rational.rb: ditto.
+
+ * test/ruby/test_complex.rb: ditto.
+
+ * test/bigdecimal/test_bigdecimal.rb: ditto.
+
+Fri Sep 19 19:43:40 2008 Yuki Sonoda <yugui@yugui.jp>
+
+ * common.mk : Reverts the changeset 18994.
+ Uses the official repository of rubyspec again.
+
+Fri Sep 19 17:41:56 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * configure.in: applied OS/2 support patch from Brendan Oakley
+ <gentux2 at gmail.com> in [ruby-core:18707].
+
+Fri Sep 19 09:29:26 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * dln.c: newer BeOS support. a patch from Pete Goodeve
+ <pete.goodeve at computer.org> in [ruby-core:18712].
+
+Fri Sep 19 03:41:25 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/nkf/nkf-utf8/nkf.c: fix memory violation. mentioned by mame [ruby-dev:36373]
+
+Fri Sep 19 01:07:36 2008 Tanaka Akira <akr@fsij.org>
+
+ * regexec.c (string_cmp_ic): add text_end argument.
+ (slow_search): call enclen with real string end.
+ (map_search): add text_end argument.
+
+Thu Sep 18 22:54:39 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * ext/openssl/ossl_pkey_ec.c (ossl_ec_key_to_string): comment out
+ fragments of unused code.
+
+Thu Sep 18 22:35:03 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * ext/bigdecimal/bigdecimal.c (VpCtoV): 1E1000...000 is interpreted as
+ Infinity. [ruby-dev:36159]
+
+ * ext/bigdecimal/bigdecimal.c (VpPower): Infinity ** 1 returns
+ Infinity instead of NaN. [ruby-dev:36159]
+
+ * test/bigdecimal/test_bigdecimal.rb: add tests for above.
+
+Thu Sep 18 22:20:08 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * error.c (Init_Exception): introduce EncodingError which is a
+ superclass for all encoding related exception classes,
+ e.g. Encoding::CompatibilityError. [ruby-dev:36371]
+
+ * transcode.c (Init_transcode): ditto.
+
+Thu Sep 18 21:57:32 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_comparable): make ascii8bit string to be
+ compatible with any other encoding.
+
+ * string.c (rb_str_cmp): use rb_str_comparable() instead of
+ rb_enc_compatible() since <=> is a comparison anyway.
+
+Thu Sep 18 21:37:14 2008 Tanaka Akira <akr@fsij.org>
+
+ * grapheme cluster implementation reverted. [ruby-dev:36375]
+
+Thu Sep 18 20:50:36 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/rake.rb (Rake::Application#standard_exception_handling):
+ replaced magic numbers for exit status.
+
+Thu Sep 18 20:37:59 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * lib/optparse.rb (OptionParser::ParseError#set_backtrace): omits
+ OptionParser internal backtraces unless debug flag is set.
+
+Thu Sep 18 20:02:48 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * lib/uri/common.rb (unescape): skip '%' to make String#hex work
+ correctly.
+
+Thu Sep 18 19:51:11 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (big2str_karatsuba): free internal buffer eagerly.
+ a patch from TOYOFUKU Chikanobu <nobu_toyofuku at nifty.com>
+ in [ruby-dev:36217].
+
+ * bignum.c (rb_big2str0): ditto.
+
+Thu Sep 18 19:43:04 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * st.c (new_size): raise RuntimeError when st_table is too big.
+ [ruby-dev:36354]
+
+Thu Sep 18 18:23:23 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode.c (enc_arg): must take pointer argument to avoid GC
+ problem. StringValueCStr modifies the argument and it should be
+ preserved while the string StringValueCStr returns is used.
+ Since the string is used by caller, the modified argument should be
+ hold by caller. Actually
+ GC.stress = true
+ def (o=Object.new).to_str()
+ "universal"+"_newline"
+ end
+ "\u3042".encode(o, "")
+ causes curious warning:
+ rb_define_const: invalid name `' for constant
+
+Thu Sep 18 17:32:44 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * transcode.c: add "Error" suffix for Encoding exception classes.
+ a patch from Tadashi Saito <shiba at mail2.accsnet.ne.jp> in
+ [ruby-dev:36346].
+
+ * encoding.c (Init_Encoding): rename EncodingCompatibilityError to
+ Encoding::CompatibilityError. [ruby-dev:36366]
+
+Thu Sep 18 17:18:35 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * transcode.c (enc_arg): revert last change. too early exception
+ raising.
+
+ * transcode.c (enc_arg): need not to take pointer argument.
+
+Sun Sep 18 02:22:15 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * test/bigdecimal/test_bigdecimal.rb: add tests to achieve over 90%
+ test coverage of bigdecimal.
+
+Wed Sep 17 21:50:14 2008 Tanaka Akira <akr@fsij.org>
+
+ * string.c (rb_str_casecmp): don't use rb_enc_codepoint.
+
+Wed Sep 17 19:55:33 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * complex.c (nucomp_s_convert): accepts complex
+ value (Complex(a,b) as a+bi).
+
+Wed Sep 17 19:16:47 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * test/ruby/test_io.rb (TestIO#test_dup): avoid infinite loop.
+ [ruby-dev:36326]
+
+ * test/ruby/test_io.rb (TestIO#test_dup): remove needless open.
+ [ruby-dev:35957]
+
+Wed Sep 17 17:44:59 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_io_extract_modeenc): process option mode: and perm: as
+ well.
+
+ * io.c (open_key_args): move mode: and perm: related code to
+ rb_io_extract_modeenc().
+
+Wed Sep 17 13:42:59 2008 Takeyuki Fujioka <xibbar@ruby-lang.org>
+
+ * lib/cgi/html.rb (checkbox_group,radio_group): bug fix
+ use size instead of bytesize.
+
+ * test/cgi/test_cgi_tag_helper.rb: test for checkbox_group,radio_group.
+
+Wed Sep 17 06:58:31 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * numeric.c: provides predicate real? instead of scalar?.
+
+ * complex.c: follows the above change.
+
+ * lib/cmath.rb: ditto.
+
+Wed Sep 17 01:56:27 2008 Tanaka Akira <akr@fsij.org>
+
+ * test/ruby/test_io_m17n.rb: use __FILE__ instead of /dev/null.
+ [ruby-dev:36327]
+
+Wed Sep 17 01:33:11 2008 Tanaka Akira <akr@fsij.org>
+
+ * include/ruby/oniguruma.h (OnigEncodingTypeST): add precise_ret
+ argument for mbc_to_code.
+ (ONIGENC_MBC_TO_CODE): provide NULL for precise_ret.
+ (ONIGENC_MBC_PRECISE_CODEPOINT): defined.
+
+ * include/ruby/encoding.h (rb_enc_mbc_precise_codepoint): defined.
+
+ * regenc.h (onigenc_single_byte_mbc_to_code): precise_ret argument
+ added.
+ (onigenc_mbn_mbc_to_code): ditto.
+
+ * regenc.c (onigenc_single_byte_mbc_to_code): precise_ret argument
+ added.
+ (onigenc_mbn_mbc_to_code): ditto.
+
+ * string.c (count_utf8_lead_bytes_with_word): removed.
+ (str_utf8_nth): removed.
+ (str_utf8_offset): removed.
+ (str_strlen): UTF-8 codepoint oriented optimization removed.
+ (rb_str_substr): ditto.
+ (enc_succ_char): use rb_enc_mbc_precise_codepoint.
+ (enc_pred_char): ditto.
+ (rb_str_succ): ditto.
+
+ * encoding.c (rb_enc_ascget): check length with
+ rb_enc_mbc_precise_codepoint.
+ (rb_enc_codepoint): use rb_enc_mbc_precise_codepoint.
+
+ * regexec.c (string_cmp_ic): add text_end argument.
+ (match_at): check end of character after exact string matches.
+
+ * enc/utf_8.c (grapheme_table): defined for extended grapheme cluster
+ boundary.
+ (grapheme_cmp): defined.
+ (get_grapheme_properties): defined.
+ (grapheme_boundary_p): defined.
+ (MAX_BYTES_LENGTH): defined.
+ (comb_char_enc_len): defined.
+ (mbc_to_code0): extracted from mbc_to_code.
+ (mbc_to_code): use mbc_to_code0.
+ (left_adjust_combchar_head): defined.
+ (utf_8): use a extended grapheme cluster as a unit.
+
+ * enc/unicode.c (onigenc_unicode_mbc_case_fold): use
+ ONIGENC_MBC_PRECISE_CODEPOINT to extract codepoints.
+ (onigenc_unicode_get_case_fold_codes_by_str): ditto.
+
+ * enc/euc_jp.c (mbc_to_code): follow mbc_to_code field change.
+ use onigenc_mbn_mbc_to_code.
+
+ * enc/shift_jis.c (mbc_to_code): ditto.
+
+ * enc/emacs_mule.c (mbc_to_code): ditto.
+
+ * enc/gbk.c (gbk_mbc_to_code): follow mbc_to_code field and
+ onigenc_mbn_mbc_to_code change.
+
+ * enc/cp949.c (cp949_mbc_to_code): ditto.
+
+ * enc/big5.c (big5_mbc_to_code): ditto.
+
+ * enc/euc_tw.c (euctw_mbc_to_code): ditto.
+
+ * enc/euc_kr.c (euckr_mbc_to_code): ditto.
+
+ * enc/gb18030.c (gb18030_mbc_to_code): ditto.
+
+ * enc/utf_32be.c (utf32be_mbc_to_code): follow mbc_to_code field
+ change.
+
+ * enc/utf_16be.c (utf16be_mbc_to_code): ditto.
+
+ * enc/utf_32le.c (utf32le_mbc_to_code): ditto.
+
+ * enc/utf_16le.c (utf16le_mbc_to_code): ditto.
+
+Wed Sep 17 01:17:12 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * transcode.c (enc_arg): raise exception when unknown encoding is
+ given.
+
+Tue Sep 16 22:23:24 2008 Takeyuki Fujioka <xibbar@ruby-lang.org>
+
+ * lib/cgi/core.rb (CGI#header): performance improvement.
+ From CGIAlt http://cgialt.rubyforge.org/
+
+ * test/cgi/test_cgi_header.rb: exception class fixed.
+
+Tue Sep 16 22:21:33 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * string.c (rb_str_concat): fix rdoc. (codepoint is integer)
+
+ * string.c (rb_str_each_codepoint): use UINT2NUM.
+
+Tue Sep 16 21:48:55 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * re.c (rb_reg_desc): Regexp#inspect should be US-ASCII.
+
+Tue Sep 16 21:33:22 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * string.c (rb_str_crypt): orthodox crypt() sees only first two bytes
+ of salt.
+
+Tue Sep 16 19:18:40 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * complex.c (nucomp_marshal_{dump,load}): preserve instance
+ variables.
+
+ * rational.c (nurat_marshal_{dump,load}): ditto.
+
+Tue Sep 16 18:28:52 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_io_gets_m): rdoc updated. limit counts in bytes.
+ [ruby-core:18617]
+
+ * io.c (rb_io_readlines, rb_f_gets): ditto.
+
+ * io.c (rb_io_readbyte): rdoc updated. [ruby-core:18617]
+
+Tue Sep 16 11:55:16 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_each_codepoint): add new methods, #codepoints
+ and #each_codepoint. a patch from Michael Selig
+ <michael.selig at fs.com.au> in [ruby-core:18532].
+
+Tue Sep 16 11:24:44 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ext/socket/mkconstants.rb: add new constants. a patch from
+ IWAMURO Motonori <deenheart+ruby at gmail.com> in [ruby-dev:36309].
+
+Tue Sep 16 09:20:42 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * test/ruby/test_io.rb (TestIO#test_dup): exception should be
+ raised from IO#dup.
+
+Tue Sep 16 08:35:29 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * test/ruby/test_io.rb (TestIO#test_dup): this test might fail if
+ there are any garbage IO objects.
+
Tue Sep 16 05:04:56 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
* configure.in (rb_cv_thread_specific): check if no warnings.
+Tue Sep 16 02:02:56 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * string.c (rb_str_buf_cat_ascii): codepoint is unsigned int.
+
+ * string.c (rb_str_concat): ditto.
+
+ * string.c (str_cat_char): ditto.
+
+ * string.c (prefix_escape): ditto.
+
+Tue Sep 16 01:47:07 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (single_byte_optimizable): make function inline. based
+ on a patch from Michael Selig <michael.selig at fs.com.au> in
+ [ruby-core:18532].
+
+ * string.c (str_modify_keep_cr): new function act as
+ rb_str_modify(), but don't clear coderange
+
+ * string.c (rb_str_casecmp): specialized for single byte strings.
+
+ * string.c (rb_str_splice): preserve coderange.
+
+ * string.c (rb_str_slice_bang, rb_str_reverse_bang,
+ rb_str_upcase_bang, rb_str_downcase_bang, tr_trans,
+ rb_str_capitalize_bang, rb_str_swapcase_bang,
+ rb_str_delete_bang, rb_str_chop_bang, rb_str_chomp_bang,
+ rb_str_lstrip_bang, rb_str_rstrip_bang): ditto.
+
+ * string.c (rb_str_clear): preset coderange.
+
+ * string.c (rb_str_split_m): specialized for splitting with a
+ string.
+
+Tue Sep 16 00:57:56 2008 Tanaka Akira <akr@fsij.org>
+
+ * re.c (rb_reg_quote): use rb_enc_mbcput to generate ASCII
+ incompatible characters properly.
+
+Tue Sep 16 00:51:59 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * encoding.c (Encoding#base_encoding): removed. [ruby-dev:36270]
+
+Tue Sep 16 00:40:56 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode_data.h (STR1_LENGTH): defined.
+ (makeSTR1LEN): defined.
+
+ * tool/transcode-tblgen.rb: use makeSTR1LEN. generate STR1 for 4 to
+ 259 bytes.
+
+ * transcode.c (rb_transcoding): new field: output_index.
+ (transcode_restartable0): use STR1_LENGTH.
+
+Mon Sep 15 23:52:45 2008 Koichi Sasada <ko1@atdot.net>
+
+ * gc.c, include/ruby/ruby.h: rename rb_register_mark_object()
+ to rb_gc_register_mark_object().
+
+ * eval.c, vm.c: initialize vm->mark_object_ary at
+ Init_top_self().
+
+ * bignum.c, complex.c, encoding.c, ext/win32ole/win32ole.c,
+ io.c, load.c, marshal.c, rational.c, ruby.c, vm.c:
+ use rb_gc_register_mark_object() instead of
+ rb_global_variable() or rb_gc_register_address().
+
+Mon Sep 15 23:37:15 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode.c (econv_opts): don't use to_sym.
+
+Mon Sep 15 23:28:28 2008 Tanaka Akira <akr@fsij.org>
+
+ * encoding.c (rb_enc_get_index): don't return -1.
+
+ * io.c (rb_scan_open_args): call FilePathValue before encoding
+ conversion.
+
+Mon Sep 15 22:11:07 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_squeeze_bang): specialized for 7bit characters in
+ ASCII compatible strings.
+
+ * string.c (rb_str_count): ditto.
+
+ * string.c (tr_trans): preserve 7bit/valid coderange flag.
+
+ * string.c (rb_str_squeeze_bang): preserve previous coderange value.
+
+ * string.c (rb_str_lstrip_bang): ditto.
+
+ * string.c (rb_str_rstrip_bang): ditto.
+
+ * encoding.c (rb_default_external_encoding): preserve
+ default_external_encoding in a static variable.
+
+ * string.c (single_byte_optimizable): check coderange first, to
+ reduce number of calling rb_enc_from_index().
+
+Mon Sep 15 20:57:00 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * lib/matrix.rb (Matrix#eql?): fixed [ruby-dev:36298].
+ Reported by an anonymous user.
+
+ * lib/matrix.rb (Vector#eql?): ditto.
+
+ * (Matrix#compare_by_row_vectors): takes comparison
+ strategy as an optional parameter.
+
+ * (Vector#compare_by): ditto.
+
+Mon Sep 15 14:34:32 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * encoding.c (RUBY_MAX_CHAR_LEN): defined.
+
+ * encoding.c (str_cat_char): use RUBY_MAX_CHAR_LEN.
+
+Mon Sep 15 13:53:33 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * encoding.c (rb_enc_compatible): accept other than strings and
+ regexps. [ruby-core:18595]
+
+ * encoding.c (rb_enc_get_index): works files and encodings.
+
+Mon Sep 15 13:17:21 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * complex.c (nucomp_eql_p): new.
+
+ * complex.c (nucomp_hash): should use hash values of the elements.
+
+ * rational.c (nurat_hash): ditto.
+
+ * hash.c (rb_any_cmp): removed an unused variable.
+
+Mon Sep 15 11:11:04 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode_data.h (rb_transcoder): resetsize_func and resetstate_func
+ also returns ssize_t.
+
+ * enc/trans/iso2022.trans: follow the type change.
+
+Mon Sep 15 10:28:10 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * test/matrix/test_matrix.rb (setup): typo.
+ (test_equality): misdefinition of the expected working.
+ Reported by an anonymous user.
+ (test_hash): added.
+
+ * test/matrix/test_vector.rb: ditto.
+
+Mon Sep 15 03:33:10 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode_data.h: return output functions ssize_t.
+
+ * transcode.c (transcode_restartable0): don't need to cast the result
+ of output functions.
+
+ * enc/trans/newline.trans: follow the type change.
+
+ * enc/trans/escape.trans: ditto.
+
+ * enc/trans/utf_16_32.trans: ditto.
+
+ * enc/trans/iso2022.trans: ditto.
+
+ * enc/trans/japanese.trans: ditto.
+
+Mon Sep 15 03:04:29 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode_data.h: output function takes output buffer size.
+
+ * transcode.c: give output buffer size for output functions.
+
+ * enc/trans/newline.trans: follow the type change.
+
+ * enc/trans/escape.trans: ditto.
+
+ * enc/trans/utf_16_32.trans: ditto.
+
+ * enc/trans/iso2022.trans: ditto.
+
+ * enc/trans/japanese.trans: ditto.
+
+Mon Sep 15 02:37:19 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * transcode.c (str_encode): returns duplicated string if nothing
+ changed. [ruby-core:18578]
+
+Sun Sep 14 22:09:01 2008 Takeyuki Fujioka <xibbar@ruby-lang.org>
+
+ * lib/cgi/core.rb (CGI::parse): performance improvement
+
+Sun Sep 14 18:33:32 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * complex.c: trivial changes.
+
+Sun Sep 14 16:15:22 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * lib/matrix.rb (Vector#eql?): typo of the method name as "eqn?".
+ (Vector#eqn?): removed. Defined by mistake.
+ Fixes [ruby-dev:36294]. Reported by weda <weda AT
+ issp.u-tokyo.ac.jp> and an anonymous user.
+
+ * test/matrix/test_matrix.rb: added.
+
+ * test/matrix/test_vector.rb: added.
+
+Sun Sep 14 16:07:04 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * ruby.c (process_options): associates the locale encoding with $0 as
+ well as ARGV.
+
+Sun Sep 14 13:48:03 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+
+ * object.c (Init_Object): added metameta-class initialization for
+ BasicObject, Object, and Module.
+ The metameta-classes of them are now the metaclass of Class, as the
+ metameta-class of Class is.
+
+ * object.c (boot_defmetametaclass): added.
+
+Sun Sep 14 10:10:43 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * complex.c (f_{add,mul,sub}): omitted some shortcuts for preserving
+ signed zero anyway.
+
+ * complex.c (nucomp_negate): new.
+
+Sun Sep 14 04:15:16 2008 Tanaka Akira <akr@fsij.org>
+
+ * include/ruby/oniguruma.h (OnigEncodingTypeST): add end argument for
+ left_adjust_char_head.
+ (ONIGENC_LEFT_ADJUST_CHAR_HEAD): add end argument.
+ (onigenc_get_left_adjust_char_head): ditto.
+
+ * include/ruby/encoding.h (rb_enc_left_char_head): add end argument.
+
+ * regenc.h (onigenc_single_byte_left_adjust_char_head): ditto.
+
+ * regenc.c (onigenc_get_right_adjust_char_head): follow the interface
+ change.
+ (onigenc_get_right_adjust_char_head_with_prev): ditto.
+ (onigenc_get_prev_char_head): ditto.
+ (onigenc_step_back): ditto.
+ (onigenc_get_left_adjust_char_head): ditto.
+ (onigenc_single_byte_code_to_mbc): ditto.
+
+ * re.c: ditto.
+
+ * string.c: ditto.
+
+ * io.c: ditto.
+
+ * regexec.c: ditto.
+
+ * enc/euc_jp.c: ditto.
+
+ * enc/cp949.c: ditto.
+
+ * enc/shift_jis.c: ditto.
+
+ * enc/gbk.c: ditto.
+
+ * enc/big5.c: ditto.
+
+ * enc/euc_tw.c: ditto.
+
+ * enc/euc_kr.c: ditto.
+
+ * enc/emacs_mule.c: ditto.
+
+ * enc/gb18030.c: ditto.
+
+ * enc/utf_8.c: ditto.
+
+ * enc/utf_16le.c: ditto.
+
+ * enc/utf_16be.c: ditto.
+
+ * enc/utf_32le.c: ditto.
+
+ * enc/utf_32be.c: ditto.
+
+Sun Sep 14 03:43:27 2008 Tanaka Akira <akr@fsij.org>
+
+ * include/ruby/oniguruma.h (ONIGENC_STEP_BACK): add end argument.
+ (onigenc_step_back): ditto.
+
+ * regenc.c (onigenc_step_back): add end argument.
+
+ * regexec.c: follow the interface change.
+
+Sun Sep 14 03:20:03 2008 Tanaka Akira <akr@fsij.org>
+
+ * include/ruby/oniguruma.h (onigenc_get_prev_char_head): add end
+ argument.
+
+ * include/ruby/encoding.h (rb_enc_prev_char): ditto.
+
+ * regenc.c (onigenc_get_prev_char_head): add end argument.
+
+ * regparse.c: follow the interface change.
+
+ * regexec.c: ditto.
+
+ * string.c: ditto.
+
+ * parse.y: ditto.
+
+Sun Sep 14 02:04:28 2008 Tanaka Akira <akr@fsij.org>
+
+ * include/ruby/oniguruma.h
+ (onigenc_get_right_adjust_char_head_with_prev): add end argument.
+
+ * regenc.c (onigenc_get_right_adjust_char_head_with_prev): use end
+ argument.
+
+ * regexec.c (forward_search_range): follow the interface change.
+
+Sun Sep 14 01:38:26 2008 Tanaka Akira <akr@fsij.org>
+
+ * include/ruby/oniguruma.h (onigenc_get_right_adjust_char_head): add
+ end argument.
+
+ * include/ruby/encoding.h (rb_enc_right_char_head): add end argument.
+
+ * regenc.c (onigenc_get_right_adjust_char_head): use end argument.
+
+ * re.c (rb_reg_adjust_startpos): follow the interface change.
+
+ * string.c (rb_str_index): ditto.
+
+ * regexec.c (backward_search_range): ditto.
+ (onig_search): ditto.
+
+Sun Sep 14 00:43:28 2008 Tanaka Akira <akr@fsij.org>
+
+ * ext/ripper/depend (ripper.o): it depends on ruby headers.
+
+Sat Sep 13 19:27:01 2008 Tanaka Akira <akr@fsij.org>
+
+ * io.c (io_encoding_set): don't need argc argument.
+ (rb_io_s_pipe): update io_encoding_set call.
+ (rb_io_set_encoding): ditto.
+
+Sat Sep 13 18:46:41 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode.c (rb_transcoding): align state field.
+
+Sat Sep 13 18:21:09 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode.c (DECORATOR_P): renamed from SUPPLEMENTAL_CONVERSION.
+
+Sat Sep 13 18:05:37 2008 Tanaka Akira <akr@fsij.org>
+
+ * io.c (make_writeconv): use rb_enc_name.
+ (make_readconv): ditto.
+
+ * transcode.c (rb_econv_open_opts): ditto.
+ (econv_args): ditto.
+ (decorate_convpath): ditto.
+ (econv_set_replacement): ditto.
+
+Sat Sep 13 11:15:38 2008 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/rexml/document.rb: fixed typo.
+
+Sat Sep 13 10:53:13 2008 Tadayoshi Funaba <tadf@dotrb.org>
+
+ * complex.c: refined.
+
+ * rational.c: ditto.
+
+Sat Sep 13 03:44:52 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode.c (rb_econv_prepare_opts): raise ArgumentError if
+ a broken string is specified as a replacement.
+
+Sat Sep 13 03:31:05 2008 Tanaka Akira <akr@fsij.org>
+
+ * iseq.c (iseq_s_compile_file): use rb_file_open_str.
+
+ * io.c (rb_file_open_generic): call validate_enc_binmode.
+ (rb_file_open_str): call FilePathValue.
+
+Sat Sep 13 02:58:05 2008 Tanaka Akira <akr@fsij.org>
+
+ * io.c (validate_enc_binmode): extracted from rb_io_extract_modeenc.
+ (rb_io_extract_modeenc): use validate_enc_binmode.
+ (io_encoding_set): call validate_enc_binmode.
+
+Sat Sep 13 02:50:34 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode.c (rb_econv_prepare_opts): initialize *opt and return 0
+ if opthash is nil.
+
+Sat Sep 13 02:29:19 2008 Tanaka Akira <akr@fsij.org>
+
+ * enc/trans/escape.trans: transcoder name renamed to use underscore.
+
+ * transcode.c: follow the renaming.
+
+Sat Sep 13 02:12:17 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode.c (rb_econv_init_by_convpath_i): new function.
+ (rb_econv_init_by_convpath): new function.
+ (econv_init): use rb_econv_init_by_convpath.
+
+Sat Sep 13 01:11:14 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode.c (econv_args): take snamev_p and dnamev_p to prevent
+ possible GC problem.
+
+Sat Sep 13 00:38:54 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode.c (enc_arg): take arg as VALUE * to prevent possible GC
+ problem.
+
+Fri Sep 12 23:19:41 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode.c (rb_econv_add_transcoder_at): fix loop condition.
+
+Fri Sep 12 22:39:46 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode.c (decorator_names): extracted from rb_econv_open.
+ (rb_econv_open): use decorator_names.
+ (econv_args): extracted from econv_init.
+ (econv_init): use econv_args.
+ (decorate_convpath): new function.
+ (search_convpath_i): new function.
+ (econv_s_search_convpath): new method.
+ (Init_transcode): new method defined.
+
+Fri Sep 12 21:55:43 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode.c (rb_econv_t): new field: num_allocated.
+ (rb_econv_alloc): extracted from
+ rb_econv_open_by_transcoder_entries.
+ (rb_econv_add_transcoder_at): extracted from rb_econv_decorate_at
+ and generalized
+ (rb_econv_open_by_transcoder_entries): use rb_econv_alloc and
+ rb_econv_add_transcoder_at.
+ (rb_econv_add_converter): extracted from rb_econv_decorate_at.
+ (rb_econv_decorate_at): use rb_econv_add_converter.
+
+
+Fri Sep 12 21:22:09 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode.c (rb_econv_t): new field: started.
+ (rb_econv_open_by_transcoder_entries): initialize started field.
+ (rb_econv_convert): set started field.
+ (rb_econv_insert_output): ditto.
+ (rb_econv_decorate_at): check started field instead of num_finished.
+
+Fri Sep 12 20:28:59 2008 Tanaka Akira <akr@fsij.org>
+
+ * regenc.c (onigenc_single_byte_code_to_mbc): follow OnigEncoding
+ change.
+
+Fri Sep 12 20:00:22 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * regparse.c (parse_exp): fix resource leak.
+
+Fri Sep 12 01:21:22 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * ext/syck/node.c (syck_replace_str2): fix wrong check to free ptr.
+
+Thu Sep 11 20:18:24 2008 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * test/win32ole/test_err_in_callback.rb (teardown): get rid
+ of infinite loop.
+
+Thu Sep 11 19:12:56 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * include/ruby/oniguruma.h (OnigCodePoint): unsigned long to unsigned int.
+
+ * include/ruby/encoding.h (rb_enc_codepoint): ditto.
+
+ * encoding.c (rb_enc_codepoint): signed int to unsigned int.
+
+ * encoding.c (rb_enc_ascget): ditto.
+
+ * string.c (rb_str_casecmp): ditto.
+
+ * string.c (enc_succ_alnum_char): ditto.
+
+ * string.c (rb_str_inspect): ditto.
+
+ * string.c (rb_str_upcase_bang): ditto.
+
+ * string.c (rb_str_downcase_bang): ditto.
+
+ * string.c (rb_str_capitalize_bang): ditto.
+
+ * string.c (rb_str_swapcase_bang): ditto.
+
+ * string.c (struct tr): ditto.
+
+ * string.c (trnext): ditto.
+
+ * string.c (tr_trans): ditto.
+
+ * string.c (tr_setup_table): ditto.
+
+ * string.c (tr_find): ditto.
+
+ * string.c (rb_str_delete_bang): ditto.
+
+ * string.c (rb_str_squeeze_bang): ditto.
+
+ * string.c (rb_str_count): ditto.
+
+ * string.c (rb_str_split_m): ditto.
+
+ * string.c (rb_str_each_line): ditto.
+
+ * string.c (rb_str_lstrip_bang): ditto.
+
+ * string.c (rb_str_rstrip_bang): ditto.
+
+ * string.c (rb_str_intern): ditto.
+
+ * dir.c (char_casecmp): ditto.
+
+ * sprintf.c (rb_str_format): ditto.
+
+ * enc/emacs_mule.c (mbc_to_code): to be 32bit clean.
+
+ * enc/emacs_mule.c (code_to_mbc): ditto.
+
+ * enc/gb18030.c (mbc_to_code): ditto.
+
+ * enc/gb18030.c (code_to_mbc): ditto.
+
+Thu Sep 11 19:09:25 2008 NARUSE, Yui <naruse@ruby-lang.org>
+
+ * ext/iconv/iconv.c: add attention for machine independent.
+
+Thu Sep 11 15:23:26 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (bigdivrem): adjust length for division and remainder.
+ a patch from TOYOFUKU Chikanobu <nobu_toyofuku at nifty.com> in
+ [ruby-dev:36231].
+
+Thu Sep 11 02:59:47 2008 Tanaka Akira <akr@fsij.org>
+
+ * io.c (io_binwrite): extracted from io_fwrite.
+
+Thu Sep 11 02:25:34 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode.c (make_encoding): new function.
+ (make_encobj): new function.
+ (econv_s_asciicompat_encoding): use make_encoding.
+ (rb_econv_open_exc): use SUPPLEMENTAL_CONVERSION.
+ (econv_convpath): use encoding object in the result.
+
+Thu Sep 11 02:14:38 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode.c (econv_convpath): new method.
+
+Wed Sep 10 23:00:43 2008 Yusuke Endoh <mame@tsg.ne.jp>
+
+ * tool/compile_prelude.rb: print "<internal:prelude>" instead of
+ "prelude.rb" on stack trace. [ruby-dev:36129]
+
+Wed Sep 10 21:19:58 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (big2str_karatsuba): remove unnecessary fixnum code. a
+ patch from TOYOFUKU Chikanobu <nobu_toyofuku at nifty.com> in
+ [ruby-dev:36217].
+
+Wed Sep 10 21:09:32 2008 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * test/win32ole/test_err_in_callback.rb: InternetExplorer should
+ be closed.
+
+ * test/win32ole/err_in_callback.rb: ditto.
+
+Wed Sep 10 18:25:19 2008 akira yamada <akira@rice.p.arika.org>
+
+ * lib/uri/common.rb (URI::Parser): new class.
+
+ * lib/uri/mailto.rb, lib/uri/generic.rb: follow the above change.
+
+ * test/uri/test_parser.rb: added tests for URI::Parser.
+
+Wed Sep 10 10:35:32 2008 Takeyuki Fujioka <xibbar@ruby-lang.org>
+
+ * lib/cgi/cookie.rb (CGI::Cookie#to_s): performance improvement
+ from http://jp.rubyist.net/magazine/?0023-Cgirb.
+
+Wed Sep 10 10:12:29 2008 akira yamada <akira@arika.org>
+
+ * lib/sync.rb (Sync_m#sync_exclusive): fixed
+ typo. [ruby-dev:36233] [RubyForge#11680]
+
+Wed Sep 10 01:57:23 2008 Tanaka Akira <akr@fsij.org>
+
+ * tool/transcode-tblgen.rb (StrSet#hash): cache hash value.
+ (ActionMap#hash): ditto.
+
+Wed Sep 10 01:26:01 2008 Tanaka Akira <akr@fsij.org>
+
+ * include/ruby/encoding.h (econv_after_output): renamed from
+ econv_output_followed_by_input.
+ (ECONV_AFTER_OUTPUT): renamed from ECONV_OUTPUT_FOLLOWED_BY_INPUT.
+
+ * transcode.c: follow the renaming.
+
+ * io.c: ditto.
+
+Wed Sep 10 01:16:07 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode.c (get_replacement_character): don't return ASCII
+ incompatible replacements.
+ (make_replacement): don't convert the result of
+ get_replacement_character.
+
+Wed Sep 10 01:05:00 2008 Tanaka Akira <akr@fsij.org>
+
+ * enc/trans/newline.trans (rb_universal_newline): swap src_encoding
+ and dst_encoding.
+
+ * transcode.c (rb_econv_decorate_at): call get_transcoder_entry only
+ once.
+ (rb_econv_binmode): follow universal_newline change.
+
+Wed Sep 10 00:01:36 2008 Tanaka Akira <akr@fsij.org>
+
+ * include/ruby/io.h (rb_io_t): rename field: writeconv_stateless to
+ writeconv_asciicompat.
+
+ * io.c: follow the renaming.
+
+ * gc.c: ditto.
+
+Tue Sep 9 23:55:26 2008 Tanaka Akira <akr@fsij.org>
+
+ * io.c (io_fwrite): raise an error if ASCII incompatible string
+ written for text mode IO without encoding conversion.
+ (rb_io_extract_modeenc): binmode requirement changed.
+
+Tue Sep 9 21:59:48 2008 Takeyuki Fujioka <xibbar@ruby-lang.org>
+
+ * lib/cgi*: split cgi.rb into four files. [ruby-dev:36041]
+
+Tue Sep 9 21:17:00 2008 Tanaka Akira <akr@fsij.org>
+
+ * include/ruby/encoding.h (ECONV_DECORATOR_MASK): merge
+ ECONV_ENCODER_MASK and ECONV_DECORATOR_MASK.
+ (ECONV_UNIVERSAL_NEWLINE_DECORATOR): renamed from
+ ECONV_UNIVERSAL_NEWLINE_DECODER.
+ (ECONV_CRLF_NEWLINE_DECORATOR): renamed from
+ ECONV_CRLF_NEWLINE_ENCODER.
+ (ECONV_CR_NEWLINE_DECORATOR): renamed from ECONV_CR_NEWLINE_ENCODER.
+ (ECONV_XML_TEXT_DECORATOR): renamed from ECONV_XML_TEXT_ENCODER.
+ (ECONV_XML_ATTR_CONTENT_DECORATOR): renamed from
+ ECONV_XML_ATTR_CONTENT_ENCODER.
+ (ECONV_STATEFUL_DECORATOR_MASK): renamed from
+ ECONV_STATEFUL_ENCODER_MASK.
+ (ECONV_XML_ATTR_QUOTE_DECORATOR): renamed from
+ ECONV_XML_ATTR_CONTENT_DECORATOR.
+
+ * io.c: follow the renaming.
+
+ * transcode.c: ditto.
+
+Tue Sep 9 20:55:55 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode.c (rb_econv_open0): make it static.
+ (rb_econv_open): place decorators at last.
+
+Tue Sep 9 20:40:15 2008 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * test/openssl/test_ssl.rb (OpenSSL#test_client_session):
+ Debian's openssl 0.9.8g-13 failed at assert(ssl.session_reused?),
+ when use default SSLContext. [ruby-dev:36167]
+
+Tue Sep 9 20:34:26 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode.c (rb_econv_t): last_trans_index removed.
+ (rb_econv_open_by_transcoder_entries): follow the type change.
+ (rb_econv_open0): ditto.
+ (rb_econv_decorate_at): ditto.
+ (rb_econv_binmode): ditto.
+ (rb_econv_insert_output): simplified because there are no decorators
+ at last.
+
+Tue Sep 9 20:21:54 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode.c (rb_econv_open): reverse the order of decoders.
+
+Tue Sep 9 20:18:26 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode.c (rb_econv_open0): num_encoders and num_decoders removed.
+
+Tue Sep 9 03:59:13 2008 Tanaka Akira <akr@fsij.org>
+
+ * io.c (make_writeconv): useless branch removed.
+
+Tue Sep 9 02:18:20 2008 Tanaka Akira <akr@fsij.org>
+
+ * include/ruby/encoding.h (rb_econv_decorate_at_first): declared.
+ (rb_econv_decorate_at_last): declared.
+
+ * transcode.c (rb_econv_open_by_transcoder_entries): initialize
+ replacement_enc. allocate outbuf for the last transcoder.
+ (rb_econv_open0): extracted from rb_econv_open.
+ (rb_econv_open): use rb_econv_open0 and decorate the result using
+ rb_econv_decorate_at_first and rb_econv_decorate_at_last.
+ (rb_econv_decorate_at): new function.
+ (rb_econv_decorate_at_first): ditto.
+ (rb_econv_decorate_at_last): ditto.
+ (rb_econv_binmode): fix iteration end condition.
+ (econv_init): don't set source_encoding_name and
+ destination_encoding_name because they are set in rb_econv_open0.
+
Tue Sep 9 01:52:28 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
* io.c (Init_IO): max_file_descriptor_lock is per-process resource.
+Tue Sep 9 01:10:54 2008 Tanaka Akira <akr@fsij.org>
+
+ * transcode.c (rb_econv_open): make ec a local variable.
+
Tue Sep 9 00:55:34 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
* eval.c (ruby_vm_init): split from ruby_init.
@@ -506,7 +4642,7 @@ Fri Sep 5 18:37:52 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
Fri Sep 5 18:16:31 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
* ext/iconv/iconv.c (iconv_create): strips glibc style option before
- charset mapping. retris without options if they seemed causing
+ charset mapping. retries without options if they seemed causing
error, and warns. [ruby-dev:36147]
Fri Sep 5 03:09:48 2008 Koichi Sasada <ko1@atdot.net>
@@ -628,7 +4764,8 @@ Thu Sep 4 19:10:27 2008 Tanaka Akira <akr@fsij.org>
* include/ruby/encoding.h (ECONV_INVALID_IGNORE): removed because
it tend to cause security problem. If the behaviour is really
required, ECONV_INVALID_REPLACE with empty string can be used.
- For example, CVE-2006-2313, CVE-2008-1036, [ruby-core:15645]
+ For example, CVE-2006-2313, CVE-2008-1036, [ruby-core:15645],
+ http://unicode.org/reports/tr36/
(ECONV_UNDEF_IGNORE): ditto.
* transcode.c (rb_econv_convert): follow the above change.
@@ -4708,7 +8845,7 @@ Fri Aug 1 23:26:45 2008 NARUSE, Yui <naruse@ruby-lang.org>
* transcode.c (transcode_loop): undefined character is replaced with
only one character. [ruby-dev:35709]
-Fri Aug 01 23:26:22 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+Fri Aug 1 23:26:22 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
Merged r16430(akr), r16431(akr), r16433(akr), r16469(nobu), and
r17874(akr) from ruby_1_8.
@@ -4752,7 +8889,7 @@ Fri Aug 1 20:55:27 2008 NARUSE, Yui <naruse@ruby-lang.org>
* enc/trans/japanese.c (to_EUC_JP_EF_infos): change size.
[ruby-dev:35714]
-Fri Aug 01 18:27:15 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
+Fri Aug 1 18:27:15 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
* parse.y (parser_yylex): removed an useless conditional, and magic
comment are ignored unless at the first of line.
@@ -5469,7 +9606,7 @@ Fri Jul 18 14:52:14 2008 NAKAMURA Usaku <usa@ruby-lang.org>
* win32/win32.c (open_ifs_socket): set overlapped mode. this is the
default mode of winsock's socket(), so lacking it is an old bug.
-Fri Jul 18 09:44:30 2008
+Fri Jul 18 09:44:30 2008 Eric Hodel <drbrain@segment7.net>
* lib/rdoc/*: Import RDoc r101.
@@ -6876,6 +11013,7 @@ Tue Jun 24 00:21:53 2008 Yusuke Endoh <mame@tsg.ne.jp>
Adam Strzelecki <ono@java.pl> in [ruby-core:17220].
Tue Jun 24 00:10:53 2008 wanabe <s.wanabe@gmail.com>
+
* compile.c (iseq_build_from_ary): fix expression to obtain
iseq->local_size and iseq->local_table_size. [ruby-dev:35205]
@@ -12745,7 +16883,7 @@ Tue Feb 12 11:38:57 2008 Yukihiro Matsumoto <matz@ruby-lang.org>
* ext/bigdecimal/bigdecimal.c (DoSomeOne): add function name argument.
-Tue Feb 12 10:25:02 2008
+Tue Feb 12 10:25:02 2008 Eric Hodel <drbrain@segment7.net>
* lib/rdoc/rdoc.rb: Wrap parse_files' read in version check for
backwards compatibility.
@@ -12901,7 +17039,7 @@ Sat Feb 9 10:03:07 2008 Tanaka Akira <akr@fsij.org>
* string.c (rb_str_new4): copy encoding from orig, instead of shared
one.
-Sat Feb 09 01:01:38 2008 NARUSE, Yui <naruse@ruby-lang.org>
+Sat Feb 9 01:01:38 2008 NARUSE, Yui <naruse@ruby-lang.org>
* file.c (lchmod_internal): fix warning cast from pointer to integer of
different size.
@@ -22335,11 +26473,11 @@ Thu Aug 23 00:04:45 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
Wed Aug 22 15:59:44 2007 Koichi Sasada <ko1@atdot.net>
* bootstraptest/test_knownbug.rb:
- fix typo of filename (test_knwonbug.rb).
+ fix typo of filename (test_knownbug.rb).
Wed Aug 22 14:04:53 2007 Koichi Sasada <ko1@atdot.net>
- * bootstraptest/test_knwonbug.rb: added. This file will contain
+ * bootstraptest/test_knownbug.rb: added. This file will contain
test cases which point out known bug. If bug is fixed, tests
should move to the suitable place.
diff --git a/LEGAL b/LEGAL
index 51dfb22de1..96cc4fdb39 100644
--- a/LEGAL
+++ b/LEGAL
@@ -5,18 +5,50 @@ All the files in this distribution are covered under either the Ruby's
license (see the file COPYING) or public-domain except some files
mentioned below.
-oniguruma.h:
+include/ruby/oniguruma.h:
regcomp.c:
regenc.[ch]:
regerror.c:
-regex.c:
regexec.c:
regint.h:
regparse.[ch]:
-ascii.c:
-euc_jp.c:
-sjis.c:
-utf8.c:
+enc/ascii.c
+enc/big5.c
+enc/cp949.c
+enc/emacs_mule.c
+enc/encdb.c
+enc/euc_jp.c
+enc/euc_kr.c
+enc/euc_tw.c
+enc/gb18030.c
+enc/gb2312.c
+enc/gbk.c
+enc/iso_8859_1.c
+enc/iso_8859_10.c
+enc/iso_8859_11.c
+enc/iso_8859_13.c
+enc/iso_8859_14.c
+enc/iso_8859_15.c
+enc/iso_8859_16.c
+enc/iso_8859_2.c
+enc/iso_8859_3.c
+enc/iso_8859_4.c
+enc/iso_8859_5.c
+enc/iso_8859_6.c
+enc/iso_8859_7.c
+enc/iso_8859_8.c
+enc/iso_8859_9.c
+enc/koi8_r.c
+enc/koi8_u.c
+enc/shift_jis.c
+enc/unicode.c
+enc/us_ascii.c
+enc/utf_16be.c
+enc/utf_16le.c
+enc/utf_32be.c
+enc/utf_32le.c
+enc/utf_8.c
+enc/windows_1251.c
Oniguruma ---- (C) K.Kosako <sndgk393 AT ybb DOT ne DOT jp>
@@ -139,7 +171,6 @@ random.c
email: matumoto@math.keio.ac.jp
st.[ch]:
-x68/*:
missing/alloca.c:
missing/dup2.c:
missing/finite.c:
@@ -149,8 +180,6 @@ missing/isnan.c:
missing/memcmp.c:
missing/memmove.c:
missing/strchr.c:
-missing/streror.c:
-missing/strftime.c:
missing/strstr.c:
missing/strtol.c:
ext/digest/sha1/sha1.[ch]:
@@ -269,18 +298,7 @@ ext/digest/rmd160/rmd160.[ch]:
Copyright (c) Katholieke Universiteit Leuven
1996, All Rights Reserved
-ext/digest/rmd160/rmd160hl.c:
-ext/digest/sha1/sha1hl.c:
-
- These files are under the beer-ware license.
-
- "THE BEER-WARE LICENSE" (Revision 42):
- <phk@login.dkuug.dk> wrote this file. As long as you retain this notice you
- can do whatever you want with this stuff. If we meet some day, and you think
- this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
-
ext/digest/sha2/sha2.[ch]:
-ext/digest/sha2/sha2hl.c:
These files are under the new-style BSD license.
diff --git a/Makefile.in b/Makefile.in
index ad5c20f7b6..dbe1b52533 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -185,16 +185,16 @@ $(srcdir)/configure: $(srcdir)/configure.in
# * GNU make v.s. HP-UX make # HP-UX make invokes the action if lex.c and keywords has same mtime.
# * svn checkout generate a file with mtime as current time
# * XFS has a mtime with fractional part
-lex.c: keywords
+lex.c: defs/keywords
@\
- if cmp -s $(srcdir)/lex.c.src $?; then \
+ if cmp -s $(srcdir)/defs/lex.c.src $?; then \
set -x; \
cp $(srcdir)/lex.c.blt $@; \
else \
set -x; \
gperf -C -p -j1 -i 1 -g -o -t -N rb_reserved_word -k1,3,$$ $? > $@.tmp && \
mv $@.tmp $@ && \
- cp $? $(srcdir)/lex.c.src && \
+ cp $? $(srcdir)/defs/lex.c.src && \
cp $@ $(srcdir)/lex.c.blt; \
fi
diff --git a/README b/README
index b898003937..7e8370ec59 100644
--- a/README
+++ b/README
@@ -16,8 +16,9 @@ Perl). It is simple, straight-forward, and extensible.
+ Iterators and Closures
+ Garbage Collection
+ Dynamic Loading of Object files(on some architecture)
- + Highly Portable(works on many UNIX machines, and on DOS,
- Windows, Mac, BeOS etc.)
+ + Highly Portable (works on many Unix-like/POSIX compatible platforms
+ as well as Windows, Mac OS X, BeOS etc.)
+ cf. http://redmine.ruby-lang.org/wiki/ruby-19/SupportedPlatforms
* How to get Ruby
diff --git a/README.EXT b/README.EXT
index 1f611dd4d1..edfbf221a6 100644
--- a/README.EXT
+++ b/README.EXT
@@ -816,7 +816,7 @@ ruby evaluator (a.k.a. YARV)
vm.c
vm_dump.c
vm_eval.c
- vm_evalbody.c
+ vm_exec.c
vm_insnhelper.c
vm_method.c
@@ -876,7 +876,6 @@ class library
math.c : Math
numeric.c : Numeric, Integer, Fixnum, Float
pack.c : Array#pack, String#unpack
- prec.c : Precision
proc.c : Binding, Proc
process.c : Process
random.c : random number
@@ -889,6 +888,9 @@ class library
struct.c : Struct
time.c : Time
+ defs/knwon_errors.def : Errno::* exception classes
+ -> known_errors.inc : automatically generated
+
multilingualization
encoding.c : Encoding
transcode.c : Encoding::Converter
@@ -898,7 +900,8 @@ multilingualization
goruby interpreter implementation
goruby.c
- golf_prelude.rb
+ golf_prelude.rb : goruby specific libraries.
+ -> golf_prelude.c : automatically generated
Appendix B. Ruby extension API reference
diff --git a/README.EXT.ja b/README.EXT.ja
index 9e31cd0ac6..9a8a4fd610 100644
--- a/README.EXT.ja
+++ b/README.EXT.ja
@@ -927,7 +927,7 @@ Rubyの評価器(通称YARV)
vm.c
vm_dump.c
vm_eval.c
- vm_evalbody.c
+ vm_exec.c
vm_insnhelper.c
vm_method.c
@@ -986,10 +986,9 @@ Rubyコマンドの実装
math.c : Math
numeric.c : Numeric, Integer, Fixnum, Float
pack.c : Array#pack, String#unpack
- prec.c : Precision
proc.c : Binding, Proc
process.c : Process
- random.c : random number
+ random.c : 乱数
range.c : Range
rational.c : Rational
re.c : Regexp, MatchData
@@ -999,6 +998,9 @@ Rubyコマンドの実装
struct.c : Struct
time.c : Time
+ defs/knwon_errors.def : 例外クラス Errno::*
+ -> known_errors.inc : 自動生成
+
多言語化
encoding.c : Encoding
transcode.c : Encoding::Converter
@@ -1008,7 +1010,8 @@ Rubyコマンドの実装
gorubyコマンドの実装
goruby.c
- golf_prelude.rb
+ golf_prelude.rb : goruby固有のライブラリ
+ -> golf_prelude.c : 自動生成
Appendix B. 拡張用関数リファレンス
diff --git a/README.ja b/README.ja
index 16dbd9368d..aeb170734d 100644
--- a/README.ja
+++ b/README.ja
@@ -20,9 +20,9 @@ Rubyはテキスト処理関係の能力などに優れ,Perlと同じくらい強力
+ イテレータとクロージャ
+ ガーベージコレクタ
+ ダイナミックローディング (アーキテクチャによる)
- + 移植性が高い.多くのUNIX上で動くだけでなく,DOSやWindows,
- Mac,BeOSなどの上でも動く
-
+ + 移植性が高い.多くのUnix-like/POSIX互換プラットフォーム上で
+ 動くだけでなく,Windows, Mac OS X,BeOSなどの上でも動く
+ cf. http://redmine.ruby-lang.org/wiki/ruby-19/SupportedPlatformsJa
* 入手法
diff --git a/array.c b/array.c
index 6195d27d07..26cbe5479b 100644
--- a/array.c
+++ b/array.c
@@ -15,6 +15,11 @@
#include "ruby/util.h"
#include "ruby/st.h"
+#ifndef ARRAY_DEBUG
+# define NDEBUG
+#endif
+#include <assert.h>
+
static ID id_cmp;
#define ARY_DEFAULT_SIZE 16
@@ -36,18 +41,182 @@ memfill(register VALUE *mem, register long size, register VALUE val)
}
}
-#define ARY_SHARED_P(a) FL_TEST(a, ELTS_SHARED)
+# define ARY_SHARED_P(ary) \
+ (assert(!FL_TEST(ary, ELTS_SHARED) || !FL_TEST(ary, RARRAY_EMBED_FLAG)), \
+ FL_TEST(ary,ELTS_SHARED))
+# define ARY_EMBED_P(ary) \
+ (assert(!FL_TEST(ary, ELTS_SHARED) || !FL_TEST(ary, RARRAY_EMBED_FLAG)), \
+ FL_TEST(ary, RARRAY_EMBED_FLAG))
+
+#define ARY_HEAP_PTR(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.ptr)
+#define ARY_HEAP_LEN(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.len)
+#define ARY_EMBED_PTR(a) (assert(ARY_EMBED_P(a)), RARRAY(a)->as.ary)
+#define ARY_EMBED_LEN(a) \
+ (assert(ARY_EMBED_P(a)), \
+ (long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \
+ (RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT)))
+#define ARY_OWNS_HEAP_P(a) (!FL_TEST(a, ELTS_SHARED|RARRAY_EMBED_FLAG))
+#define FL_SET_EMBED(a) do { \
+ assert(!ARY_SHARED_P(a)); \
+ assert(!OBJ_FROZEN(a)); \
+ FL_SET(a, RARRAY_EMBED_FLAG); \
+} while (0)
+#define FL_UNSET_EMBED(ary) FL_UNSET(ary, RARRAY_EMBED_FLAG|RARRAY_EMBED_LEN_MASK)
+#define FL_SET_SHARED(ary) do { \
+ assert(!ARY_EMBED_P(ary)); \
+ FL_SET(ary, ELTS_SHARED); \
+} while (0)
+#define FL_UNSET_SHARED(ary) FL_UNSET(ary, ELTS_SHARED)
+
+#define ARY_SET_PTR(ary, p) do { \
+ assert(!ARY_EMBED_P(ary)); \
+ assert(!OBJ_FROZEN(ary)); \
+ RARRAY(ary)->as.heap.ptr = (p); \
+} while (0)
+#define ARY_SET_EMBED_LEN(ary, n) do { \
+ long tmp_n = n; \
+ assert(ARY_EMBED_P(ary)); \
+ assert(!OBJ_FROZEN(ary)); \
+ RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK; \
+ RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT; \
+} while (0)
+#define ARY_SET_HEAP_LEN(ary, n) do { \
+ assert(!ARY_EMBED_P(ary)); \
+ RARRAY(ary)->as.heap.len = n; \
+} while (0)
#define ARY_SET_LEN(ary, n) do { \
- RARRAY(ary)->len = (n);\
+ if (ARY_EMBED_P(ary)) { \
+ ARY_SET_EMBED_LEN(ary, n); \
+ } \
+ else { \
+ ARY_SET_HEAP_LEN(ary, n); \
+ } \
+ assert(RARRAY_LEN(ary) == n); \
} while (0)
+#define ARY_INCREASE_PTR(ary, n) do { \
+ assert(!ARY_EMBED_P(ary)); \
+ assert(!OBJ_FROZEN(ary)); \
+ RARRAY(ary)->as.heap.ptr += n; \
+} while (0)
+#define ARY_INCREASE_LEN(ary, n) do { \
+ assert(!OBJ_FROZEN(ary)); \
+ if (ARY_EMBED_P(ary)) { \
+ ARY_SET_EMBED_LEN(ary, RARRAY_LEN(ary)+n); \
+ } \
+ else { \
+ RARRAY(ary)->as.heap.len += n; \
+ } \
+} while (0)
-#define ARY_CAPA(ary) RARRAY(ary)->aux.capa
-#define RESIZE_CAPA(ary,capacity) do {\
- REALLOC_N(RARRAY(ary)->ptr, VALUE, (capacity));\
- RARRAY(ary)->aux.capa = (capacity);\
+#define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? RARRAY_EMBED_LEN_MAX : \
+ ARY_SHARED_ROOT_P(ary) ? RARRAY_LEN(ary) : RARRAY(ary)->as.heap.aux.capa)
+#define ARY_SET_CAPA(ary, n) do { \
+ assert(!ARY_EMBED_P(ary)); \
+ assert(!ARY_SHARED_P(ary)); \
+ assert(!OBJ_FROZEN(ary)); \
+ RARRAY(ary)->as.heap.aux.capa = (n); \
+} while (0)
+
+#define ARY_SHARED(ary) (assert(ARY_SHARED_P(ary)), RARRAY(ary)->as.heap.aux.shared)
+#define ARY_SET_SHARED(ary, value) do { \
+ assert(!ARY_EMBED_P(ary)); \
+ assert(ARY_SHARED_P(ary)); \
+ assert(ARY_SHARED_ROOT_P(value)); \
+ RARRAY(ary)->as.heap.aux.shared = (value); \
+} while (0)
+#define RARRAY_SHARED_ROOT_FLAG FL_USER5
+#define ARY_SHARED_ROOT_P(ary) (FL_TEST(ary, RARRAY_SHARED_ROOT_FLAG))
+#define ARY_SHARED_NUM(ary) \
+ (assert(ARY_SHARED_ROOT_P(ary)), RARRAY(ary)->as.heap.aux.capa)
+#define ARY_SET_SHARED_NUM(ary, value) do { \
+ assert(ARY_SHARED_ROOT_P(ary)); \
+ RARRAY(ary)->as.heap.aux.capa = (value); \
+} while (0)
+#define FL_SET_SHARED_ROOT(ary) do { \
+ assert(!ARY_EMBED_P(ary)); \
+ FL_SET(ary, RARRAY_SHARED_ROOT_FLAG); \
} while (0)
+static void
+ary_resize_capa(VALUE ary, long capacity)
+{
+ assert(RARRAY_LEN(ary) <= capacity);
+ assert(!OBJ_FROZEN(ary));
+ assert(!ARY_SHARED_P(ary));
+ if (capacity > RARRAY_EMBED_LEN_MAX) {
+ if (ARY_EMBED_P(ary)) {
+ long len = ARY_EMBED_LEN(ary);
+ VALUE *ptr = ALLOC_N(VALUE, (capacity));
+ MEMCPY(ptr, ARY_EMBED_PTR(ary), VALUE, len);
+ FL_UNSET_EMBED(ary);
+ ARY_SET_PTR(ary, ptr);
+ ARY_SET_HEAP_LEN(ary, len);
+ }
+ else {
+ REALLOC_N(RARRAY(ary)->as.heap.ptr, VALUE, (capacity));
+ }
+ ARY_SET_CAPA(ary, (capacity));
+ }
+ else {
+ if (!ARY_EMBED_P(ary)) {
+ long len = RARRAY_LEN(ary);
+ VALUE *ptr = RARRAY_PTR(ary);
+ MEMCPY(RARRAY(ary)->as.ary, ptr, VALUE, len);
+ FL_SET_EMBED(ary);
+ ARY_SET_LEN(ary, len);
+ xfree(ptr);
+ }
+ }
+}
+
+static void
+rb_ary_decrement_share(VALUE shared)
+{
+ if (shared) {
+ int num = ARY_SHARED_NUM(shared) - 1;
+ if (num == 0) {
+ rb_ary_free(shared);
+ rb_gc_force_recycle(shared);
+ }
+ else if (num > 0) {
+ ARY_SET_SHARED_NUM(shared, num);
+ }
+ }
+}
+
+static void
+rb_ary_unshare(VALUE ary)
+{
+ VALUE shared = RARRAY(ary)->as.heap.aux.shared;
+ rb_ary_decrement_share(shared);
+ FL_UNSET_SHARED(ary);
+}
+
+static inline void
+rb_ary_unshare_safe(VALUE ary) {
+ if (ARY_SHARED_P(ary) && !ARY_EMBED_P(ary)) {
+ rb_ary_unshare(ary);
+ }
+}
+
+static VALUE
+rb_ary_increment_share(VALUE shared) {
+ int num = ARY_SHARED_NUM(shared);
+ if (num >= 0) {
+ ARY_SET_SHARED_NUM(shared, num + 1);
+ }
+ return shared;
+}
+
+static void
+rb_ary_set_shared(VALUE ary, VALUE shared)
+{
+ rb_ary_increment_share(shared);
+ FL_SET_SHARED(ary);
+ ARY_SET_SHARED(ary, shared);
+}
+
static inline void
rb_ary_modify_check(VALUE ary)
{
@@ -59,15 +228,25 @@ rb_ary_modify_check(VALUE ary)
static void
rb_ary_modify(VALUE ary)
{
- VALUE *ptr;
-
rb_ary_modify_check(ary);
if (ARY_SHARED_P(ary)) {
- ptr = ALLOC_N(VALUE, RARRAY_LEN(ary));
- FL_UNSET(ary, ELTS_SHARED);
- RARRAY(ary)->aux.capa = RARRAY_LEN(ary);
- MEMCPY(ptr, RARRAY_PTR(ary), VALUE, RARRAY_LEN(ary));
- RARRAY(ary)->ptr = ptr;
+ long len = RARRAY_LEN(ary);
+ if (len <= RARRAY_EMBED_LEN_MAX) {
+ VALUE *ptr = ARY_HEAP_PTR(ary);
+ VALUE shared = ARY_SHARED(ary);
+ FL_UNSET_SHARED(ary);
+ FL_SET_EMBED(ary);
+ MEMCPY(ARY_EMBED_PTR(ary), ptr, VALUE, len);
+ rb_ary_decrement_share(shared);
+ ARY_SET_EMBED_LEN(ary, len);
+ }
+ else {
+ VALUE *ptr = ALLOC_N(VALUE, len);
+ MEMCPY(ptr, RARRAY_PTR(ary), VALUE, len);
+ rb_ary_unshare(ary);
+ ARY_SET_CAPA(ary, len);
+ ARY_SET_PTR(ary, ptr);
+ }
}
}
@@ -97,10 +276,8 @@ ary_alloc(VALUE klass)
{
NEWOBJ(ary, struct RArray);
OBJSETUP(ary, klass, T_ARRAY);
-
- ary->len = 0;
- ary->ptr = 0;
- ary->aux.capa = 0;
+ FL_SET_EMBED((VALUE)ary);
+ ARY_SET_EMBED_LEN((VALUE)ary, 0);
return (VALUE)ary;
}
@@ -117,9 +294,12 @@ ary_new(VALUE klass, long len)
rb_raise(rb_eArgError, "array size too big");
}
ary = ary_alloc(klass);
- if (len == 0) len++;
- RARRAY(ary)->ptr = ALLOC_N(VALUE, len);
- RARRAY(ary)->aux.capa = len;
+ if (len > RARRAY_EMBED_LEN_MAX) {
+ FL_UNSET_EMBED(ary);
+ ARY_SET_PTR(ary, ALLOC_N(VALUE, len));
+ ARY_SET_CAPA(ary, len);
+ ARY_SET_HEAP_LEN(ary, 0);
+ }
return ary;
}
@@ -134,7 +314,7 @@ rb_ary_new2(long len)
VALUE
rb_ary_new(void)
{
- return rb_ary_new2(ARY_DEFAULT_SIZE);
+ return rb_ary_new2(RARRAY_EMBED_LEN_MAX);
}
#include <stdarg.h>
@@ -154,7 +334,7 @@ rb_ary_new3(long n, ...)
}
va_end(ar);
- RARRAY(ary)->len = n;
+ ARY_SET_LEN(ary, n);
return ary;
}
@@ -166,7 +346,7 @@ rb_ary_new4(long n, const VALUE *elts)
ary = rb_ary_new2(n);
if (n > 0 && elts) {
MEMCPY(RARRAY_PTR(ary), elts, VALUE, n);
- RARRAY(ary)->len = n;
+ ARY_SET_LEN(ary, n);
}
return ary;
@@ -181,31 +361,49 @@ rb_ary_tmp_new(long len)
void
rb_ary_free(VALUE ary)
{
- if (!ARY_SHARED_P(ary)) {
- xfree(RARRAY(ary)->ptr);
+ if (ARY_OWNS_HEAP_P(ary)) {
+ xfree(RARRAY_PTR(ary));
}
}
static VALUE
ary_make_shared(VALUE ary)
{
+ assert(!ARY_EMBED_P(ary));
if (ARY_SHARED_P(ary)) {
- return RARRAY(ary)->aux.shared;
+ return ARY_SHARED(ary);
}
else {
NEWOBJ(shared, struct RArray);
OBJSETUP(shared, 0, T_ARRAY);
-
- shared->len = RARRAY(ary)->len;
- shared->ptr = RARRAY(ary)->ptr;
- shared->aux.capa = RARRAY(ary)->aux.capa;
- RARRAY(ary)->aux.shared = (VALUE)shared;
- FL_SET(ary, ELTS_SHARED);
+ FL_UNSET_EMBED(shared);
+
+ ARY_SET_LEN((VALUE)shared, RARRAY_LEN(ary));
+ ARY_SET_PTR((VALUE)shared, RARRAY_PTR(ary));
+ FL_SET_SHARED_ROOT(shared);
+ ARY_SET_SHARED_NUM((VALUE)shared, 1);
+ FL_SET_SHARED(ary);
+ ARY_SET_SHARED(ary, (VALUE)shared);
OBJ_FREEZE(shared);
return (VALUE)shared;
}
}
+
+static VALUE
+ary_make_substitution(VALUE ary)
+{
+ if (RARRAY_LEN(ary) <= RARRAY_EMBED_LEN_MAX) {
+ VALUE subst = rb_ary_new2(RARRAY_LEN(ary));
+ MEMCPY(ARY_EMBED_PTR(subst), RARRAY_PTR(ary), VALUE, RARRAY_LEN(ary));
+ ARY_SET_EMBED_LEN(subst, RARRAY_LEN(ary));
+ return subst;
+ }
+ else {
+ return rb_ary_increment_share(ary_make_shared(ary));
+ }
+}
+
VALUE
rb_assoc_new(VALUE car, VALUE cdr)
{
@@ -296,10 +494,12 @@ rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
rb_ary_modify(ary);
if (argc == 0) {
- if (RARRAY_PTR(ary) && !ARY_SHARED_P(ary)) {
- xfree(RARRAY(ary)->ptr);
+ if (ARY_OWNS_HEAP_P(ary) && RARRAY_PTR(ary)) {
+ xfree(RARRAY_PTR(ary));
}
- RARRAY(ary)->len = 0;
+ rb_ary_unshare_safe(ary);
+ FL_SET_EMBED(ary);
+ ARY_SET_EMBED_LEN(ary, 0);
if (rb_block_given_p()) {
rb_warning("given block not used");
}
@@ -322,7 +522,7 @@ rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
rb_raise(rb_eArgError, "array size too big");
}
rb_ary_modify(ary);
- RESIZE_CAPA(ary, len);
+ ary_resize_capa(ary, len);
if (rb_block_given_p()) {
long i;
@@ -331,12 +531,12 @@ rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
}
for (i=0; i<len; i++) {
rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
- RARRAY(ary)->len = i + 1;
+ ARY_SET_LEN(ary, i + 1);
}
}
else {
memfill(RARRAY_PTR(ary), len, val);
- RARRAY(ary)->len = len;
+ ARY_SET_LEN(ary, len);
}
return ary;
}
@@ -353,15 +553,11 @@ rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
static VALUE
rb_ary_s_create(int argc, VALUE *argv, VALUE klass)
{
- VALUE ary = ary_alloc(klass);
-
- if (argc < 0) {
- rb_raise(rb_eArgError, "negative array size");
+ VALUE ary = ary_new(klass, argc);
+ if (argc > 0 && argv) {
+ MEMCPY(RARRAY_PTR(ary), argv, VALUE, argc);
+ ARY_SET_LEN(ary, argc);
}
- RARRAY(ary)->ptr = ALLOC_N(VALUE, argc);
- RARRAY(ary)->aux.capa = argc;
- MEMCPY(RARRAY_PTR(ary), argv, VALUE, argc);
- RARRAY(ary)->len = argc;
return ary;
}
@@ -391,7 +587,7 @@ rb_ary_store(VALUE ary, long idx, VALUE val)
new_capa = (ARY_MAX_SIZE - idx) / 2;
}
new_capa += idx;
- RESIZE_CAPA(ary, new_capa);
+ ary_resize_capa(ary, new_capa);
}
if (idx > RARRAY_LEN(ary)) {
rb_mem_clear(RARRAY_PTR(ary) + RARRAY_LEN(ary),
@@ -399,28 +595,49 @@ rb_ary_store(VALUE ary, long idx, VALUE val)
}
if (idx >= RARRAY_LEN(ary)) {
- RARRAY(ary)->len = idx + 1;
+ ARY_SET_LEN(ary, idx + 1);
}
RARRAY_PTR(ary)[idx] = val;
}
static VALUE
-ary_shared_array(VALUE klass, VALUE ary)
+ary_make_partial(VALUE ary, VALUE klass, long offset, long len)
{
- VALUE val = ary_alloc(klass);
+ assert(offset >= 0);
+ assert(len >= 0);
+ assert(offset+len <= RARRAY_LEN(ary));
- ary_make_shared(ary);
- RARRAY(val)->ptr = RARRAY(ary)->ptr;
- RARRAY(val)->len = RARRAY(ary)->len;
- RARRAY(val)->aux.shared = RARRAY(ary)->aux.shared;
- FL_SET(val, ELTS_SHARED);
- return val;
+ if (len <= RARRAY_EMBED_LEN_MAX) {
+ VALUE result = ary_alloc(klass);
+ MEMCPY(ARY_EMBED_PTR(result), RARRAY_PTR(ary) + offset, VALUE, len);
+ ARY_SET_EMBED_LEN(result, len);
+ return result;
+ }
+ else {
+ VALUE shared, result = ary_alloc(klass);
+ FL_UNSET_EMBED(result);
+
+ shared = ary_make_shared(ary);
+ ARY_SET_PTR(result, RARRAY_PTR(ary));
+ ARY_SET_LEN(result, RARRAY_LEN(ary));
+ rb_ary_set_shared(result, shared);
+
+ ARY_INCREASE_PTR(result, offset);
+ ARY_SET_LEN(result, len);
+ return result;
+ }
}
+enum ary_take_pos_flags
+{
+ ARY_TAKE_FIRST = 0,
+ ARY_TAKE_LAST = 1
+};
+
static VALUE
-ary_shared_first(int argc, VALUE *argv, VALUE ary, int last)
+ary_take_first_or_last(int argc, VALUE *argv, VALUE ary, enum ary_take_pos_flags last)
{
- VALUE nv, result;
+ VALUE nv;
long n;
long offset = 0;
@@ -435,11 +652,7 @@ ary_shared_first(int argc, VALUE *argv, VALUE ary, int last)
if (last) {
offset = RARRAY_LEN(ary) - n;
}
- result = ary_shared_array(rb_cArray, ary);
- RARRAY(result)->ptr += offset;
- RARRAY(result)->len = n;
-
- return result;
+ return ary_make_partial(ary, rb_cArray, offset, n);
}
/*
@@ -490,14 +703,14 @@ rb_ary_pop(VALUE ary)
long n;
rb_ary_modify_check(ary);
if (RARRAY_LEN(ary) == 0) return Qnil;
- if (!ARY_SHARED_P(ary) &&
+ if (ARY_OWNS_HEAP_P(ary) &&
RARRAY_LEN(ary) * 3 < ARY_CAPA(ary) &&
ARY_CAPA(ary) > ARY_DEFAULT_SIZE)
{
- RESIZE_CAPA(ary, RARRAY_LEN(ary) * 2);
+ ary_resize_capa(ary, RARRAY_LEN(ary) * 2);
}
n = RARRAY_LEN(ary)-1;
- RARRAY(ary)->len = n;
+ ARY_SET_LEN(ary, n);
return RARRAY_PTR(ary)[n];
}
@@ -528,8 +741,8 @@ rb_ary_pop_m(int argc, VALUE *argv, VALUE ary)
}
rb_ary_modify_check(ary);
- result = ary_shared_first(argc, argv, ary, Qtrue);
- RARRAY(ary)->len -= RARRAY_LEN(result);
+ result = ary_take_first_or_last(argc, argv, ary, Qtrue);
+ ARY_INCREASE_LEN(ary, -RARRAY_LEN(result));
return result;
}
@@ -544,14 +757,16 @@ rb_ary_shift(VALUE ary)
if (!ARY_SHARED_P(ary)) {
if (RARRAY_LEN(ary) < ARY_DEFAULT_SIZE) {
MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+1, VALUE, RARRAY_LEN(ary)-1);
- RARRAY(ary)->len--;
+ ARY_INCREASE_LEN(ary, -1);
return top;
}
+ assert(!ARY_EMBED_P(ary)); /* ARY_EMBED_LEN_MAX < ARY_DEFAULT_SIZE */
+
RARRAY_PTR(ary)[0] = Qnil;
ary_make_shared(ary);
}
- RARRAY(ary)->ptr++; /* shift ptr */
- RARRAY(ary)->len--;
+ ARY_INCREASE_PTR(ary, 1); /* shift ptr */
+ ARY_INCREASE_LEN(ary, -1);
return top;
}
@@ -588,16 +803,15 @@ rb_ary_shift_m(int argc, VALUE *argv, VALUE ary)
}
rb_ary_modify_check(ary);
- result = ary_shared_first(argc, argv, ary, Qfalse);
+ result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
n = RARRAY_LEN(result);
if (ARY_SHARED_P(ary)) {
- RARRAY(ary)->ptr += n;
- RARRAY(ary)->len -= n;
- }
+ ARY_INCREASE_PTR(ary, n);
+ }
else {
MEMMOVE(RARRAY_PTR(ary), RARRAY_PTR(ary)+n, VALUE, RARRAY_LEN(ary)-n);
- RARRAY(ary)->len -= n;
}
+ ARY_INCREASE_LEN(ary, -n);
return result;
}
@@ -621,14 +835,14 @@ rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary)
if (argc == 0) return ary;
rb_ary_modify(ary);
- if (RARRAY(ary)->aux.capa <= (len = RARRAY(ary)->len) + argc) {
- RESIZE_CAPA(ary, len + argc + ARY_DEFAULT_SIZE);
+ if (ARY_CAPA(ary) <= (len = RARRAY_LEN(ary)) + argc) {
+ ary_resize_capa(ary, len + argc + ARY_DEFAULT_SIZE);
}
/* sliding items */
- MEMMOVE(RARRAY(ary)->ptr + argc, RARRAY(ary)->ptr, VALUE, len);
- MEMCPY(RARRAY(ary)->ptr, argv, VALUE, argc);
- RARRAY(ary)->len += argc;
+ MEMMOVE(RARRAY_PTR(ary) + argc, RARRAY_PTR(ary), VALUE, len);
+ MEMCPY(RARRAY_PTR(ary), argv, VALUE, argc);
+ ARY_INCREASE_LEN(ary, argc);
return ary;
}
@@ -662,8 +876,7 @@ rb_ary_entry(VALUE ary, long offset)
VALUE
rb_ary_subseq(VALUE ary, long beg, long len)
{
- VALUE klass, ary2, shared;
- VALUE *ptr;
+ VALUE klass;
if (beg > RARRAY_LEN(ary)) return Qnil;
if (beg < 0 || len < 0) return Qnil;
@@ -674,15 +887,7 @@ rb_ary_subseq(VALUE ary, long beg, long len)
klass = rb_obj_class(ary);
if (len == 0) return ary_new(klass, 0);
- shared = ary_make_shared(ary);
- ptr = RARRAY_PTR(ary);
- ary2 = ary_alloc(klass);
- RARRAY(ary2)->ptr = ptr + beg;
- RARRAY(ary2)->len = len;
- RARRAY(ary2)->aux.shared = shared;
- FL_SET(ary2, ELTS_SHARED);
-
- return ary2;
+ return ary_make_partial(ary, klass, beg, len);
}
/*
@@ -792,7 +997,7 @@ rb_ary_first(int argc, VALUE *argv, VALUE ary)
return RARRAY_PTR(ary)[0];
}
else {
- return ary_shared_first(argc, argv, ary, Qfalse);
+ return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
}
}
@@ -817,7 +1022,7 @@ rb_ary_last(int argc, VALUE *argv, VALUE ary)
return RARRAY_PTR(ary)[RARRAY_LEN(ary)-1];
}
else {
- return ary_shared_first(argc, argv, ary, Qtrue);
+ return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
}
}
@@ -995,30 +1200,26 @@ rb_ary_splice(VALUE ary, long beg, long len, VALUE rpl)
}
len = beg + rlen;
if (len >= ARY_CAPA(ary)) {
- RESIZE_CAPA(ary, len);
+ ary_resize_capa(ary, len);
}
rb_mem_clear(RARRAY_PTR(ary) + RARRAY_LEN(ary), beg - RARRAY_LEN(ary));
if (rlen > 0) {
MEMCPY(RARRAY_PTR(ary) + beg, RARRAY_PTR(rpl), VALUE, rlen);
}
- RARRAY(ary)->len = len;
+ ARY_SET_LEN(ary, len);
}
else {
long alen;
- if (beg + len > RARRAY_LEN(ary)) {
- len = RARRAY_LEN(ary) - beg;
- }
-
alen = RARRAY_LEN(ary) + rlen - len;
if (alen >= ARY_CAPA(ary)) {
- RESIZE_CAPA(ary, alen);
+ ary_resize_capa(ary, alen);
}
if (len != rlen) {
MEMMOVE(RARRAY_PTR(ary) + beg + rlen, RARRAY_PTR(ary) + beg + len,
VALUE, RARRAY_LEN(ary) - (beg + len));
- RARRAY(ary)->len = alen;
+ ARY_SET_LEN(ary, alen);
}
if (rlen > 0) {
MEMMOVE(RARRAY_PTR(ary) + beg, RARRAY_PTR(rpl), VALUE, rlen);
@@ -1236,10 +1437,11 @@ VALUE
rb_ary_dup(VALUE ary)
{
VALUE dup = rb_ary_new2(RARRAY_LEN(ary));
-
+ int is_embed = ARY_EMBED_P(dup);
DUPSETUP(dup, ary);
+ if (is_embed) FL_SET_EMBED(dup);
MEMCPY(RARRAY_PTR(dup), RARRAY_PTR(ary), VALUE, RARRAY_LEN(ary));
- RARRAY(dup)->len = RARRAY_LEN(ary);
+ ARY_SET_LEN(dup, RARRAY_LEN(ary));
return dup;
}
@@ -1283,7 +1485,10 @@ rb_ary_join(VALUE ary, VALUE sep)
case T_STRING:
break;
case T_ARRAY:
- {
+ if (tmp == ary) {
+ tmp = rb_usascii_str_new2("[...]");
+ }
+ else {
VALUE args[2];
args[0] = tmp;
@@ -1546,8 +1751,9 @@ VALUE
rb_ary_sort_bang(VALUE ary)
{
rb_ary_modify(ary);
+ assert(!ARY_SHARED_P(ary));
if (RARRAY_LEN(ary) > 1) {
- VALUE tmp = ary_make_shared(ary);
+ VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */
struct ary_sort_data data;
RBASIC(tmp)->klass = 0;
@@ -1556,18 +1762,47 @@ rb_ary_sort_bang(VALUE ary)
data.opt_inited = 0;
ruby_qsort(RARRAY_PTR(tmp), RARRAY_LEN(tmp), sizeof(VALUE),
rb_block_given_p()?sort_1:sort_2, &data);
- if (RARRAY(ary)->ptr != RARRAY(tmp)->ptr) {
- if (!ARY_SHARED_P(ary)) xfree(RARRAY(ary)->ptr);
- RARRAY(ary)->ptr = RARRAY(tmp)->ptr;
- RARRAY(ary)->len = RARRAY(tmp)->len;
- RARRAY(ary)->aux.capa = RARRAY(tmp)->aux.capa;
- FL_SET(ary, ELTS_SHARED);
- };
- FL_UNSET(ary, ELTS_SHARED);
- RARRAY(tmp)->ptr = 0;
- RARRAY(tmp)->len = 0;
- RARRAY(tmp)->aux.capa = 0;
- RBASIC(tmp)->klass = rb_cArray;
+
+ if (ARY_EMBED_P(tmp)) {
+ assert(ARY_EMBED_P(tmp));
+ if (ARY_SHARED_P(ary)) { /* ary might be destructively operated in the given block */
+ rb_ary_unshare(ary);
+ }
+ FL_SET_EMBED(ary);
+ MEMCPY(RARRAY_PTR(ary), ARY_EMBED_PTR(tmp), VALUE, ARY_EMBED_LEN(tmp));
+ ARY_SET_LEN(ary, ARY_EMBED_LEN(tmp));
+ }
+ else {
+ assert(!ARY_EMBED_P(tmp));
+ if (ARY_HEAP_PTR(ary) == ARY_HEAP_PTR(tmp)) {
+ assert(!ARY_EMBED_P(ary));
+ FL_UNSET_SHARED(ary);
+ ARY_SET_CAPA(ary, ARY_CAPA(tmp));
+ }
+ else {
+ assert(!ARY_SHARED_P(tmp));
+ if (ARY_EMBED_P(ary)) {
+ FL_UNSET_EMBED(ary);
+ }
+ else if (ARY_SHARED_P(ary)) {
+ /* ary might be destructively operated in the given block */
+ rb_ary_unshare(ary);
+ }
+ else {
+ xfree(ARY_HEAP_PTR(ary));
+ }
+ ARY_SET_PTR(ary, RARRAY_PTR(tmp));
+ ARY_SET_HEAP_LEN(ary, RARRAY_LEN(tmp));
+ ARY_SET_CAPA(ary, ARY_CAPA(tmp));
+ }
+ /* tmp was lost ownership for the ptr */
+ FL_UNSET(tmp, FL_FREEZE);
+ FL_SET_EMBED(tmp);
+ ARY_SET_EMBED_LEN(tmp, 0);
+ FL_SET(tmp, FL_FREEZE);
+ }
+ /* tmp will be GC'ed. */
+ RBASIC(tmp)->klass = rb_cArray;
}
return ary;
}
@@ -1776,10 +2011,10 @@ rb_ary_delete(VALUE ary, VALUE item)
rb_ary_modify(ary);
if (RARRAY_LEN(ary) > i2) {
- RARRAY(ary)->len = i2;
+ ARY_SET_LEN(ary, i2);
if (i2 * 2 < ARY_CAPA(ary) &&
ARY_CAPA(ary) > ARY_DEFAULT_SIZE) {
- RESIZE_CAPA(ary, i2*2);
+ ary_resize_capa(ary, i2*2);
}
}
@@ -1802,7 +2037,7 @@ rb_ary_delete_at(VALUE ary, long pos)
del = RARRAY_PTR(ary)[pos];
MEMMOVE(RARRAY_PTR(ary)+pos, RARRAY_PTR(ary)+pos+1, VALUE,
RARRAY_LEN(ary)-pos-1);
- RARRAY(ary)->len--;
+ ARY_INCREASE_LEN(ary, -1);
return del;
}
@@ -1919,7 +2154,7 @@ rb_ary_reject_bang(VALUE ary)
if (RARRAY_LEN(ary) == i2) return Qnil;
if (i2 < RARRAY_LEN(ary))
- RARRAY(ary)->len = i2;
+ ARY_SET_LEN(ary, i2);
return ary;
}
@@ -2087,22 +2322,41 @@ rb_ary_transpose(VALUE ary)
VALUE
rb_ary_replace(VALUE copy, VALUE orig)
{
- VALUE shared;
- VALUE *ptr;
-
orig = to_ary(orig);
rb_ary_modify_check(copy);
if (copy == orig) return copy;
- shared = ary_make_shared(orig);
- if (!ARY_SHARED_P(copy)) {
- ptr = RARRAY(copy)->ptr;
- xfree(ptr);
- }
- RARRAY(copy)->ptr = RARRAY(orig)->ptr;
- RARRAY(copy)->len = RARRAY(orig)->len;
- RARRAY(copy)->aux.shared = shared;
- FL_SET(copy, ELTS_SHARED);
+ if (RARRAY_LEN(orig) <= RARRAY_EMBED_LEN_MAX) {
+ VALUE *ptr;
+ VALUE shared = 0;
+
+ if (ARY_OWNS_HEAP_P(copy)) {
+ xfree(RARRAY_PTR(copy));
+ }
+ else if (ARY_SHARED_P(copy)) {
+ shared = ARY_SHARED(copy);
+ FL_UNSET_SHARED(copy);
+ }
+ FL_SET_EMBED(copy);
+ ptr = RARRAY_PTR(orig);
+ MEMCPY(RARRAY_PTR(copy), ptr, VALUE, RARRAY_LEN(orig));
+ if (shared) {
+ rb_ary_decrement_share(shared);
+ }
+ ARY_SET_LEN(copy, RARRAY_LEN(orig));
+ }
+ else {
+ VALUE shared = ary_make_shared(orig);
+ if (ARY_OWNS_HEAP_P(copy)) {
+ xfree(RARRAY_PTR(copy));
+ } else {
+ rb_ary_unshare_safe(copy);
+ }
+ FL_UNSET_EMBED(copy);
+ ARY_SET_PTR(copy, RARRAY_PTR(orig));
+ ARY_SET_LEN(copy, RARRAY_LEN(orig));
+ rb_ary_set_shared(copy, shared);
+ }
return copy;
}
@@ -2120,9 +2374,9 @@ VALUE
rb_ary_clear(VALUE ary)
{
rb_ary_modify(ary);
- RARRAY(ary)->len = 0;
+ ARY_SET_LEN(ary, 0);
if (ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
- RESIZE_CAPA(ary, ARY_DEFAULT_SIZE * 2);
+ ary_resize_capa(ary, ARY_DEFAULT_SIZE * 2);
}
return ary;
}
@@ -2196,10 +2450,10 @@ rb_ary_fill(int argc, VALUE *argv, VALUE ary)
end = beg + len;
if (RARRAY_LEN(ary) < end) {
if (end >= ARY_CAPA(ary)) {
- RESIZE_CAPA(ary, end);
+ ary_resize_capa(ary, end);
}
rb_mem_clear(RARRAY_PTR(ary) + RARRAY_LEN(ary), end - RARRAY_LEN(ary));
- RARRAY(ary)->len = end;
+ ARY_SET_LEN(ary, end);
}
if (block_p) {
@@ -2243,7 +2497,7 @@ rb_ary_plus(VALUE x, VALUE y)
z = rb_ary_new2(len);
MEMCPY(RARRAY_PTR(z), RARRAY_PTR(x), VALUE, RARRAY_LEN(x));
MEMCPY(RARRAY_PTR(z) + RARRAY_LEN(x), RARRAY_PTR(y), VALUE, RARRAY_LEN(y));
- RARRAY(z)->len = len;
+ ARY_SET_LEN(z, len);
return z;
}
@@ -2305,7 +2559,7 @@ rb_ary_times(VALUE ary, VALUE times)
len *= RARRAY_LEN(ary);
ary2 = ary_new(rb_obj_class(ary), len);
- RARRAY(ary2)->len = len;
+ ARY_SET_LEN(ary2, len);
for (i=0; i<len; i+=RARRAY_LEN(ary)) {
MEMCPY(RARRAY_PTR(ary2)+i, RARRAY_PTR(ary), VALUE, RARRAY_LEN(ary));
@@ -2714,7 +2968,7 @@ rb_ary_uniq_bang(VALUE ary)
rb_ary_store(ary, j++, v);
}
}
- RARRAY(ary)->len = j;
+ ARY_SET_LEN(ary, j);
return ary;
}
@@ -2766,10 +3020,10 @@ rb_ary_compact_bang(VALUE ary)
if (RARRAY_LEN(ary) == n) {
return Qnil;
}
+ ARY_SET_LEN(ary, n);
if (n * 2 < ARY_CAPA(ary) && ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
- RESIZE_CAPA(ary, n * 2);
+ ary_resize_capa(ary, n * 2);
}
- RARRAY(ary)->len = n;
return ary;
}
@@ -3041,33 +3295,30 @@ rb_ary_sample(int argc, VALUE *argv, VALUE ary)
case 2:
i = rb_genrand_real()*len;
j = rb_genrand_real()*(len-1);
- if (j == i) j++;
+ if (j >= i) j++;
return rb_ary_new3(2, ptr[i], ptr[j]);
case 3:
i = rb_genrand_real()*len;
j = rb_genrand_real()*(len-1);
k = rb_genrand_real()*(len-2);
- if (j == i) j++;
- if ((k == i) ? (++k == j) : (k == j) ? (++k == i): 0) ++k;
+ {
+ long l = j, g = i;
+ if (j >= i) l = i, g = ++j;
+ if (k >= l && (++k >= g)) ++k;
+ }
return rb_ary_new3(3, ptr[i], ptr[j], ptr[k]);
}
if (n < sizeof(idx)/sizeof(idx[0])) {
- idx[0] = rb_genrand_real()*len;
+ long sorted[sizeof(idx)/sizeof(idx[0])];
+ sorted[0] = idx[0] = rb_genrand_real()*len;
for (i=1; i<n; i++) {
- long p = i;
k = rb_genrand_real()*--len;
- retry:
- j = 0;
- do {
- if (idx[j] == k) {
- ++k;
- if (p < j) goto retry;
- }
- else if (idx[j] > k) {
- if (p > j) p = j;
- }
- } while (++j < i);
- idx[i] = k;
+ for (j = 0; j < i; ++j) {
+ if (k < sorted[j]) break;
+ ++k;
+ }
+ memmove(&sorted[j+1], &sorted[j], sizeof(sorted[0])*(i-j));
+ sorted[j] = idx[i] = k;
}
result = rb_ary_new2(n);
for (i=0; i<n; i++) {
@@ -3084,6 +3335,7 @@ rb_ary_sample(int argc, VALUE *argv, VALUE ary)
RARRAY_PTR(result)[i] = nv;
}
}
+ ARY_SET_LEN(result, n);
return result;
}
@@ -3166,7 +3418,7 @@ permute0(long n, long r, long *p, long index, int *used, VALUE values)
const VALUE *values_array = RARRAY_PTR(values);
for (j = 0; j < r; j++) result_array[j] = values_array[p[j]];
- RARRAY(result)->len = r;
+ ARY_SET_LEN(result, r);
rb_yield(result);
}
}
@@ -3226,13 +3478,15 @@ rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
long *p = (long*)RSTRING_PTR(t0);
volatile VALUE t1 = tmpbuf(n,sizeof(int));
int *used = (int*)RSTRING_PTR(t1);
- VALUE ary0 = ary_make_shared(ary); /* private defensive copy of ary */
+ VALUE ary0 = ary_make_substitution(ary); /* private defensive copy of ary */
+ RBASIC(ary0)->klass = 0;
for (i = 0; i < n; i++) used[i] = 0; /* initialize array */
permute0(n, r, p, 0, used, ary0); /* compute and yield permutations */
RB_GC_GUARD(t0);
RB_GC_GUARD(t1);
+ RBASIC(ary0)->klass = rb_cArray;
}
return ary;
}
diff --git a/benchmark/bm_loop_for.rb b/benchmark/bm_loop_for.rb
new file mode 100644
index 0000000000..0fc4cc1511
--- /dev/null
+++ b/benchmark/bm_loop_for.rb
@@ -0,0 +1,3 @@
+for i in 1..30_000_000
+ #
+end
diff --git a/benchmark/bm_loop_times.rb b/benchmark/bm_loop_times.rb
index c5317b8228..521f72ad1a 100644
--- a/benchmark/bm_loop_times.rb
+++ b/benchmark/bm_loop_times.rb
@@ -1 +1 @@
-30000000.times{|e|}
+30_000_000.times{|e|}
diff --git a/bignum.c b/bignum.c
index 75975a6a9b..333b2bf3b8 100644
--- a/bignum.c
+++ b/bignum.c
@@ -759,13 +759,14 @@ static void
power_cache_init(void)
{
VALUE cache_value = rb_ary_new2(35 * MAX_BIG2STR_TABLE_ENTRIES);
+ MEMZERO(RARRAY_PTR(cache_value), VALUE, 35 * MAX_BIG2STR_TABLE_ENTRIES);
rb_big2str_power_cache = cache_value;
}
static inline VALUE
power_cache_get_power0(big2str_power_cache_t cache, int base, int i)
{
- if (NIL_P(cache[base - 2][i])) {
+ if (!cache[base - 2][i]) {
if (i == 0) {
cache[base - 2][i] =
rb_big_pow(rb_int2big(base), INT2FIX(KARATSUBA_DIGITS));
@@ -894,21 +895,6 @@ big2str_karatsuba(VALUE x, int base, char* ptr,
long lh, ll, m1;
VALUE b, q, r;
- if (FIXNUM_P(x)) {
- VALUE str = rb_fix2str(x, base);
- char* str_ptr = RSTRING_PTR(str);
- long str_len = RSTRING_LEN(str);
- if (trim) {
- if (FIX2INT(x) == 0) return 0;
- MEMCPY(ptr, str_ptr, char, str_len);
- return str_len;
- }
- else {
- memset(ptr, '0', len - str_len);
- MEMCPY(ptr + len - str_len, str_ptr, char, str_len);
- return len;
- }
- }
if (BIGZEROP(x)) {
if (trim) return 0;
else {
@@ -923,10 +909,12 @@ big2str_karatsuba(VALUE x, int base, char* ptr,
b = power_cache_get_power(base, n1, &m1);
bigdivmod(x, b, &q, &r);
- lh = big2str_karatsuba(q, base, ptr, (len - m1)/2,
+ lh = big2str_karatsuba(q, base, ptr, (len - m1)/2,
len - m1, hbase, trim);
+ rb_big_resize(q, 0);
ll = big2str_karatsuba(r, base, ptr + lh, m1/2,
- m1, hbase, !lh && trim);
+ m1, hbase, !lh && trim);
+ rb_big_resize(r, 0);
return lh + ll;
}
@@ -969,6 +957,7 @@ rb_big2str0(VALUE x, int base, int trim)
len = off + big2str_karatsuba(xx, base, ptr + off, n1,
n2, hbase, trim);
}
+ rb_big_resize(xx, 0);
ptr[len] = '\0';
rb_str_resize(ss, len);
@@ -1624,6 +1613,7 @@ rb_big_mul(VALUE x, VALUE y)
}
struct big_div_struct {
+ VALUE x, y;
long nx, ny;
BDIGIT *yds, *zds;
VALUE stop;
@@ -1748,6 +1738,8 @@ bigdivrem(VALUE x, VALUE y, VALUE *divp, VALUE *modp)
while (j--) zds[j] = xds[j];
}
+ bds.x = x;
+ bds.y = y;
bds.nx = nx;
bds.ny = ny;
bds.zds = zds;
@@ -1765,6 +1757,7 @@ bigdivrem(VALUE x, VALUE y, VALUE *divp, VALUE *modp)
zds = BDIGITS(*divp);
j = (nx==ny ? nx+2 : nx+1) - ny;
for (i = 0;i < j;i++) zds[i] = zds[i+ny];
+ if (!zds[i-1]) i--;
RBIGNUM_SET_LEN(*divp, i);
}
if (modp) { /* normalize remainder */
@@ -1780,6 +1773,7 @@ bigdivrem(VALUE x, VALUE y, VALUE *divp, VALUE *modp)
t2 = BIGUP(q);
}
}
+ if (!zds[ny-1]) ny--;
RBIGNUM_SET_LEN(*modp, ny);
RBIGNUM_SET_SIGN(*modp, RBIGNUM_SIGN(x));
}
@@ -2113,9 +2107,6 @@ rb_big_pow(VALUE x, VALUE y)
break;
case T_BIGNUM:
- if (rb_funcall(y, '<', 1, INT2FIX(0)))
- return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
-
rb_warn("in a**b, b may be too big");
d = rb_big2dbl(y);
break;
@@ -2124,7 +2115,7 @@ rb_big_pow(VALUE x, VALUE y)
yy = FIX2LONG(y);
if (yy < 0)
- return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
+ return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
else {
VALUE z = 0;
SIGNED_VALUE mask;
diff --git a/bin/erb b/bin/erb
index a6fcd5370c..8541437dc1 100755
--- a/bin/erb
+++ b/bin/erb
@@ -72,20 +72,6 @@ class ERB
end
raise "invalid trim mode #{arg.dump}" unless arg =~ /^[0-2]$/
trim_mode = arg.to_i
- when '-K' # KCODE
- arg = ARGV.req_arg
- case arg.downcase
- when 'e', '-e', 'euc'
- $KCODE = 'EUC'
- when 's', '-s', 'sjis'
- $KCODE = 'SJIS'
- when 'u', '-u', 'utf8'
- $KCODE = 'UTF8'
- when 'n', '-n', 'none'
- $KCODE = 'NONE'
- else
- raise "invalid KCODE #{arg.dump}"
- end
when '-P'
disable_percent = true
when '--help'
@@ -104,7 +90,6 @@ class ERB
-v enable verbose mode
-d set $DEBUG to true
-r [library] load a library
- -K [kcode] specify KANJI code-set
-S [safe_level] set $SAFE (0..4)
-T [trim_mode] specify trim_mode (0..2, -)
-P ignore lines which start with "%"
diff --git a/bin/ri b/bin/ri
index 0d4e3304d8..243557403c 100755
--- a/bin/ri
+++ b/bin/ri
@@ -1,6 +1,5 @@
-#!/usr//bin/env ruby
+#!/usr/bin/env ruby
require 'rdoc/ri/driver'
RDoc::RI::Driver.run ARGV
-
diff --git a/bin/testrb b/bin/testrb
index ff49cb5466..2e323f5cb0 100755
--- a/bin/testrb
+++ b/bin/testrb
@@ -1,5 +1,9 @@
#!/usr/bin/env ruby
require 'test/unit'
-(r = Test::Unit::AutoRunner.new(true)).process_args(ARGV) or
- abort r.options.banner + " tests..."
-exit r.run
+Test::Unit.setup_argv {|files|
+ if files.empty?
+ puts "Usage: testrb [options] tests..."
+ exit 1
+ end
+ files
+}
diff --git a/blockinlining.c b/blockinlining.c
index 3f4aa86fe5..a65906632e 100644
--- a/blockinlining.c
+++ b/blockinlining.c
@@ -9,7 +9,6 @@
**********************************************************************/
#include "ruby/ruby.h"
-#include "ruby/node.h"
#include "vm_core.h"
static VALUE
diff --git a/bootstraptest/test_method.rb b/bootstraptest/test_method.rb
index 63c6ad2db1..33e7436e6e 100644
--- a/bootstraptest/test_method.rb
+++ b/bootstraptest/test_method.rb
@@ -1069,3 +1069,18 @@ assert_equal 'ok', %q{
break :ok
end
}, '[ruby-dev:36028]'
+
+assert_equal '[1, 2, [3, 4]]', %q{
+ def regular(a, b, *c)
+ [a, b, c]
+ end
+ regular(*[], 1, *[], *[2, 3], *[], 4)
+}, '[ruby-core:19413]'
+
+assert_equal '[1, [:foo, 3, 4, :foo]]', %q{
+ def regular(a, *b)
+ [a, b]
+ end
+ a = b = [:foo]
+ regular(1, *a, *[3, 4], *b)
+}
diff --git a/bootstraptest/test_thread.rb b/bootstraptest/test_thread.rb
index f9a5beef2d..ce90737ebf 100644
--- a/bootstraptest/test_thread.rb
+++ b/bootstraptest/test_thread.rb
@@ -363,5 +363,9 @@ assert_equal 'ok', %q{
}, '[ruby-dev:35414]'
assert_equal 'ok', %q{
- 10000.times { Thread.new(true) {|x| x == false } }; :ok
+ begin
+ 10000.times { Thread.new(true) {|x| x == false } }
+ rescue NoMemoryError, StandardError
+ end
+ :ok
}
diff --git a/class.c b/class.c
index 733ddcd6dc..058233c8e7 100644
--- a/class.c
+++ b/class.c
@@ -10,9 +10,8 @@
**********************************************************************/
#include "ruby/ruby.h"
-#include "ruby/node.h"
#include "ruby/st.h"
-#include "vm_core.h"
+#include "node.h"
#include <ctype.h>
static VALUE
@@ -69,6 +68,8 @@ struct clone_method_data {
VALUE klass;
};
+VALUE rb_iseq_clone(VALUE iseqval, VALUE newcbase);
+
static int
clone_method(ID mid, NODE *body, struct clone_method_data *data)
{
@@ -187,7 +188,25 @@ VALUE
rb_make_metaclass(VALUE obj, VALUE super)
{
if (BUILTIN_TYPE(obj) == T_CLASS && FL_TEST(obj, FL_SINGLETON)) {
- return RBASIC(obj)->klass = rb_cClass;
+ VALUE metaclass, meta_of_super;
+ if (RBASIC(obj)->klass == obj) { /* for meta^(n)-class of Class */
+ metaclass = rb_class_boot(obj);
+ RBASIC(metaclass)->klass = metaclass;
+ }
+ else {
+ metaclass = rb_class_boot(super);
+ RBASIC(metaclass)->klass = rb_singleton_class(RBASIC(obj)->klass);
+ }
+ FL_SET(metaclass, FL_SINGLETON);
+ rb_singleton_class_attached(metaclass, obj);
+ RBASIC(obj)->klass = metaclass;
+
+ meta_of_super = RCLASS(obj)->ptr->super;
+ while (FL_TEST(meta_of_super, T_ICLASS)) {
+ meta_of_super = RCLASS(meta_of_super)->ptr->super;
+ }
+ RCLASS(metaclass)->ptr->super = rb_singleton_class(meta_of_super);
+ return metaclass;
}
else {
VALUE metasuper;
@@ -248,7 +267,7 @@ rb_define_class(const char *name, VALUE super)
rb_warn("no super class for `%s', Object assumed", name);
}
klass = rb_define_class_id(id, super);
- rb_register_mark_object(klass);
+ rb_gc_register_mark_object(klass);
rb_name_class(klass, id);
rb_const_set(rb_cObject, id, klass);
rb_class_inherited(super, klass);
@@ -320,7 +339,7 @@ rb_define_module(const char *name)
rb_raise(rb_eTypeError, "%s is not a module", rb_obj_classname(module));
}
module = rb_define_module_id(id);
- rb_register_mark_object(module);
+ rb_gc_register_mark_object(module);
rb_const_set(rb_cObject, id, module);
return module;
@@ -620,9 +639,9 @@ class_instance_method_list(int argc, VALUE *argv, VALUE mod, int (*func) (ID, lo
* call-seq:
* mod.instance_methods(include_super=true) => array
*
- * Returns an array containing the names of public instance methods in
- * the receiver. For a module, these are the public methods; for a
- * class, they are the instance (not singleton) methods. With no
+ * Returns an array containing the names of instance methods that is callable
+ * from outside in the receiver. For a module, these are the public methods;
+ * for a class, they are the instance (not singleton) methods. With no
* argument, or with an argument that is <code>false</code>, the
* instance methods in <i>mod</i> are returned, otherwise the methods
* in <i>mod</i> and <i>mod</i>'s superclasses are returned.
diff --git a/common.mk b/common.mk
index 2c19df0b47..390fb2d678 100644
--- a/common.mk
+++ b/common.mk
@@ -9,7 +9,7 @@ RUBYOPT = -
SPEC_GIT_BASE = git://github.com/rubyspec
MSPEC_GIT_URL = $(SPEC_GIT_BASE)/mspec.git
-RUBYSPEC_GIT_URL = git://github.com/yugui/rubyspec.git
+RUBYSPEC_GIT_URL = $(SPEC_GIT_BASE)/rubyspec.git
STATIC_RUBY = static-ruby
@@ -17,6 +17,7 @@ EXTCONF = extconf.rb
RBCONFIG = ./.rbconfig.time
LIBRUBY_EXTS = ./.libruby-with-ext.time
RDOCOUT = $(EXTOUT)/rdoc
+ID_H_TARGET = -id.h-
DMYEXT = dmyext.$(OBJEXT)
NORMALMAINOBJ = main.$(OBJEXT)
@@ -24,6 +25,7 @@ MAINOBJ = $(NORMALMAINOBJ)
EXTOBJS =
DLDOBJS = $(DMYEXT)
MINIOBJS = $(ARCHMINIOBJS) dmyencoding.$(OBJEXT) miniprelude.$(OBJEXT)
+ENC_MK = enc.mk
COMMONOBJS = array.$(OBJEXT) \
bignum.$(OBJEXT) \
@@ -49,7 +51,6 @@ COMMONOBJS = array.$(OBJEXT) \
pack.$(OBJEXT) \
parse.$(OBJEXT) \
process.$(OBJEXT) \
- prec.$(OBJEXT) \
random.$(OBJEXT) \
range.$(OBJEXT) \
rational.$(OBJEXT) \
@@ -61,6 +62,7 @@ COMMONOBJS = array.$(OBJEXT) \
regparse.$(OBJEXT) \
regsyntax.$(OBJEXT) \
ruby.$(OBJEXT) \
+ safe.$(OBJEXT) \
signal.$(OBJEXT) \
sprintf.$(OBJEXT) \
st.$(OBJEXT) \
@@ -72,7 +74,6 @@ COMMONOBJS = array.$(OBJEXT) \
util.$(OBJEXT) \
variable.$(OBJEXT) \
version.$(OBJEXT) \
- blockinlining.$(OBJEXT) \
compile.$(OBJEXT) \
debug.$(OBJEXT) \
iseq.$(OBJEXT) \
@@ -120,7 +121,8 @@ COMPILE_PRELUDE = $(MINIRUBY) -I$(srcdir) -rrbconfig $(srcdir)/tool/compile_prel
VCS = svn
-all: $(MKFILES) incs $(PREP) $(RBCONFIG) $(LIBRUBY) encs
+all: encs exts
+exts: $(MKFILES) incs $(PREP) $(RBCONFIG) $(LIBRUBY)
@$(MINIRUBY) $(srcdir)/ext/extmk.rb --make="$(MAKE)" $(EXTMK_ARGS)
prog: $(PROGRAM) $(WPROGRAM)
@@ -334,7 +336,7 @@ clean-local::
@$(RM) *.inc y.tab.c y.output encdb.h transdb.h
clean-ext::
clean-enc:
- @-$(MAKE) -f enc.mk $(MFLAGS) clean
+ @-$(MAKE) -f $(ENC_MK) $(MFLAGS) clean
clean-golf:
@$(RM) $(GORUBY)$(EXEEXT) $(GOLFOBJS)
@@ -345,7 +347,7 @@ distclean-local:: clean-local
@$(RM) *~ *.bak *.stackdump core *.core gmon.out $(PREP)
distclean-ext::
distclean-enc: clean-enc
- @-$(MAKE) -f enc.mk $(MFLAGS) distclean
+ @-$(MAKE) -f $(ENC_MK) $(MFLAGS) distclean
distclean-golf: clean-golf
@$(RM) $(GOLFPRELUDES)
@@ -361,19 +363,19 @@ check: test test-all
btest: miniruby$(EXEEXT) PHONY
$(BOOTSTRAPRUBY) "$(srcdir)/bootstraptest/runner.rb" --ruby="$(MINIRUBY)" $(OPTS)
-btest-miniruby: miniruby$(EXEEXT) $(RBCONFIG) $(PROGRAM) PHONY
- @$(MINIRUBY) "$(srcdir)/bootstraptest/runner.rb" --ruby="$(MINIRUBY)" -q
+btest-ruby: miniruby$(EXEEXT) $(RBCONFIG) $(PROGRAM) PHONY
+ @$(MINIRUBY) "$(srcdir)/bootstraptest/runner.rb" --ruby="$(PROGRAM) -I$(srcdir)/lib" -q
test-sample: miniruby$(EXEEXT) $(RBCONFIG) $(PROGRAM) PHONY
@$(MINIRUBY) $(srcdir)/rubytest.rb
-test-knownbug: miniruby$(EXEEXT) $(PROGRAM) PHONY
- $(BOOTSTRAPRUBY) "$(srcdir)/bootstraptest/runner.rb" --ruby="$(PROGRAM)" $(OPTS) $(srcdir)/KNOWNBUGS.rb
+test-knownbug: miniruby$(EXEEXT) $(PROGRAM) $(RBCONFIG) PHONY
+ $(MINIRUBY) "$(srcdir)/bootstraptest/runner.rb" --ruby="$(PROGRAM)" $(OPTS) $(srcdir)/KNOWNBUGS.rb
-test: test-sample btest-miniruby test-knownbug
+test: test-sample btest-ruby test-knownbug
test-all:
- $(RUNRUBY) "$(srcdir)/test/runner.rb" --basedir="$(TESTSDIR)" --runner=$(TESTUI) $(TESTS)
+ $(RUNRUBY) "$(srcdir)/test/runner.rb" $(TESTS)
extconf: $(PREP)
$(MAKEDIRS) "$(EXTCONFDIR)"
@@ -384,10 +386,14 @@ $(RBCONFIG): $(srcdir)/mkconfig.rb config.status $(PREP)
-install_name=$(RUBY_INSTALL_NAME) \
-so_name=$(RUBY_SO_NAME) rbconfig.rb
-encs: enc.mk $(LIBRUBY) $(PREP) transdb.h
- $(MAKE) -f enc.mk MINIRUBY="$(MINIRUBY)" $(MFLAGS)
+encs: enc trans
+encs enc trans: $(ENC_MK) $(LIBRUBY) $(PREP)
+ $(MAKE) -f $(ENC_MK) RUBY="$(MINIRUBY)" MINIRUBY="$(MINIRUBY)" $(MFLAGS) $@
-enc.mk: $(srcdir)/enc/make_encmake.rb $(srcdir)/enc/Makefile.in $(srcdir)/enc/depend \
+enc: {$(VPATH)}encdb.h
+trans: {$(VPATH)}transdb.h
+
+$(ENC_MK): $(srcdir)/enc/make_encmake.rb $(srcdir)/enc/Makefile.in $(srcdir)/enc/depend \
$(srcdir)/lib/mkmf.rb $(RBCONFIG)
$(MINIRUBY) $(srcdir)/enc/make_encmake.rb --builtin-encs="$(BUILTIN_ENCOBJS)" --builtin-transes="$(BUILTIN_TRANSOBJS)" $@ $(ENCS)
@@ -404,7 +410,7 @@ parse.h {$(VPATH)}parse.h: {$(VPATH)}parse.c
$(YACC) -d $(YFLAGS) -o y.tab.c $(<:\\=/)
sed -f $(srcdir)/tool/ytab.sed -e "/^#/s!y\.tab\.c!$@!" y.tab.c > $@.new
@$(MV) $@.new $@
- sed -e "/^#/s!y\.tab\.h!$(@:.c=.h)!" y.tab.h > $(@:.c=.h).new
+ sed -e "/^#line.*y\.tab\.h/d;/^#line.*parse\.y/d" y.tab.h > $(@:.c=.h).new
@$(IFCHANGE) $(@:.c=.h) $(@:.c=.h).new
@$(RM) y.tab.c y.tab.h
@@ -425,7 +431,6 @@ strstr.$(OBJEXT): {$(VPATH)}strstr.c
strtod.$(OBJEXT): {$(VPATH)}strtod.c
strtol.$(OBJEXT): {$(VPATH)}strtol.c
nt.$(OBJEXT): {$(VPATH)}nt.c
-x68.$(OBJEXT): {$(VPATH)}x68.c
os2.$(OBJEXT): {$(VPATH)}os2.c
dl_os2.$(OBJEXT): {$(VPATH)}dl_os2.c
ia64.$(OBJEXT): {$(VPATH)}ia64.s
@@ -437,238 +442,150 @@ win32.$(OBJEXT): {$(VPATH)}win32.c
###
-RUBY_H_INCLUDES = {$(VPATH)}ruby.h {$(VPATH)}config.h {$(VPATH)}defines.h \
- {$(VPATH)}intern.h {$(VPATH)}missing.h
-
-ID_H_INCLUDES = {$(VPATH)}id.h {$(VPATH)}parse.h {$(VPATH)}parse.y
-
-VM_CORE_H_INCLUDES = {$(VPATH)}vm_core.h {$(VPATH)}mvm.h {$(VPATH)}private_object.h
-
-array.$(OBJEXT): {$(VPATH)}array.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
- {$(VPATH)}util.h
-bignum.$(OBJEXT): {$(VPATH)}bignum.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h
-class.$(OBJEXT): {$(VPATH)}class.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
- {$(VPATH)}node.h $(VM_CORE_H_INCLUDES) \
- {$(VPATH)}debug.h {$(VPATH)}vm_opts.h {$(VPATH)}id.h \
- {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}mvm.h {$(VPATH)}parse.h \
- {$(VPATH)}parse.y
-compar.$(OBJEXT): {$(VPATH)}compar.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h
-complex.$(OBJEXT): {$(VPATH)}complex.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
- {$(VPATH)}mvm.h
-dir.$(OBJEXT): {$(VPATH)}dir.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
- {$(VPATH)}util.h {$(VPATH)}encoding.h {$(VPATH)}oniguruma.h
-dln.$(OBJEXT): {$(VPATH)}dln.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
- {$(VPATH)}dln.h
+RUBY_H_INCLUDES = {$(VPATH)}ruby.h {$(VPATH)}config.h {$(VPATH)}defines.h \
+ {$(VPATH)}intern.h {$(VPATH)}missing.h \
+ {$(VPATH)}public_object.h {$(VPATH)}vm.h
+ENCODING_H_INCLUDES= {$(VPATH)}encoding.h {$(VPATH)}oniguruma.h
+ID_H_INCLUDES = {$(VPATH)}id.h
+VM_CORE_H_INCLUDES = {$(VPATH)}vm_core.h {$(VPATH)}vm_opts.h \
+ {$(VPATH)}thread_$(THREAD_MODEL).h \
+ {$(VPATH)}node.h $(ID_H_INCLUDES)
+array.$(OBJEXT): {$(VPATH)}array.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h
+bignum.$(OBJEXT): {$(VPATH)}bignum.c $(RUBY_H_INCLUDES)
+class.$(OBJEXT): {$(VPATH)}class.c $(RUBY_H_INCLUDES) {$(VPATH)}node.h
+compar.$(OBJEXT): {$(VPATH)}compar.c $(RUBY_H_INCLUDES)
+complex.$(OBJEXT): {$(VPATH)}complex.c $(RUBY_H_INCLUDES)
+dir.$(OBJEXT): {$(VPATH)}dir.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h \
+ $(ENCODING_H_INCLUDES)
+dln.$(OBJEXT): {$(VPATH)}dln.c {$(VPATH)}dln.h $(RUBY_H_INCLUDES)
dmydln.$(OBJEXT): {$(VPATH)}dmydln.c dln.$(OBJEXT)
dmyext.$(OBJEXT): {$(VPATH)}dmyext.c
-dmyencoding.$(OBJEXT): {$(VPATH)}dmyencoding.c {$(VPATH)}encoding.c \
- $(RUBY_H_INCLUDES) {$(VPATH)}st.h {$(VPATH)}encoding.h \
- {$(VPATH)}oniguruma.h {$(VPATH)}regenc.h {$(VPATH)}util.h
+dmyencoding.$(OBJEXT): {$(VPATH)}dmyencoding.c $(RUBY_H_INCLUDES) \
+ {$(VPATH)}regenc.h {$(VPATH)}util.h $(ENCODING_H_INCLUDES) \
+ {$(VPATH)}encoding.c
encoding.$(OBJEXT): {$(VPATH)}encoding.c $(RUBY_H_INCLUDES) \
- {$(VPATH)}st.h {$(VPATH)}encoding.h {$(VPATH)}oniguruma.h \
- {$(VPATH)}regenc.h {$(VPATH)}util.h
-enum.$(OBJEXT): {$(VPATH)}enum.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
- {$(VPATH)}node.h {$(VPATH)}util.h
-enumerator.$(OBJEXT): {$(VPATH)}enumerator.c $(RUBY_H_INCLUDES) \
- {$(VPATH)}st.h {$(VPATH)}debug.h {$(VPATH)}node.h
-error.$(OBJEXT): {$(VPATH)}error.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
- $(VM_CORE_H_INCLUDES) {$(VPATH)}node.h \
- {$(VPATH)}debug.h {$(VPATH)}vm_opts.h $(ID_H_INCLUDES) \
- {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}mvm.h {$(VPATH)}parse.y
+ $(ENCODING_H_INCLUDES) {$(VPATH)}regenc.h {$(VPATH)}util.h
+enum.$(OBJEXT): {$(VPATH)}enum.c $(RUBY_H_INCLUDES) {$(VPATH)}node.h \
+ {$(VPATH)}util.h
+enumerator.$(OBJEXT): {$(VPATH)}enumerator.c $(RUBY_H_INCLUDES)
+error.$(OBJEXT): {$(VPATH)}error.c {$(VPATH)}known_errors.inc $(RUBY_H_INCLUDES) \
+ $(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h
eval.$(OBJEXT): {$(VPATH)}eval.c {$(VPATH)}eval_intern.h \
- $(RUBY_H_INCLUDES) {$(VPATH)}st.h {$(VPATH)}node.h {$(VPATH)}util.h \
- $(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h \
- {$(VPATH)}vm_opts.h $(ID_H_INCLUDES) {$(VPATH)}thread_$(THREAD_MODEL).h \
- {$(VPATH)}dln.h {$(VPATH)}eval_error.c {$(VPATH)}eval_safe.c \
- {$(VPATH)}eval_jump.c {$(VPATH)}mvm.h {$(VPATH)}parse.y
+ $(RUBY_H_INCLUDES) $(VM_CORE_H_INCLUDES) {$(VPATH)}eval_error.c \
+ {$(VPATH)}eval_jump.c {$(VPATH)}debug.h \
+ {$(VPATH)}iseq.h
load.$(OBJEXT): {$(VPATH)}load.c {$(VPATH)}eval_intern.h \
- $(RUBY_H_INCLUDES) {$(VPATH)}st.h {$(VPATH)}node.h {$(VPATH)}util.h \
- $(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h \
- {$(VPATH)}vm_opts.h $(ID_H_INCLUDES) {$(VPATH)}thread_$(THREAD_MODEL).h \
- {$(VPATH)}dln.h {$(VPATH)}mvm.h {$(VPATH)}parse.y
-file.$(OBJEXT): {$(VPATH)}file.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
- {$(VPATH)}io.h {$(VPATH)}encoding.h {$(VPATH)}oniguruma.h \
- {$(VPATH)}util.h {$(VPATH)}dln.h
-gc.$(OBJEXT): {$(VPATH)}gc.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
- {$(VPATH)}node.h {$(VPATH)}re.h {$(VPATH)}regex.h \
- {$(VPATH)}oniguruma.h {$(VPATH)}io.h {$(VPATH)}encoding.h \
- $(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h {$(VPATH)}vm_opts.h \
- $(ID_H_INCLUDES) {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}gc.h \
- {$(VPATH)}eval_intern.h {$(VPATH)}util.h {$(VPATH)}mvm.h \
- {$(VPATH)}parse.y {$(VPATH)}dln.h
-hash.$(OBJEXT): {$(VPATH)}hash.c $(RUBY_H_INCLUDES) $(ID_H_INCLUDES) \
- {$(VPATH)}st.h {$(VPATH)}util.h \
- {$(VPATH)}eval_intern.h {$(VPATH)}node.h $(VM_CORE_H_INCLUDES) \
- {$(VPATH)}mvm.h {$(VPATH)}debug.h {$(VPATH)}vm_opts.h {$(VPATH)}parse.y \
- {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}dln.h
-inits.$(OBJEXT): {$(VPATH)}inits.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h
-io.$(OBJEXT): {$(VPATH)}io.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
- {$(VPATH)}io.h {$(VPATH)}encoding.h {$(VPATH)}oniguruma.h \
- {$(VPATH)}util.h $(VM_CORE_H_INCLUDES) \
- {$(VPATH)}debug.h {$(VPATH)}vm_opts.h {$(VPATH)}id.h \
- {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}mvm.h {$(VPATH)}node.h \
- {$(VPATH)}parse.h {$(VPATH)}parse.y
-main.$(OBJEXT): {$(VPATH)}main.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
- {$(VPATH)}mvm.h
-marshal.$(OBJEXT): {$(VPATH)}marshal.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
- {$(VPATH)}io.h {$(VPATH)}encoding.h {$(VPATH)}oniguruma.h \
- {$(VPATH)}util.h
-math.$(OBJEXT): {$(VPATH)}math.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h
-numeric.$(OBJEXT): {$(VPATH)}numeric.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
- {$(VPATH)}encoding.h {$(VPATH)}oniguruma.h
-object.$(OBJEXT): {$(VPATH)}object.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
- {$(VPATH)}util.h {$(VPATH)}debug.h {$(VPATH)}node.h
-pack.$(OBJEXT): {$(VPATH)}pack.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h
-parse.$(OBJEXT): {$(VPATH)}parse.c {$(VPATH)}parse.y $(RUBY_H_INCLUDES) \
- {$(VPATH)}st.h {$(VPATH)}node.h {$(VPATH)}encoding.h {$(VPATH)}gc.h \
- {$(VPATH)}oniguruma.h $(ID_H_INCLUDES) {$(VPATH)}regenc.h \
- {$(VPATH)}regex.h {$(VPATH)}util.h {$(VPATH)}lex.c {$(VPATH)}keywords \
- {$(VPATH)}debug.h {$(VPATH)}id.c
-prec.$(OBJEXT): {$(VPATH)}prec.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h
+ {$(VPATH)}util.h $(RUBY_H_INCLUDES) $(VM_CORE_H_INCLUDES) \
+ {$(VPATH)}dln.h {$(VPATH)}debug.h
+file.$(OBJEXT): {$(VPATH)}file.c $(RUBY_H_INCLUDES) {$(VPATH)}io.h \
+ $(ENCODING_H_INCLUDES) {$(VPATH)}util.h {$(VPATH)}dln.h
+gc.$(OBJEXT): {$(VPATH)}gc.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \
+ {$(VPATH)}regex.h $(ENCODING_H_INCLUDES) $(VM_CORE_H_INCLUDES) \
+ {$(VPATH)}gc.h {$(VPATH)}io.h {$(VPATH)}eval_intern.h {$(VPATH)}util.h \
+ {$(VPATH)}debug.h
+hash.$(OBJEXT): {$(VPATH)}hash.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h
+inits.$(OBJEXT): {$(VPATH)}inits.c $(RUBY_H_INCLUDES)
+io.$(OBJEXT): {$(VPATH)}io.c $(RUBY_H_INCLUDES) {$(VPATH)}io.h \
+ {$(VPATH)}util.h $(ENCODING_H_INCLUDES)
+main.$(OBJEXT): {$(VPATH)}main.c $(RUBY_H_INCLUDES) {$(VPATH)}debug.h \
+ {$(VPATH)}node.h
+marshal.$(OBJEXT): {$(VPATH)}marshal.c $(RUBY_H_INCLUDES) {$(VPATH)}io.h \
+ $(ENCODING_H_INCLUDES) {$(VPATH)}util.h
+math.$(OBJEXT): {$(VPATH)}math.c $(RUBY_H_INCLUDES)
+numeric.$(OBJEXT): {$(VPATH)}numeric.c $(RUBY_H_INCLUDES) \
+ $(ENCODING_H_INCLUDES)
+object.$(OBJEXT): {$(VPATH)}object.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h
+pack.$(OBJEXT): {$(VPATH)}pack.c $(RUBY_H_INCLUDES)
+parse.$(OBJEXT): {$(VPATH)}parse.c $(RUBY_H_INCLUDES) \
+ {$(VPATH)}node.h $(ENCODING_H_INCLUDES) $(ID_H_INCLUDES) \
+ {$(VPATH)}regenc.h {$(VPATH)}regex.h {$(VPATH)}util.h {$(VPATH)}lex.c \
+ {$(VPATH)}defs/keywords {$(VPATH)}id.c
proc.$(OBJEXT): {$(VPATH)}proc.c {$(VPATH)}eval_intern.h \
- $(RUBY_H_INCLUDES) {$(VPATH)}st.h {$(VPATH)}node.h {$(VPATH)}util.h \
- $(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h \
- {$(VPATH)}vm_opts.h $(ID_H_INCLUDES) {$(VPATH)}thread_$(THREAD_MODEL).h \
- {$(VPATH)}dln.h {$(VPATH)}gc.h {$(VPATH)}mvm.h {$(VPATH)}parse.y
-process.$(OBJEXT): {$(VPATH)}process.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
- $(VM_CORE_H_INCLUDES) {$(VPATH)}util.h {$(VPATH)}node.h \
- {$(VPATH)}debug.h {$(VPATH)}vm_opts.h $(ID_H_INCLUDES) \
- {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}io.h {$(VPATH)}encoding.h \
- {$(VPATH)}oniguruma.h {$(VPATH)}mvm.h {$(VPATH)}parse.y {$(VPATH)}dln.h
-random.$(OBJEXT): {$(VPATH)}random.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h
-range.$(OBJEXT): {$(VPATH)}range.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
- {$(VPATH)}encoding.h {$(VPATH)}oniguruma.h
-rational.$(OBJEXT): {$(VPATH)}rational.c $(RUBY_H_INCLUDES) \
- {$(VPATH)}st.h {$(VPATH)}mvm.h
-re.$(OBJEXT): {$(VPATH)}re.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
- {$(VPATH)}re.h {$(VPATH)}regex.h {$(VPATH)}oniguruma.h \
- {$(VPATH)}encoding.h {$(VPATH)}util.h {$(VPATH)}regint.h \
- {$(VPATH)}regenc.h
+ $(RUBY_H_INCLUDES) {$(VPATH)}gc.h $(VM_CORE_H_INCLUDES) \
+ {$(VPATH)}debug.h
+process.$(OBJEXT): {$(VPATH)}process.c $(RUBY_H_INCLUDES) \
+ {$(VPATH)}util.h {$(VPATH)}io.h $(ENCODING_H_INCLUDES) {$(VPATH)}dln.h \
+ $(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h
+random.$(OBJEXT): {$(VPATH)}random.c $(RUBY_H_INCLUDES)
+range.$(OBJEXT): {$(VPATH)}range.c $(RUBY_H_INCLUDES) \
+ $(ENCODING_H_INCLUDES)
+rational.$(OBJEXT): {$(VPATH)}rational.c $(RUBY_H_INCLUDES)
+re.$(OBJEXT): {$(VPATH)}re.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \
+ {$(VPATH)}regex.h $(ENCODING_H_INCLUDES) {$(VPATH)}util.h \
+ {$(VPATH)}regint.h {$(VPATH)}regenc.h
regcomp.$(OBJEXT): {$(VPATH)}regcomp.c {$(VPATH)}regparse.h \
- {$(VPATH)}regint.h {$(VPATH)}config.h {$(VPATH)}defines.h \
- {$(VPATH)}regenc.h {$(VPATH)}oniguruma.h {$(VPATH)}st.h {$(VPATH)}ruby.h \
- {$(VPATH)}missing.h {$(VPATH)}intern.h
+ {$(VPATH)}regint.h {$(VPATH)}regenc.h {$(VPATH)}oniguruma.h \
+ $(RUBY_H_INCLUDES)
regenc.$(OBJEXT): {$(VPATH)}regenc.c {$(VPATH)}regint.h \
- {$(VPATH)}config.h {$(VPATH)}defines.h {$(VPATH)}regenc.h \
- {$(VPATH)}oniguruma.h {$(VPATH)}st.h {$(VPATH)}ruby.h \
- {$(VPATH)}missing.h {$(VPATH)}intern.h
+ {$(VPATH)}regenc.h {$(VPATH)}oniguruma.h $(RUBY_H_INCLUDES)
regerror.$(OBJEXT): {$(VPATH)}regerror.c {$(VPATH)}regint.h \
- {$(VPATH)}config.h {$(VPATH)}defines.h {$(VPATH)}regenc.h \
- {$(VPATH)}oniguruma.h {$(VPATH)}st.h {$(VPATH)}ruby.h \
- {$(VPATH)}missing.h {$(VPATH)}intern.h
+ {$(VPATH)}regenc.h {$(VPATH)}oniguruma.h $(RUBY_H_INCLUDES)
regexec.$(OBJEXT): {$(VPATH)}regexec.c {$(VPATH)}regint.h \
- {$(VPATH)}config.h {$(VPATH)}defines.h {$(VPATH)}regenc.h \
- {$(VPATH)}oniguruma.h {$(VPATH)}st.h {$(VPATH)}ruby.h \
- {$(VPATH)}missing.h {$(VPATH)}intern.h
+ {$(VPATH)}regenc.h {$(VPATH)}oniguruma.h $(RUBY_H_INCLUDES)
regparse.$(OBJEXT): {$(VPATH)}regparse.c {$(VPATH)}regparse.h \
- {$(VPATH)}regint.h {$(VPATH)}config.h {$(VPATH)}defines.h \
- {$(VPATH)}regenc.h {$(VPATH)}oniguruma.h {$(VPATH)}st.h {$(VPATH)}ruby.h \
- {$(VPATH)}missing.h {$(VPATH)}intern.h
+ {$(VPATH)}regint.h {$(VPATH)}regenc.h {$(VPATH)}oniguruma.h \
+ $(RUBY_H_INCLUDES)
regsyntax.$(OBJEXT): {$(VPATH)}regsyntax.c {$(VPATH)}regint.h \
- {$(VPATH)}config.h {$(VPATH)}defines.h {$(VPATH)}regenc.h \
- {$(VPATH)}oniguruma.h {$(VPATH)}st.h {$(VPATH)}ruby.h \
- {$(VPATH)}missing.h {$(VPATH)}intern.h
-ruby.$(OBJEXT): {$(VPATH)}ruby.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
- {$(VPATH)}node.h {$(VPATH)}encoding.h {$(VPATH)}oniguruma.h \
- {$(VPATH)}eval_intern.h {$(VPATH)}util.h \
- $(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h {$(VPATH)}vm_opts.h \
- $(ID_H_INCLUDES) {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}dln.h \
- {$(VPATH)}mvm.h {$(VPATH)}parse.y
-signal.$(OBJEXT): {$(VPATH)}signal.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
- {$(VPATH)}node.h $(VM_CORE_H_INCLUDES) \
- {$(VPATH)}debug.h {$(VPATH)}vm_opts.h $(ID_H_INCLUDES) \
- {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}mvm.h {$(VPATH)}parse.y
-sprintf.$(OBJEXT): {$(VPATH)}sprintf.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
- {$(VPATH)}re.h {$(VPATH)}regex.h {$(VPATH)}oniguruma.h \
- {$(VPATH)}encoding.h {$(VPATH)}vsnprintf.c
+ {$(VPATH)}regenc.h {$(VPATH)}oniguruma.h $(RUBY_H_INCLUDES)
+ruby.$(OBJEXT): {$(VPATH)}ruby.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h \
+ $(ENCODING_H_INCLUDES) {$(VPATH)}eval_intern.h $(VM_CORE_H_INCLUDES) \
+ {$(VPATH)}dln.h {$(VPATH)}debug.h
+safe.$(OBJEXT): {$(VPATH)}safe.c $(RUBY_H_INCLUDES) \
+ $(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h
+signal.$(OBJEXT): {$(VPATH)}signal.c $(RUBY_H_INCLUDES) \
+ $(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h
+sprintf.$(OBJEXT): {$(VPATH)}sprintf.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \
+ {$(VPATH)}regex.h {$(VPATH)}vsnprintf.c $(ENCODING_H_INCLUDES)
st.$(OBJEXT): {$(VPATH)}st.c {$(VPATH)}config.h {$(VPATH)}defines.h \
- {$(VPATH)}st.h
-strftime.$(OBJEXT): {$(VPATH)}strftime.c {$(VPATH)}config.h \
- {$(VPATH)}ruby.h {$(VPATH)}defines.h {$(VPATH)}missing.h \
+ {$(VPATH)}st.h {$(VPATH)}ruby.h {$(VPATH)}missing.h {$(VPATH)}intern.h
+strftime.$(OBJEXT): {$(VPATH)}strftime.c {$(VPATH)}ruby.h \
+ {$(VPATH)}config.h {$(VPATH)}defines.h {$(VPATH)}missing.h \
{$(VPATH)}intern.h {$(VPATH)}st.h
-string.$(OBJEXT): {$(VPATH)}string.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
- {$(VPATH)}re.h {$(VPATH)}regex.h {$(VPATH)}oniguruma.h \
- {$(VPATH)}encoding.h
-struct.$(OBJEXT): {$(VPATH)}struct.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h
+string.$(OBJEXT): {$(VPATH)}string.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \
+ {$(VPATH)}regex.h $(ENCODING_H_INCLUDES)
+struct.$(OBJEXT): {$(VPATH)}struct.c $(RUBY_H_INCLUDES)
thread.$(OBJEXT): {$(VPATH)}thread.c {$(VPATH)}eval_intern.h \
- $(RUBY_H_INCLUDES) {$(VPATH)}st.h {$(VPATH)}node.h {$(VPATH)}util.h \
- $(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h \
- {$(VPATH)}vm_opts.h $(ID_H_INCLUDES) {$(VPATH)}thread_$(THREAD_MODEL).h \
- {$(VPATH)}dln.h {$(VPATH)}vm.h {$(VPATH)}gc.h \
- {$(VPATH)}thread_$(THREAD_MODEL).c {$(VPATH)}mvm.h {$(VPATH)}parse.y
+ $(RUBY_H_INCLUDES) {$(VPATH)}gc.h $(VM_CORE_H_INCLUDES) \
+ {$(VPATH)}debug.h {$(VPATH)}thread_$(THREAD_MODEL).c
transcode.$(OBJEXT): {$(VPATH)}transcode.c $(RUBY_H_INCLUDES) \
- {$(VPATH)}st.h {$(VPATH)}encoding.h {$(VPATH)}oniguruma.h \
- {$(VPATH)}transcode_data.h
-cont.$(OBJEXT): {$(VPATH)}cont.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
- $(VM_CORE_H_INCLUDES) {$(VPATH)}node.h \
- {$(VPATH)}debug.h {$(VPATH)}vm_opts.h $(ID_H_INCLUDES) \
- {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}gc.h \
- {$(VPATH)}eval_intern.h {$(VPATH)}util.h {$(VPATH)}dln.h {$(VPATH)}mvm.h \
- {$(VPATH)}parse.y
-mvm.$(OBJEXT): {$(VPATH)}mvm.c $(RUBY_H_INCLUDES) $(VM_CORE_H_INCLUDES) \
- {$(VPATH)}st.h {$(VPATH)}thread_$(THREAD_MODEL).h
-time.$(OBJEXT): {$(VPATH)}time.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
- {$(VPATH)}encoding.h {$(VPATH)}oniguruma.h
-util.$(OBJEXT): {$(VPATH)}util.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
- {$(VPATH)}util.h
+ $(ENCODING_H_INCLUDES) {$(VPATH)}transcode_data.h
+cont.$(OBJEXT): {$(VPATH)}cont.c $(RUBY_H_INCLUDES) \
+ $(VM_CORE_H_INCLUDES) {$(VPATH)}gc.h {$(VPATH)}eval_intern.h \
+ {$(VPATH)}debug.h
+time.$(OBJEXT): {$(VPATH)}time.c $(RUBY_H_INCLUDES) \
+ $(ENCODING_H_INCLUDES)
+util.$(OBJEXT): {$(VPATH)}util.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h
variable.$(OBJEXT): {$(VPATH)}variable.c $(RUBY_H_INCLUDES) \
- {$(VPATH)}st.h {$(VPATH)}node.h {$(VPATH)}util.h
-version.$(OBJEXT): {$(VPATH)}version.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
+ {$(VPATH)}node.h {$(VPATH)}util.h
+version.$(OBJEXT): {$(VPATH)}version.c $(RUBY_H_INCLUDES) \
{$(VPATH)}version.h $(srcdir)/revision.h
-compile.$(OBJEXT): {$(VPATH)}compile.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
- {$(VPATH)}node.h $(VM_CORE_H_INCLUDES) \
- {$(VPATH)}debug.h {$(VPATH)}vm_opts.h $(ID_H_INCLUDES) \
- {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}compile.h \
- {$(VPATH)}insns.inc {$(VPATH)}insns_info.inc {$(VPATH)}optinsn.inc \
- {$(VPATH)}mvm.h {$(VPATH)}parse.y
-iseq.$(OBJEXT): {$(VPATH)}iseq.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
- {$(VPATH)}node.h {$(VPATH)}gc.h $(VM_CORE_H_INCLUDES) \
- {$(VPATH)}debug.h {$(VPATH)}vm_opts.h $(ID_H_INCLUDES) \
- {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}insns.inc \
- {$(VPATH)}insns_info.inc {$(VPATH)}node_name.inc {$(VPATH)}mvm.h \
- {$(VPATH)}parse.y
-vm.$(OBJEXT): {$(VPATH)}vm.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
- {$(VPATH)}node.h {$(VPATH)}encoding.h {$(VPATH)}oniguruma.h \
- {$(VPATH)}gc.h {$(VPATH)}insnhelper.h {$(VPATH)}eval_intern.h \
- {$(VPATH)}util.h $(VM_CORE_H_INCLUDES) \
- {$(VPATH)}debug.h {$(VPATH)}vm_opts.h $(ID_H_INCLUDES) \
- {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}dln.h {$(VPATH)}vm.h \
- {$(VPATH)}vm_insnhelper.c {$(VPATH)}insns.inc {$(VPATH)}vm_evalbody.c \
- {$(VPATH)}vmtc.inc {$(VPATH)}vm.inc {$(VPATH)}insns.def \
- {$(VPATH)}vm_method.c {$(VPATH)}vm_eval.c {$(VPATH)}mvm.h \
- {$(VPATH)}parse.y
-vm_dump.$(OBJEXT): {$(VPATH)}vm_dump.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
- {$(VPATH)}node.h $(VM_CORE_H_INCLUDES) \
- {$(VPATH)}debug.h {$(VPATH)}vm_opts.h $(ID_H_INCLUDES) \
- {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}vm.h {$(VPATH)}mvm.h \
- {$(VPATH)}parse.y
-debug.$(OBJEXT): {$(VPATH)}debug.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
- {$(VPATH)}encoding.h {$(VPATH)}oniguruma.h {$(VPATH)}debug.h \
- {$(VPATH)}node.h $(VM_CORE_H_INCLUDES) \
- {$(VPATH)}vm_opts.h $(ID_H_INCLUDES) {$(VPATH)}thread_$(THREAD_MODEL).h \
- {$(VPATH)}util.h {$(VPATH)}eval_intern.h {$(VPATH)}mvm.h \
- {$(VPATH)}parse.y {$(VPATH)}dln.h
-blockinlining.$(OBJEXT): {$(VPATH)}blockinlining.c $(RUBY_H_INCLUDES) \
- {$(VPATH)}st.h {$(VPATH)}node.h $(VM_CORE_H_INCLUDES) \
- {$(VPATH)}debug.h {$(VPATH)}vm_opts.h $(ID_H_INCLUDES) \
- {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}mvm.h {$(VPATH)}parse.y
-id.$(OBJEXT): {$(VPATH)}id.c $(RUBY_H_INCLUDES) \
- {$(VPATH)}st.h $(ID_H_INCLUDES)
+compile.$(OBJEXT): {$(VPATH)}compile.c {$(VPATH)}iseq.h \
+ $(RUBY_H_INCLUDES) $(VM_CORE_H_INCLUDES) {$(VPATH)}insns.inc \
+ {$(VPATH)}insns_info.inc {$(VPATH)}optinsn.inc {$(VPATH)}debug.h
+iseq.$(OBJEXT): {$(VPATH)}iseq.c {$(VPATH)}gc.h {$(VPATH)}iseq.h \
+ $(RUBY_H_INCLUDES) $(VM_CORE_H_INCLUDES) {$(VPATH)}insns.inc \
+ {$(VPATH)}insns_info.inc {$(VPATH)}node_name.inc {$(VPATH)}debug.h
+vm.$(OBJEXT): {$(VPATH)}vm.c {$(VPATH)}gc.h {$(VPATH)}iseq.h \
+ {$(VPATH)}eval_intern.h $(RUBY_H_INCLUDES) $(ENCODING_H_INCLUDES) \
+ $(VM_CORE_H_INCLUDES) {$(VPATH)}vm_method.c {$(VPATH)}vm_eval.c \
+ {$(VPATH)}vm_insnhelper.c {$(VPATH)}vm_insnhelper.h {$(VPATH)}vm_exec.c \
+ {$(VPATH)}vm_exec.h {$(VPATH)}insns.def {$(VPATH)}vmtc.inc \
+ {$(VPATH)}vm.inc {$(VPATH)}insns.inc {$(VPATH)}debug.h
+vm_dump.$(OBJEXT): {$(VPATH)}vm_dump.c $(RUBY_H_INCLUDES) \
+ $(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h
+debug.$(OBJEXT): {$(VPATH)}debug.c $(RUBY_H_INCLUDES) \
+ $(ENCODING_H_INCLUDES) $(VM_CORE_H_INCLUDES) {$(VPATH)}eval_intern.h \
+ {$(VPATH)}util.h {$(VPATH)}debug.h
+id.$(OBJEXT): {$(VPATH)}id.c $(RUBY_H_INCLUDES) $(ID_H_INCLUDES)
miniprelude.$(OBJEXT): {$(VPATH)}miniprelude.c $(RUBY_H_INCLUDES) \
- {$(VPATH)}st.h $(VM_CORE_H_INCLUDES) {$(VPATH)}node.h \
- {$(VPATH)}debug.h {$(VPATH)}vm_opts.h $(ID_H_INCLUDES) \
- {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}mvm.h {$(VPATH)}parse.y
-prelude.$(OBJEXT): {$(VPATH)}prelude.c $(RUBY_H_INCLUDES) {$(VPATH)}st.h \
- $(VM_CORE_H_INCLUDES) {$(VPATH)}node.h \
- {$(VPATH)}debug.h {$(VPATH)}vm_opts.h $(ID_H_INCLUDES) \
- {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}mvm.h {$(VPATH)}parse.y
+ $(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h
+prelude.$(OBJEXT): {$(VPATH)}prelude.c $(RUBY_H_INCLUDES) \
+ $(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h
golf_prelude.$(OBJEXT): {$(VPATH)}golf_prelude.c $(RUBY_H_INCLUDES) \
- {$(VPATH)}st.h $(VM_CORE_H_INCLUDES) {$(VPATH)}node.h \
- {$(VPATH)}debug.h {$(VPATH)}vm_opts.h $(ID_H_INCLUDES) \
- {$(VPATH)}thread_$(THREAD_MODEL).h {$(VPATH)}mvm.h {$(VPATH)}parse.y
+ $(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h
goruby.$(OBJEXT): {$(VPATH)}goruby.c {$(VPATH)}main.c $(RUBY_H_INCLUDES) \
- {$(VPATH)}st.h {$(VPATH)}mvm.h
+ {$(VPATH)}debug.h {$(VPATH)}node.h
ascii.$(OBJEXT): {$(VPATH)}ascii.c {$(VPATH)}regenc.h {$(VPATH)}config.h \
{$(VPATH)}defines.h {$(VPATH)}oniguruma.h
@@ -691,7 +608,7 @@ INSNS = opt_sc.inc optinsn.inc optunifs.inc insns.inc insns_info.inc \
INSNS2VMOPT = --srcdir="$(srcdir)"
-$(INSNS): $(srcdir)/insns.def {$(VPATH)}vm_opts.h
+$(INSNS): $(srcdir)/insns.def {$(VPATH)}vm_opts.h $(srcdir)/defs/opt_operand.def $(srcdir)/defs/opt_insn_unif.def
@$(RM) $(PROGRAM)
$(BASERUBY) -Ks $(srcdir)/tool/insns2vm.rb $(INSNS2VMOPT) $@
@@ -713,10 +630,10 @@ vm.inc: $(srcdir)/template/vm.inc.tmpl
srcs: {$(VPATH)}parse.c {$(VPATH)}lex.c {$(VPATH)}newline.c $(srcdir)/ext/ripper/ripper.c srcs-enc
-srcs-enc: enc.mk
- $(MAKE) -f enc.mk RUBY="$(MINIRUBY)" MINIRUBY="$(MINIRUBY)" $(MFLAGS) srcs
+srcs-enc: $(ENC_MK)
+ $(MAKE) -f $(ENC_MK) RUBY="$(MINIRUBY)" MINIRUBY="$(MINIRUBY)" $(MFLAGS) srcs
-incs: $(INSNS) {$(VPATH)}node_name.inc {$(VPATH)}encdb.h {$(VPATH)}transdb.h $(srcdir)/revision.h
+incs: $(INSNS) {$(VPATH)}node_name.inc {$(VPATH)}encdb.h {$(VPATH)}transdb.h {$(VPATH)}known_errors.inc $(srcdir)/revision.h
insns: $(INSNS)
@@ -731,6 +648,13 @@ transdb.h: $(PREP) srcs-enc
$(MINIRUBY) $(srcdir)/enc/trans/make_transdb.rb $@.new $(srcdir)/enc/trans enc/trans
$(IFCHANGE) "$@" "$@.new"
+# {$(VPATH)}id.h: {$(VPATH)}parse.h $(srcdir)/tool/generic_erb.rb $(srcdir)/template/id.h.tmpl
+# $(BASERUBY) $(srcdir)/tool/generic_erb.rb --if-change --output=$@ \
+# $(srcdir)/template/id.h.tmpl --vpath=$(VPATH) parse.h
+
+known_errors.inc: $(srcdir)/template/known_errors.inc.tmpl $(srcdir)/defs/known_errors.def
+ $(BASERUBY) $(srcdir)/tool/generic_erb.rb -c -o $@ $(srcdir)/template/known_errors.inc.tmpl $(srcdir)/defs/known_errors.def
+
miniprelude.c: $(srcdir)/tool/compile_prelude.rb $(srcdir)/prelude.rb
$(BASERUBY) -I$(srcdir) $(srcdir)/tool/compile_prelude.rb $(srcdir)/prelude.rb $@
@@ -748,10 +672,12 @@ prereq: incs srcs preludes
preludes: {$(VPATH)}miniprelude.c
preludes: {$(srcdir)}golf_prelude.c
-$(srcdir)/revision.h: $(REVISION_FORCE)
+$(srcdir)/revision.h: $(srcdir)/version.h $(srcdir)/ChangeLog $(REVISION_FORCE)
@set LC_MESSAGES=C
-@$(SET_LC_MESSAGES) $(VCS) info "$(@D)" | \
- sed -n "s/.*Rev:/#define RUBY_REVISION/p" > "$@.tmp"
+ sed -n \
+ -e 's,^URL:.*/branches/\([^/]*\)$$,#define RUBY_BRANCH_NAME "\1",p' \
+ -e "s/.*Rev:/#define RUBY_REVISION/p" > "$@.tmp"
@$(IFCHANGE) "$@" "$@.tmp"
$(srcdir)/ext/ripper/ripper.c:
@@ -787,13 +713,6 @@ tbench: $(PROGRAM) PHONY
--executables="$(COMPARE_RUBY); $(RUNRUBY)" \
--pattern='bmx_' --directory=$(srcdir)/benchmark $(OPTS)
-aotc: $(PROGRAM) PHONY
- ./$(PROGRAM) -I$(srcdir)/lib $(srcdir)/bin/ruby2cext $(srcdir)/test.rb
-
-vmasm: vm.$(ASMEXT)
-
-# vm.o : CFLAGS += -fno-crossjumping
-
run.gdb:
echo b ruby_debug_breakpoint > run.gdb
echo '# handle SIGINT nostop' >> run.gdb
@@ -806,15 +725,11 @@ run.gdb:
gdb: miniruby$(EXEEXT) run.gdb PHONY
gdb -x run.gdb --quiet --args $(MINIRUBY) $(srcdir)/test.rb
-# Intel VTune
-
-vtune: miniruby$(EXEEXT)
- vtl activity -c sampling -app ".\miniruby$(EXEEXT)","-I$(srcdir)/lib $(srcdir)/test.rb" run
- vtl view -hf -mn miniruby$(EXEEXT) -sum -sort -cd
- vtl view -ha -mn miniruby$(EXEEXT) -sum -sort -cd | $(RUNRUBY) $(srcdir)/tool/vtlh.rb > ha.lines
+gdb-ruby: $(PROGRAM) run.gdb PHONY
+ gdb -x run.gdb --quiet --args $(PROGRAM) $(srcdir)/test.rb
-dist: $(PREP) $(PROGRAM)
- $(srcdir)/tool/make-snapshot . $(TARNAME)
+dist:
+ $(BASERUBY) $(srcdir)/tool/make-snapshot tmp $(RELNAME)
up:
@$(VCS) up "$(srcdir)"
diff --git a/compile.c b/compile.c
index 41d1a9247f..40af15997f 100644
--- a/compile.c
+++ b/compile.c
@@ -10,25 +10,13 @@
**********************************************************************/
#include "ruby/ruby.h"
-#include "ruby/node.h"
#define USE_INSN_STACK_INCREASE 1
#include "vm_core.h"
-#include "compile.h"
+#include "iseq.h"
#include "insns.inc"
#include "insns_info.inc"
-#ifdef HAVE_STDARG_PROTOTYPES
-#include <stdarg.h>
-#define va_init_list(a,b) va_start(a,b)
-#else
-#include <varargs.h>
-#define va_init_list(a,b) va_start(a)
-#endif
-
-VALUE iseq_load(VALUE self, VALUE data, VALUE parent, VALUE opt);
-
-/* types */
typedef struct iseq_link_element {
enum {
@@ -82,6 +70,232 @@ struct iseq_compile_data_ensure_node_stack {
struct ensure_range *erange;
};
+/**
+ * debug function(macro) interface depend on CPDEBUG
+ * if it is less than 0, runtime option is in effect.
+ *
+ * debug level:
+ * 0: no debug output
+ * 1: show node type
+ * 2: show node important parameters
+ * ...
+ * 5: show other parameters
+ * 10: show every AST array
+ */
+
+#ifndef CPDEBUG
+#define CPDEBUG 0
+#endif
+
+#if CPDEBUG >= 0
+#define compile_debug CPDEBUG
+#else
+#define compile_debug iseq->compile_data->option->debug_level
+#endif
+
+NORETURN(PRINTF_ARGS(void rb_compile_bug(const char*, int, const char*, ...), 3, 4));
+
+#if CPDEBUG
+
+#define compile_debug_print_indent(level) \
+ ruby_debug_print_indent(level, compile_debug, gl_node_level * 2)
+
+#define debugp(header, value) (void) \
+ (compile_debug_print_indent(1) && \
+ ruby_debug_print_value(1, compile_debug, header, value))
+
+#define debugi(header, id) (void) \
+ (compile_debug_print_indent(1) && \
+ ruby_debug_print_id(1, compile_debug, header, id))
+
+#define debugp_param(header, value) (void) \
+ (compile_debug_print_indent(1) && \
+ ruby_debug_print_value(1, compile_debug, header, value))
+
+#define debugp_verbose(header, value) (void) \
+ (compile_debug_print_indent(2) && \
+ ruby_debug_print_value(2, compile_debug, header, value))
+
+#define debugp_verbose_node(header, value) (void) \
+ (compile_debug_print_indent(10) && \
+ ruby_debug_print_value(10, compile_debug, header, value))
+
+#define debug_node_start(node) ((void) \
+ (compile_debug_print_indent(1) && \
+ (ruby_debug_print_node(1, CPDEBUG, "", (NODE *)node), gl_node_level)), \
+ gl_node_level++)
+
+#define debug_node_end() gl_node_level --;
+
+#else
+
+static inline ID
+r_id(ID id)
+{
+ return id;
+}
+
+static inline VALUE
+r_value(VALUE value)
+{
+ return value;
+}
+
+#define debugi(header, id) r_id(id)
+#define debugp(header, value) r_value(value)
+#define debugp_verbose(header, value) r_value(value)
+#define debugp_verbose_node(header, value) r_value(value)
+#define debugp_param(header, value) r_value(value)
+#define debug_node_start(node) ((void)0)
+#define debug_node_end() ((void)0)
+#endif
+
+#if CPDEBUG > 1 || CPDEBUG < 0
+PRINTF_ARGS(void ruby_debug_printf(const char*, ...), 1, 2);
+#define debugs if (compile_debug_print_indent(1)) ruby_debug_printf
+#define debug_compile(msg, v) ((void)(compile_debug_print_indent(1) && fputs(msg, stderr)), (v))
+#else
+#define debugs if(0)printf
+#define debug_compile(msg, v) (v)
+#endif
+
+
+/* create new label */
+#define NEW_LABEL(l) new_label_body(iseq, l)
+
+#define iseq_filename(iseq) \
+ (((rb_iseq_t*)DATA_PTR(iseq))->filename)
+
+#define NEW_ISEQVAL(node, name, type) \
+ new_child_iseq(iseq, node, name, 0, type)
+
+#define NEW_CHILD_ISEQVAL(node, name, type) \
+ new_child_iseq(iseq, node, name, iseq->self, type)
+
+#define NEW_SPECIAQL_BLOCK_ISEQVAL(iseq, sym) \
+ new_child_iseq(iseq, iseq->node, iseq->name, iseq->parent_iseq, iseq->type, sym)
+
+/* add instructions */
+#define ADD_SEQ(seq1, seq2) \
+ APPEND_LIST(seq1, seq2)
+
+/* add an instruction */
+#define ADD_INSN(seq, line, insn) \
+ ADD_ELEM(seq, (LINK_ELEMENT *) new_insn_body(iseq, line, BIN(insn), 0))
+
+/* add an instruction with label operand */
+#define ADD_INSNL(seq, line, insn, label) \
+ ADD_ELEM(seq, (LINK_ELEMENT *) \
+ new_insn_body(iseq, line, BIN(insn), 1, (VALUE)label))
+
+/* add an instruction with some operands (1, 2, 3, 5) */
+#define ADD_INSN1(seq, line, insn, op1) \
+ ADD_ELEM(seq, (LINK_ELEMENT *) \
+ new_insn_body(iseq, line, BIN(insn), 1, (VALUE)op1))
+
+#define ADD_INSN2(seq, line, insn, op1, op2) \
+ ADD_ELEM(seq, (LINK_ELEMENT *) \
+ new_insn_body(iseq, line, BIN(insn), 2, (VALUE)op1, (VALUE)op2))
+
+#define ADD_INSN3(seq, line, insn, op1, op2, op3) \
+ ADD_ELEM(seq, (LINK_ELEMENT *) \
+ new_insn_body(iseq, line, BIN(insn), 3, (VALUE)op1, (VALUE)op2, (VALUE)op3))
+
+/* Specific Insn factory */
+#define ADD_SEND(seq, line, id, argc) \
+ ADD_SEND_R(seq, line, id, argc, (VALUE)Qfalse, (VALUE)INT2FIX(0))
+
+#define ADD_CALL_RECEIVER(seq, line) \
+ ADD_INSN(seq, line, putnil)
+
+#define ADD_CALL(seq, line, id, argc) \
+ ADD_SEND_R(seq, line, id, argc, (VALUE)Qfalse, (VALUE)INT2FIX(VM_CALL_FCALL_BIT))
+
+#define ADD_CALL_WITH_BLOCK(seq, line, id, argc, block) \
+ ADD_SEND_R(seq, line, id, argc, block, (VALUE)INT2FIX(VM_CALL_FCALL_BIT))
+
+#define ADD_SEND_R(seq, line, id, argc, block, flag) \
+ ADD_ELEM(seq, (LINK_ELEMENT *) \
+ new_insn_send(iseq, line, \
+ (VALUE)id, (VALUE)argc, (VALUE)block, (VALUE)flag))
+
+#define ADD_TRACE(seq, line, event) \
+ do { \
+ if ((event) == RUBY_EVENT_LINE && iseq->coverage && \
+ RARRAY_PTR(iseq->coverage)[(line) - 1] == Qnil) { \
+ RARRAY_PTR(iseq->coverage)[(line) - 1] = INT2FIX(0); \
+ ADD_INSN1(seq, line, trace, INT2FIX(RUBY_EVENT_COVERAGE)); \
+ } \
+ if (iseq->compile_data->option->trace_instruction) { \
+ ADD_INSN1(seq, line, trace, INT2FIX(event)); \
+ } \
+ }while(0);
+
+/* add label */
+#define ADD_LABEL(seq, label) \
+ ADD_ELEM(seq, (LINK_ELEMENT *) label)
+
+#define ADD_ADJUST(seq, line, label) \
+ ADD_ELEM(seq, (LINK_ELEMENT *) new_adjust_body(iseq, label, line))
+
+#define ADD_ADJUST_RESTORE(seq, label) \
+ ADD_ELEM(seq, (LINK_ELEMENT *) new_adjust_body(iseq, label, -1))
+
+#define ADD_CATCH_ENTRY(type, ls, le, iseqv, lc) \
+ (rb_ary_push(iseq->compile_data->catch_table_ary, \
+ rb_ary_new3(5, type, \
+ (VALUE)(ls) | 1, (VALUE)(le) | 1, \
+ iseqv, (VALUE)(lc) | 1)))
+
+/* compile node */
+#define COMPILE(anchor, desc, node) \
+ (debug_compile("== " desc "\n", \
+ iseq_compile_each(iseq, anchor, node, 0)))
+
+/* compile node, this node's value will be poped */
+#define COMPILE_POPED(anchor, desc, node) \
+ (debug_compile("== " desc "\n", \
+ iseq_compile_each(iseq, anchor, node, 1)))
+
+/* compile node, which is poped when 'poped' is true */
+#define COMPILE_(anchor, desc, node, poped) \
+ (debug_compile("== " desc "\n", \
+ iseq_compile_each(iseq, anchor, node, poped)))
+
+#define OPERAND_AT(insn, idx) \
+ (((INSN*)(insn))->operands[idx])
+
+#define INSN_OF(insn) \
+ (((INSN*)(insn))->insn_id)
+
+/* error */
+#define COMPILE_ERROR(strs) \
+{ \
+ VALUE tmp = GET_THREAD()->errinfo; \
+ if (compile_debug) rb_compile_bug strs; \
+ GET_THREAD()->errinfo = iseq->compile_data->err_info; \
+ rb_compile_error strs; \
+ iseq->compile_data->err_info = GET_THREAD()->errinfo; \
+ GET_THREAD()->errinfo = tmp; \
+ ret = 0; \
+ break; \
+}
+
+#define ERROR_ARGS ruby_sourcefile, nd_line(node),
+
+
+#define COMPILE_OK 1
+#define COMPILE_NG 0
+
+
+/* leave name uninitialized so that compiler warn if INIT_ANCHOR is
+ * missing */
+#define DECL_ANCHOR(name) \
+ LINK_ANCHOR *name, name##_body__ = {{0,},}
+#define INIT_ANCHOR(name) \
+ (name##_body__.last = &name##_body__.anchor, name = &name##_body__)
+
+
#include "optinsn.inc"
#if OPT_INSTRUCTIONS_UNIFICATION
#include "optunifs.inc"
@@ -1095,6 +1309,8 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
rb_compile_error(RSTRING_PTR(iseq->filename), iobj->line_no,
"operand size miss! (%d for %d)",
iobj->operand_size, len - 1);
+ xfree(generated_iseq);
+ xfree(insn_info_table);
return 0;
}
@@ -1135,7 +1351,12 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
rb_compile_error(RSTRING_PTR(iseq->filename), iobj->line_no,
"unknown label");
}
- rb_hash_aset(map, obj, INT2FIX(lobj->position - (pos+len)));
+ if (!st_lookup(rb_hash_tbl(map), obj, 0)) {
+ rb_hash_aset(map, obj, INT2FIX(lobj->position - (pos+len)));
+ }
+ else {
+ rb_warning("duplicated when clause is ignored");
+ }
}
generated_iseq[pos + 1 + j] = map;
iseq_add_mark_object(iseq, map);
@@ -1184,6 +1405,8 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *anchor)
default:
rb_compile_error(RSTRING_PTR(iseq->filename), iobj->line_no,
"unknown operand type: %c", type);
+ xfree(generated_iseq);
+ xfree(insn_info_table);
return 0;
}
}
@@ -3346,8 +3569,8 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
}
case NODE_MASGN:{
- compile_massign(iseq, ret, node, poped);
- break;
+ compile_massign(iseq, ret, node, poped);
+ break;
}
case NODE_LASGN:{
@@ -3431,45 +3654,45 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
break;
}
case NODE_OP_ASGN1: {
- DECL_ANCHOR(args);
- VALUE argc;
- unsigned long flag = 0;
- ID id = node->nd_mid;
-
- /*
- * a[x] (op)= y
- *
- * eval a # a
- * eval x # a x
- * dupn 2 # a x a x
- * send :[] # a x a[x]
- * eval y # a x a[x] y
- * send op # a x a[x]+y
- * send []= # ret
- */
-
- /*
- * nd_recv[nd_args->nd_body] (nd_mid)= nd_args->nd_head;
- * NODE_OP_ASGN nd_recv
- * nd_args->nd_head
- * nd_args->nd_body
- * nd_mid
- */
-
- COMPILE(ret, "NODE_OP_ASGN1 recv", node->nd_recv);
- if (nd_type(node->nd_args->nd_body) != NODE_ZARRAY) {
- INIT_ANCHOR(args);
- argc = setup_args(iseq, args, node->nd_args->nd_body, &flag);
- ADD_SEQ(ret, args);
- }
- else {
- argc = INT2FIX(0);
- }
- ADD_INSN1(ret, nd_line(node), dupn, INT2FIX(FIX2INT(argc)+1));
- ADD_SEND_R(ret, nd_line(node), ID2SYM(idAREF), argc, Qfalse, LONG2FIX(flag));
+ DECL_ANCHOR(args);
+ VALUE argc;
+ unsigned long flag = 0;
+ ID id = node->nd_mid;
+
+ /*
+ * a[x] (op)= y
+ *
+ * eval a # a
+ * eval x # a x
+ * dupn 2 # a x a x
+ * send :[] # a x a[x]
+ * eval y # a x a[x] y
+ * send op # a x a[x]+y
+ * send []= # ret
+ */
+
+ /*
+ * nd_recv[nd_args->nd_body] (nd_mid)= nd_args->nd_head;
+ * NODE_OP_ASGN nd_recv
+ * nd_args->nd_head
+ * nd_args->nd_body
+ * nd_mid
+ */
+
+ COMPILE(ret, "NODE_OP_ASGN1 recv", node->nd_recv);
+ if (nd_type(node->nd_args->nd_body) != NODE_ZARRAY) {
+ INIT_ANCHOR(args);
+ argc = setup_args(iseq, args, node->nd_args->nd_body, &flag);
+ ADD_SEQ(ret, args);
+ }
+ else {
+ argc = INT2FIX(0);
+ }
+ ADD_INSN1(ret, nd_line(node), dupn, INT2FIX(FIX2INT(argc)+1));
+ ADD_SEND_R(ret, nd_line(node), ID2SYM(idAREF), argc, Qfalse, LONG2FIX(flag));
- if (id == 0 || id == 1) {
- /* 0: or, 1: and
+ if (id == 0 || id == 1) {
+ /* 0: or, 1: and
a[x] ||= y
unless/if a[x]
@@ -3477,64 +3700,64 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
else
nil
end
- */
- LABEL *label = NEW_LABEL(nd_line(node));
- LABEL *lfin = NEW_LABEL(nd_line(node));
-
- if (id == 0) {
- /* or */
- ADD_INSN(ret, nd_line(node), dup);
- ADD_INSNL(ret, nd_line(node), branchif, label);
- ADD_INSN(ret, nd_line(node), pop);
- }
- else {
- /* and */
- ADD_INSN(ret, nd_line(node), dup);
- ADD_INSNL(ret, nd_line(node), branchunless, label);
- ADD_INSN(ret, nd_line(node), pop);
- }
+ */
+ LABEL *label = NEW_LABEL(nd_line(node));
+ LABEL *lfin = NEW_LABEL(nd_line(node));
+
+ if (id == 0) {
+ /* or */
+ ADD_INSN(ret, nd_line(node), dup);
+ ADD_INSNL(ret, nd_line(node), branchif, label);
+ ADD_INSN(ret, nd_line(node), pop);
+ }
+ else {
+ /* and */
+ ADD_INSN(ret, nd_line(node), dup);
+ ADD_INSNL(ret, nd_line(node), branchunless, label);
+ ADD_INSN(ret, nd_line(node), pop);
+ }
- COMPILE(ret, "NODE_OP_ASGN1 args->head: ", node->nd_args->nd_head);
- if (flag & VM_CALL_ARGS_SPLAT_BIT) {
- ADD_INSN1(ret, nd_line(node), newarray, INT2FIX(1));
- ADD_INSN(ret, nd_line(node), concatarray);
- ADD_SEND_R(ret, nd_line(node), ID2SYM(idASET),
- argc, Qfalse, LONG2FIX(flag));
- }
- else {
- ADD_SEND_R(ret, nd_line(node), ID2SYM(idASET),
- INT2FIX(FIX2INT(argc) + 1), Qfalse, LONG2FIX(flag));
- }
- ADD_INSNL(ret, nd_line(node), jump, lfin);
- ADD_LABEL(ret, label);
- if (id == 0 || id == 1) { /* 0: or, 1: and */
- ADD_INSN(ret, nd_line(node), swap);
- ADD_INSN(ret, nd_line(node), pop);
- ADD_INSN(ret, nd_line(node), swap);
- ADD_INSN(ret, nd_line(node), pop);
- }
- ADD_LABEL(ret, lfin);
- }
- else {
- COMPILE(ret, "NODE_OP_ASGN1 args->head: ", node->nd_args->nd_head);
- ADD_SEND(ret, nd_line(node), ID2SYM(id), INT2FIX(1));
- if (flag & VM_CALL_ARGS_SPLAT_BIT) {
- ADD_INSN1(ret, nd_line(node), newarray, INT2FIX(1));
- ADD_INSN(ret, nd_line(node), concatarray);
- ADD_SEND_R(ret, nd_line(node), ID2SYM(idASET),
- argc, Qfalse, LONG2FIX(flag));
- }
- else {
- ADD_SEND_R(ret, nd_line(node), ID2SYM(idASET),
- INT2FIX(FIX2INT(argc) + 1), Qfalse, LONG2FIX(flag));
- }
- }
+ COMPILE(ret, "NODE_OP_ASGN1 args->head: ", node->nd_args->nd_head);
+ if (flag & VM_CALL_ARGS_SPLAT_BIT) {
+ ADD_INSN1(ret, nd_line(node), newarray, INT2FIX(1));
+ ADD_INSN(ret, nd_line(node), concatarray);
+ ADD_SEND_R(ret, nd_line(node), ID2SYM(idASET),
+ argc, Qfalse, LONG2FIX(flag));
+ }
+ else {
+ ADD_SEND_R(ret, nd_line(node), ID2SYM(idASET),
+ INT2FIX(FIX2INT(argc) + 1), Qfalse, LONG2FIX(flag));
+ }
+ ADD_INSNL(ret, nd_line(node), jump, lfin);
+ ADD_LABEL(ret, label);
+ if (id == 0 || id == 1) { /* 0: or, 1: and */
+ ADD_INSN(ret, nd_line(node), swap);
+ ADD_INSN(ret, nd_line(node), pop);
+ ADD_INSN(ret, nd_line(node), swap);
+ ADD_INSN(ret, nd_line(node), pop);
+ }
+ ADD_LABEL(ret, lfin);
+ }
+ else {
+ COMPILE(ret, "NODE_OP_ASGN1 args->head: ", node->nd_args->nd_head);
+ ADD_SEND(ret, nd_line(node), ID2SYM(id), INT2FIX(1));
+ if (flag & VM_CALL_ARGS_SPLAT_BIT) {
+ ADD_INSN1(ret, nd_line(node), newarray, INT2FIX(1));
+ ADD_INSN(ret, nd_line(node), concatarray);
+ ADD_SEND_R(ret, nd_line(node), ID2SYM(idASET),
+ argc, Qfalse, LONG2FIX(flag));
+ }
+ else {
+ ADD_SEND_R(ret, nd_line(node), ID2SYM(idASET),
+ INT2FIX(FIX2INT(argc) + 1), Qfalse, LONG2FIX(flag));
+ }
+ }
- if (poped) {
- ADD_INSN(ret, nd_line(node), pop);
- }
+ if (poped) {
+ ADD_INSN(ret, nd_line(node), pop);
+ }
- break;
+ break;
}
case NODE_OP_ASGN2:{
ID atype = node->nd_next->nd_mid;
@@ -4188,13 +4411,13 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
break;
}
case NODE_SPLAT:{
- COMPILE(ret, "splat", node->nd_head);
- ADD_INSN1(ret, nd_line(node), splatarray, Qfalse);
+ COMPILE(ret, "splat", node->nd_head);
+ ADD_INSN1(ret, nd_line(node), splatarray, Qfalse);
- if (poped) {
- ADD_INSN(ret, nd_line(node), pop);
- }
- break;
+ if (poped) {
+ ADD_INSN(ret, nd_line(node), pop);
+ }
+ break;
}
case NODE_DEFN:{
VALUE iseqval = NEW_ISEQVAL(node->nd_defn,
@@ -4681,7 +4904,7 @@ insn_data_to_s_detail(INSN *iobj)
break;
case TS_GENTRY:
{
- struct global_entry *entry = (struct global_entry *)
+ struct rb_global_entry *entry = (struct rb_global_entry *)
(OPERAND_AT(iobj, j) & (~1));
rb_str_cat2(str, rb_id2name(entry->id));
}
@@ -5051,3 +5274,55 @@ iseq_build_from_ary(rb_iseq_t *iseq, VALUE locals, VALUE args,
iseq_build_body(iseq, anchor, body, labels_table);
return iseq->self;
}
+
+/* for parser */
+
+int
+rb_dvar_defined(ID id)
+{
+ rb_thread_t *th = GET_THREAD();
+ rb_iseq_t *iseq;
+ if (th->base_block && (iseq = th->base_block->iseq)) {
+ while (iseq->type == ISEQ_TYPE_BLOCK ||
+ iseq->type == ISEQ_TYPE_RESCUE ||
+ iseq->type == ISEQ_TYPE_ENSURE ||
+ iseq->type == ISEQ_TYPE_EVAL) {
+ int i;
+
+ for (i = 0; i < iseq->local_table_size; i++) {
+ if (iseq->local_table[i] == id) {
+ return 1;
+ }
+ }
+ iseq = iseq->parent_iseq;
+ }
+ }
+ return 0;
+}
+
+int
+rb_local_defined(ID id)
+{
+ rb_thread_t *th = GET_THREAD();
+ rb_iseq_t *iseq;
+
+ if (th->base_block && th->base_block->iseq) {
+ int i;
+ iseq = th->base_block->iseq->local_iseq;
+
+ for (i=0; i<iseq->local_table_size; i++) {
+ if (iseq->local_table[i] == id) {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+int
+rb_parse_in_eval(void)
+{
+ return GET_THREAD()->parse_in_eval != 0;
+}
+
+
diff --git a/compile.h b/compile.h
deleted file mode 100644
index 4bd4e99e2c..0000000000
--- a/compile.h
+++ /dev/null
@@ -1,241 +0,0 @@
-/**********************************************************************
-
- compile.h -
-
- $Author$
- created at: 04/01/01 23:36:57 JST
-
- Copyright (C) 2004-2007 Koichi Sasada
-
-**********************************************************************/
-
-#ifndef RUBY_COMPILE_H
-#define RUBY_COMPILE_H
-
-/* */
-/**
- * debug function(macro) interface depend on CPDEBUG
- * if it is less than 0, runtime option is in effect.
- *
- * debug level:
- * 0: no debug output
- * 1: show node type
- * 2: show node important parameters
- * ...
- * 5: show other parameters
- * 10: show every AST array
- */
-
-#ifndef CPDEBUG
-#define CPDEBUG 0
-#endif
-
-#if CPDEBUG >= 0
-#define compile_debug CPDEBUG
-#else
-#define compile_debug iseq->compile_data->option->debug_level
-#endif
-
-NORETURN(PRINTF_ARGS(void rb_compile_bug(const char*, int, const char*, ...), 3, 4));
-
-#if CPDEBUG
-
-#define compile_debug_print_indent(level) \
- ruby_debug_print_indent(level, compile_debug, gl_node_level * 2)
-
-#define debugp(header, value) (void) \
- (compile_debug_print_indent(1) && \
- ruby_debug_print_value(1, compile_debug, header, value))
-
-#define debugi(header, id) (void) \
- (compile_debug_print_indent(1) && \
- ruby_debug_print_id(1, compile_debug, header, id))
-
-#define debugp_param(header, value) (void) \
- (compile_debug_print_indent(1) && \
- ruby_debug_print_value(1, compile_debug, header, value))
-
-#define debugp_verbose(header, value) (void) \
- (compile_debug_print_indent(2) && \
- ruby_debug_print_value(2, compile_debug, header, value))
-
-#define debugp_verbose_node(header, value) (void) \
- (compile_debug_print_indent(10) && \
- ruby_debug_print_value(10, compile_debug, header, value))
-
-#define debug_node_start(node) ((void) \
- (compile_debug_print_indent(1) && \
- (ruby_debug_print_node(1, CPDEBUG, "", (NODE *)node), gl_node_level)), \
- gl_node_level++)
-
-#define debug_node_end() gl_node_level --;
-
-#else
-
-static inline ID
-r_id(ID id)
-{
- return id;
-}
-
-static inline VALUE
-r_value(VALUE value)
-{
- return value;
-}
-
-#define debugi(header, id) r_id(id)
-#define debugp(header, value) r_value(value)
-#define debugp_verbose(header, value) r_value(value)
-#define debugp_verbose_node(header, value) r_value(value)
-#define debugp_param(header, value) r_value(value)
-#define debug_node_start(node) ((void)0)
-#define debug_node_end() ((void)0)
-#endif
-
-#if CPDEBUG > 1 || CPDEBUG < 0
-PRINTF_ARGS(void ruby_debug_printf(const char*, ...), 1, 2);
-#define debugs if (compile_debug_print_indent(1)) ruby_debug_printf
-#define debug_compile(msg, v) ((void)(compile_debug_print_indent(1) && fputs(msg, stderr)), (v))
-#else
-#define debugs if(0)printf
-#define debug_compile(msg, v) (v)
-#endif
-
-
-/* create new label */
-#define NEW_LABEL(l) new_label_body(iseq, l)
-
-#define iseq_filename(iseq) \
- (((rb_iseq_t*)DATA_PTR(iseq))->filename)
-
-#define NEW_ISEQVAL(node, name, type) \
- new_child_iseq(iseq, node, name, 0, type)
-
-#define NEW_CHILD_ISEQVAL(node, name, type) \
- new_child_iseq(iseq, node, name, iseq->self, type)
-
-#define NEW_SPECIAQL_BLOCK_ISEQVAL(iseq, sym) \
- new_child_iseq(iseq, iseq->node, iseq->name, iseq->parent_iseq, iseq->type, sym)
-
-/* add instructions */
-#define ADD_SEQ(seq1, seq2) \
- APPEND_LIST(seq1, seq2)
-
-/* add an instruction */
-#define ADD_INSN(seq, line, insn) \
- ADD_ELEM(seq, (LINK_ELEMENT *) new_insn_body(iseq, line, BIN(insn), 0))
-
-/* add an instruction with label operand */
-#define ADD_INSNL(seq, line, insn, label) \
- ADD_ELEM(seq, (LINK_ELEMENT *) \
- new_insn_body(iseq, line, BIN(insn), 1, (VALUE)label))
-
-/* add an instruction with some operands (1, 2, 3, 5) */
-#define ADD_INSN1(seq, line, insn, op1) \
- ADD_ELEM(seq, (LINK_ELEMENT *) \
- new_insn_body(iseq, line, BIN(insn), 1, (VALUE)op1))
-
-#define ADD_INSN2(seq, line, insn, op1, op2) \
- ADD_ELEM(seq, (LINK_ELEMENT *) \
- new_insn_body(iseq, line, BIN(insn), 2, (VALUE)op1, (VALUE)op2))
-
-#define ADD_INSN3(seq, line, insn, op1, op2, op3) \
- ADD_ELEM(seq, (LINK_ELEMENT *) \
- new_insn_body(iseq, line, BIN(insn), 3, (VALUE)op1, (VALUE)op2, (VALUE)op3))
-
-/* Specific Insn factory */
-#define ADD_SEND(seq, line, id, argc) \
- ADD_SEND_R(seq, line, id, argc, (VALUE)Qfalse, (VALUE)INT2FIX(0))
-
-#define ADD_CALL_RECEIVER(seq, line) \
- ADD_INSN(seq, line, putnil)
-
-#define ADD_CALL(seq, line, id, argc) \
- ADD_SEND_R(seq, line, id, argc, (VALUE)Qfalse, (VALUE)INT2FIX(VM_CALL_FCALL_BIT))
-
-#define ADD_CALL_WITH_BLOCK(seq, line, id, argc, block) \
- ADD_SEND_R(seq, line, id, argc, block, (VALUE)INT2FIX(VM_CALL_FCALL_BIT))
-
-#define ADD_SEND_R(seq, line, id, argc, block, flag) \
- ADD_ELEM(seq, (LINK_ELEMENT *) \
- new_insn_send(iseq, line, \
- (VALUE)id, (VALUE)argc, (VALUE)block, (VALUE)flag))
-
-#define ADD_TRACE(seq, line, event) \
- do { \
- if ((event) == RUBY_EVENT_LINE && iseq->coverage && \
- RARRAY_PTR(iseq->coverage)[(line) - 1] == Qnil) { \
- RARRAY_PTR(iseq->coverage)[(line) - 1] = INT2FIX(0); \
- ADD_INSN1(seq, line, trace, INT2FIX(RUBY_EVENT_COVERAGE)); \
- } \
- if (iseq->compile_data->option->trace_instruction) { \
- ADD_INSN1(seq, line, trace, INT2FIX(event)); \
- } \
- }while(0);
-
-/* add label */
-#define ADD_LABEL(seq, label) \
- ADD_ELEM(seq, (LINK_ELEMENT *) label)
-
-#define ADD_ADJUST(seq, line, label) \
- ADD_ELEM(seq, (LINK_ELEMENT *) new_adjust_body(iseq, label, line))
-
-#define ADD_ADJUST_RESTORE(seq, label) \
- ADD_ELEM(seq, (LINK_ELEMENT *) new_adjust_body(iseq, label, -1))
-
-#define ADD_CATCH_ENTRY(type, ls, le, iseqv, lc) \
- (rb_ary_push(iseq->compile_data->catch_table_ary, \
- rb_ary_new3(5, type, \
- (VALUE)(ls) | 1, (VALUE)(le) | 1, \
- iseqv, (VALUE)(lc) | 1)))
-
-/* compile node */
-#define COMPILE(anchor, desc, node) \
- (debug_compile("== " desc "\n", \
- iseq_compile_each(iseq, anchor, node, 0)))
-
-/* compile node, this node's value will be poped */
-#define COMPILE_POPED(anchor, desc, node) \
- (debug_compile("== " desc "\n", \
- iseq_compile_each(iseq, anchor, node, 1)))
-
-/* compile node, which is poped when 'poped' is true */
-#define COMPILE_(anchor, desc, node, poped) \
- (debug_compile("== " desc "\n", \
- iseq_compile_each(iseq, anchor, node, poped)))
-
-#define OPERAND_AT(insn, idx) \
- (((INSN*)(insn))->operands[idx])
-
-#define INSN_OF(insn) \
- (((INSN*)(insn))->insn_id)
-
-/* error */
-#define COMPILE_ERROR(strs) \
-{ \
- VALUE tmp = GET_THREAD()->errinfo; \
- if (compile_debug) rb_compile_bug strs; \
- GET_THREAD()->errinfo = iseq->compile_data->err_info; \
- rb_compile_error strs; \
- iseq->compile_data->err_info = GET_THREAD()->errinfo; \
- GET_THREAD()->errinfo = tmp; \
- ret = 0; \
- break; \
-}
-
-#define ERROR_ARGS ruby_sourcefile, nd_line(node),
-
-
-#define COMPILE_OK 1
-#define COMPILE_NG 0
-
-
-/* leave name uninitialized so that compiler warn if INIT_ANCHOR is
- * missing */
-#define DECL_ANCHOR(name) \
- LINK_ANCHOR *name, name##_body__ = {{0,},}
-#define INIT_ANCHOR(name) \
- (name##_body__.last = &name##_body__.anchor, name = &name##_body__)
-
-#endif /* RUBY_COMPILE_H */
diff --git a/complex.c b/complex.c
index dc1e8bae5e..90900751b1 100644
--- a/complex.c
+++ b/complex.c
@@ -19,11 +19,10 @@
#define ONE INT2FIX(1)
#define TWO INT2FIX(2)
-static ID id_Unify, id_abs, id_abs2, id_arg, id_cmp, id_conjugate,
- id_convert, id_denominator, id_divmod, id_equal_p, id_exact_p, id_expt,
- id_floor, id_format, id_idiv, id_inspect, id_negate, id_new, id_new_bang,
- id_numerator, id_polar, id_quo, id_scalar_p, id_to_f, id_to_i, id_to_r,
- id_to_s, id_truncate;
+static ID id_abs, id_abs2, id_arg, id_cmp, id_conj, id_convert,
+ id_denominator, id_divmod, id_equal_p, id_expt, id_floor, id_hash,
+ id_idiv, id_inspect, id_negate, id_numerator, id_polar, id_quo,
+ id_real_p, id_to_f, id_to_i, id_to_r, id_to_s;
#define f_boolcast(x) ((x) ? Qtrue : Qfalse)
@@ -62,17 +61,17 @@ m_##n(VALUE x, VALUE y)\
return rb_funcall(rb_mMath, id_##n, 2, x, y);\
}
+#define PRESERVE_SIGNEDZERO
+
inline static VALUE
f_add(VALUE x, VALUE y)
{
- if (FIXNUM_P(y)) {
- if (FIX2LONG(y) == 0)
- return x;
- }
- else if (FIXNUM_P(x)) {
- if (FIX2LONG(x) == 0)
- return y;
- }
+#ifndef PRESERVE_SIGNEDZERO
+ if (FIXNUM_P(y) && FIX2LONG(y) == 0)
+ return x;
+ else if (FIXNUM_P(x) && FIX2LONG(x) == 0)
+ return y;
+#endif
return rb_funcall(x, '+', 1, y);
}
@@ -119,37 +118,36 @@ binop(mod, '%')
inline static VALUE
f_mul(VALUE x, VALUE y)
{
+#ifndef PRESERVE_SIGNEDZERO
if (FIXNUM_P(y)) {
- long _iy = FIX2LONG(y);
- if (_iy == 0) {
- if (TYPE(x) == T_FLOAT)
- return rb_float_new(0.0);
- else
+ long iy = FIX2LONG(y);
+ if (iy == 0) {
+ if (FIXNUM_P(x) || TYPE(x) == T_BIGNUM)
return ZERO;
}
- else if (_iy == 1)
+ else if (iy == 1)
return x;
}
else if (FIXNUM_P(x)) {
- long _ix = FIX2LONG(x);
- if (_ix == 0) {
- if (TYPE(y) == T_FLOAT)
- return rb_float_new(0.0);
- else
+ long ix = FIX2LONG(x);
+ if (ix == 0) {
+ if (FIXNUM_P(y) || TYPE(y) == T_BIGNUM)
return ZERO;
}
- else if (_ix == 1)
+ else if (ix == 1)
return y;
}
+#endif
return rb_funcall(x, '*', 1, y);
}
inline static VALUE
f_sub(VALUE x, VALUE y)
{
- if (FIXNUM_P(y))
- if (FIX2LONG(y) == 0)
- return x;
+#ifndef PRESERVE_SIGNEDZERO
+ if (FIXNUM_P(y) && FIX2LONG(y) == 0)
+ return x;
+#endif
return rb_funcall(x, '-', 1, y);
}
@@ -158,23 +156,20 @@ binop(xor, '^')
fun1(abs)
fun1(abs2)
fun1(arg)
-fun1(conjugate)
+fun1(conj)
fun1(denominator)
-fun1(exact_p)
fun1(floor)
+fun1(hash)
fun1(inspect)
fun1(negate)
fun1(numerator)
fun1(polar)
-fun1(scalar_p)
-
-#define f_real_p f_scalar_p
+fun1(real_p)
fun1(to_f)
fun1(to_i)
fun1(to_r)
fun1(to_s)
-fun1(truncate)
fun2(divmod)
@@ -198,6 +193,8 @@ f_negative_p(VALUE x)
return rb_funcall(x, '<', 1, ZERO);
}
+#define f_positive_p(x) (!f_negative_p(x))
+
inline static VALUE
f_zero_p(VALUE x)
{
@@ -206,6 +203,8 @@ f_zero_p(VALUE x)
return rb_funcall(x, id_equal_p, 1, ZERO);
}
+#define f_nonzero_p(x) (!f_zero_p(x))
+
inline static VALUE
f_one_p(VALUE x)
{
@@ -250,6 +249,9 @@ k_complex_p(VALUE x)
return f_kind_of_p(x, rb_cComplex);
}
+#define k_exact_p(x) (!k_float_p(x))
+#define k_inexact_p(x) k_float_p(x)
+
#define get_dat1(x) \
struct RComplex *dat;\
dat = ((struct RComplex *)(x))
@@ -260,13 +262,13 @@ k_complex_p(VALUE x)
bdat = ((struct RComplex *)(y))
inline static VALUE
-nucomp_s_new_internal(VALUE klass, VALUE real, VALUE image)
+nucomp_s_new_internal(VALUE klass, VALUE real, VALUE imag)
{
NEWOBJ(obj, struct RComplex);
OBJSETUP(obj, klass, T_COMPLEX);
obj->real = real;
- obj->image = image;
+ obj->imag = imag;
return (VALUE)obj;
}
@@ -277,27 +279,29 @@ nucomp_s_alloc(VALUE klass)
return nucomp_s_new_internal(klass, ZERO, ZERO);
}
+#if 0
static VALUE
nucomp_s_new_bang(int argc, VALUE *argv, VALUE klass)
{
- VALUE real, image;
+ VALUE real, imag;
- switch (rb_scan_args(argc, argv, "11", &real, &image)) {
+ switch (rb_scan_args(argc, argv, "11", &real, &imag)) {
case 1:
if (!k_numeric_p(real))
real = f_to_i(real);
- image = ZERO;
+ imag = ZERO;
break;
default:
if (!k_numeric_p(real))
real = f_to_i(real);
- if (!k_numeric_p(image))
- image = f_to_i(image);
+ if (!k_numeric_p(imag))
+ imag = f_to_i(imag);
break;
}
- return nucomp_s_new_internal(klass, real, image);
+ return nucomp_s_new_internal(klass, real, imag);
}
+#endif
inline static VALUE
f_complex_new_bang1(VALUE klass, VALUE x)
@@ -314,7 +318,19 @@ f_complex_new_bang2(VALUE klass, VALUE x, VALUE y)
return nucomp_s_new_internal(klass, x, y);
}
-#define f_unify_p(klass) rb_const_defined(klass, id_Unify)
+#if RUBY_VERSION_CODE < 200
+#define CANON
+#endif
+
+#ifdef CANON
+static int canonicalization = 0;
+
+void
+nucomp_canonicalize(int f)
+{
+ canonicalization = f;
+}
+#endif
inline static void
nucomp_real_check(VALUE num)
@@ -332,76 +348,60 @@ nucomp_real_check(VALUE num)
}
inline static VALUE
-nucomp_s_canonicalize_internal(VALUE klass, VALUE real, VALUE image)
+nucomp_s_canonicalize_internal(VALUE klass, VALUE real, VALUE imag)
{
+#ifdef CANON
#define CL_CANON
#ifdef CL_CANON
- if (f_zero_p(image) && f_unify_p(klass) &&
- !k_float_p(real) && !k_float_p(image))
+ if (f_zero_p(imag) && k_exact_p(imag) && canonicalization)
return real;
#else
- if (f_zero_p(image) && f_unify_p(klass))
+ if (f_zero_p(imag) && canonicalization)
return real;
#endif
- else if (f_real_p(real) && f_real_p(image))
- return nucomp_s_new_internal(klass, real, image);
+#endif
+ if (f_real_p(real) && f_real_p(imag))
+ return nucomp_s_new_internal(klass, real, imag);
else if (f_real_p(real)) {
- get_dat1(image);
+ get_dat1(imag);
return nucomp_s_new_internal(klass,
- f_sub(real, dat->image),
+ f_sub(real, dat->imag),
f_add(ZERO, dat->real));
}
- else if (f_real_p(image)) {
+ else if (f_real_p(imag)) {
get_dat1(real);
return nucomp_s_new_internal(klass,
dat->real,
- f_add(dat->image, image));
+ f_add(dat->imag, imag));
}
else {
- get_dat2(real, image);
+ get_dat2(real, imag);
return nucomp_s_new_internal(klass,
- f_sub(adat->real, bdat->image),
- f_add(adat->image, bdat->real));
- }
-}
-
-#if 0
-static VALUE
-nucomp_s_canonicalize(int argc, VALUE *argv, VALUE klass)
-{
- VALUE real, image;
-
- switch (rb_scan_args(argc, argv, "11", &real, &image)) {
- case 1:
- image = ZERO;
- break;
+ f_sub(adat->real, bdat->imag),
+ f_add(adat->imag, bdat->real));
}
-
- nucomp_real_check(real);
- nucomp_real_check(image);
-
- return nucomp_s_canonicalize_internal(klass, real, image);
}
-#endif
static VALUE
nucomp_s_new(int argc, VALUE *argv, VALUE klass)
{
- VALUE real, image;
+ VALUE real, imag;
- switch (rb_scan_args(argc, argv, "11", &real, &image)) {
+ switch (rb_scan_args(argc, argv, "11", &real, &imag)) {
case 1:
- image = ZERO;
+ nucomp_real_check(real);
+ imag = ZERO;
+ break;
+ default:
+ nucomp_real_check(real);
+ nucomp_real_check(imag);
break;
}
- nucomp_real_check(real);
- nucomp_real_check(image);
-
- return nucomp_s_canonicalize_internal(klass, real, image);
+ return nucomp_s_canonicalize_internal(klass, real, imag);
}
inline static VALUE
@@ -424,73 +424,86 @@ nucomp_f_complex(int argc, VALUE *argv, VALUE klass)
return rb_funcall2(rb_cComplex, id_convert, argc, argv);
}
-extern VALUE math_atan2(VALUE obj, VALUE x, VALUE y);
-extern VALUE math_cos(VALUE obj, VALUE x);
-extern VALUE math_cosh(VALUE obj, VALUE x);
-extern VALUE math_exp(VALUE obj, VALUE x);
-extern VALUE math_hypot(VALUE obj, VALUE x, VALUE y);
-extern VALUE math_log(int argc, VALUE *argv);
-extern VALUE math_sin(VALUE obj, VALUE x);
-extern VALUE math_sinh(VALUE obj, VALUE x);
-extern VALUE math_sqrt(VALUE obj, VALUE x);
+#define imp1(n) \
+extern VALUE rb_math_##n(VALUE x);\
+inline static VALUE \
+m_##n##_bang(VALUE x)\
+{\
+ return rb_math_##n(x);\
+}
-#define m_atan2_bang(x,y) math_atan2(Qnil,x,y)
-#define m_cos_bang(x) math_cos(Qnil,x)
-#define m_cosh_bang(x) math_cosh(Qnil,x)
-#define m_exp_bang(x) math_exp(Qnil,x)
-#define m_hypot(x,y) math_hypot(Qnil,x,y)
+#define imp2(n) \
+extern VALUE rb_math_##n(VALUE x, VALUE y);\
+inline static VALUE \
+m_##n##_bang(VALUE x, VALUE y)\
+{\
+ return rb_math_##n(x, y);\
+}
+
+imp2(atan2)
+imp1(cos)
+imp1(cosh)
+imp1(exp)
+imp2(hypot)
+
+#define m_hypot(x,y) m_hypot_bang(x,y)
+
+extern VALUE rb_math_log(int argc, VALUE *argv);
static VALUE
m_log_bang(VALUE x)
{
- return math_log(1, &x);
+ return rb_math_log(1, &x);
}
-#define m_sin_bang(x) math_sin(Qnil,x)
-#define m_sinh_bang(x) math_sinh(Qnil,x)
-#define m_sqrt_bang(x) math_sqrt(Qnil,x)
+imp1(sin)
+imp1(sinh)
+imp1(sqrt)
static VALUE
m_cos(VALUE x)
{
- get_dat1(x);
-
if (f_real_p(x))
return m_cos_bang(x);
- return f_complex_new2(rb_cComplex,
- f_mul(m_cos_bang(dat->real),
- m_cosh_bang(dat->image)),
- f_mul(f_negate(m_sin_bang(dat->real)),
- m_sinh_bang(dat->image)));
+ {
+ get_dat1(x);
+ return f_complex_new2(rb_cComplex,
+ f_mul(m_cos_bang(dat->real),
+ m_cosh_bang(dat->imag)),
+ f_mul(f_negate(m_sin_bang(dat->real)),
+ m_sinh_bang(dat->imag)));
+ }
}
static VALUE
m_sin(VALUE x)
{
- get_dat1(x);
-
if (f_real_p(x))
return m_sin_bang(x);
- return f_complex_new2(rb_cComplex,
- f_mul(m_sin_bang(dat->real),
- m_cosh_bang(dat->image)),
- f_mul(m_cos_bang(dat->real),
- m_sinh_bang(dat->image)));
+ {
+ get_dat1(x);
+ return f_complex_new2(rb_cComplex,
+ f_mul(m_sin_bang(dat->real),
+ m_cosh_bang(dat->imag)),
+ f_mul(m_cos_bang(dat->real),
+ m_sinh_bang(dat->imag)));
+ }
}
+#if 0
static VALUE
m_sqrt(VALUE x)
{
if (f_real_p(x)) {
- if (!f_negative_p(x))
+ if (f_positive_p(x))
return m_sqrt_bang(x);
return f_complex_new2(rb_cComplex, ZERO, m_sqrt_bang(f_negate(x)));
}
else {
get_dat1(x);
- if (f_negative_p(dat->image))
- return f_conjugate(m_sqrt(f_conjugate(x)));
+ if (f_negative_p(dat->imag))
+ return f_conj(m_sqrt(f_conj(x)));
else {
VALUE a = f_abs(x);
return f_complex_new2(rb_cComplex,
@@ -499,6 +512,7 @@ m_sqrt(VALUE x)
}
}
}
+#endif
inline static VALUE
f_complex_polar(VALUE klass, VALUE x, VALUE y)
@@ -524,30 +538,38 @@ nucomp_real(VALUE self)
}
static VALUE
-nucomp_image(VALUE self)
+nucomp_imag(VALUE self)
{
get_dat1(self);
- return dat->image;
+ return dat->imag;
+}
+
+static VALUE
+nucomp_negate(VALUE self)
+{
+ get_dat1(self);
+ return f_complex_new2(CLASS_OF(self),
+ f_negate(dat->real), f_negate(dat->imag));
}
static VALUE
nucomp_add(VALUE self, VALUE other)
{
if (k_complex_p(other)) {
- VALUE real, image;
+ VALUE real, imag;
get_dat2(self, other);
real = f_add(adat->real, bdat->real);
- image = f_add(adat->image, bdat->image);
+ imag = f_add(adat->imag, bdat->imag);
- return f_complex_new2(CLASS_OF(self), real, image);
+ return f_complex_new2(CLASS_OF(self), real, imag);
}
if (k_numeric_p(other) && f_real_p(other)) {
get_dat1(self);
return f_complex_new2(CLASS_OF(self),
- f_add(dat->real, other), dat->image);
+ f_add(dat->real, other), dat->imag);
}
return rb_num_coerce_bin(self, other, '+');
}
@@ -556,20 +578,20 @@ static VALUE
nucomp_sub(VALUE self, VALUE other)
{
if (k_complex_p(other)) {
- VALUE real, image;
+ VALUE real, imag;
get_dat2(self, other);
real = f_sub(adat->real, bdat->real);
- image = f_sub(adat->image, bdat->image);
+ imag = f_sub(adat->imag, bdat->imag);
- return f_complex_new2(CLASS_OF(self), real, image);
+ return f_complex_new2(CLASS_OF(self), real, imag);
}
if (k_numeric_p(other) && f_real_p(other)) {
get_dat1(self);
return f_complex_new2(CLASS_OF(self),
- f_sub(dat->real, other), dat->image);
+ f_sub(dat->real, other), dat->imag);
}
return rb_num_coerce_bin(self, other, '-');
}
@@ -578,23 +600,23 @@ static VALUE
nucomp_mul(VALUE self, VALUE other)
{
if (k_complex_p(other)) {
- VALUE real, image;
+ VALUE real, imag;
get_dat2(self, other);
real = f_sub(f_mul(adat->real, bdat->real),
- f_mul(adat->image, bdat->image));
- image = f_add(f_mul(adat->real, bdat->image),
- f_mul(adat->image, bdat->real));
+ f_mul(adat->imag, bdat->imag));
+ imag = f_add(f_mul(adat->real, bdat->imag),
+ f_mul(adat->imag, bdat->real));
- return f_complex_new2(CLASS_OF(self), real, image);
+ return f_complex_new2(CLASS_OF(self), real, imag);
}
if (k_numeric_p(other) && f_real_p(other)) {
get_dat1(self);
return f_complex_new2(CLASS_OF(self),
f_mul(dat->real, other),
- f_mul(dat->image, other));
+ f_mul(dat->imag, other));
}
return rb_num_coerce_bin(self, other, '*');
}
@@ -608,23 +630,23 @@ nucomp_div(VALUE self, VALUE other)
get_dat2(self, other);
if (TYPE(adat->real) == T_FLOAT ||
- TYPE(adat->image) == T_FLOAT ||
+ TYPE(adat->imag) == T_FLOAT ||
TYPE(bdat->real) == T_FLOAT ||
- TYPE(bdat->image) == T_FLOAT) {
- VALUE magn = m_hypot(bdat->real, bdat->image);
+ TYPE(bdat->imag) == T_FLOAT) {
+ VALUE magn = m_hypot(bdat->real, bdat->imag);
VALUE tmp = f_complex_new_bang2(CLASS_OF(self),
f_div(bdat->real, magn),
- f_div(bdat->image, magn));
- return f_div(f_mul(self, f_conjugate(tmp)), magn);
+ f_div(bdat->imag, magn));
+ return f_div(f_mul(self, f_conj(tmp)), magn);
}
- return f_div(f_mul(self, f_conjugate(other)), f_abs2(other));
+ return f_div(f_mul(self, f_conj(other)), f_abs2(other));
}
if (k_numeric_p(other) && f_real_p(other)) {
get_dat1(self);
return f_complex_new2(CLASS_OF(self),
f_div(dat->real, other),
- f_div(dat->image, other));
+ f_div(dat->imag, other));
}
return rb_num_coerce_bin(self, other, '/');
}
@@ -639,13 +661,13 @@ nucomp_fdiv(VALUE self, VALUE other)
return f_div(f_complex_new2(CLASS_OF(self),
f_to_f(dat->real),
- f_to_f(dat->image)), other);
+ f_to_f(dat->imag)), other);
}
static VALUE
nucomp_expt(VALUE self, VALUE other)
{
- if (f_zero_p(other))
+ if (k_exact_p(other) && f_zero_p(other))
return f_complex_new_bang1(CLASS_OF(self), ONE);
if (k_rational_p(other) && f_one_p(f_denominator(other)))
@@ -661,7 +683,7 @@ nucomp_expt(VALUE self, VALUE other)
theta = RARRAY_PTR(a)[1];
ore = dat->real;
- oim = dat->image;
+ oim = dat->imag;
nr = m_exp_bang(f_sub(f_mul(ore, m_log_bang(r)),
f_mul(oim, theta)));
ntheta = f_add(f_mul(theta, ore), f_mul(oim, m_log_bang(r)));
@@ -675,7 +697,7 @@ nucomp_expt(VALUE self, VALUE other)
z = x;
n = f_sub(other, ONE);
- while (!f_zero_p(n)) {
+ while (f_nonzero_p(n)) {
VALUE a;
while (a = f_divmod(n, TWO),
@@ -684,8 +706,8 @@ nucomp_expt(VALUE self, VALUE other)
x = f_complex_new2(CLASS_OF(self),
f_sub(f_mul(dat->real, dat->real),
- f_mul(dat->image, dat->image)),
- f_mul(f_mul(TWO, dat->real), dat->image));
+ f_mul(dat->imag, dat->imag)),
+ f_mul(f_mul(TWO, dat->real), dat->imag));
n = RARRAY_PTR(a)[0];
}
z = f_mul(z, x);
@@ -714,12 +736,12 @@ nucomp_equal_p(VALUE self, VALUE other)
get_dat2(self, other);
return f_boolcast(f_equal_p(adat->real, bdat->real) &&
- f_equal_p(adat->image, bdat->image));
+ f_equal_p(adat->imag, bdat->imag));
}
if (k_numeric_p(other) && f_real_p(other)) {
get_dat1(self);
- return f_boolcast(f_equal_p(dat->real, other) && f_zero_p(dat->image));
+ return f_boolcast(f_equal_p(dat->real, other) && f_zero_p(dat->imag));
}
return f_equal_p(other, self);
}
@@ -739,7 +761,7 @@ static VALUE
nucomp_abs(VALUE self)
{
get_dat1(self);
- return m_hypot(dat->real, dat->image);
+ return m_hypot(dat->real, dat->imag);
}
static VALUE
@@ -747,21 +769,21 @@ nucomp_abs2(VALUE self)
{
get_dat1(self);
return f_add(f_mul(dat->real, dat->real),
- f_mul(dat->image, dat->image));
+ f_mul(dat->imag, dat->imag));
}
static VALUE
nucomp_arg(VALUE self)
{
get_dat1(self);
- return m_atan2_bang(dat->image, dat->real);
+ return m_atan2_bang(dat->imag, dat->real);
}
static VALUE
nucomp_rect(VALUE self)
{
get_dat1(self);
- return rb_assoc_new(dat->real, dat->image);
+ return rb_assoc_new(dat->real, dat->imag);
}
static VALUE
@@ -771,30 +793,32 @@ nucomp_polar(VALUE self)
}
static VALUE
-nucomp_conjugate(VALUE self)
+nucomp_conj(VALUE self)
{
get_dat1(self);
- return f_complex_new2(CLASS_OF(self), dat->real, f_negate(dat->image));
+ return f_complex_new2(CLASS_OF(self), dat->real, f_negate(dat->imag));
}
+#if 0
static VALUE
-nucomp_real_p(VALUE self)
+nucomp_true(VALUE self)
{
- return Qfalse;
+ return Qtrue;
}
+#endif
-#if 0
static VALUE
-nucomp_complex_p(VALUE self)
+nucomp_false(VALUE self)
{
- return Qtrue;
+ return Qfalse;
}
+#if 0
static VALUE
nucomp_exact_p(VALUE self)
{
get_dat1(self);
- return f_boolcast(f_exact_p(dat->real) && f_exact_p(dat->image));
+ return f_boolcast(f_exact_p(dat->real) && f_exact_p(dat->imag));
}
static VALUE
@@ -810,7 +834,7 @@ static VALUE
nucomp_denominator(VALUE self)
{
get_dat1(self);
- return rb_lcm(f_denominator(dat->real), f_denominator(dat->image));
+ return rb_lcm(f_denominator(dat->real), f_denominator(dat->imag));
}
static VALUE
@@ -824,15 +848,29 @@ nucomp_numerator(VALUE self)
return f_complex_new2(CLASS_OF(self),
f_mul(f_numerator(dat->real),
f_div(cd, f_denominator(dat->real))),
- f_mul(f_numerator(dat->image),
- f_div(cd, f_denominator(dat->image))));
+ f_mul(f_numerator(dat->imag),
+ f_div(cd, f_denominator(dat->imag))));
}
static VALUE
nucomp_hash(VALUE self)
{
get_dat1(self);
- return f_xor(dat->real, dat->image);
+ return f_xor(f_hash(dat->real), f_hash(dat->imag));
+}
+
+static VALUE
+nucomp_eql_p(VALUE self, VALUE other)
+{
+ if (k_complex_p(other)) {
+ get_dat2(self, other);
+
+ return f_boolcast((CLASS_OF(adat->real) == CLASS_OF(bdat->real)) &&
+ (CLASS_OF(adat->imag) == CLASS_OF(bdat->imag)) &&
+ f_equal_p(self, other));
+
+ }
+ return Qfalse;
}
#ifndef HAVE_SIGNBIT
@@ -874,12 +912,12 @@ nucomp_to_s(VALUE self)
get_dat1(self);
- impos = f_tpositive_p(dat->image);
+ impos = f_tpositive_p(dat->imag);
s = f_to_s(dat->real);
rb_str_cat2(s, !impos ? "-" : "+");
- rb_str_concat(s, f_to_s(f_abs(dat->image)));
+ rb_str_concat(s, f_to_s(f_abs(dat->imag)));
rb_str_cat2(s, "i");
return s;
@@ -892,13 +930,13 @@ nucomp_inspect(VALUE self)
get_dat1(self);
- impos = f_tpositive_p(dat->image);
+ impos = f_tpositive_p(dat->imag);
s = rb_str_new2("(");
rb_str_concat(s, f_inspect(dat->real));
rb_str_cat2(s, !impos ? "-" : "+");
- rb_str_concat(s, f_inspect(f_abs(dat->image)));
+ rb_str_concat(s, f_inspect(f_abs(dat->imag)));
rb_str_cat2(s, "i)");
return s;
@@ -907,8 +945,12 @@ nucomp_inspect(VALUE self)
static VALUE
nucomp_marshal_dump(VALUE self)
{
+ VALUE a;
get_dat1(self);
- return rb_assoc_new(dat->real, dat->image);
+
+ a = rb_assoc_new(dat->real, dat->imag);
+ rb_copy_generic_ivar(a, self);
+ return a;
}
static VALUE
@@ -916,7 +958,8 @@ nucomp_marshal_load(VALUE self, VALUE a)
{
get_dat1(self);
dat->real = RARRAY_PTR(a)[0];
- dat->image = RARRAY_PTR(a)[1];
+ dat->imag = RARRAY_PTR(a)[1];
+ rb_copy_generic_ivar(self, a);
return self;
}
@@ -956,7 +999,7 @@ nucomp_to_i(VALUE self)
{
get_dat1(self);
- if (k_float_p(dat->image) || !f_zero_p(dat->image)) {
+ if (k_inexact_p(dat->imag) || f_nonzero_p(dat->imag)) {
VALUE s = f_to_s(self);
rb_raise(rb_eRangeError, "can't convert %s into Integer",
StringValuePtr(s));
@@ -969,7 +1012,7 @@ nucomp_to_f(VALUE self)
{
get_dat1(self);
- if (k_float_p(dat->image) || !f_zero_p(dat->image)) {
+ if (k_inexact_p(dat->imag) || f_nonzero_p(dat->imag)) {
VALUE s = f_to_s(self);
rb_raise(rb_eRangeError, "can't convert %s into Float",
StringValuePtr(s));
@@ -982,7 +1025,7 @@ nucomp_to_r(VALUE self)
{
get_dat1(self);
- if (k_float_p(dat->image) || !f_zero_p(dat->image)) {
+ if (k_inexact_p(dat->imag) || f_nonzero_p(dat->imag)) {
VALUE s = f_to_s(self);
rb_raise(rb_eRangeError, "can't convert %s into Rational",
StringValuePtr(s));
@@ -1124,9 +1167,8 @@ string_to_c_internal(VALUE self)
}
if (NIL_P(m)) {
m = f_match(comp_pat2, s);
- if (NIL_P(m)) {
+ if (NIL_P(m))
return rb_assoc_new(Qnil, self);
- }
sr = f_aref(m, INT2FIX(1));
if (NIL_P(f_aref(m, INT2FIX(2))))
si = Qnil;
@@ -1164,7 +1206,6 @@ string_to_c_internal(VALUE self)
return rb_assoc_new(rb_complex_polar(r, i), re);
else
return rb_assoc_new(rb_complex_new2(r, i), re);
-
}
}
@@ -1206,7 +1247,7 @@ nucomp_s_convert(int argc, VALUE *argv, VALUE klass)
{
VALUE a1, a2, backref;
- rb_scan_args(argc, argv, "02", &a1, &a2);
+ rb_scan_args(argc, argv, "11", &a1, &a2);
backref = rb_backref_get();
rb_match_busy(backref);
@@ -1238,7 +1279,7 @@ nucomp_s_convert(int argc, VALUE *argv, VALUE klass)
{
get_dat1(a1);
- if (!k_float_p(dat->image) && f_zero_p(dat->image))
+ if (k_exact_p(dat->imag) && f_zero_p(dat->imag))
a1 = dat->real;
}
}
@@ -1248,16 +1289,28 @@ nucomp_s_convert(int argc, VALUE *argv, VALUE klass)
{
get_dat1(a2);
- if (!k_float_p(dat->image) && f_zero_p(dat->image))
+ if (k_exact_p(dat->imag) && f_zero_p(dat->imag))
a2 = dat->real;
}
}
switch (TYPE(a1)) {
case T_COMPLEX:
- if (NIL_P(a2) || f_zero_p(a2))
+ if (argc == 1 || (k_exact_p(a2) && f_zero_p(a2)))
+ return a1;
+ }
+
+ if (argc == 1) {
+ if (k_numeric_p(a1) && !f_real_p(a1))
return a1;
}
+ else {
+ if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
+ (!f_real_p(a1) || !f_real_p(a2)))
+ return f_add(a1,
+ f_mul(a2,
+ f_complex_new_bang2(rb_cComplex, ZERO, ONE)));
+ }
{
VALUE argv2[2];
@@ -1269,20 +1322,6 @@ nucomp_s_convert(int argc, VALUE *argv, VALUE klass)
/* --- */
-#define id_Complex rb_intern("Complex")
-
-static VALUE
-numeric_re(VALUE self)
-{
- return rb_Complex1(self);
-}
-
-static VALUE
-numeric_im(VALUE self)
-{
- return rb_Complex2(ZERO, self);
-}
-
static VALUE
numeric_real(VALUE self)
{
@@ -1290,7 +1329,7 @@ numeric_real(VALUE self)
}
static VALUE
-numeric_image(VALUE self)
+numeric_imag(VALUE self)
{
return INT2FIX(0);
}
@@ -1306,7 +1345,7 @@ numeric_abs2(VALUE self)
static VALUE
numeric_arg(VALUE self)
{
- if (!f_negative_p(self))
+ if (f_positive_p(self))
return INT2FIX(0);
return rb_const_get(rb_mMath, id_PI);
}
@@ -1314,7 +1353,7 @@ numeric_arg(VALUE self)
static VALUE
numeric_rect(VALUE self)
{
- return rb_assoc_new(self, ZERO);
+ return rb_assoc_new(self, INT2FIX(0));
}
static VALUE
@@ -1324,7 +1363,7 @@ numeric_polar(VALUE self)
}
static VALUE
-numeric_conjugate(VALUE self)
+numeric_conj(VALUE self)
{
return self;
}
@@ -1335,34 +1374,29 @@ Init_Complex(void)
#undef rb_intern
#define rb_intern(str) rb_intern_const(str)
- id_Unify = rb_intern("Unify");
id_abs = rb_intern("abs");
id_abs2 = rb_intern("abs2");
id_arg = rb_intern("arg");
id_cmp = rb_intern("<=>");
- id_conjugate = rb_intern("conjugate");
+ id_conj = rb_intern("conj");
id_convert = rb_intern("convert");
id_denominator = rb_intern("denominator");
id_divmod = rb_intern("divmod");
id_equal_p = rb_intern("==");
- id_exact_p = rb_intern("exact?");
id_expt = rb_intern("**");
id_floor = rb_intern("floor");
- id_format = rb_intern("format");
+ id_hash = rb_intern("hash");
id_idiv = rb_intern("div");
id_inspect = rb_intern("inspect");
id_negate = rb_intern("-@");
- id_new = rb_intern("new");
- id_new_bang = rb_intern("new!");
id_numerator = rb_intern("numerator");
id_polar = rb_intern("polar");
id_quo = rb_intern("quo");
- id_scalar_p = rb_intern("scalar?");
+ id_real_p = rb_intern("real?");
id_to_f = rb_intern("to_f");
id_to_i = rb_intern("to_i");
id_to_r = rb_intern("to_r");
id_to_s = rb_intern("to_s");
- id_truncate = rb_intern("truncate");
}
void
@@ -1373,16 +1407,14 @@ InitVM_Complex(rb_vm_t *vm)
rb_cComplex = rb_define_class(COMPLEX_NAME, rb_cNumeric);
rb_define_alloc_func(rb_cComplex, nucomp_s_alloc);
- rb_funcall(rb_cComplex, rb_intern("private_class_method"), 1,
- ID2SYM(rb_intern("allocate")));
-
- rb_define_singleton_method(rb_cComplex, "new!", nucomp_s_new_bang, -1);
- rb_funcall(rb_cComplex, rb_intern("private_class_method"), 1,
- ID2SYM(rb_intern("new!")));
+ rb_undef_method(CLASS_OF(rb_cComplex), "allocate");
- rb_define_singleton_method(rb_cComplex, "new", nucomp_s_new, -1);
- rb_funcall(rb_cComplex, rb_intern("private_class_method"), 1,
- ID2SYM(rb_intern("new")));
+#if 0
+ rb_define_private_method(CLASS_OF(rb_cComplex), "new!", nucomp_s_new_bang, -1);
+ rb_define_private_method(CLASS_OF(rb_cComplex), "new", nucomp_s_new, -1);
+#else
+ rb_undef_method(CLASS_OF(rb_cComplex), "new");
+#endif
rb_define_singleton_method(rb_cComplex, "rectangular", nucomp_s_new, -1);
rb_define_singleton_method(rb_cComplex, "rect", nucomp_s_new, -1);
@@ -1409,9 +1441,10 @@ InitVM_Complex(rb_vm_t *vm)
#endif
rb_define_method(rb_cComplex, "real", nucomp_real, 0);
- rb_define_method(rb_cComplex, "image", nucomp_image, 0);
- rb_define_method(rb_cComplex, "imag", nucomp_image, 0);
+ rb_define_method(rb_cComplex, "imaginary", nucomp_imag, 0);
+ rb_define_method(rb_cComplex, "imag", nucomp_imag, 0);
+ rb_define_method(rb_cComplex, "-@", nucomp_negate, 0);
rb_define_method(rb_cComplex, "+", nucomp_add, 1);
rb_define_method(rb_cComplex, "-", nucomp_sub, 1);
rb_define_method(rb_cComplex, "*", nucomp_mul, 1);
@@ -1432,24 +1465,24 @@ InitVM_Complex(rb_vm_t *vm)
rb_define_method(rb_cComplex, "rectangular", nucomp_rect, 0);
rb_define_method(rb_cComplex, "rect", nucomp_rect, 0);
rb_define_method(rb_cComplex, "polar", nucomp_polar, 0);
- rb_define_method(rb_cComplex, "conjugate", nucomp_conjugate, 0);
- rb_define_method(rb_cComplex, "conj", nucomp_conjugate, 0);
+ rb_define_method(rb_cComplex, "conjugate", nucomp_conj, 0);
+ rb_define_method(rb_cComplex, "conj", nucomp_conj, 0);
#if 0
- rb_define_method(rb_cComplex, "~", nucomp_conjugate, 0); /* gcc */
+ rb_define_method(rb_cComplex, "~", nucomp_conj, 0); /* gcc */
#endif
+ rb_define_method(rb_cComplex, "real?", nucomp_false, 0);
#if 0
- rb_define_method(rb_cComplex, "real?", nucomp_real_p, 0);
- rb_define_method(rb_cComplex, "complex?", nucomp_complex_p, 0);
+ rb_define_method(rb_cComplex, "complex?", nucomp_true, 0);
rb_define_method(rb_cComplex, "exact?", nucomp_exact_p, 0);
rb_define_method(rb_cComplex, "inexact?", nucomp_inexact_p, 0);
#endif
- rb_define_method(rb_cComplex, "scalar?", nucomp_real_p, 0);
rb_define_method(rb_cComplex, "numerator", nucomp_numerator, 0);
rb_define_method(rb_cComplex, "denominator", nucomp_denominator, 0);
rb_define_method(rb_cComplex, "hash", nucomp_hash, 0);
+ rb_define_method(rb_cComplex, "eql?", nucomp_eql_p, 1);
rb_define_method(rb_cComplex, "to_s", nucomp_to_s, 0);
rb_define_method(rb_cComplex, "inspect", nucomp_inspect, 0);
@@ -1469,17 +1502,13 @@ InitVM_Complex(rb_vm_t *vm)
rb_define_method(rb_cString, "to_c", string_to_c, 0);
- rb_define_singleton_method(rb_cComplex, "convert", nucomp_s_convert, -1);
- rb_funcall(rb_cComplex, rb_intern("private_class_method"), 1,
- ID2SYM(rb_intern("convert")));
+ rb_define_private_method(CLASS_OF(rb_cComplex), "convert", nucomp_s_convert, -1);
/* --- */
- rb_define_method(rb_cNumeric, "re", numeric_re, 0);
- rb_define_method(rb_cNumeric, "im", numeric_im, 0);
rb_define_method(rb_cNumeric, "real", numeric_real, 0);
- rb_define_method(rb_cNumeric, "image", numeric_image, 0);
- rb_define_method(rb_cNumeric, "imag", numeric_image, 0);
+ rb_define_method(rb_cNumeric, "imaginary", numeric_imag, 0);
+ rb_define_method(rb_cNumeric, "imag", numeric_imag, 0);
rb_define_method(rb_cNumeric, "abs2", numeric_abs2, 0);
rb_define_method(rb_cNumeric, "arg", numeric_arg, 0);
rb_define_method(rb_cNumeric, "angle", numeric_arg, 0);
@@ -1487,9 +1516,15 @@ InitVM_Complex(rb_vm_t *vm)
rb_define_method(rb_cNumeric, "rectangular", numeric_rect, 0);
rb_define_method(rb_cNumeric, "rect", numeric_rect, 0);
rb_define_method(rb_cNumeric, "polar", numeric_polar, 0);
- rb_define_method(rb_cNumeric, "conjugate", numeric_conjugate, 0);
- rb_define_method(rb_cNumeric, "conj", numeric_conjugate, 0);
+ rb_define_method(rb_cNumeric, "conjugate", numeric_conj, 0);
+ rb_define_method(rb_cNumeric, "conj", numeric_conj, 0);
rb_define_const(rb_cComplex, "I",
f_complex_new_bang2(rb_cComplex, ZERO, ONE));
}
+
+/*
+Local variables:
+c-file-style: "ruby"
+End:
+*/
diff --git a/configure.in b/configure.in
index b589e51ccc..ef782295e1 100644
--- a/configure.in
+++ b/configure.in
@@ -520,7 +520,7 @@ darwin*) LIBS="-lobjc $LIBS"
#endif
],
[
- test "x$target_cpu" = xppc && ac_cv_header_ucontext_h=no
+ test "x$target_cpu" = xpowerpc && ac_cv_header_ucontext_h=no
],
[
AC_DEFINE(BROKEN_SETREUID, 1)
@@ -611,21 +611,6 @@ bsdi*) LIBS="-lm $LIBS"
AC_DEFINE(BROKEN_SETREGID, 1)
ac_cv_sizeof_rlim_t=8;;
freebsd*) LIBS="-lm $LIBS"
- AC_CACHE_CHECK([whether -lxpg4 has to be linked],
- rb_cv_lib_xpg4_needed,
- [AC_TRY_CPP([
-#include <osreldate.h>
-#if __FreeBSD_version < 400020 || \
- (__FreeBSD_version >= 500000 && __FreeBSD_version < 500005)
-#error needs libxpg4
-#endif
- ],
- rb_cv_lib_xpg4_needed=no,
- rb_cv_lib_xpg4_needed=yes,
- rb_cv_lib_xpg4_needed=yes)])
- if test "$rb_cv_lib_xpg4_needed" = yes; then
- AC_CHECK_LIB(xpg4, setlocale)
- fi
;;
dragonfly*) LIBS="-lm $LIBS"
;;
@@ -1056,6 +1041,7 @@ AC_CACHE_VAL(rb_cv_frptr,
__ptr dnl
bufpos dnl
_p dnl
+ __bufpos dnl
; do
AC_TRY_COMPILE([#include <stdio.h>
],
@@ -1075,6 +1061,7 @@ else
[for frend in dnl
_IO_read_end dnl
bufread dnl
+ __bufread dnl
; do
AC_TRY_COMPILE([#include <stdio.h>
],
@@ -1278,7 +1265,13 @@ dnl wheather use dln_a_out or not
AC_ARG_WITH(dln-a-out,
[ --with-dln-a-out use dln_a_out if possible], [
case $withval in
- yes) with_dln_a_out=yes;;
+ dnl (
+ yes)
+ if test "$enable_shared" = yes; then
+ AC_MSG_ERROR(dln_a_out can not make shared library)
+ fi
+ with_dln_a_out=yes;;
+ dnl (
*) with_dln_a_out=no;;
esac], [with_dln_a_out=no])
@@ -1296,6 +1289,9 @@ rb_cv_binary_elf=no)])
if test "$rb_cv_binary_elf" = yes; then
AC_DEFINE(USE_ELF)
+ if test "$with_dln_a_out" = yes; then
+ AC_MSG_ERROR(dln_a_out does not work with ELF)
+ fi
fi
case "$target_os" in
@@ -1446,10 +1442,12 @@ if test "$with_dln_a_out" != yes; then
powerpc*)
: ${LDSHARED="ld -xms"}
DLDFLAGS="$DLDFLAGS "'-export Init_$(TARGET) -lbe -lroot glue-noinit.a init_term_dyn.o start_dyn.o'
- ;;
+ LDFLAGS="$LDFLAGS -L/boot/home/config/lib -lbe -lroot"
+ ;;
i586*)
: ${LDSHARED="ld -shared"}
- DLDFLAGS="$DLDFLAGS -L/boot/develop/lib/x86 -lbe -lroot"
+ DLDFLAGS="$DLDFLAGS -L/boot/develop/lib/x86 -L/boot/home/config/lib \$(topdir)/_APP_ -lbe -lroot"
+ LDFLAGS="$LDFLAGS -L/boot/develop/lib/x86 -L/boot/home/config/lib -lbe -lroot"
;;
esac
: ${LIBPATHENV=LIBRARY_PATH}
@@ -1470,7 +1468,7 @@ if test "$with_dln_a_out" != yes; then
: ${LDSHARED='ld -Bshareable -x'}
LDFLAGS="$LDFLAGS -L/lib -L/usr/lib -L/usr/local/lib"
rb_cv_dlopen=yes;;
- cygwin*|mingw*) : ${LDSHARED="${CC} -shared -s"}
+ cygwin*|mingw*) : ${LDSHARED="${CC} -shared "'$(if $(filter-out -g -g0,$(debugflags)),,-s)'}
XLDFLAGS="$XLDFLAGS -Wl,--stack,0x00200000,--enable-auto-import"
DLDFLAGS="${DLDFLAGS} -Wl,--enable-auto-image-base,--enable-auto-import,--export-all"
: ${LIBPATHENV=""}
@@ -1478,7 +1476,7 @@ if test "$with_dln_a_out" != yes; then
hiuxmpp) : ${LDSHARED='ld -r'} ;;
atheos*) : ${LDSHARED="$CC -shared"}
rb_cv_dlopen=yes ;;
- os2-emx*) LDFLAGS="$LDFLAGS -Zbsd-signals"
+ os2-emx*) LDFLAGS="$LDFLAGS -Zomf"
;;
*) : ${LDSHARED='ld'} ;;
esac
@@ -1698,9 +1696,9 @@ ENABLE_SHARED=no
AC_ARG_ENABLE(shared,
[ --enable-shared build a shared library for Ruby. ],
[enable_shared=$enableval])
+LIBRUBYARG_SHARED='-l$(RUBY_SO_NAME)'
if test "$enable_shared" = 'yes'; then
LIBRUBY='$(LIBRUBY_SO)'
- LIBRUBYARG_SHARED='-l$(RUBY_SO_NAME)'
LIBRUBYARG='$(LIBRUBYARG_SHARED)'
CFLAGS="$CFLAGS $CCDLFLAGS"
ENABLE_SHARED=yes
@@ -1777,7 +1775,9 @@ if test "$enable_shared" = 'yes'; then
esac
fi
if test "$enable_rpath" = yes; then
- LIBRUBYARG_SHARED="${linker_flag}-R ${linker_flag}\$(libdir) -L\$(libdir) $LIBRUBYARG_SHARED"
+ LIBRUBY_RPATHFLAGS="${linker_flag}-R ${linker_flag}\$(libdir) -L\$(libdir)"
+ LIBRUBYARG_SHARED="$LIBRUBY_RPATHFLAGS $LIBRUBYARG_SHARED"
+ LIBRUBYARG_STATIC="$LIBRUBY_RPATHFLAGS $LIBRUBYARG_STATIC"
fi
LDFLAGS="-L. $LDFLAGS"
@@ -1822,7 +1822,7 @@ case "$target_os" in
MINIDLNOBJ=dmydln.o
;;
os2-emx)
- CFLAGS="$CFLAGS -DOS2 -Zmts"
+ CFLAGS="$CFLAGS -DOS2"
LIBRUBY_A=`echo $LIBRUBY_A | sed 's/^lib//'`
LIBRUBY_SO=`echo $LIBRUBY_SO | sed 's/^lib//'`
LIBRUBY_ALIASES=`for i in $LIBRUBY_ALIASES; do echo "$i"; done | sed 's/^lib//'`
@@ -1849,6 +1849,7 @@ case "$target_os" in
CFLAGS="$CFLAGS -relax_pointers"
;;
esac
+ CPPFLAGS="$CPPFLAGS -I/boot/home/config/include"
;;
cygwin*|mingw*)
LIBRUBY_DLDFLAGS="${DLDFLAGS}"' -Wl,--out-implib=$(LIBRUBY)'
@@ -1917,7 +1918,7 @@ dnl (
dnl (
*yes*)
echo "include Makefile" > GNUmakefile
- echo "include uncommon.mk" >> GNUmakefile
+ echo "-include uncommon.mk" >> GNUmakefile
gnumake=yes;;
dnl (
*)
@@ -1983,7 +1984,7 @@ case "$target_os" in
rubyw_install_name="$RUBYW_INSTALL_NAME"
;;
esac
-RUBY_LIB_PREFIX=`eval echo \\"${libdir}/ruby\\"`
+RUBY_LIB_PREFIX=`eval echo \\"${libdir}/${RUBY_INSTALL_NAME}\\"`
AC_ARG_WITH(ruby-version,
[ --with-ruby-version=STR ruby version string for version specific directories [[full]] (full|minor|STR)],
@@ -2001,13 +2002,13 @@ esac
AC_ARG_WITH(sitedir,
[ --with-sitedir=DIR site libraries in DIR [[LIBDIR/ruby/site_ruby]]],
[sitedir=$withval],
- [sitedir='${libdir}/ruby/site_ruby'])
+ [sitedir='${libdir}/${RUBY_INSTALL_NAME}/site_ruby'])
SITE_DIR=`eval echo \\"${sitedir}\\"`
AC_ARG_WITH(vendordir,
[ --with-vendordir=DIR vendor libraries in DIR [[LIBDIR/ruby/vendor_ruby]]],
[vendordir=$withval],
- [vendordir='${libdir}/ruby/vendor_ruby'])
+ [vendordir='${libdir}/${RUBY_INSTALL_NAME}/vendor_ruby'])
VENDOR_DIR=`eval echo \\"${vendordir}\\"`
case "$target_os" in
@@ -2076,7 +2077,7 @@ fi
AC_ARG_WITH(rubyhdrdir,
[ --with-ruby-hdrdir=DIR core headers in DIR [INCLUDEDIR]],
[rubyhdrdir=$withval],
- [rubyhdrdir='${includedir}/ruby-${ruby_version}'])
+ [rubyhdrdir='${includedir}/${RUBY_INSTALL_NAME}-${ruby_version}'])
AC_ARG_WITH(sitehdrdir,
[ --with-site-hdrdir=DIR core headers in DIR [INCLUDEDIR]],
@@ -2106,7 +2107,7 @@ AC_ARG_WITH(mantype,
])
if test -z "$MANTYPE"; then
AC_PATH_PROGS(NROFF, nroff awf, /bin/false, "/usr/bin:/usr/ucb")
- if ${NROFF} -mdoc ${srcdir}/ruby.1 >/dev/null 2>&1; then
+ if ${NROFF} -mdoc ${srcdir}/man/ruby.1 >/dev/null 2>&1; then
MANTYPE=doc
else
MANTYPE=man
diff --git a/cont.c b/cont.c
index 260a81f25e..d62226d043 100644
--- a/cont.c
+++ b/cont.c
@@ -14,6 +14,8 @@
#include "gc.h"
#include "eval_intern.h"
+#define CAPTURE_JUST_VALID_VM_STACK 1
+
enum context_type {
CONTINUATION_CONTEXT = 0,
FIBER_CONTEXT = 1,
@@ -21,9 +23,14 @@ enum context_type {
};
typedef struct rb_context_struct {
+ enum context_type type;
VALUE self;
VALUE value;
VALUE *vm_stack;
+#ifdef CAPTURE_JUST_VALID_VM_STACK
+ int vm_stack_slen; /* length of stack (head of th->stack) */
+ int vm_stack_clen; /* length of control frames (tail of th->stack) */
+#endif
VALUE *machine_stack;
VALUE *machine_stack_src;
#ifdef __ia64
@@ -34,14 +41,28 @@ typedef struct rb_context_struct {
rb_thread_t saved_thread;
rb_jmpbuf_t jmpbuf;
int machine_stack_size;
- VALUE prev;
- int alive;
- enum context_type type;
} rb_context_t;
+enum fiber_status {
+ CREATED,
+ RUNNING,
+ TERMINATED,
+};
+
+typedef struct rb_fiber_struct {
+ rb_context_t cont;
+ VALUE prev;
+ enum fiber_status status;
+ struct rb_fiber_struct *prev_fiber;
+ struct rb_fiber_struct *next_fiber;
+} rb_fiber_t;
+
#define GetContPtr(obj, ptr) \
Data_Get_Struct(obj, rb_context_t, ptr)
+#define GetFiberPtr(obj, ptr) \
+ Data_Get_Struct(obj, rb_fiber_t, ptr)
+
NOINLINE(static VALUE cont_capture(volatile int *stat));
void rb_thread_mark(rb_thread_t *th);
@@ -53,12 +74,16 @@ cont_mark(void *ptr)
if (ptr) {
rb_context_t *cont = ptr;
rb_gc_mark(cont->value);
- rb_gc_mark(cont->prev);
rb_thread_mark(&cont->saved_thread);
if (cont->vm_stack) {
+#ifdef CAPTURE_JUST_VALID_VM_STACK
rb_gc_mark_locations(cont->vm_stack,
- cont->vm_stack + cont->saved_thread.stack_size);
+ cont->vm_stack + cont->vm_stack_slen + cont->vm_stack_clen);
+#elif
+ rb_gc_mark_localtion(cont->vm_stack,
+ cont->vm_stack, cont->saved_thread.stack_size);
+#endif
}
if (cont->machine_stack) {
@@ -81,23 +106,70 @@ cont_free(void *ptr)
RUBY_FREE_ENTER("cont");
if (ptr) {
rb_context_t *cont = ptr;
- RUBY_FREE_UNLESS_NULL(cont->saved_thread.stack);
+ RUBY_FREE_UNLESS_NULL(cont->saved_thread.stack); fflush(stdout);
RUBY_FREE_UNLESS_NULL(cont->machine_stack);
#ifdef __ia64
RUBY_FREE_UNLESS_NULL(cont->machine_register_stack);
#endif
RUBY_FREE_UNLESS_NULL(cont->vm_stack);
- if (cont->type == FIBER_CONTEXT) {
- st_free_table(cont->saved_thread.local_storage);
- }
-
+ /* free rb_cont_t or rb_fiber_t */
ruby_xfree(ptr);
}
RUBY_FREE_LEAVE("cont");
}
static void
+fiber_mark(void *ptr)
+{
+ RUBY_MARK_ENTER("cont");
+ if (ptr) {
+ rb_fiber_t *fib = ptr;
+ rb_gc_mark(fib->prev);
+ cont_mark(&fib->cont);
+ }
+ RUBY_MARK_LEAVE("cont");
+}
+
+static void
+fiber_link_join(rb_fiber_t *fib)
+{
+ VALUE current_fibval = rb_fiber_current();
+ rb_fiber_t *current_fib;
+ GetFiberPtr(current_fibval, current_fib);
+
+ /* join fiber link */
+ fib->next_fiber = current_fib->next_fiber;
+ fib->prev_fiber = current_fib;
+ current_fib->next_fiber->prev_fiber = fib;
+ current_fib->next_fiber = fib;
+}
+
+static void
+fiber_link_remove(rb_fiber_t *fib)
+{
+ fib->prev_fiber->next_fiber = fib->next_fiber;
+ fib->next_fiber->prev_fiber = fib->prev_fiber;
+}
+
+static void
+fiber_free(void *ptr)
+{
+ RUBY_FREE_ENTER("fiber");
+ if (ptr) {
+ rb_fiber_t *fib = ptr;
+
+ if (fib->cont.type != ROOT_FIBER_CONTEXT) {
+ st_free_table(fib->cont.saved_thread.local_storage);
+ }
+ fiber_link_remove(fib);
+
+ cont_free(&fib->cont);
+ }
+ RUBY_FREE_LEAVE("fiber");
+}
+
+static void
cont_save_machine_stack(rb_thread_t *th, rb_context_t *cont)
{
int size;
@@ -147,21 +219,24 @@ cont_save_machine_stack(rb_thread_t *th, rb_context_t *cont)
#endif
}
+static void
+cont_init(rb_context_t *cont)
+{
+ rb_thread_t *th = GET_THREAD();
+
+ /* save thread context */
+ cont->saved_thread = *th;
+}
+
static rb_context_t *
cont_new(VALUE klass)
{
rb_context_t *cont;
volatile VALUE contval;
- rb_thread_t *th = GET_THREAD();
contval = Data_Make_Struct(klass, rb_context_t, cont_mark, cont_free, cont);
-
cont->self = contval;
- cont->alive = Qtrue;
-
- /* save thread context */
- cont->saved_thread = *th;
-
+ cont_init(cont);
return cont;
}
@@ -179,8 +254,16 @@ cont_capture(volatile int *stat)
contval = cont->self;
sth = &cont->saved_thread;
+#ifdef CAPTURE_JUST_VALID_VM_STACK
+ cont->vm_stack_slen = th->cfp->sp + th->mark_stack_len - th->stack;
+ cont->vm_stack_clen = th->stack + th->stack_size - (VALUE*)th->cfp;
+ cont->vm_stack = ALLOC_N(VALUE, cont->vm_stack_slen + cont->vm_stack_clen);
+ MEMCPY(cont->vm_stack, th->stack, VALUE, cont->vm_stack_slen);
+ MEMCPY(cont->vm_stack + cont->vm_stack_slen, (VALUE*)th->cfp, VALUE, cont->vm_stack_clen);
+#elif
cont->vm_stack = ALLOC_N(VALUE, th->stack_size);
MEMCPY(cont->vm_stack, th->stack, VALUE, th->stack_size);
+#endif
sth->stack = 0;
cont_save_machine_stack(th, cont);
@@ -220,7 +303,13 @@ cont_restore_1(rb_context_t *cont)
th->stack_size = fcont->saved_thread.stack_size;
th->stack = fcont->saved_thread.stack;
}
+#ifdef CAPTURE_JUST_VALID_VM_STACK
+ MEMCPY(th->stack, cont->vm_stack, VALUE, cont->vm_stack_slen);
+ MEMCPY(th->stack + sth->stack_size - cont->vm_stack_clen,
+ cont->vm_stack + cont->vm_stack_slen, VALUE, cont->vm_stack_clen);
+#elif
MEMCPY(th->stack, cont->vm_stack, VALUE, sth->stack_size);
+#endif
}
else {
/* fiber */
@@ -461,10 +550,6 @@ rb_cont_call(int argc, VALUE *argv, VALUE contval)
if (th->fiber != cont->saved_thread.fiber) {
rb_raise(rb_eRuntimeError, "continuation called across fiber");
}
-
- if (!fcont->alive) {
- rb_raise(rb_eRuntimeError, "continuation called dead fiber");
- }
}
cont->value = make_passing_arg(argc, argv);
@@ -479,25 +564,32 @@ rb_cont_call(int argc, VALUE *argv, VALUE contval)
#define FIBER_VM_STACK_SIZE (4 * 1024)
-static rb_context_t *
+static rb_fiber_t *
fiber_alloc(VALUE klass)
{
- rb_context_t *cont = cont_new(klass);
+ rb_fiber_t *fib;
+ volatile VALUE fibval = Data_Make_Struct(klass, rb_fiber_t, fiber_mark, fiber_free, fib);
- cont->type = FIBER_CONTEXT;
- cont->prev = Qnil;
+ fib->cont.self = fibval;
+ fib->cont.type = FIBER_CONTEXT;
+ cont_init(&fib->cont);
+ fib->prev = Qnil;
+ fib->status = CREATED;
- return cont;
+ return fib;
}
static VALUE
fiber_new(VALUE klass, VALUE proc)
{
- rb_context_t *cont = fiber_alloc(klass);
- VALUE contval = cont->self;
+ rb_fiber_t *fib = fiber_alloc(klass);
+ VALUE fibval = fib->cont.self;
+ rb_context_t *cont = &fib->cont;
rb_thread_t *th = &cont->saved_thread;
- /* initialize */
+ fiber_link_join(fib);
+
+ /* initialize cont */
cont->vm_stack = 0;
th->stack = 0;
@@ -524,7 +616,7 @@ fiber_new(VALUE klass, VALUE proc)
MEMCPY(&cont->jmpbuf, &th->root_jmpbuf, rb_jmpbuf_t, 1);
- return contval;
+ return fibval;
}
VALUE
@@ -542,11 +634,11 @@ rb_fiber_s_new(VALUE self)
static VALUE
return_fiber(void)
{
- rb_context_t *cont;
+ rb_fiber_t *fib;
VALUE curr = rb_fiber_current();
- GetContPtr(curr, cont);
+ GetFiberPtr(curr, fib);
- if (cont->prev == Qnil) {
+ if (fib->prev == Qnil) {
rb_thread_t *th = GET_THREAD();
if (th->root_fiber != curr) {
@@ -557,8 +649,8 @@ return_fiber(void)
}
}
else {
- VALUE prev = cont->prev;
- cont->prev = Qnil;
+ VALUE prev = fib->prev;
+ fib->prev = Qnil;
return prev;
}
}
@@ -566,10 +658,10 @@ return_fiber(void)
VALUE rb_fiber_transfer(VALUE fib, int argc, VALUE *argv);
static void
-rb_fiber_terminate(rb_context_t *cont)
+rb_fiber_terminate(rb_fiber_t *fib)
{
- VALUE value = cont->value;
- cont->alive = Qfalse;
+ VALUE value = fib->cont.value;
+ fib->status = TERMINATED;
rb_fiber_transfer(return_fiber(), 1, &value);
}
@@ -577,12 +669,15 @@ void
rb_fiber_start(void)
{
rb_thread_t *th = GET_THREAD();
+ rb_fiber_t *fib;
rb_context_t *cont;
rb_proc_t *proc;
VALUE args;
int state;
- GetContPtr(th->fiber, cont);
+ GetFiberPtr(th->fiber, fib);
+ cont = &fib->cont;
+
TH_PUSH_TAG(th);
if ((state = EXEC_TAG()) == 0) {
GetProcPtr(cont->saved_thread.first_proc, proc);
@@ -592,6 +687,7 @@ rb_fiber_start(void)
th->local_lfp = proc->block.lfp;
th->local_svar = Qnil;
+ fib->status = RUNNING;
cont->value = vm_invoke_proc(th, proc, proc->block.self, 1, &args, 0);
}
TH_POP_TAG();
@@ -607,46 +703,57 @@ rb_fiber_start(void)
RUBY_VM_SET_INTERRUPT(th);
}
- rb_fiber_terminate(cont);
+ rb_fiber_terminate(fib);
rb_bug("rb_fiber_start: unreachable");
}
+static rb_fiber_t *
+root_fiber_alloc(rb_thread_t *th)
+{
+ rb_fiber_t *fib;
+
+ /* no need to allocate vm stack */
+ fib = fiber_alloc(rb_cFiber);
+ fib->cont.type = ROOT_FIBER_CONTEXT;
+ fib->prev_fiber = fib->next_fiber = fib;
+
+ return fib;
+}
+
VALUE
rb_fiber_current()
{
rb_thread_t *th = GET_THREAD();
if (th->fiber == 0) {
/* save root */
- rb_context_t *cont = fiber_alloc(rb_cFiber);
- cont->type = ROOT_FIBER_CONTEXT;
- th->root_fiber = th->fiber = cont->self;
+ rb_fiber_t *fib = root_fiber_alloc(th);
+ th->root_fiber = th->fiber = fib->cont.self;
}
return th->fiber;
}
static VALUE
-fiber_store(rb_context_t *next_cont)
+fiber_store(rb_fiber_t *next_fib)
{
rb_thread_t *th = GET_THREAD();
- rb_context_t *cont;
+ rb_fiber_t *fib;
if (th->fiber) {
- GetContPtr(th->fiber, cont);
- cont->saved_thread = *th;
+ GetFiberPtr(th->fiber, fib);
+ fib->cont.saved_thread = *th;
}
else {
/* create current fiber */
- cont = fiber_alloc(rb_cFiber); /* no need to allocate vm stack */
- cont->type = ROOT_FIBER_CONTEXT;
- th->root_fiber = th->fiber = cont->self;
+ fib = root_fiber_alloc(th);
+ th->root_fiber = th->fiber = fib->cont.self;
}
- cont_save_machine_stack(th, cont);
+ cont_save_machine_stack(th, &fib->cont);
- if (ruby_setjmp(cont->jmpbuf)) {
+ if (ruby_setjmp(fib->cont.jmpbuf)) {
/* restored */
- GetContPtr(th->fiber, cont);
- return cont->value;
+ GetFiberPtr(th->fiber, fib);
+ return fib->cont.value;
}
else {
return Qundef;
@@ -654,13 +761,15 @@ fiber_store(rb_context_t *next_cont)
}
static inline VALUE
-fiber_switch(VALUE fib, int argc, VALUE *argv, int is_resume)
+fiber_switch(VALUE fibval, int argc, VALUE *argv, int is_resume)
{
VALUE value;
+ rb_fiber_t *fib;
rb_context_t *cont;
rb_thread_t *th = GET_THREAD();
- GetContPtr(fib, cont);
+ GetFiberPtr(fibval, fib);
+ cont = &fib->cont;
if (cont->saved_thread.self != th->self) {
rb_raise(rb_eFiberError, "fiber called across threads");
@@ -668,18 +777,18 @@ fiber_switch(VALUE fib, int argc, VALUE *argv, int is_resume)
else if (cont->saved_thread.trap_tag != th->trap_tag) {
rb_raise(rb_eFiberError, "fiber called across trap");
}
- else if (!cont->alive) {
+ else if (fib->status == TERMINATED) {
rb_raise(rb_eFiberError, "dead fiber called");
}
if (is_resume) {
- cont->prev = rb_fiber_current();
+ fib->prev = rb_fiber_current();
}
cont->value = make_passing_arg(argc, argv);
- if ((value = fiber_store(cont)) == Qundef) {
- cont_restore_0(cont, &value);
+ if ((value = fiber_store(fib)) == Qundef) {
+ cont_restore_0(&fib->cont, &value);
rb_bug("rb_fiber_resume: unreachable");
}
@@ -695,16 +804,16 @@ rb_fiber_transfer(VALUE fib, int argc, VALUE *argv)
}
VALUE
-rb_fiber_resume(VALUE fib, int argc, VALUE *argv)
+rb_fiber_resume(VALUE fibval, int argc, VALUE *argv)
{
- rb_context_t *cont;
- GetContPtr(fib, cont);
+ rb_fiber_t *fib;
+ GetFiberPtr(fibval, fib);
- if (cont->prev != Qnil) {
+ if (fib->prev != Qnil) {
rb_raise(rb_eFiberError, "double resume");
}
- return fiber_switch(fib, argc, argv, 1);
+ return fiber_switch(fibval, argc, argv, 1);
}
VALUE
@@ -714,11 +823,11 @@ rb_fiber_yield(int argc, VALUE *argv)
}
VALUE
-rb_fiber_alive_p(VALUE fib)
+rb_fiber_alive_p(VALUE fibval)
{
- rb_context_t *cont;
- GetContPtr(fib, cont);
- return cont->alive;
+ rb_fiber_t *fib;
+ GetFiberPtr(fibval, fib);
+ return fib->status != TERMINATED;
}
static VALUE
diff --git a/cygwin/GNUmakefile.in b/cygwin/GNUmakefile.in
index f6883492b7..081c927575 100644
--- a/cygwin/GNUmakefile.in
+++ b/cygwin/GNUmakefile.in
@@ -1,5 +1,5 @@
include Makefile
-include uncommon.mk
+-include uncommon.mk
ENABLE_SHARED=@ENABLE_SHARED@
DLLWRAP = @DLLWRAP@ --target=@target_os@
@@ -9,7 +9,7 @@ ifeq (@target_os@,cygwin)
else
DLL_BASE_NAME := $(RUBY_SO_NAME)
DLLWRAP += -mno-cygwin
- VPATH += $(srcdir)/win32
+ VPATH := $(VPATH):$(srcdir)/win32
endif
ifneq ($(ENABLE_SHARED),yes)
diff --git a/debug.h b/debug.h
index 5c4b19a78b..d5670651a4 100644
--- a/debug.h
+++ b/debug.h
@@ -13,7 +13,7 @@
#define RUBY_DEBUG_H
#include "ruby/ruby.h"
-#include "ruby/node.h"
+#include "node.h"
#define dpv(h,v) ruby_debug_print_value(-1, 0, h, v)
#define dp(v) ruby_debug_print_value(-1, 0, "", v)
@@ -29,4 +29,8 @@ int ruby_debug_print_indent(int level, int debug_level, int indent_level);
void ruby_debug_breakpoint(void);
void ruby_debug_gc_check_func(void);
+#ifdef RUBY_DEBUG_ENV
+void ruby_set_debug_option(const char *str);
+#endif
+
#endif /* RUBY_DEBUG_H */
diff --git a/keywords b/defs/keywords
index f0d82a7667..f0d82a7667 100644
--- a/keywords
+++ b/defs/keywords
diff --git a/defs/known_errors.def b/defs/known_errors.def
new file mode 100644
index 0000000000..9f09aa9c22
--- /dev/null
+++ b/defs/known_errors.def
@@ -0,0 +1,122 @@
+EPERM
+ENOENT
+ESRCH
+EINTR
+EIO
+ENXIO
+E2BIG
+ENOEXEC
+EBADF
+ECHILD
+EAGAIN
+ENOMEM
+EACCES
+EFAULT
+ENOTBLK
+EBUSY
+EEXIST
+EXDEV
+ENODEV
+ENOTDIR
+EISDIR
+EINVAL
+ENFILE
+EMFILE
+ENOTTY
+ETXTBSY
+EFBIG
+ENOSPC
+ESPIPE
+EROFS
+EMLINK
+EPIPE
+EDOM
+ERANGE
+EDEADLK
+ENAMETOOLONG
+ENOLCK
+ENOSYS
+ENOTEMPTY
+ELOOP
+EWOULDBLOCK
+ENOMSG
+EIDRM
+ECHRNG
+EL2NSYNC
+EL3HLT
+EL3RST
+ELNRNG
+EUNATCH
+ENOCSI
+EL2HLT
+EBADE
+EBADR
+EXFULL
+ENOANO
+EBADRQC
+EBADSLT
+EDEADLOCK
+EBFONT
+ENOSTR
+ENODATA
+ETIME
+ENOSR
+ENONET
+ENOPKG
+EREMOTE
+ENOLINK
+EADV
+ESRMNT
+ECOMM
+EPROTO
+EMULTIHOP
+EDOTDOT
+EBADMSG
+EOVERFLOW
+ENOTUNIQ
+EBADFD
+EREMCHG
+ELIBACC
+ELIBBAD
+ELIBSCN
+ELIBMAX
+ELIBEXEC
+EILSEQ
+ERESTART
+ESTRPIPE
+EUSERS
+ENOTSOCK
+EDESTADDRREQ
+EMSGSIZE
+EPROTOTYPE
+ENOPROTOOPT
+EPROTONOSUPPORT
+ESOCKTNOSUPPORT
+EOPNOTSUPP
+EPFNOSUPPORT
+EAFNOSUPPORT
+EADDRINUSE
+EADDRNOTAVAIL
+ENETDOWN
+ENETUNREACH
+ENETRESET
+ECONNABORTED
+ECONNRESET
+ENOBUFS
+EISCONN
+ENOTCONN
+ESHUTDOWN
+ETOOMANYREFS
+ETIMEDOUT
+ECONNREFUSED
+EHOSTDOWN
+EHOSTUNREACH
+EALREADY
+EINPROGRESS
+ESTALE
+EUCLEAN
+ENOTNAM
+ENAVAIL
+EISNAM
+EREMOTEIO
+EDQUOT
diff --git a/lex.c.src b/defs/lex.c.src
index f0d82a7667..f0d82a7667 100644
--- a/lex.c.src
+++ b/defs/lex.c.src
diff --git a/opt_insn_unif.def b/defs/opt_insn_unif.def
index 1ac613dbea..1ac613dbea 100644
--- a/opt_insn_unif.def
+++ b/defs/opt_insn_unif.def
diff --git a/opt_operand.def b/defs/opt_operand.def
index 5ca1d74028..5ca1d74028 100644
--- a/opt_operand.def
+++ b/defs/opt_operand.def
diff --git a/dir.c b/dir.c
index 05fcf106d9..9d8348fc02 100644
--- a/dir.c
+++ b/dir.c
@@ -94,7 +94,7 @@ static int
char_casecmp(const char *p1, const char *p2, rb_encoding *enc, const int nocase)
{
const char *p1end, *p2end;
- int c1, c2;
+ unsigned int c1, c2;
if (!*p1 || !*p2) return !!*p1 - !!*p2;
p1end = p1 + strlen(p1);
@@ -428,16 +428,6 @@ dir_check(VALUE dir)
if (dirp->dir == NULL) dir_closed();\
} while (0)
-static VALUE
-dir_enc_str_new(const char *p, long len, rb_encoding *enc)
-{
- VALUE path = rb_tainted_str_new(p, len);
- if (rb_enc_asciicompat(enc) && rb_enc_str_asciionly_p(path)) {
- enc = rb_usascii_encoding();
- }
- rb_enc_associate(path, enc);
- return path;
-}
/*
* call-seq:
@@ -499,7 +489,7 @@ dir_read(VALUE dir)
errno = 0;
dp = readdir(dirp->dir);
if (dp) {
- return dir_enc_str_new(dp->d_name, NAMLEN(dp), dirp->enc);
+ return rb_external_str_new_with_enc(dp->d_name, NAMLEN(dp), dirp->enc);
}
else if (errno == 0) { /* end of stream */
return Qnil;
@@ -537,7 +527,7 @@ dir_each(VALUE dir)
GetDIR(dir, dirp);
rewinddir(dirp->dir);
for (dp = readdir(dirp->dir); dp != NULL; dp = readdir(dirp->dir)) {
- rb_yield(dir_enc_str_new(dp->d_name, NAMLEN(dp), dirp->enc));
+ rb_yield(rb_external_str_new_with_enc(dp->d_name, NAMLEN(dp), dirp->enc));
if (dirp->dir == NULL) dir_closed();
}
return dir;
@@ -698,7 +688,7 @@ ruby_dirfd(const char *path)
# elif defined O_DIRECTORY
return open(path, O_RDONLY|O_DIRECTORY);
# else
-# error don't know how to open directory.
+# error do not know how to open directory.
# endif
}
#endif
@@ -1516,7 +1506,7 @@ rb_glob(const char *path, void (*func)(const char *, VALUE, void *), VALUE arg)
static void
push_pattern(const char *path, VALUE ary, void *enc)
{
- rb_ary_push(ary, dir_enc_str_new(path, strlen(path), enc));
+ rb_ary_push(ary, rb_external_str_new_with_enc(path, strlen(path), enc));
}
static int
@@ -1661,7 +1651,7 @@ dir_globs(long argc, VALUE *argv, int flags)
for (i = 0; i < argc; ++i) {
int status;
VALUE str = argv[i];
- StringValue(str);
+ SafeStringValue(str);
status = push_glob(ary, str, flags);
if (status) GLOB_JUMP_TAG(status);
}
diff --git a/distruby.rb b/distruby.rb
deleted file mode 100644
index 613da0eb9c..0000000000
--- a/distruby.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-#!./miniruby
-
-if RUBY_PATCHLEVEL.zero?
- dirname = sprintf 'ruby-%s', RUBY_VERSION
- tagname = dirname.gsub /ruby-(\d)\.(\d)\.(\d)/, 'v\1_\2_\3'
-else
- dirname = sprintf 'ruby-%s-p%u', RUBY_VERSION, RUBY_PATCHLEVEL
- tagname = dirname.gsub /ruby-(\d)\.(\d)\.(\d)-p/, 'v\1_\2_\3_'
-end
-tgzname = dirname + '.tar.gz'
-tbzname = dirname + '.tar.bz2'
-zipname = dirname + '.zip'
-repos = 'http://svn.ruby-lang.org/repos/ruby/tags/' + tagname
-
-STDERR.puts 'exporting sources...'
-system 'svn', 'export', '-q', repos, dirname
-Dir.chdir dirname do
- STDERR.puts 'generating configure...'
- system 'autoconf'
- system 'rm', '-rf', 'autom4te.cache'
-
- STDERR.puts 'generating parse.c...'
- system 'bison', '-y', '-o', 'parse.c', 'parse.y'
-end
-
-STDERR.puts 'generating tarballs...'
-ENV['GZIP'] = '-9'
-system 'tar', 'chofzp', tgzname, dirname
-system 'tar', 'chojfp', tbzname, dirname
-system 'zip', '-q9r', zipname, dirname
-
-require 'digest/md5'
-require 'digest/sha2'
-for name in [tgzname, tbzname, zipname] do
- open name, 'rb' do |fp|
- str = fp.read
- md5 = Digest::MD5.hexdigest str
- sha = Digest::SHA256.hexdigest str
- printf "MD5(%s)= %s\nSHA256(%s)= %s\nSIZE(%s)= %s\n\n",
- name, md5,
- name, sha,
- name, str.size
- end
-end
-
-
-
-#
-# Local Variables:
-# mode: ruby
-# code: utf-8
-# indent-tabs-mode: t
-# tab-width: 3
-# ruby-indent-level: 3
-# fill-column: 79
-# default-justification: full
-# End:
-# vi: ts=3 sw=3
-
diff --git a/djgpp/GNUmakefile.in b/djgpp/GNUmakefile.in
deleted file mode 100644
index b11e7fdc35..0000000000
--- a/djgpp/GNUmakefile.in
+++ /dev/null
@@ -1,3 +0,0 @@
-include Makefile
-VPATH = $(srcdir) $(srcdir)/missing
-include uncommon.mk
diff --git a/djgpp/README.djgpp b/djgpp/README.djgpp
deleted file mode 100644
index f1f413a478..0000000000
--- a/djgpp/README.djgpp
+++ /dev/null
@@ -1,21 +0,0 @@
-* How to compile and install on djgpp
-
-This is what you need to do to compile and install Ruby:
-
- 1. Run configure.bat, which will generate config.h and Makefile
- (GNU sed required).
- Message like this is normal:
- sed.exe: can't read 123456789: No such file or directory (ENOENT)
-
- 2. Edit defines.h if you need. Probably this step will not need.
-
- 3. Remove comment mark(#) before the module names from ext/Setup.dj (or
- add module names if not present).
-
- 4. Run make.
-
- 5. Optionally, run 'make test' to check whether the compiled Ruby
- interpreter works well. If you see the message "test succeeded",
- your ruby works as it should (hopefully).
-
- 6. Run 'make install'
diff --git a/djgpp/config.hin b/djgpp/config.hin
deleted file mode 100644
index f90f2ed061..0000000000
--- a/djgpp/config.hin
+++ /dev/null
@@ -1,114 +0,0 @@
-
-#define PACKAGE_NAME ""
-#define PACKAGE_TARNAME ""
-#define PACKAGE_VERSION ""
-#define PACKAGE_STRING ""
-#define PACKAGE_BUGREPORT ""
-#define USE_BUILTIN_FRAME_ADDRESS 1
-#define STDC_HEADERS 1
-#define HAVE_SYS_TYPES_H 1
-#define HAVE_SYS_STAT_H 1
-#define HAVE_STDLIB_H 1
-#define HAVE_STRING_H 1
-#define HAVE_MEMORY_H 1
-#define HAVE_STRINGS_H 1
-#define HAVE_UNISTD_H 1
-#define HAVE_LONG_LONG 1
-#define HAVE_OFF_T 1
-#define SIZEOF_INT 4
-#define SIZEOF_SHORT 2
-#define SIZEOF_LONG 4
-#define SIZEOF_LONG_LONG 8
-#define SIZEOF___INT64 0
-#define SIZEOF_OFF_T 4
-#define SIZEOF_VOIDP 4
-#define SIZEOF_FLOAT 4
-#define SIZEOF_DOUBLE 8
-#define HAVE_PROTOTYPES 1
-#define TOKEN_PASTE(x,y) x##y
-#define HAVE_STDARG_PROTOTYPES 1
-#define NORETURN(x) x __attribute__ ((noreturn))
-#define HAVE_DECL_SYS_NERR 1
-#define HAVE_DIRENT_H 1
-#define STDC_HEADERS 1
-#define HAVE_SYS_WAIT_H 1
-#define HAVE_STDLIB_H 1
-#define HAVE_STRING_H 1
-#define HAVE_UNISTD_H 1
-#define HAVE_LIMITS_H 1
-#define HAVE_SYS_FILE_H 1
-#define HAVE_SYS_IOCTL_H 1
-#define HAVE_FCNTL_H 1
-#define HAVE_SYS_FCNTL_H 1
-#define HAVE_SYS_TIME_H 1
-#define HAVE_SYS_TIMES_H 1
-#define HAVE_SYS_PARAM_H 1
-#define HAVE_PWD_H 1
-#define HAVE_UTIME_H 1
-#define HAVE_MEMORY_H 1
-#define HAVE_DIRECT_H 1
-#define HAVE_SYS_RESOURCE_H 1
-#define HAVE_STRUCT_STAT_ST_BLKSIZE 1
-#define HAVE_ST_BLKSIZE 1
-#define HAVE_STRUCT_STAT_ST_RDEV 1
-#define HAVE_ST_RDEV 1
-#define GETGROUPS_T gid_t
-#define RETSIGTYPE void
-#define HAVE_ALLOCA 1
-#define HAVE_DUP2 1
-#define HAVE_MEMMOVE 1
-#define HAVE_MKDIR 1
-#define HAVE_STRCASECMP 1
-#define HAVE_STRNCASECMP 1
-#define HAVE_STRERROR 1
-#define HAVE_STRFTIME 1
-#define HAVE_STRCHR 1
-#define HAVE_STRSTR 1
-#define HAVE_STRTOUL 1
-#define HAVE_ISINF 1
-#define HAVE_ISNAN 1
-#define HAVE_FINITE 1
-#define HAVE_HYPOT 1
-#define HAVE_ACOSH 1
-#define HAVE_FMOD 1
-#define HAVE_WAITPID 1
-#define HAVE_FSYNC 1
-#define HAVE_TRUNCATE 1
-#define HAVE_CHSIZE 1
-#define HAVE_TIMES 1
-#define HAVE_UTIMES 1
-#define HAVE_FCNTL 1
-#define HAVE_SYMLINK 1
-#define HAVE_SETITIMER 1
-#define HAVE_PAUSE 1
-#define HAVE_GETPGRP 1
-#define HAVE_SETPGID 1
-#define HAVE_GETGROUPS 1
-#define HAVE_GETRLIMIT 1
-#define HAVE_SIGPROCMASK 1
-#define HAVE_SIGACTION 1
-#define HAVE_SETSID 1
-#define HAVE_TELLDIR 1
-#define HAVE_SEEKDIR 1
-#define HAVE_MKTIME 1
-#define HAVE_COSH 1
-#define HAVE_SINH 1
-#define HAVE_TANH 1
-#define HAVE_STRUCT_TM_TM_ZONE 1
-#define HAVE_TM_ZONE 1
-#define HAVE_STRUCT_TM_TM_GMTOFF 1
-#define POSIX_SIGNAL 1
-#define GETPGRP_VOID 1
-#define SETPGRP_VOID 1
-#define RSHIFT(x,y) ((x)>>(int)y)
-#define FILE_COUNT _cnt
-#define FILE_READPTR _ptr
-#define NEED_IO_FLUSH_BETWEEN_RW 1
-#define DEFAULT_KCODE KCODE_NONE
-#define DLEXT ".so"
-#define RUBY_LIB "/lib/ruby/@MAJOR@.@MINOR@.@TEENY@"
-#define RUBY_SITE_LIB "/lib/ruby/site_ruby"
-#define RUBY_SITE_LIB2 "/lib/ruby/site_ruby/@MAJOR@.@MINOR@.@TEENY@"
-#define RUBY_PLATFORM "i386-msdosdjgpp"
-#define RUBY_ARCHLIB "/lib/ruby/@MAJOR@.@MINOR@.@TEENY@/i386-msdosdjgpp"
-#define RUBY_SITE_ARCHLIB "/lib/ruby/site_ruby/@MAJOR@.@MINOR@.@TEENY@/i386-msdosdjgpp"
diff --git a/djgpp/config.sed b/djgpp/config.sed
deleted file mode 100644
index 1805789520..0000000000
--- a/djgpp/config.sed
+++ /dev/null
@@ -1,128 +0,0 @@
-/^SHELL/s,/bin/sh,$(COMSPEC),
-;s%/bin/rm%rm%
-;s%|| true%%
-;/\/dev\/null/ {
-;s,/dev/null 2>&1, nul,
-;s,2> /dev/null,,
-;}
-;/^config.status/ {
-; N;N;N;N;N;d
-;}
-:t
- /@[a-zA-Z_][a-zA-Z_0-9]*@/!b
-s,@srcdir@,.,g;t t
-s,@top_srcdir@,..,;t t
-s,@PATH_SEPARATOR@,:,;t t
-s,@PACKAGE_NAME@,,;t t
-s,@PACKAGE_TARNAME@,,;t t
-s,@PACKAGE_VERSION@,,;t t
-s,@PACKAGE_STRING@,,;t t
-s,@PACKAGE_BUGREPORT@,,;t t
-s,@exec_prefix@,${prefix},;t t
-s,@prefix@,/dev/env/DJDIR,;t t
-s%@program_transform_name@%s,^,,%;t t
-s,@bindir@,${exec_prefix}/bin,;t t
-s,@sbindir@,${exec_prefix}/sbin,;t t
-s,@libexecdir@,${exec_prefix}/libexec,;t t
-s,@datadir@,${prefix}/share,;t t
-s,@sysconfdir@,${prefix}/etc,;t t
-s,@sharedstatedir@,${prefix}/com,;t t
-s,@localstatedir@,${prefix}/var,;t t
-s,@libdir@,${exec_prefix}/lib,;t t
-s,@includedir@,${prefix}/include,;t t
-s,@oldincludedir@,/usr/include,;t t
-s,@infodir@,${prefix}/info,;t t
-s,@mandir@,${prefix}/man,;t t
-s,@build_alias@,i586-pc-msdosdjgpp,;t t
-s,@host_alias@,i586-pc-msdosdjgpp,;t t
-s,@target_alias@,i386-msdosdjgpp,;t t
-s,@DEFS@,,;t t
-s,@ECHO_C@,,;t t
-s,@ECHO_N@,-n,;t t
-s,@ECHO_T@,,;t t
-s,@LIBS@,-lm ,;t t
-s,@MAJOR@,1,;t t
-s,@MINOR@,7,;t t
-s,@TEENY@,3,;t t
-s,@build@,i586-pc-msdosdjgpp,;t t
-s,@build_cpu@,i586,;t t
-s,@build_vendor@,pc,;t t
-s,@build_os@,msdosdjgpp,;t t
-s,@host@,i586-pc-msdosdjgpp,;t t
-s,@host_cpu@,i586,;t t
-s,@host_vendor@,pc,;t t
-s,@host_os@,msdosdjgpp,;t t
-s,@target@,i386-pc-msdosdjgpp,;t t
-s,@target_cpu@,i386,;t t
-s,@target_vendor@,pc,;t t
-s,@target_os@,msdosdjgpp,;t t
-s,@CC@,gcc,;t t
-s,@ac_ct_CC@,,;t t
-s,@CFLAGS@,-Os,;t t
-s,@LDFLAGS@,,;t t
-s,@CPPFLAGS@,,;t t
-s,@EXEEXT@,.exe,;t t
-s,@OBJEXT@,o,;t t
-s,@CPP@,gcc -E,;t t
-s,@EGREP@,grep -E,;t t
-s,@GNU_LD@,yes,;t t
-s,@CPPOUTFILE@,-o conftest.i,;t t
-s,@OUTFLAG@,-o ,;t t
-s,@YACC@,bison -y,;t t
-s,@RANLIB@,ranlib,;t t
-s,@ac_ct_RANLIB@,,;t t
-s,@AR@,ar,;t t
-s,@ac_ct_AR@,,;t t
-s,@NM@,,;t t
-s,@ac_ct_NM@,,;t t
-s,@WINDRES@,,;t t
-s,@ac_ct_WINDRES@,,;t t
-s,@DLLWRAP@,,;t t
-s,@ac_ct_DLLWRAP@,,;t t
-s,@LN_S@,ln -s,;t t
-s,@SET_MAKE@,,;t t
-s,@LIBOBJS@,crypt.o flock.o vsnprintf.o,;t t
-s,@ALLOCA@,,;t t
-s,@XCFLAGS@,,;t t
-s,@XLDFLAGS@, -L.,;t t
-s,@DLDFLAGS@,,;t t
-s,@STATIC@,,;t t
-s,@CCDLFLAGS@,,;t t
-s,@LDSHARED@,ld,;t t
-s,@DLEXT@,so,;t t
-s,@DLEXT2@,,;t t
-s,@LIBEXT@,a,;t t
-s,@LINK_SO@,,;t t
-s,@LIBPATHFLAG@, -L%s,;t t
-s,@STRIP@,strip,;t t
-s,@EXTSTATIC@,,;t t
-s,@setup@,Setup.dj,;t t
-s,@MINIRUBY@,./miniruby,;t t
-s,@PREP@,,;t t
-s,@ARCHFILE@,,;t t
-s,@LIBRUBY_LDSHARED@,ld,;t t
-s,@LIBRUBY_DLDFLAGS@,,;t t
-s,@RUBY_INSTALL_NAME@,ruby,;t t
-s,@rubyw_install_name@,,;t t
-s,@RUBYW_INSTALL_NAME@,,;t t
-s,@RUBY_SO_NAME@,$(RUBY_INSTALL_NAME),;t t
-s,@LIBRUBY_A@,lib$(RUBY_INSTALL_NAME).a,;t t
-s,@LIBRUBY_SO@,lib$(RUBY_SO_NAME).so.$(MAJOR).$(MINOR).$(TEENY),;t t
-s,@LIBRUBY_ALIASES@,lib$(RUBY_SO_NAME).so,;t t
-s,@LIBRUBY@,$(LIBRUBY_A),;t t
-s,@LIBRUBYARG@,-l$(RUBY_INSTALL_NAME),;t t
-s,@SOLIBS@,,;t t
-s,@DLDLIBS@,-lc,;t t
-s,@ENABLE_SHARED@,no,;t t
-s,@MAINLIBS@,,;t t
-s,@COMMON_LIBS@,,;t t
-s,@COMMON_MACROS@,,;t t
-s,@COMMON_HEADERS@,,;t t
-s,@EXPORT_PREFIX@,,;t t
-s,@MAKEFILES@,Makefile,;t t
-s,@arch@,i386-msdosdjgpp,;t t
-s,@sitearch@,i386-msdosdjgpp,;t t
-s,@sitedir@,${prefix}/lib/ruby/site_ruby,;t t
-s,@configure_args@,,;t t
-/^,THIS_IS_DUMMY_PATTERN_/i\
-ac_given_srcdir=.
diff --git a/djgpp/configure.bat b/djgpp/configure.bat
deleted file mode 100755
index e6a5d79d4a..0000000000
--- a/djgpp/configure.bat
+++ /dev/null
@@ -1,20 +0,0 @@
-@echo off
-if exist configure.bat cd ..
-if exist djgpp\version.sed goto exist
- sed -n -f djgpp\mkver.sed < version.h > djgpp\version.sed
-:exist
-set _conv_=-f djgpp\config.sed -f djgpp\version.sed
-sed %_conv_% < Makefile.in > Makefile
-sed %_conv_% < djgpp\config.hin > config.h
-echo LFN check > 12345678
-sed -n /LFN/d 123456789 > nul
-if errorlevel 2 goto LFN
- copy missing\vsnprintf.c missing\vsnprint.c > nul
- copy djgpp\config.sed config.sta > nul
-goto end
-:LFN
- copy djgpp\config.sed config.status > nul
-:end
-set _conv_=
-del 12345678
-echo Now you must run a make.
diff --git a/djgpp/mkver.sed b/djgpp/mkver.sed
deleted file mode 100644
index f29b9ddd3e..0000000000
--- a/djgpp/mkver.sed
+++ /dev/null
@@ -1 +0,0 @@
-/RUBY_VERSION /s/^.*\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*$/s,@MAJOR@,\1,;s,@MINOR@,\2,;s,@TEENY@,\3,/p
diff --git a/dln.c b/dln.c
index b4f2dd45c8..67c0f2c4c9 100644
--- a/dln.c
+++ b/dln.c
@@ -45,7 +45,7 @@ void *xrealloc();
#define free(x) xfree(x)
#include <stdio.h>
-#if defined(_WIN32) || defined(__VMS)
+#if defined(_WIN32)
#include "missing/file.h"
#endif
#include <sys/types.h>
@@ -70,18 +70,6 @@ void *xrealloc();
char *getenv();
#endif
-#if defined(__VMS)
-#pragma builtins
-#include <dlfcn.h>
-#endif
-
-#ifdef __MACOS__
-# include <TextUtils.h>
-# include <CodeFragments.h>
-# include <Aliases.h>
-# include "macruby_private.h"
-#endif
-
#if defined(__APPLE__) && defined(__MACH__) /* Mac OS X */
# if defined(HAVE_DLOPEN)
/* Mac OS X with dlopen (10.3 or later) */
@@ -119,11 +107,7 @@ init_funcname_len(char **buf, const char *file)
/* Load the file as an object one */
for (slash = file-1; *file; file++) /* Find position of last '/' */
-#ifdef __MACOS__
- if (*file == ':') slash = file;
-#else
if (*file == '/') slash = file;
-#endif
len = strlen(FUNCNAME_PATTERN) + strlen(slash + 1);
*buf = xmalloc(len);
@@ -1116,15 +1100,6 @@ dln_sym(const char *name)
#include <windows.h>
#endif
-#ifdef _WIN32_WCE
-#undef FormatMessage
-#define FormatMessage FormatMessageA
-#undef LoadLibrary
-#define LoadLibrary LoadLibraryA
-#undef GetProcAddress
-#define GetProcAddress GetProcAddressA
-#endif
-
static const char *
dln_strerror(void)
{
@@ -1442,7 +1417,8 @@ dln_load(const char *file)
/* load extention module */
img_id = load_add_on(file);
if (img_id <= 0) {
- rb_loaderror("Failed to load %.200s", file);
+ rb_loaderror("Failed to load add_on %.200s error_code=%x",
+ file, img_id);
}
/* find symbol for module initialize function. */
@@ -1479,82 +1455,6 @@ dln_load(const char *file)
}
#endif /* __BEOS__*/
-#ifdef __MACOS__ /* Mac OS 9 or before */
-# define DLN_DEFINED
- {
- OSErr err;
- FSSpec libspec;
- CFragConnectionID connID;
- Ptr mainAddr;
- char errMessage[1024];
- Boolean isfolder, didsomething;
- Str63 fragname;
- Ptr symAddr;
- CFragSymbolClass class;
- void (*init_fct)();
- char fullpath[MAXPATHLEN];
-
- strcpy(fullpath, file);
-
- /* resolve any aliases to find the real file */
- c2pstr(fullpath);
- (void)FSMakeFSSpec(0, 0, fullpath, &libspec);
- err = ResolveAliasFile(&libspec, 1, &isfolder, &didsomething);
- if (err) {
- rb_loaderror("Unresolved Alias - %s", file);
- }
-
- /* Load the fragment (or return the connID if it is already loaded */
- fragname[0] = 0;
- err = GetDiskFragment(&libspec, 0, 0, fragname,
- kLoadCFrag, &connID, &mainAddr,
- errMessage);
- if (err) {
- p2cstr(errMessage);
- rb_loaderror("%s - %s",errMessage , file);
- }
-
- /* Locate the address of the correct init function */
- c2pstr(buf);
- err = FindSymbol(connID, buf, &symAddr, &class);
- if (err) {
- rb_loaderror("Unresolved symbols - %s" , file);
- }
- init_fct = (void (*)())symAddr;
- (*init_fct)();
- return (void*)init_fct;
- }
-#endif /* __MACOS__ */
-
-#if defined(__VMS)
-#define DLN_DEFINED
- {
- void *handle, (*init_fct)();
- char *fname, *p1, *p2;
-
- fname = (char *)__alloca(strlen(file)+1);
- strcpy(fname,file);
- if (p1 = strrchr(fname,'/'))
- fname = p1 + 1;
- if (p2 = strrchr(fname,'.'))
- *p2 = '\0';
-
- if ((handle = (void*)dlopen(fname, 0)) == NULL) {
- error = dln_strerror();
- goto failed;
- }
-
- if ((init_fct = (void (*)())dlsym(handle, buf)) == NULL) {
- error = DLN_ERROR();
- dlclose(handle);
- goto failed;
- }
- /* Call the init code */
- (*init_fct)();
- return handle;
- }
-#endif /* __VMS */
-
#ifndef DLN_DEFINED
rb_notimplement();
#endif
@@ -1580,7 +1480,7 @@ dln_find_exe_r(const char *fname, const char *path, char *buf, int size)
}
if (!path) {
-#if defined(MSDOS) || defined(_WIN32) || defined(__human68k__) || defined(__MACOS__)
+#if defined(_WIN32)
path = "/usr/local/bin;/usr/ucb;/usr/bin;/bin;.";
#else
path = "/usr/local/bin:/usr/ucb:/usr/bin:/bin:.";
@@ -1592,13 +1492,8 @@ dln_find_exe_r(const char *fname, const char *path, char *buf, int size)
char *
dln_find_file_r(const char *fname, const char *path, char *buf, int size)
{
-#ifndef __MACOS__
if (!path) path = ".";
return dln_find_1(fname, path, buf, size, 0);
-#else
- if (!path) path = ".";
- return _macruby_path_conv_posix_to_macos(dln_find_1(fname, path, buf, size, 0));
-#endif
}
#ifndef HAVE_MVM
@@ -1625,9 +1520,6 @@ dln_find_1(const char *fname, const char *path, char *fbuf, int size,
register const char *ep;
register char *bp;
struct stat st;
-#ifdef __MACOS__
- const char* mac_fullpath;
-#endif
#define RETURN_IF(expr) if (expr) return (char *)fname;
@@ -1714,17 +1606,9 @@ dln_find_1(const char *fname, const char *path, char *fbuf, int size,
#if defined(DOSISH)
if (exe_flag) {
static const char extension[][5] = {
-#if defined(MSDOS)
- ".com", ".exe", ".bat",
-#if defined(DJGPP)
- ".btm", ".sh", ".ksh", ".pl", ".sed",
-#endif
-#elif defined(__EMX__) || defined(_WIN32)
+#if defined(__EMX__) || defined(_WIN32)
".exe", ".com", ".cmd", ".bat",
/* end of __EMX__ or _WIN32 */
-#else
- ".r", ".R", ".x", ".X", ".bat", ".BAT",
-/* __human68k__ */
#endif
};
int j;
@@ -1737,37 +1621,19 @@ dln_find_1(const char *fname, const char *path, char *fbuf, int size,
continue;
}
strcpy(bp + i, extension[j]);
-#ifndef __MACOS__
if (stat(fbuf, &st) == 0)
return fbuf;
-#else
- if (mac_fullpath = _macruby_exist_file_in_libdir_as_posix_name(fbuf))
- return mac_fullpath;
-
-#endif
}
goto next;
}
-#endif /* MSDOS or _WIN32 or __human68k__ or __EMX__ */
+#endif /* _WIN32 or __EMX__ */
-#ifndef __MACOS__
if (stat(fbuf, &st) == 0) {
if (exe_flag == 0) return fbuf;
/* looking for executable */
if (!S_ISDIR(st.st_mode) && eaccess(fbuf, X_OK) == 0)
return fbuf;
}
-#else
- if (mac_fullpath = _macruby_exist_file_in_libdir_as_posix_name(fbuf)) {
- if (exe_flag == 0) return mac_fullpath;
- /* looking for executable */
- if (stat(mac_fullpath, &st) == 0) {
- if (!S_ISDIR(st.st_mode) && eaccess(mac_fullpath, X_OK) == 0)
- return mac_fullpath;
- }
- }
-#endif
-
next:
/* if not, and no other alternatives, life is bleak */
if (*ep == '\0') {
diff --git a/dmyext.c b/dmyext.c
index 2b48cd61cf..35344eee9d 100644
--- a/dmyext.c
+++ b/dmyext.c
@@ -1,4 +1,4 @@
-#include "ruby/mvm.h"
+#include "ruby/vm.h"
void
Init_ext(void)
diff --git a/doc/NEWS b/doc/NEWS
index 77ecf74178..92a499ec6c 100644
--- a/doc/NEWS
+++ b/doc/NEWS
@@ -164,7 +164,7 @@ Compatible
* Readline
o Readline.vi_editing_mode?
o Readline.emacs_editing_mode?
- o Readline.HISTORY::clear
+ o Readline::HISTORY.clear
* Misc. new methods
o public_send
o GC.count
diff --git a/enc/Makefile.in b/enc/Makefile.in
index b7762191c4..d9bb8fd68e 100644
--- a/enc/Makefile.in
+++ b/enc/Makefile.in
@@ -38,7 +38,6 @@ INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir) -I$(top_srcdir)
DEFS = @DEFS@
CPPFLAGS = @CPPFLAGS@ -DONIG_ENC_REGISTER=rb_enc_register
LDFLAGS = @LDFLAGS@
-LIBS = @LIBRUBYARG@ @LIBS@ $(EXTLIBS)
LDSHARED = @LDSHARED@
ldflags = $(LDFLAGS)
dldflags = @DLDFLAGS@
diff --git a/enc/big5.c b/enc/big5.c
index 70a316ea2c..9993f472e1 100644
--- a/enc/big5.c
+++ b/enc/big5.c
@@ -165,7 +165,7 @@ static const char BIG5_CAN_BE_TRAIL_TABLE[256] = {
#define BIG5_ISMB_TRAIL(byte) BIG5_CAN_BE_TRAIL_TABLE[(byte)]
static UChar*
-big5_left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc)
+big5_left_adjust_char_head(const UChar* start, const UChar* s, const UChar* end, OnigEncoding enc)
{
const UChar *p;
int len;
@@ -181,7 +181,7 @@ big5_left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc)
}
}
}
- len = enclen(enc, p, s);
+ len = enclen(enc, p, end);
if (p + len > s) return (UChar* )p;
p += len;
return (UChar* )(p + ((s - p) & ~1));
diff --git a/enc/cp949.c b/enc/cp949.c
index 0046460625..009443aed4 100644
--- a/enc/cp949.c
+++ b/enc/cp949.c
@@ -165,7 +165,7 @@ cp949_is_code_ctype(OnigCodePoint code, unsigned int ctype, OnigEncoding enc)
}
static UChar*
-cp949_left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc)
+cp949_left_adjust_char_head(const UChar* start, const UChar* s, const UChar* end, OnigEncoding enc)
{
const UChar *p;
int len;
@@ -181,7 +181,7 @@ cp949_left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc
}
}
}
- len = enclen(enc, p, s);
+ len = enclen(enc, p, end);
if (p + len > s) return (UChar* )p;
p += len;
return (UChar* )(p + ((s - p) & ~1));
diff --git a/enc/depend b/enc/depend
index 1ae1d71a6e..938b15bb25 100644
--- a/enc/depend
+++ b/enc/depend
@@ -1,3 +1,4 @@
+% enable_shared = CONFIG['ENABLE_SHARED'] == 'yes'
% deffile = (true if /\$\(DEFFILE\)/ =~ CONFIG["LINK_SO"])
% encs = Dir.open($srcdir) {|d| d.grep(/.+\.c\z/)} - BUILTIN_ENCS
% encs.each {|e| e.chomp!(".c")}
@@ -40,6 +41,12 @@
VPATH = <%=%w[$(arch_hdrdir)/ruby $(hdrdir)/ruby $(srcdir) $(encsrcdir)].join(CONFIG["PATH_SEPARATOR"])%>
LIBPATH = <%=libpathflag($DEFLIBPATH)%>
+LIBS = <%=
+if enable_shared or RbConfig.expand(CONFIG["LIBRUBY"].dup) != RbConfig.expand(CONFIG["LIBRUBY_A"].dup)
+ CONFIG['LIBRUBYARG']
+else
+ ''
+end %> <%=CONFIG['LIBS']%> $(EXTLIBS)
ENCOBJS = <%=encs.map {|e|"enc/#{e}.$(OBJEXT)"}.join(" \\\n\t ")%><%="\n" if encs.size>1%>
ENCSOS = <%=encs.map {|e|"$(ENCSODIR)/#{e}.$(DLEXT)"}.join(" \\\n\t ")%><%="\n" if encs.size>1%>
@@ -62,7 +69,10 @@ TRANSCLEANOBJS = <%=cleanobjs.map {|clean|
clean.gsub(/\$\*(\.\w+)?/) {"$(TRANSOBJS#{$1 ? ":.#{CONFIG["OBJEXT"]}=#{$1}" : ""})"}
}.join(" ")%>
-all: $(ENCSOS) $(TRANSSOS)
+encs: all
+all: enc trans
+enc: $(ENCSOS)
+trans: $(TRANSSOS)
srcs: $(TRANSCSRCS)
diff --git a/enc/emacs_mule.c b/enc/emacs_mule.c
index 9ebb44339a..be7f842259 100644
--- a/enc/emacs_mule.c
+++ b/enc/emacs_mule.c
@@ -237,7 +237,6 @@ mbc_to_code(const UChar* p, const UChar* end, OnigEncoding enc)
c = *p++;
n <<= 8; n += c;
}
- n &= 0x7FFFFFFF;
return n;
}
@@ -258,7 +257,7 @@ code_to_mbc(OnigCodePoint code, UChar *buf, OnigEncoding enc)
{
UChar *p = buf;
- if ((code & 0xff000000) != 0) *p++ = (UChar )(((code >> 24) | 0x80));
+ if ((code & 0xff000000) != 0) *p++ = (UChar )(((code >> 24) & 0xff));
if ((code & 0xff0000) != 0) *p++ = (UChar )(((code >> 16) & 0xff));
if ((code & 0xff00) != 0) *p++ = (UChar )(((code >> 8) & 0xff));
*p++ = (UChar )(code & 0xff);
@@ -294,7 +293,7 @@ mbc_case_fold(OnigCaseFoldType flag,
}
static UChar*
-left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc)
+left_adjust_char_head(const UChar* start, const UChar* s, const UChar* end, OnigEncoding enc)
{
const UChar *p;
diff --git a/enc/euc_jp.c b/enc/euc_jp.c
index fb8bf41c25..21f30ad2f3 100644
--- a/enc/euc_jp.c
+++ b/enc/euc_jp.c
@@ -222,7 +222,7 @@ mbc_case_fold(OnigCaseFoldType flag,
}
static UChar*
-left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc)
+left_adjust_char_head(const UChar* start, const UChar* s, const UChar* end, OnigEncoding enc)
{
/* In this encoding
mb-trail bytes doesn't mix with single bytes.
@@ -234,7 +234,7 @@ left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc)
p = s;
while (!eucjp_islead(*p) && p > start) p--;
- len = enclen(enc, p, s);
+ len = enclen(enc, p, end);
if (p + len > s) return (UChar* )p;
p += len;
return (UChar* )(p + ((s - p) & ~1));
diff --git a/enc/euc_kr.c b/enc/euc_kr.c
index 1b5ec893c1..f20a57e69a 100644
--- a/enc/euc_kr.c
+++ b/enc/euc_kr.c
@@ -145,7 +145,7 @@ euckr_is_code_ctype(OnigCodePoint code, unsigned int ctype, OnigEncoding enc)
#define euckr_islead(c) ((c) < 0xa1 || (c) == 0xff)
static UChar*
-euckr_left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc)
+euckr_left_adjust_char_head(const UChar* start, const UChar* s, const UChar* end, OnigEncoding enc)
{
/* Assumed in this encoding,
mb-trail bytes don't mix with single bytes.
@@ -157,7 +157,7 @@ euckr_left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc
p = s;
while (!euckr_islead(*p) && p > start) p--;
- len = enclen(enc, p, s);
+ len = enclen(enc, p, end);
if (p + len > s) return (UChar* )p;
p += len;
return (UChar* )(p + ((s - p) & ~1));
diff --git a/enc/euc_tw.c b/enc/euc_tw.c
index ca38983d53..d025a0dd45 100644
--- a/enc/euc_tw.c
+++ b/enc/euc_tw.c
@@ -187,7 +187,7 @@ euctw_is_code_ctype(OnigCodePoint code, unsigned int ctype, OnigEncoding enc)
#define euctw_islead(c) ((UChar )((c) - 0xa1) > 0xfe - 0xa1)
static UChar*
-euctw_left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc)
+euctw_left_adjust_char_head(const UChar* start, const UChar* s, const UChar* end, OnigEncoding enc)
{
/* Assumed in this encoding,
mb-trail bytes don't mix with single bytes.
@@ -199,7 +199,7 @@ euctw_left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc
p = s;
while (!euctw_islead(*p) && p > start) p--;
- len = enclen(enc, p, s);
+ len = enclen(enc, p, end);
if (p + len > s) return (UChar* )p;
p += len;
return (UChar* )(p + ((s - p) & ~1));
diff --git a/enc/gb18030.c b/enc/gb18030.c
index 804f3cdc00..16c8c1c17f 100644
--- a/enc/gb18030.c
+++ b/enc/gb18030.c
@@ -178,16 +178,12 @@ gb18030_mbc_to_code(const UChar* p, const UChar* end, OnigEncoding enc)
c = *p++;
n <<= 8; n += c;
}
- n &= 0x7FFFFFFF;
return n;
}
static int
gb18030_code_to_mbc(OnigCodePoint code, UChar *buf, OnigEncoding enc)
{
- if ((code & 0xff000000) != 0) {
- code |= 0x80000000;
- }
return onigenc_mb4_code_to_mbc(enc, code, buf);
}
@@ -249,7 +245,7 @@ enum state {
};
static UChar*
-gb18030_left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc)
+gb18030_left_adjust_char_head(const UChar* start, const UChar* s, const UChar* end, OnigEncoding enc)
{
const UChar *p;
enum state state = S_START;
diff --git a/enc/gbk.c b/enc/gbk.c
index 8b45ed4dc9..3efb1bf636 100644
--- a/enc/gbk.c
+++ b/enc/gbk.c
@@ -165,7 +165,7 @@ gbk_is_code_ctype(OnigCodePoint code, unsigned int ctype, OnigEncoding enc)
}
static UChar*
-gbk_left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc)
+gbk_left_adjust_char_head(const UChar* start, const UChar* s, const UChar* end, OnigEncoding enc)
{
const UChar *p;
int len;
@@ -181,7 +181,7 @@ gbk_left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc)
}
}
}
- len = enclen(enc, p, s);
+ len = enclen(enc, p, end);
if (p + len > s) return (UChar* )p;
p += len;
return (UChar* )(p + ((s - p) & ~1));
diff --git a/enc/shift_jis.c b/enc/shift_jis.c
index f74afffa92..b4d8592a27 100644
--- a/enc/shift_jis.c
+++ b/enc/shift_jis.c
@@ -229,7 +229,7 @@ is_code_ctype(OnigCodePoint code, unsigned int ctype)
#endif
static UChar*
-left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc)
+left_adjust_char_head(const UChar* start, const UChar* s, const UChar* end, OnigEncoding enc)
{
const UChar *p;
int len;
@@ -245,7 +245,7 @@ left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc)
}
}
}
- len = enclen(enc, p, s);
+ len = enclen(enc, p, end);
if (p + len > s) return (UChar* )p;
p += len;
return (UChar* )(p + ((s - p) & ~1));
diff --git a/enc/trans/escape.trans b/enc/trans/escape.trans
index 63836c37a6..f45f27bc41 100644
--- a/enc/trans/escape.trans
+++ b/enc/trans/escape.trans
@@ -5,19 +5,19 @@
str.unpack("H*")[0]
end
- transcode_tblgen("", "amp-escaped", [
+ transcode_tblgen("", "amp_escape", [
["{00-25,27-FF}", :nomap],
["26", hexstr("&amp;")]
])
- transcode_tblgen("", "xml-text-escaped", [
+ transcode_tblgen("", "xml_text_escape", [
["{00-25,27-3B,3D,3F-FF}", :nomap],
["26", hexstr("&amp;")],
["3C", hexstr("&lt;")],
["3E", hexstr("&gt;")]
])
- transcode_tblgen("", "xml-attr-content-escaped", [
+ transcode_tblgen("", "xml_attr_content_escape", [
["{00-21,23-25,27-3B,3D,3F-FF}", :nomap],
["22", hexstr("&quot;")],
["26", hexstr("&amp;")],
@@ -43,8 +43,8 @@ escape_xml_attr_quote_init(void *statep)
return 0;
}
-static int
-fun_so_escape_xml_attr_quote(void *statep, const unsigned char *s, size_t l, unsigned char *o)
+static ssize_t
+fun_so_escape_xml_attr_quote(void *statep, const unsigned char *s, size_t l, unsigned char *o, size_t osize)
{
unsigned char *sp = statep;
int n = 0;
@@ -56,8 +56,8 @@ fun_so_escape_xml_attr_quote(void *statep, const unsigned char *s, size_t l, uns
return n;
}
-static int
-escape_xml_attr_quote_finish(void *statep, unsigned char *o)
+static ssize_t
+escape_xml_attr_quote_finish(void *statep, unsigned char *o, size_t osize)
{
unsigned char *sp = statep;
int n = 0;
@@ -74,7 +74,7 @@ escape_xml_attr_quote_finish(void *statep, unsigned char *o)
static const rb_transcoder
rb_escape_xml_attr_quote = {
- "", "xml-attr-quoted", escape_xml_attr_quote,
+ "", "xml_attr_quote", escape_xml_attr_quote,
TRANSCODE_TABLE_INFO,
1, /* input_unit_length */
1, /* max_input */
diff --git a/enc/trans/ibm437-tbl.rb b/enc/trans/ibm437-tbl.rb
new file mode 100644
index 0000000000..5ae64d621e
--- /dev/null
+++ b/enc/trans/ibm437-tbl.rb
@@ -0,0 +1,130 @@
+IBM437_TO_UCS_TBL = [
+ ["FF",0xA0],
+ ["AD",0xA1],
+ ["9B",0xA2],
+ ["9C",0xA3],
+ ["9D",0xA5],
+ ["A6",0xAA],
+ ["AE",0xAB],
+ ["AA",0xAC],
+ ["F8",0xB0],
+ ["F1",0xB1],
+ ["FD",0xB2],
+ ["E6",0xB5],
+ ["FA",0xB7],
+ ["A7",0xBA],
+ ["AF",0xBB],
+ ["AC",0xBC],
+ ["AB",0xBD],
+ ["A8",0xBF],
+ ["8E",0xC4],
+ ["8F",0xC5],
+ ["92",0xC6],
+ ["80",0xC7],
+ ["90",0xC9],
+ ["A5",0xD1],
+ ["99",0xD6],
+ ["9A",0xDC],
+ ["E1",0xDF],
+ ["85",0xE0],
+ ["A0",0xE1],
+ ["83",0xE2],
+ ["84",0xE4],
+ ["86",0xE5],
+ ["91",0xE6],
+ ["87",0xE7],
+ ["8A",0xE8],
+ ["82",0xE9],
+ ["88",0xEA],
+ ["89",0xEB],
+ ["8D",0xEC],
+ ["A1",0xED],
+ ["8C",0xEE],
+ ["8B",0xEF],
+ ["A4",0xF1],
+ ["95",0xF2],
+ ["A2",0xF3],
+ ["93",0xF4],
+ ["94",0xF6],
+ ["F6",0xF7],
+ ["97",0xF9],
+ ["A3",0xFA],
+ ["96",0xFB],
+ ["81",0xFC],
+ ["98",0xFF],
+ ["9F",0x192],
+ ["E2",0x393],
+ ["E9",0x398],
+ ["E4",0x3A3],
+ ["E8",0x3A6],
+ ["EA",0x3A9],
+ ["E0",0x3B1],
+ ["EB",0x3B4],
+ ["EE",0x3B5],
+ ["E3",0x3C0],
+ ["E5",0x3C3],
+ ["E7",0x3C4],
+ ["ED",0x3C6],
+ ["FC",0x207F],
+ ["9E",0x20A7],
+ ["F9",0x2219],
+ ["FB",0x221A],
+ ["EC",0x221E],
+ ["EF",0x2229],
+ ["F7",0x2248],
+ ["F0",0x2261],
+ ["F3",0x2264],
+ ["F2",0x2265],
+ ["A9",0x2310],
+ ["F4",0x2320],
+ ["F5",0x2321],
+ ["C4",0x2500],
+ ["B3",0x2502],
+ ["DA",0x250C],
+ ["BF",0x2510],
+ ["C0",0x2514],
+ ["D9",0x2518],
+ ["C3",0x251C],
+ ["B4",0x2524],
+ ["C2",0x252C],
+ ["C1",0x2534],
+ ["C5",0x253C],
+ ["CD",0x2550],
+ ["BA",0x2551],
+ ["D5",0x2552],
+ ["D6",0x2553],
+ ["C9",0x2554],
+ ["B8",0x2555],
+ ["B7",0x2556],
+ ["BB",0x2557],
+ ["D4",0x2558],
+ ["D3",0x2559],
+ ["C8",0x255A],
+ ["BE",0x255B],
+ ["BD",0x255C],
+ ["BC",0x255D],
+ ["C6",0x255E],
+ ["C7",0x255F],
+ ["CC",0x2560],
+ ["B5",0x2561],
+ ["B6",0x2562],
+ ["B9",0x2563],
+ ["D1",0x2564],
+ ["D2",0x2565],
+ ["CB",0x2566],
+ ["CF",0x2567],
+ ["D0",0x2568],
+ ["CA",0x2569],
+ ["D8",0x256A],
+ ["D7",0x256B],
+ ["CE",0x256C],
+ ["DF",0x2580],
+ ["DC",0x2584],
+ ["DB",0x2588],
+ ["DD",0x258C],
+ ["DE",0x2590],
+ ["B0",0x2591],
+ ["B1",0x2592],
+ ["B2",0x2593],
+ ["FE",0x25A0],
+] \ No newline at end of file
diff --git a/enc/trans/ibm775-tbl.rb b/enc/trans/ibm775-tbl.rb
new file mode 100644
index 0000000000..f55679f409
--- /dev/null
+++ b/enc/trans/ibm775-tbl.rb
@@ -0,0 +1,130 @@
+IBM775_TO_UCS_TBL = [
+ ["FF",0xA0],
+ ["96",0xA2],
+ ["9C",0xA3],
+ ["9F",0xA4],
+ ["A7",0xA6],
+ ["F5",0xA7],
+ ["A8",0xA9],
+ ["AE",0xAB],
+ ["AA",0xAC],
+ ["F0",0xAD],
+ ["A9",0xAE],
+ ["F8",0xB0],
+ ["F1",0xB1],
+ ["FD",0xB2],
+ ["FC",0xB3],
+ ["E6",0xB5],
+ ["F4",0xB6],
+ ["FA",0xB7],
+ ["FB",0xB9],
+ ["AF",0xBB],
+ ["AC",0xBC],
+ ["AB",0xBD],
+ ["F3",0xBE],
+ ["8E",0xC4],
+ ["8F",0xC5],
+ ["92",0xC6],
+ ["90",0xC9],
+ ["E0",0xD3],
+ ["E5",0xD5],
+ ["99",0xD6],
+ ["9E",0xD7],
+ ["9D",0xD8],
+ ["9A",0xDC],
+ ["E1",0xDF],
+ ["84",0xE4],
+ ["86",0xE5],
+ ["91",0xE6],
+ ["82",0xE9],
+ ["A2",0xF3],
+ ["E4",0xF5],
+ ["94",0xF6],
+ ["F6",0xF7],
+ ["9B",0xF8],
+ ["81",0xFC],
+ ["A0",0x100],
+ ["83",0x101],
+ ["B5",0x104],
+ ["D0",0x105],
+ ["80",0x106],
+ ["87",0x107],
+ ["B6",0x10C],
+ ["D1",0x10D],
+ ["ED",0x112],
+ ["89",0x113],
+ ["B8",0x116],
+ ["D3",0x117],
+ ["B7",0x118],
+ ["D2",0x119],
+ ["95",0x122],
+ ["85",0x123],
+ ["A1",0x12A],
+ ["8C",0x12B],
+ ["BD",0x12E],
+ ["D4",0x12F],
+ ["E8",0x136],
+ ["E9",0x137],
+ ["EA",0x13B],
+ ["EB",0x13C],
+ ["AD",0x141],
+ ["88",0x142],
+ ["E3",0x143],
+ ["E7",0x144],
+ ["EE",0x145],
+ ["EC",0x146],
+ ["E2",0x14C],
+ ["93",0x14D],
+ ["8A",0x156],
+ ["8B",0x157],
+ ["97",0x15A],
+ ["98",0x15B],
+ ["BE",0x160],
+ ["D5",0x161],
+ ["C7",0x16A],
+ ["D7",0x16B],
+ ["C6",0x172],
+ ["D6",0x173],
+ ["8D",0x179],
+ ["A5",0x17A],
+ ["A3",0x17B],
+ ["A4",0x17C],
+ ["CF",0x17D],
+ ["D8",0x17E],
+ ["EF",0x2019],
+ ["F2",0x201C],
+ ["A6",0x201D],
+ ["F7",0x201E],
+ ["F9",0x2219],
+ ["C4",0x2500],
+ ["B3",0x2502],
+ ["DA",0x250C],
+ ["BF",0x2510],
+ ["C0",0x2514],
+ ["D9",0x2518],
+ ["C3",0x251C],
+ ["B4",0x2524],
+ ["C2",0x252C],
+ ["C1",0x2534],
+ ["C5",0x253C],
+ ["CD",0x2550],
+ ["BA",0x2551],
+ ["C9",0x2554],
+ ["BB",0x2557],
+ ["C8",0x255A],
+ ["BC",0x255D],
+ ["CC",0x2560],
+ ["B9",0x2563],
+ ["CB",0x2566],
+ ["CA",0x2569],
+ ["CE",0x256C],
+ ["DF",0x2580],
+ ["DC",0x2584],
+ ["DB",0x2588],
+ ["DD",0x258C],
+ ["DE",0x2590],
+ ["B0",0x2591],
+ ["B1",0x2592],
+ ["B2",0x2593],
+ ["FE",0x25A0],
+] \ No newline at end of file
diff --git a/enc/trans/ibm852-tbl.rb b/enc/trans/ibm852-tbl.rb
new file mode 100644
index 0000000000..6cec51cf80
--- /dev/null
+++ b/enc/trans/ibm852-tbl.rb
@@ -0,0 +1,130 @@
+IBM852_TO_UCS_TBL = [
+ ["FF",0xA0],
+ ["CF",0xA4],
+ ["F5",0xA7],
+ ["F9",0xA8],
+ ["AE",0xAB],
+ ["AA",0xAC],
+ ["F0",0xAD],
+ ["F8",0xB0],
+ ["EF",0xB4],
+ ["F7",0xB8],
+ ["AF",0xBB],
+ ["B5",0xC1],
+ ["B6",0xC2],
+ ["8E",0xC4],
+ ["80",0xC7],
+ ["90",0xC9],
+ ["D3",0xCB],
+ ["D6",0xCD],
+ ["D7",0xCE],
+ ["E0",0xD3],
+ ["E2",0xD4],
+ ["99",0xD6],
+ ["9E",0xD7],
+ ["E9",0xDA],
+ ["9A",0xDC],
+ ["ED",0xDD],
+ ["E1",0xDF],
+ ["A0",0xE1],
+ ["83",0xE2],
+ ["84",0xE4],
+ ["87",0xE7],
+ ["82",0xE9],
+ ["89",0xEB],
+ ["A1",0xED],
+ ["8C",0xEE],
+ ["A2",0xF3],
+ ["93",0xF4],
+ ["94",0xF6],
+ ["F6",0xF7],
+ ["A3",0xFA],
+ ["81",0xFC],
+ ["EC",0xFD],
+ ["C6",0x102],
+ ["C7",0x103],
+ ["A4",0x104],
+ ["A5",0x105],
+ ["8F",0x106],
+ ["86",0x107],
+ ["AC",0x10C],
+ ["9F",0x10D],
+ ["D2",0x10E],
+ ["D4",0x10F],
+ ["D1",0x110],
+ ["D0",0x111],
+ ["A8",0x118],
+ ["A9",0x119],
+ ["B7",0x11A],
+ ["D8",0x11B],
+ ["91",0x139],
+ ["92",0x13A],
+ ["95",0x13D],
+ ["96",0x13E],
+ ["9D",0x141],
+ ["88",0x142],
+ ["E3",0x143],
+ ["E4",0x144],
+ ["D5",0x147],
+ ["E5",0x148],
+ ["8A",0x150],
+ ["8B",0x151],
+ ["E8",0x154],
+ ["EA",0x155],
+ ["FC",0x158],
+ ["FD",0x159],
+ ["97",0x15A],
+ ["98",0x15B],
+ ["B8",0x15E],
+ ["AD",0x15F],
+ ["E6",0x160],
+ ["E7",0x161],
+ ["DD",0x162],
+ ["EE",0x163],
+ ["9B",0x164],
+ ["9C",0x165],
+ ["DE",0x16E],
+ ["85",0x16F],
+ ["EB",0x170],
+ ["FB",0x171],
+ ["8D",0x179],
+ ["AB",0x17A],
+ ["BD",0x17B],
+ ["BE",0x17C],
+ ["A6",0x17D],
+ ["A7",0x17E],
+ ["F3",0x2C7],
+ ["F4",0x2D8],
+ ["FA",0x2D9],
+ ["F2",0x2DB],
+ ["F1",0x2DD],
+ ["C4",0x2500],
+ ["B3",0x2502],
+ ["DA",0x250C],
+ ["BF",0x2510],
+ ["C0",0x2514],
+ ["D9",0x2518],
+ ["C3",0x251C],
+ ["B4",0x2524],
+ ["C2",0x252C],
+ ["C1",0x2534],
+ ["C5",0x253C],
+ ["CD",0x2550],
+ ["BA",0x2551],
+ ["C9",0x2554],
+ ["BB",0x2557],
+ ["C8",0x255A],
+ ["BC",0x255D],
+ ["CC",0x2560],
+ ["B9",0x2563],
+ ["CB",0x2566],
+ ["CA",0x2569],
+ ["CE",0x256C],
+ ["DF",0x2580],
+ ["DC",0x2584],
+ ["DB",0x2588],
+ ["B0",0x2591],
+ ["B1",0x2592],
+ ["B2",0x2593],
+ ["FE",0x25A0],
+] \ No newline at end of file
diff --git a/enc/trans/ibm855-tbl.rb b/enc/trans/ibm855-tbl.rb
new file mode 100644
index 0000000000..7e0cc5014f
--- /dev/null
+++ b/enc/trans/ibm855-tbl.rb
@@ -0,0 +1,130 @@
+IBM855_TO_UCS_TBL = [
+ ["FF",0xA0],
+ ["CF",0xA4],
+ ["FD",0xA7],
+ ["AE",0xAB],
+ ["F0",0xAD],
+ ["AF",0xBB],
+ ["85",0x401],
+ ["81",0x402],
+ ["83",0x403],
+ ["87",0x404],
+ ["89",0x405],
+ ["8B",0x406],
+ ["8D",0x407],
+ ["8F",0x408],
+ ["91",0x409],
+ ["93",0x40A],
+ ["95",0x40B],
+ ["97",0x40C],
+ ["99",0x40E],
+ ["9B",0x40F],
+ ["A1",0x410],
+ ["A3",0x411],
+ ["EC",0x412],
+ ["AD",0x413],
+ ["A7",0x414],
+ ["A9",0x415],
+ ["EA",0x416],
+ ["F4",0x417],
+ ["B8",0x418],
+ ["BE",0x419],
+ ["C7",0x41A],
+ ["D1",0x41B],
+ ["D3",0x41C],
+ ["D5",0x41D],
+ ["D7",0x41E],
+ ["DD",0x41F],
+ ["E2",0x420],
+ ["E4",0x421],
+ ["E6",0x422],
+ ["E8",0x423],
+ ["AB",0x424],
+ ["B6",0x425],
+ ["A5",0x426],
+ ["FC",0x427],
+ ["F6",0x428],
+ ["FA",0x429],
+ ["9F",0x42A],
+ ["F2",0x42B],
+ ["EE",0x42C],
+ ["F8",0x42D],
+ ["9D",0x42E],
+ ["E0",0x42F],
+ ["A0",0x430],
+ ["A2",0x431],
+ ["EB",0x432],
+ ["AC",0x433],
+ ["A6",0x434],
+ ["A8",0x435],
+ ["E9",0x436],
+ ["F3",0x437],
+ ["B7",0x438],
+ ["BD",0x439],
+ ["C6",0x43A],
+ ["D0",0x43B],
+ ["D2",0x43C],
+ ["D4",0x43D],
+ ["D6",0x43E],
+ ["D8",0x43F],
+ ["E1",0x440],
+ ["E3",0x441],
+ ["E5",0x442],
+ ["E7",0x443],
+ ["AA",0x444],
+ ["B5",0x445],
+ ["A4",0x446],
+ ["FB",0x447],
+ ["F5",0x448],
+ ["F9",0x449],
+ ["9E",0x44A],
+ ["F1",0x44B],
+ ["ED",0x44C],
+ ["F7",0x44D],
+ ["9C",0x44E],
+ ["DE",0x44F],
+ ["84",0x451],
+ ["80",0x452],
+ ["82",0x453],
+ ["86",0x454],
+ ["88",0x455],
+ ["8A",0x456],
+ ["8C",0x457],
+ ["8E",0x458],
+ ["90",0x459],
+ ["92",0x45A],
+ ["94",0x45B],
+ ["96",0x45C],
+ ["98",0x45E],
+ ["9A",0x45F],
+ ["EF",0x2116],
+ ["C4",0x2500],
+ ["B3",0x2502],
+ ["DA",0x250C],
+ ["BF",0x2510],
+ ["C0",0x2514],
+ ["D9",0x2518],
+ ["C3",0x251C],
+ ["B4",0x2524],
+ ["C2",0x252C],
+ ["C1",0x2534],
+ ["C5",0x253C],
+ ["CD",0x2550],
+ ["BA",0x2551],
+ ["C9",0x2554],
+ ["BB",0x2557],
+ ["C8",0x255A],
+ ["BC",0x255D],
+ ["CC",0x2560],
+ ["B9",0x2563],
+ ["CB",0x2566],
+ ["CA",0x2569],
+ ["CE",0x256C],
+ ["DF",0x2580],
+ ["DC",0x2584],
+ ["DB",0x2588],
+ ["B0",0x2591],
+ ["B1",0x2592],
+ ["B2",0x2593],
+ ["FE",0x25A0],
+] \ No newline at end of file
diff --git a/enc/trans/ibm857-tbl.rb b/enc/trans/ibm857-tbl.rb
new file mode 100644
index 0000000000..5b20d389d3
--- /dev/null
+++ b/enc/trans/ibm857-tbl.rb
@@ -0,0 +1,127 @@
+IBM857_TO_UCS_TBL = [
+ ["FF",0xA0],
+ ["AD",0xA1],
+ ["BD",0xA2],
+ ["9C",0xA3],
+ ["CF",0xA4],
+ ["BE",0xA5],
+ ["DD",0xA6],
+ ["F5",0xA7],
+ ["F9",0xA8],
+ ["B8",0xA9],
+ ["D1",0xAA],
+ ["AE",0xAB],
+ ["AA",0xAC],
+ ["F0",0xAD],
+ ["A9",0xAE],
+ ["EE",0xAF],
+ ["F8",0xB0],
+ ["F1",0xB1],
+ ["FD",0xB2],
+ ["FC",0xB3],
+ ["EF",0xB4],
+ ["E6",0xB5],
+ ["F4",0xB6],
+ ["FA",0xB7],
+ ["F7",0xB8],
+ ["FB",0xB9],
+ ["D0",0xBA],
+ ["AF",0xBB],
+ ["AC",0xBC],
+ ["AB",0xBD],
+ ["F3",0xBE],
+ ["A8",0xBF],
+ ["B7",0xC0],
+ ["B5",0xC1],
+ ["B6",0xC2],
+ ["C7",0xC3],
+ ["8E",0xC4],
+ ["8F",0xC5],
+ ["92",0xC6],
+ ["80",0xC7],
+ ["D4",0xC8],
+ ["90",0xC9],
+ ["D2",0xCA],
+ ["D3",0xCB],
+ ["DE",0xCC],
+ ["D6",0xCD],
+ ["D7",0xCE],
+ ["D8",0xCF],
+ ["A5",0xD1],
+ ["E3",0xD2],
+ ["E0",0xD3],
+ ["E2",0xD4],
+ ["E5",0xD5],
+ ["99",0xD6],
+ ["E8",0xD7],
+ ["9D",0xD8],
+ ["EB",0xD9],
+ ["E9",0xDA],
+ ["EA",0xDB],
+ ["9A",0xDC],
+ ["E1",0xDF],
+ ["85",0xE0],
+ ["A0",0xE1],
+ ["83",0xE2],
+ ["C6",0xE3],
+ ["84",0xE4],
+ ["86",0xE5],
+ ["91",0xE6],
+ ["87",0xE7],
+ ["8A",0xE8],
+ ["82",0xE9],
+ ["88",0xEA],
+ ["89",0xEB],
+ ["EC",0xEC],
+ ["A1",0xED],
+ ["8C",0xEE],
+ ["8B",0xEF],
+ ["A4",0xF1],
+ ["95",0xF2],
+ ["A2",0xF3],
+ ["93",0xF4],
+ ["E4",0xF5],
+ ["94",0xF6],
+ ["F6",0xF7],
+ ["9B",0xF8],
+ ["97",0xF9],
+ ["A3",0xFA],
+ ["96",0xFB],
+ ["81",0xFC],
+ ["ED",0xFF],
+ ["A6",0x11E],
+ ["A7",0x11F],
+ ["98",0x130],
+ ["8D",0x131],
+ ["9E",0x15E],
+ ["9F",0x15F],
+ ["C4",0x2500],
+ ["B3",0x2502],
+ ["DA",0x250C],
+ ["BF",0x2510],
+ ["C0",0x2514],
+ ["D9",0x2518],
+ ["C3",0x251C],
+ ["B4",0x2524],
+ ["C2",0x252C],
+ ["C1",0x2534],
+ ["C5",0x253C],
+ ["CD",0x2550],
+ ["BA",0x2551],
+ ["C9",0x2554],
+ ["BB",0x2557],
+ ["C8",0x255A],
+ ["BC",0x255D],
+ ["CC",0x2560],
+ ["B9",0x2563],
+ ["CB",0x2566],
+ ["CA",0x2569],
+ ["CE",0x256C],
+ ["DF",0x2580],
+ ["DC",0x2584],
+ ["DB",0x2588],
+ ["B0",0x2591],
+ ["B1",0x2592],
+ ["B2",0x2593],
+ ["FE",0x25A0],
+] \ No newline at end of file
diff --git a/enc/trans/ibm860-tbl.rb b/enc/trans/ibm860-tbl.rb
new file mode 100644
index 0000000000..ae218a129f
--- /dev/null
+++ b/enc/trans/ibm860-tbl.rb
@@ -0,0 +1,130 @@
+IBM860_TO_UCS_TBL = [
+ ["FF",0xA0],
+ ["AD",0xA1],
+ ["9B",0xA2],
+ ["9C",0xA3],
+ ["A6",0xAA],
+ ["AE",0xAB],
+ ["AA",0xAC],
+ ["F8",0xB0],
+ ["F1",0xB1],
+ ["FD",0xB2],
+ ["E6",0xB5],
+ ["FA",0xB7],
+ ["A7",0xBA],
+ ["AF",0xBB],
+ ["AC",0xBC],
+ ["AB",0xBD],
+ ["A8",0xBF],
+ ["91",0xC0],
+ ["86",0xC1],
+ ["8F",0xC2],
+ ["8E",0xC3],
+ ["80",0xC7],
+ ["92",0xC8],
+ ["90",0xC9],
+ ["89",0xCA],
+ ["98",0xCC],
+ ["8B",0xCD],
+ ["A5",0xD1],
+ ["A9",0xD2],
+ ["9F",0xD3],
+ ["8C",0xD4],
+ ["99",0xD5],
+ ["9D",0xD9],
+ ["96",0xDA],
+ ["9A",0xDC],
+ ["E1",0xDF],
+ ["85",0xE0],
+ ["A0",0xE1],
+ ["83",0xE2],
+ ["84",0xE3],
+ ["87",0xE7],
+ ["8A",0xE8],
+ ["82",0xE9],
+ ["88",0xEA],
+ ["8D",0xEC],
+ ["A1",0xED],
+ ["A4",0xF1],
+ ["95",0xF2],
+ ["A2",0xF3],
+ ["93",0xF4],
+ ["94",0xF5],
+ ["F6",0xF7],
+ ["97",0xF9],
+ ["A3",0xFA],
+ ["81",0xFC],
+ ["E2",0x393],
+ ["E9",0x398],
+ ["E4",0x3A3],
+ ["E8",0x3A6],
+ ["EA",0x3A9],
+ ["E0",0x3B1],
+ ["EB",0x3B4],
+ ["EE",0x3B5],
+ ["E3",0x3C0],
+ ["E5",0x3C3],
+ ["E7",0x3C4],
+ ["ED",0x3C6],
+ ["FC",0x207F],
+ ["9E",0x20A7],
+ ["F9",0x2219],
+ ["FB",0x221A],
+ ["EC",0x221E],
+ ["EF",0x2229],
+ ["F7",0x2248],
+ ["F0",0x2261],
+ ["F3",0x2264],
+ ["F2",0x2265],
+ ["F4",0x2320],
+ ["F5",0x2321],
+ ["C4",0x2500],
+ ["B3",0x2502],
+ ["DA",0x250C],
+ ["BF",0x2510],
+ ["C0",0x2514],
+ ["D9",0x2518],
+ ["C3",0x251C],
+ ["B4",0x2524],
+ ["C2",0x252C],
+ ["C1",0x2534],
+ ["C5",0x253C],
+ ["CD",0x2550],
+ ["BA",0x2551],
+ ["D5",0x2552],
+ ["D6",0x2553],
+ ["C9",0x2554],
+ ["B8",0x2555],
+ ["B7",0x2556],
+ ["BB",0x2557],
+ ["D4",0x2558],
+ ["D3",0x2559],
+ ["C8",0x255A],
+ ["BE",0x255B],
+ ["BD",0x255C],
+ ["BC",0x255D],
+ ["C6",0x255E],
+ ["C7",0x255F],
+ ["CC",0x2560],
+ ["B5",0x2561],
+ ["B6",0x2562],
+ ["B9",0x2563],
+ ["D1",0x2564],
+ ["D2",0x2565],
+ ["CB",0x2566],
+ ["CF",0x2567],
+ ["D0",0x2568],
+ ["CA",0x2569],
+ ["D8",0x256A],
+ ["D7",0x256B],
+ ["CE",0x256C],
+ ["DF",0x2580],
+ ["DC",0x2584],
+ ["DB",0x2588],
+ ["DD",0x258C],
+ ["DE",0x2590],
+ ["B0",0x2591],
+ ["B1",0x2592],
+ ["B2",0x2593],
+ ["FE",0x25A0],
+] \ No newline at end of file
diff --git a/enc/trans/ibm861-tbl.rb b/enc/trans/ibm861-tbl.rb
new file mode 100644
index 0000000000..c24042a76c
--- /dev/null
+++ b/enc/trans/ibm861-tbl.rb
@@ -0,0 +1,130 @@
+IBM861_TO_UCS_TBL = [
+ ["FF",0xA0],
+ ["AD",0xA1],
+ ["9C",0xA3],
+ ["AE",0xAB],
+ ["AA",0xAC],
+ ["F8",0xB0],
+ ["F1",0xB1],
+ ["FD",0xB2],
+ ["E6",0xB5],
+ ["FA",0xB7],
+ ["AF",0xBB],
+ ["AC",0xBC],
+ ["AB",0xBD],
+ ["A8",0xBF],
+ ["A4",0xC1],
+ ["8E",0xC4],
+ ["8F",0xC5],
+ ["92",0xC6],
+ ["80",0xC7],
+ ["90",0xC9],
+ ["A5",0xCD],
+ ["8B",0xD0],
+ ["A6",0xD3],
+ ["99",0xD6],
+ ["9D",0xD8],
+ ["A7",0xDA],
+ ["9A",0xDC],
+ ["97",0xDD],
+ ["8D",0xDE],
+ ["E1",0xDF],
+ ["85",0xE0],
+ ["A0",0xE1],
+ ["83",0xE2],
+ ["84",0xE4],
+ ["86",0xE5],
+ ["91",0xE6],
+ ["87",0xE7],
+ ["8A",0xE8],
+ ["82",0xE9],
+ ["88",0xEA],
+ ["89",0xEB],
+ ["A1",0xED],
+ ["8C",0xF0],
+ ["A2",0xF3],
+ ["93",0xF4],
+ ["94",0xF6],
+ ["F6",0xF7],
+ ["9B",0xF8],
+ ["A3",0xFA],
+ ["96",0xFB],
+ ["81",0xFC],
+ ["98",0xFD],
+ ["95",0xFE],
+ ["9F",0x192],
+ ["E2",0x393],
+ ["E9",0x398],
+ ["E4",0x3A3],
+ ["E8",0x3A6],
+ ["EA",0x3A9],
+ ["E0",0x3B1],
+ ["EB",0x3B4],
+ ["EE",0x3B5],
+ ["E3",0x3C0],
+ ["E5",0x3C3],
+ ["E7",0x3C4],
+ ["ED",0x3C6],
+ ["FC",0x207F],
+ ["9E",0x20A7],
+ ["F9",0x2219],
+ ["FB",0x221A],
+ ["EC",0x221E],
+ ["EF",0x2229],
+ ["F7",0x2248],
+ ["F0",0x2261],
+ ["F3",0x2264],
+ ["F2",0x2265],
+ ["A9",0x2310],
+ ["F4",0x2320],
+ ["F5",0x2321],
+ ["C4",0x2500],
+ ["B3",0x2502],
+ ["DA",0x250C],
+ ["BF",0x2510],
+ ["C0",0x2514],
+ ["D9",0x2518],
+ ["C3",0x251C],
+ ["B4",0x2524],
+ ["C2",0x252C],
+ ["C1",0x2534],
+ ["C5",0x253C],
+ ["CD",0x2550],
+ ["BA",0x2551],
+ ["D5",0x2552],
+ ["D6",0x2553],
+ ["C9",0x2554],
+ ["B8",0x2555],
+ ["B7",0x2556],
+ ["BB",0x2557],
+ ["D4",0x2558],
+ ["D3",0x2559],
+ ["C8",0x255A],
+ ["BE",0x255B],
+ ["BD",0x255C],
+ ["BC",0x255D],
+ ["C6",0x255E],
+ ["C7",0x255F],
+ ["CC",0x2560],
+ ["B5",0x2561],
+ ["B6",0x2562],
+ ["B9",0x2563],
+ ["D1",0x2564],
+ ["D2",0x2565],
+ ["CB",0x2566],
+ ["CF",0x2567],
+ ["D0",0x2568],
+ ["CA",0x2569],
+ ["D8",0x256A],
+ ["D7",0x256B],
+ ["CE",0x256C],
+ ["DF",0x2580],
+ ["DC",0x2584],
+ ["DB",0x2588],
+ ["DD",0x258C],
+ ["DE",0x2590],
+ ["B0",0x2591],
+ ["B1",0x2592],
+ ["B2",0x2593],
+ ["FE",0x25A0],
+] \ No newline at end of file
diff --git a/enc/trans/ibm862-tbl.rb b/enc/trans/ibm862-tbl.rb
new file mode 100644
index 0000000000..31d6fb0243
--- /dev/null
+++ b/enc/trans/ibm862-tbl.rb
@@ -0,0 +1,130 @@
+IBM862_TO_UCS_TBL = [
+ ["FF",0xA0],
+ ["AD",0xA1],
+ ["9B",0xA2],
+ ["9C",0xA3],
+ ["9D",0xA5],
+ ["A6",0xAA],
+ ["AE",0xAB],
+ ["AA",0xAC],
+ ["F8",0xB0],
+ ["F1",0xB1],
+ ["FD",0xB2],
+ ["E6",0xB5],
+ ["FA",0xB7],
+ ["A7",0xBA],
+ ["AF",0xBB],
+ ["AC",0xBC],
+ ["AB",0xBD],
+ ["A8",0xBF],
+ ["A5",0xD1],
+ ["E1",0xDF],
+ ["A0",0xE1],
+ ["A1",0xED],
+ ["A4",0xF1],
+ ["A2",0xF3],
+ ["F6",0xF7],
+ ["A3",0xFA],
+ ["9F",0x192],
+ ["E2",0x393],
+ ["E9",0x398],
+ ["E4",0x3A3],
+ ["E8",0x3A6],
+ ["EA",0x3A9],
+ ["E0",0x3B1],
+ ["EB",0x3B4],
+ ["EE",0x3B5],
+ ["E3",0x3C0],
+ ["E5",0x3C3],
+ ["E7",0x3C4],
+ ["ED",0x3C6],
+ ["80",0x5D0],
+ ["81",0x5D1],
+ ["82",0x5D2],
+ ["83",0x5D3],
+ ["84",0x5D4],
+ ["85",0x5D5],
+ ["86",0x5D6],
+ ["87",0x5D7],
+ ["88",0x5D8],
+ ["89",0x5D9],
+ ["8A",0x5DA],
+ ["8B",0x5DB],
+ ["8C",0x5DC],
+ ["8D",0x5DD],
+ ["8E",0x5DE],
+ ["8F",0x5DF],
+ ["90",0x5E0],
+ ["91",0x5E1],
+ ["92",0x5E2],
+ ["93",0x5E3],
+ ["94",0x5E4],
+ ["95",0x5E5],
+ ["96",0x5E6],
+ ["97",0x5E7],
+ ["98",0x5E8],
+ ["99",0x5E9],
+ ["9A",0x5EA],
+ ["FC",0x207F],
+ ["9E",0x20A7],
+ ["F9",0x2219],
+ ["FB",0x221A],
+ ["EC",0x221E],
+ ["EF",0x2229],
+ ["F7",0x2248],
+ ["F0",0x2261],
+ ["F3",0x2264],
+ ["F2",0x2265],
+ ["A9",0x2310],
+ ["F4",0x2320],
+ ["F5",0x2321],
+ ["C4",0x2500],
+ ["B3",0x2502],
+ ["DA",0x250C],
+ ["BF",0x2510],
+ ["C0",0x2514],
+ ["D9",0x2518],
+ ["C3",0x251C],
+ ["B4",0x2524],
+ ["C2",0x252C],
+ ["C1",0x2534],
+ ["C5",0x253C],
+ ["CD",0x2550],
+ ["BA",0x2551],
+ ["D5",0x2552],
+ ["D6",0x2553],
+ ["C9",0x2554],
+ ["B8",0x2555],
+ ["B7",0x2556],
+ ["BB",0x2557],
+ ["D4",0x2558],
+ ["D3",0x2559],
+ ["C8",0x255A],
+ ["BE",0x255B],
+ ["BD",0x255C],
+ ["BC",0x255D],
+ ["C6",0x255E],
+ ["C7",0x255F],
+ ["CC",0x2560],
+ ["B5",0x2561],
+ ["B6",0x2562],
+ ["B9",0x2563],
+ ["D1",0x2564],
+ ["D2",0x2565],
+ ["CB",0x2566],
+ ["CF",0x2567],
+ ["D0",0x2568],
+ ["CA",0x2569],
+ ["D8",0x256A],
+ ["D7",0x256B],
+ ["CE",0x256C],
+ ["DF",0x2580],
+ ["DC",0x2584],
+ ["DB",0x2588],
+ ["DD",0x258C],
+ ["DE",0x2590],
+ ["B0",0x2591],
+ ["B1",0x2592],
+ ["B2",0x2593],
+ ["FE",0x25A0],
+] \ No newline at end of file
diff --git a/enc/trans/ibm863-tbl.rb b/enc/trans/ibm863-tbl.rb
new file mode 100644
index 0000000000..db110cf38c
--- /dev/null
+++ b/enc/trans/ibm863-tbl.rb
@@ -0,0 +1,130 @@
+IBM863_TO_UCS_TBL = [
+ ["FF",0xA0],
+ ["9B",0xA2],
+ ["9C",0xA3],
+ ["98",0xA4],
+ ["A0",0xA6],
+ ["8F",0xA7],
+ ["A4",0xA8],
+ ["AE",0xAB],
+ ["AA",0xAC],
+ ["A7",0xAF],
+ ["F8",0xB0],
+ ["F1",0xB1],
+ ["FD",0xB2],
+ ["A6",0xB3],
+ ["A1",0xB4],
+ ["E6",0xB5],
+ ["86",0xB6],
+ ["FA",0xB7],
+ ["A5",0xB8],
+ ["AF",0xBB],
+ ["AC",0xBC],
+ ["AB",0xBD],
+ ["AD",0xBE],
+ ["8E",0xC0],
+ ["84",0xC2],
+ ["80",0xC7],
+ ["91",0xC8],
+ ["90",0xC9],
+ ["92",0xCA],
+ ["94",0xCB],
+ ["A8",0xCE],
+ ["95",0xCF],
+ ["99",0xD4],
+ ["9D",0xD9],
+ ["9E",0xDB],
+ ["9A",0xDC],
+ ["E1",0xDF],
+ ["85",0xE0],
+ ["83",0xE2],
+ ["87",0xE7],
+ ["8A",0xE8],
+ ["82",0xE9],
+ ["88",0xEA],
+ ["89",0xEB],
+ ["8C",0xEE],
+ ["8B",0xEF],
+ ["A2",0xF3],
+ ["93",0xF4],
+ ["F6",0xF7],
+ ["97",0xF9],
+ ["A3",0xFA],
+ ["96",0xFB],
+ ["81",0xFC],
+ ["9F",0x192],
+ ["E2",0x393],
+ ["E9",0x398],
+ ["E4",0x3A3],
+ ["E8",0x3A6],
+ ["EA",0x3A9],
+ ["E0",0x3B1],
+ ["EB",0x3B4],
+ ["EE",0x3B5],
+ ["E3",0x3C0],
+ ["E5",0x3C3],
+ ["E7",0x3C4],
+ ["ED",0x3C6],
+ ["8D",0x2017],
+ ["FC",0x207F],
+ ["F9",0x2219],
+ ["FB",0x221A],
+ ["EC",0x221E],
+ ["EF",0x2229],
+ ["F7",0x2248],
+ ["F0",0x2261],
+ ["F3",0x2264],
+ ["F2",0x2265],
+ ["A9",0x2310],
+ ["F4",0x2320],
+ ["F5",0x2321],
+ ["C4",0x2500],
+ ["B3",0x2502],
+ ["DA",0x250C],
+ ["BF",0x2510],
+ ["C0",0x2514],
+ ["D9",0x2518],
+ ["C3",0x251C],
+ ["B4",0x2524],
+ ["C2",0x252C],
+ ["C1",0x2534],
+ ["C5",0x253C],
+ ["CD",0x2550],
+ ["BA",0x2551],
+ ["D5",0x2552],
+ ["D6",0x2553],
+ ["C9",0x2554],
+ ["B8",0x2555],
+ ["B7",0x2556],
+ ["BB",0x2557],
+ ["D4",0x2558],
+ ["D3",0x2559],
+ ["C8",0x255A],
+ ["BE",0x255B],
+ ["BD",0x255C],
+ ["BC",0x255D],
+ ["C6",0x255E],
+ ["C7",0x255F],
+ ["CC",0x2560],
+ ["B5",0x2561],
+ ["B6",0x2562],
+ ["B9",0x2563],
+ ["D1",0x2564],
+ ["D2",0x2565],
+ ["CB",0x2566],
+ ["CF",0x2567],
+ ["D0",0x2568],
+ ["CA",0x2569],
+ ["D8",0x256A],
+ ["D7",0x256B],
+ ["CE",0x256C],
+ ["DF",0x2580],
+ ["DC",0x2584],
+ ["DB",0x2588],
+ ["DD",0x258C],
+ ["DE",0x2590],
+ ["B0",0x2591],
+ ["B1",0x2592],
+ ["B2",0x2593],
+ ["FE",0x25A0],
+] \ No newline at end of file
diff --git a/enc/trans/ibm865-tbl.rb b/enc/trans/ibm865-tbl.rb
new file mode 100644
index 0000000000..22e322fb31
--- /dev/null
+++ b/enc/trans/ibm865-tbl.rb
@@ -0,0 +1,130 @@
+IBM865_TO_UCS_TBL = [
+ ["FF",0xA0],
+ ["AD",0xA1],
+ ["9C",0xA3],
+ ["AF",0xA4],
+ ["A6",0xAA],
+ ["AE",0xAB],
+ ["AA",0xAC],
+ ["F8",0xB0],
+ ["F1",0xB1],
+ ["FD",0xB2],
+ ["E6",0xB5],
+ ["FA",0xB7],
+ ["A7",0xBA],
+ ["AC",0xBC],
+ ["AB",0xBD],
+ ["A8",0xBF],
+ ["8E",0xC4],
+ ["8F",0xC5],
+ ["92",0xC6],
+ ["80",0xC7],
+ ["90",0xC9],
+ ["A5",0xD1],
+ ["99",0xD6],
+ ["9D",0xD8],
+ ["9A",0xDC],
+ ["E1",0xDF],
+ ["85",0xE0],
+ ["A0",0xE1],
+ ["83",0xE2],
+ ["84",0xE4],
+ ["86",0xE5],
+ ["91",0xE6],
+ ["87",0xE7],
+ ["8A",0xE8],
+ ["82",0xE9],
+ ["88",0xEA],
+ ["89",0xEB],
+ ["8D",0xEC],
+ ["A1",0xED],
+ ["8C",0xEE],
+ ["8B",0xEF],
+ ["A4",0xF1],
+ ["95",0xF2],
+ ["A2",0xF3],
+ ["93",0xF4],
+ ["94",0xF6],
+ ["F6",0xF7],
+ ["9B",0xF8],
+ ["97",0xF9],
+ ["A3",0xFA],
+ ["96",0xFB],
+ ["81",0xFC],
+ ["98",0xFF],
+ ["9F",0x192],
+ ["E2",0x393],
+ ["E9",0x398],
+ ["E4",0x3A3],
+ ["E8",0x3A6],
+ ["EA",0x3A9],
+ ["E0",0x3B1],
+ ["EB",0x3B4],
+ ["EE",0x3B5],
+ ["E3",0x3C0],
+ ["E5",0x3C3],
+ ["E7",0x3C4],
+ ["ED",0x3C6],
+ ["FC",0x207F],
+ ["9E",0x20A7],
+ ["F9",0x2219],
+ ["FB",0x221A],
+ ["EC",0x221E],
+ ["EF",0x2229],
+ ["F7",0x2248],
+ ["F0",0x2261],
+ ["F3",0x2264],
+ ["F2",0x2265],
+ ["A9",0x2310],
+ ["F4",0x2320],
+ ["F5",0x2321],
+ ["C4",0x2500],
+ ["B3",0x2502],
+ ["DA",0x250C],
+ ["BF",0x2510],
+ ["C0",0x2514],
+ ["D9",0x2518],
+ ["C3",0x251C],
+ ["B4",0x2524],
+ ["C2",0x252C],
+ ["C1",0x2534],
+ ["C5",0x253C],
+ ["CD",0x2550],
+ ["BA",0x2551],
+ ["D5",0x2552],
+ ["D6",0x2553],
+ ["C9",0x2554],
+ ["B8",0x2555],
+ ["B7",0x2556],
+ ["BB",0x2557],
+ ["D4",0x2558],
+ ["D3",0x2559],
+ ["C8",0x255A],
+ ["BE",0x255B],
+ ["BD",0x255C],
+ ["BC",0x255D],
+ ["C6",0x255E],
+ ["C7",0x255F],
+ ["CC",0x2560],
+ ["B5",0x2561],
+ ["B6",0x2562],
+ ["B9",0x2563],
+ ["D1",0x2564],
+ ["D2",0x2565],
+ ["CB",0x2566],
+ ["CF",0x2567],
+ ["D0",0x2568],
+ ["CA",0x2569],
+ ["D8",0x256A],
+ ["D7",0x256B],
+ ["CE",0x256C],
+ ["DF",0x2580],
+ ["DC",0x2584],
+ ["DB",0x2588],
+ ["DD",0x258C],
+ ["DE",0x2590],
+ ["B0",0x2591],
+ ["B1",0x2592],
+ ["B2",0x2593],
+ ["FE",0x25A0],
+] \ No newline at end of file
diff --git a/enc/trans/ibm866-tbl.rb b/enc/trans/ibm866-tbl.rb
new file mode 100644
index 0000000000..95b9ee7534
--- /dev/null
+++ b/enc/trans/ibm866-tbl.rb
@@ -0,0 +1,130 @@
+IBM866_TO_UCS_TBL = [
+ ["FF",0xA0],
+ ["FD",0xA4],
+ ["F8",0xB0],
+ ["FA",0xB7],
+ ["F0",0x401],
+ ["F2",0x404],
+ ["F4",0x407],
+ ["F6",0x40E],
+ ["80",0x410],
+ ["81",0x411],
+ ["82",0x412],
+ ["83",0x413],
+ ["84",0x414],
+ ["85",0x415],
+ ["86",0x416],
+ ["87",0x417],
+ ["88",0x418],
+ ["89",0x419],
+ ["8A",0x41A],
+ ["8B",0x41B],
+ ["8C",0x41C],
+ ["8D",0x41D],
+ ["8E",0x41E],
+ ["8F",0x41F],
+ ["90",0x420],
+ ["91",0x421],
+ ["92",0x422],
+ ["93",0x423],
+ ["94",0x424],
+ ["95",0x425],
+ ["96",0x426],
+ ["97",0x427],
+ ["98",0x428],
+ ["99",0x429],
+ ["9A",0x42A],
+ ["9B",0x42B],
+ ["9C",0x42C],
+ ["9D",0x42D],
+ ["9E",0x42E],
+ ["9F",0x42F],
+ ["A0",0x430],
+ ["A1",0x431],
+ ["A2",0x432],
+ ["A3",0x433],
+ ["A4",0x434],
+ ["A5",0x435],
+ ["A6",0x436],
+ ["A7",0x437],
+ ["A8",0x438],
+ ["A9",0x439],
+ ["AA",0x43A],
+ ["AB",0x43B],
+ ["AC",0x43C],
+ ["AD",0x43D],
+ ["AE",0x43E],
+ ["AF",0x43F],
+ ["E0",0x440],
+ ["E1",0x441],
+ ["E2",0x442],
+ ["E3",0x443],
+ ["E4",0x444],
+ ["E5",0x445],
+ ["E6",0x446],
+ ["E7",0x447],
+ ["E8",0x448],
+ ["E9",0x449],
+ ["EA",0x44A],
+ ["EB",0x44B],
+ ["EC",0x44C],
+ ["ED",0x44D],
+ ["EE",0x44E],
+ ["EF",0x44F],
+ ["F1",0x451],
+ ["F3",0x454],
+ ["F5",0x457],
+ ["F7",0x45E],
+ ["FC",0x2116],
+ ["F9",0x2219],
+ ["FB",0x221A],
+ ["C4",0x2500],
+ ["B3",0x2502],
+ ["DA",0x250C],
+ ["BF",0x2510],
+ ["C0",0x2514],
+ ["D9",0x2518],
+ ["C3",0x251C],
+ ["B4",0x2524],
+ ["C2",0x252C],
+ ["C1",0x2534],
+ ["C5",0x253C],
+ ["CD",0x2550],
+ ["BA",0x2551],
+ ["D5",0x2552],
+ ["D6",0x2553],
+ ["C9",0x2554],
+ ["B8",0x2555],
+ ["B7",0x2556],
+ ["BB",0x2557],
+ ["D4",0x2558],
+ ["D3",0x2559],
+ ["C8",0x255A],
+ ["BE",0x255B],
+ ["BD",0x255C],
+ ["BC",0x255D],
+ ["C6",0x255E],
+ ["C7",0x255F],
+ ["CC",0x2560],
+ ["B5",0x2561],
+ ["B6",0x2562],
+ ["B9",0x2563],
+ ["D1",0x2564],
+ ["D2",0x2565],
+ ["CB",0x2566],
+ ["CF",0x2567],
+ ["D0",0x2568],
+ ["CA",0x2569],
+ ["D8",0x256A],
+ ["D7",0x256B],
+ ["CE",0x256C],
+ ["DF",0x2580],
+ ["DC",0x2584],
+ ["DB",0x2588],
+ ["DD",0x258C],
+ ["DE",0x2590],
+ ["B0",0x2591],
+ ["B1",0x2592],
+ ["B2",0x2593],
+ ["FE",0x25A0],
+] \ No newline at end of file
diff --git a/enc/trans/ibm869-tbl.rb b/enc/trans/ibm869-tbl.rb
new file mode 100644
index 0000000000..437e41ad98
--- /dev/null
+++ b/enc/trans/ibm869-tbl.rb
@@ -0,0 +1,121 @@
+IBM869_TO_UCS_TBL = [
+ ["FF",0xA0],
+ ["9C",0xA3],
+ ["8A",0xA6],
+ ["F5",0xA7],
+ ["F9",0xA8],
+ ["97",0xA9],
+ ["AE",0xAB],
+ ["89",0xAC],
+ ["F0",0xAD],
+ ["F8",0xB0],
+ ["F1",0xB1],
+ ["99",0xB2],
+ ["9A",0xB3],
+ ["88",0xB7],
+ ["AF",0xBB],
+ ["AB",0xBD],
+ ["EF",0x384],
+ ["F7",0x385],
+ ["86",0x386],
+ ["8D",0x388],
+ ["8F",0x389],
+ ["90",0x38A],
+ ["92",0x38C],
+ ["95",0x38E],
+ ["98",0x38F],
+ ["A1",0x390],
+ ["A4",0x391],
+ ["A5",0x392],
+ ["A6",0x393],
+ ["A7",0x394],
+ ["A8",0x395],
+ ["A9",0x396],
+ ["AA",0x397],
+ ["AC",0x398],
+ ["AD",0x399],
+ ["B5",0x39A],
+ ["B6",0x39B],
+ ["B7",0x39C],
+ ["B8",0x39D],
+ ["BD",0x39E],
+ ["BE",0x39F],
+ ["C6",0x3A0],
+ ["C7",0x3A1],
+ ["CF",0x3A3],
+ ["D0",0x3A4],
+ ["D1",0x3A5],
+ ["D2",0x3A6],
+ ["D3",0x3A7],
+ ["D4",0x3A8],
+ ["D5",0x3A9],
+ ["91",0x3AA],
+ ["96",0x3AB],
+ ["9B",0x3AC],
+ ["9D",0x3AD],
+ ["9E",0x3AE],
+ ["9F",0x3AF],
+ ["FC",0x3B0],
+ ["D6",0x3B1],
+ ["D7",0x3B2],
+ ["D8",0x3B3],
+ ["DD",0x3B4],
+ ["DE",0x3B5],
+ ["E0",0x3B6],
+ ["E1",0x3B7],
+ ["E2",0x3B8],
+ ["E3",0x3B9],
+ ["E4",0x3BA],
+ ["E5",0x3BB],
+ ["E6",0x3BC],
+ ["E7",0x3BD],
+ ["E8",0x3BE],
+ ["E9",0x3BF],
+ ["EA",0x3C0],
+ ["EB",0x3C1],
+ ["ED",0x3C2],
+ ["EC",0x3C3],
+ ["EE",0x3C4],
+ ["F2",0x3C5],
+ ["F3",0x3C6],
+ ["F4",0x3C7],
+ ["F6",0x3C8],
+ ["FA",0x3C9],
+ ["A0",0x3CA],
+ ["FB",0x3CB],
+ ["A2",0x3CC],
+ ["A3",0x3CD],
+ ["FD",0x3CE],
+ ["8E",0x2015],
+ ["8B",0x2018],
+ ["8C",0x2019],
+ ["C4",0x2500],
+ ["B3",0x2502],
+ ["DA",0x250C],
+ ["BF",0x2510],
+ ["C0",0x2514],
+ ["D9",0x2518],
+ ["C3",0x251C],
+ ["B4",0x2524],
+ ["C2",0x252C],
+ ["C1",0x2534],
+ ["C5",0x253C],
+ ["CD",0x2550],
+ ["BA",0x2551],
+ ["C9",0x2554],
+ ["BB",0x2557],
+ ["C8",0x255A],
+ ["BC",0x255D],
+ ["CC",0x2560],
+ ["B9",0x2563],
+ ["CB",0x2566],
+ ["CA",0x2569],
+ ["CE",0x256C],
+ ["DF",0x2580],
+ ["DC",0x2584],
+ ["DB",0x2588],
+ ["B0",0x2591],
+ ["B1",0x2592],
+ ["B2",0x2593],
+ ["FE",0x25A0],
+] \ No newline at end of file
diff --git a/enc/trans/iso-8859-1-tbl.rb b/enc/trans/iso-8859-1-tbl.rb
new file mode 100644
index 0000000000..05397e6417
--- /dev/null
+++ b/enc/trans/iso-8859-1-tbl.rb
@@ -0,0 +1,98 @@
+ISO_8859_1_TO_UCS_TBL = [
+ ["A0",0xA0],
+ ["A1",0xA1],
+ ["A2",0xA2],
+ ["A3",0xA3],
+ ["A4",0xA4],
+ ["A5",0xA5],
+ ["A6",0xA6],
+ ["A7",0xA7],
+ ["A8",0xA8],
+ ["A9",0xA9],
+ ["AA",0xAA],
+ ["AB",0xAB],
+ ["AC",0xAC],
+ ["AD",0xAD],
+ ["AE",0xAE],
+ ["AF",0xAF],
+ ["B0",0xB0],
+ ["B1",0xB1],
+ ["B2",0xB2],
+ ["B3",0xB3],
+ ["B4",0xB4],
+ ["B5",0xB5],
+ ["B6",0xB6],
+ ["B7",0xB7],
+ ["B8",0xB8],
+ ["B9",0xB9],
+ ["BA",0xBA],
+ ["BB",0xBB],
+ ["BC",0xBC],
+ ["BD",0xBD],
+ ["BE",0xBE],
+ ["BF",0xBF],
+ ["C0",0xC0],
+ ["C1",0xC1],
+ ["C2",0xC2],
+ ["C3",0xC3],
+ ["C4",0xC4],
+ ["C5",0xC5],
+ ["C6",0xC6],
+ ["C7",0xC7],
+ ["C8",0xC8],
+ ["C9",0xC9],
+ ["CA",0xCA],
+ ["CB",0xCB],
+ ["CC",0xCC],
+ ["CD",0xCD],
+ ["CE",0xCE],
+ ["CF",0xCF],
+ ["D0",0xD0],
+ ["D1",0xD1],
+ ["D2",0xD2],
+ ["D3",0xD3],
+ ["D4",0xD4],
+ ["D5",0xD5],
+ ["D6",0xD6],
+ ["D7",0xD7],
+ ["D8",0xD8],
+ ["D9",0xD9],
+ ["DA",0xDA],
+ ["DB",0xDB],
+ ["DC",0xDC],
+ ["DD",0xDD],
+ ["DE",0xDE],
+ ["DF",0xDF],
+ ["E0",0xE0],
+ ["E1",0xE1],
+ ["E2",0xE2],
+ ["E3",0xE3],
+ ["E4",0xE4],
+ ["E5",0xE5],
+ ["E6",0xE6],
+ ["E7",0xE7],
+ ["E8",0xE8],
+ ["E9",0xE9],
+ ["EA",0xEA],
+ ["EB",0xEB],
+ ["EC",0xEC],
+ ["ED",0xED],
+ ["EE",0xEE],
+ ["EF",0xEF],
+ ["F0",0xF0],
+ ["F1",0xF1],
+ ["F2",0xF2],
+ ["F3",0xF3],
+ ["F4",0xF4],
+ ["F5",0xF5],
+ ["F6",0xF6],
+ ["F7",0xF7],
+ ["F8",0xF8],
+ ["F9",0xF9],
+ ["FA",0xFA],
+ ["FB",0xFB],
+ ["FC",0xFC],
+ ["FD",0xFD],
+ ["FE",0xFE],
+ ["FF",0xFF],
+]
diff --git a/enc/trans/iso2022.trans b/enc/trans/iso2022.trans
index f8a9c2c2e1..7dc2c19e37 100644
--- a/enc/trans/iso2022.trans
+++ b/enc/trans/iso2022.trans
@@ -70,8 +70,8 @@ fun_si_iso2022jp_decoder(void *statep, const unsigned char *s, size_t l)
return (VALUE)INVALID;
}
-static int
-fun_so_iso2022jp_decoder(void *statep, const unsigned char *s, size_t l, unsigned char* o)
+static ssize_t
+fun_so_iso2022jp_decoder(void *statep, const unsigned char *s, size_t l, unsigned char* o, size_t osize)
{
unsigned char *sp = statep;
if (s[0] == 0x1b) {
@@ -119,8 +119,8 @@ rb_iso2022jp_decoder = {
NULL, fun_si_iso2022jp_decoder, NULL, fun_so_iso2022jp_decoder
};
-static int
-fun_so_iso2022jp_encoder(void *statep, const unsigned char *s, size_t l, unsigned char *o)
+static ssize_t
+fun_so_iso2022jp_encoder(void *statep, const unsigned char *s, size_t l, unsigned char *o, size_t osize)
{
unsigned char *sp = statep;
unsigned char *output0 = o;
@@ -163,7 +163,7 @@ fun_so_iso2022jp_encoder(void *statep, const unsigned char *s, size_t l, unsigne
return o - output0;
}
-static int
+static ssize_t
iso2022jp_encoder_reset_sequence_size(void *statep)
{
unsigned char *sp = statep;
@@ -172,8 +172,8 @@ iso2022jp_encoder_reset_sequence_size(void *statep)
return 0;
}
-static int
-finish_iso2022jp_encoder(void *statep, unsigned char *o)
+static ssize_t
+finish_iso2022jp_encoder(void *statep, unsigned char *o, size_t osize)
{
unsigned char *sp = statep;
unsigned char *output0 = o;
@@ -203,8 +203,8 @@ rb_iso2022jp_encoder = {
iso2022jp_encoder_reset_sequence_size, finish_iso2022jp_encoder
};
-static int
-fun_so_stateless_iso2022jp_to_eucjp(void *statep, const unsigned char *s, size_t l, unsigned char *o)
+static ssize_t
+fun_so_stateless_iso2022jp_to_eucjp(void *statep, const unsigned char *s, size_t l, unsigned char *o, size_t osize)
{
o[0] = s[1];
o[1] = s[2];
@@ -223,8 +223,8 @@ rb_stateless_iso2022jp_to_eucjp = {
NULL, NULL, NULL, fun_so_stateless_iso2022jp_to_eucjp,
};
-static int
-fun_so_eucjp_to_stateless_iso2022jp(void *statep, const unsigned char *s, size_t l, unsigned char *o)
+static ssize_t
+fun_so_eucjp_to_stateless_iso2022jp(void *statep, const unsigned char *s, size_t l, unsigned char *o, size_t osize)
{
o[0] = EMACS_MULE_LEADING_CODE_JISX0208_1983;
o[1] = s[0];
diff --git a/enc/trans/japanese.trans b/enc/trans/japanese.trans
index 12321f587f..ce5d0bb70f 100644
--- a/enc/trans/japanese.trans
+++ b/enc/trans/japanese.trans
@@ -19,8 +19,8 @@
<%= transcode_generated_code %>
-static int
-fun_so_eucjp2sjis(void *statep, const unsigned char *s, size_t l, unsigned char *o)
+static ssize_t
+fun_so_eucjp2sjis(void *statep, const unsigned char *s, size_t l, unsigned char *o, size_t osize)
{
if (s[0] == 0x8e) {
o[0] = s[1];
@@ -40,8 +40,8 @@ fun_so_eucjp2sjis(void *statep, const unsigned char *s, size_t l, unsigned char
}
}
-static int
-fun_so_sjis2eucjp(void *statep, const unsigned char *s, size_t l, unsigned char *o)
+static ssize_t
+fun_so_sjis2eucjp(void *statep, const unsigned char *s, size_t l, unsigned char *o, size_t osize)
{
if (l == 1) {
o[0] = '\x8e';
diff --git a/enc/trans/maccroatian-tbl.rb b/enc/trans/maccroatian-tbl.rb
new file mode 100644
index 0000000000..359878ec1f
--- /dev/null
+++ b/enc/trans/maccroatian-tbl.rb
@@ -0,0 +1,129 @@
+MACCROATIAN_TO_UCS_TBL = [
+ ["CA",0xA0],
+ ["C1",0xA1],
+ ["A2",0xA2],
+ ["A3",0xA3],
+ ["DB",0xA4],
+ ["A4",0xA7],
+ ["AC",0xA8],
+ ["D9",0xA9],
+ ["BB",0xAA],
+ ["C7",0xAB],
+ ["C2",0xAC],
+ ["A8",0xAE],
+ ["F8",0xAF],
+ ["A1",0xB0],
+ ["B1",0xB1],
+ ["AB",0xB4],
+ ["B5",0xB5],
+ ["A6",0xB6],
+ ["E1",0xB7],
+ ["FC",0xB8],
+ ["BC",0xBA],
+ ["DF",0xBB],
+ ["C0",0xBF],
+ ["CB",0xC0],
+ ["E7",0xC1],
+ ["E5",0xC2],
+ ["CC",0xC3],
+ ["80",0xC4],
+ ["81",0xC5],
+ ["DE",0xC6],
+ ["82",0xC7],
+ ["E9",0xC8],
+ ["83",0xC9],
+ ["FD",0xCA],
+ ["FA",0xCB],
+ ["ED",0xCC],
+ ["EA",0xCD],
+ ["EB",0xCE],
+ ["EC",0xCF],
+ ["84",0xD1],
+ ["F1",0xD2],
+ ["EE",0xD3],
+ ["EF",0xD4],
+ ["CD",0xD5],
+ ["85",0xD6],
+ ["AF",0xD8],
+ ["F4",0xD9],
+ ["F2",0xDA],
+ ["F3",0xDB],
+ ["86",0xDC],
+ ["A7",0xDF],
+ ["88",0xE0],
+ ["87",0xE1],
+ ["89",0xE2],
+ ["8B",0xE3],
+ ["8A",0xE4],
+ ["8C",0xE5],
+ ["FE",0xE6],
+ ["8D",0xE7],
+ ["8F",0xE8],
+ ["8E",0xE9],
+ ["90",0xEA],
+ ["91",0xEB],
+ ["93",0xEC],
+ ["92",0xED],
+ ["94",0xEE],
+ ["95",0xEF],
+ ["96",0xF1],
+ ["98",0xF2],
+ ["97",0xF3],
+ ["99",0xF4],
+ ["9B",0xF5],
+ ["9A",0xF6],
+ ["D6",0xF7],
+ ["BF",0xF8],
+ ["9D",0xF9],
+ ["9C",0xFA],
+ ["9E",0xFB],
+ ["9F",0xFC],
+ ["C6",0x106],
+ ["E6",0x107],
+ ["C8",0x10C],
+ ["E8",0x10D],
+ ["D0",0x110],
+ ["F0",0x111],
+ ["F5",0x131],
+ ["CE",0x152],
+ ["CF",0x153],
+ ["A9",0x160],
+ ["B9",0x161],
+ ["AE",0x17D],
+ ["BE",0x17E],
+ ["C4",0x192],
+ ["F6",0x2C6],
+ ["FF",0x2C7],
+ ["FB",0x2DA],
+ ["F7",0x2DC],
+ ["F9",0x3C0],
+ ["E0",0x2013],
+ ["D1",0x2014],
+ ["D4",0x2018],
+ ["D5",0x2019],
+ ["E2",0x201A],
+ ["D2",0x201C],
+ ["D3",0x201D],
+ ["E3",0x201E],
+ ["A0",0x2020],
+ ["A5",0x2022],
+ ["C9",0x2026],
+ ["E4",0x2030],
+ ["DC",0x2039],
+ ["DD",0x203A],
+ ["DA",0x2044],
+ ["AA",0x2122],
+ ["BD",0x2126],
+ ["B6",0x2202],
+ ["B4",0x2206],
+ ["B8",0x220F],
+ ["B7",0x2211],
+ ["C3",0x221A],
+ ["B0",0x221E],
+ ["BA",0x222B],
+ ["C5",0x2248],
+ ["AD",0x2260],
+ ["B2",0x2264],
+ ["B3",0x2265],
+ ["D7",0x25CA],
+] \ No newline at end of file
diff --git a/enc/trans/maccyrillic-tbl.rb b/enc/trans/maccyrillic-tbl.rb
new file mode 100644
index 0000000000..378aa8c3bc
--- /dev/null
+++ b/enc/trans/maccyrillic-tbl.rb
@@ -0,0 +1,130 @@
+MACCYRILLIC_TO_UCS_TBL = [
+ ["CA",0xA0],
+ ["A2",0xA2],
+ ["A3",0xA3],
+ ["FF",0xA4],
+ ["A4",0xA7],
+ ["A9",0xA9],
+ ["C7",0xAB],
+ ["C2",0xAC],
+ ["A8",0xAE],
+ ["A1",0xB0],
+ ["B1",0xB1],
+ ["B5",0xB5],
+ ["A6",0xB6],
+ ["C8",0xBB],
+ ["D6",0xF7],
+ ["C4",0x192],
+ ["DD",0x401],
+ ["AB",0x402],
+ ["AE",0x403],
+ ["B8",0x404],
+ ["C1",0x405],
+ ["A7",0x406],
+ ["BA",0x407],
+ ["B7",0x408],
+ ["BC",0x409],
+ ["BE",0x40A],
+ ["CB",0x40B],
+ ["CD",0x40C],
+ ["D8",0x40E],
+ ["DA",0x40F],
+ ["80",0x410],
+ ["81",0x411],
+ ["82",0x412],
+ ["83",0x413],
+ ["84",0x414],
+ ["85",0x415],
+ ["86",0x416],
+ ["87",0x417],
+ ["88",0x418],
+ ["89",0x419],
+ ["8A",0x41A],
+ ["8B",0x41B],
+ ["8C",0x41C],
+ ["8D",0x41D],
+ ["8E",0x41E],
+ ["8F",0x41F],
+ ["90",0x420],
+ ["91",0x421],
+ ["92",0x422],
+ ["93",0x423],
+ ["94",0x424],
+ ["95",0x425],
+ ["96",0x426],
+ ["97",0x427],
+ ["98",0x428],
+ ["99",0x429],
+ ["9A",0x42A],
+ ["9B",0x42B],
+ ["9C",0x42C],
+ ["9D",0x42D],
+ ["9E",0x42E],
+ ["9F",0x42F],
+ ["E0",0x430],
+ ["E1",0x431],
+ ["E2",0x432],
+ ["E3",0x433],
+ ["E4",0x434],
+ ["E5",0x435],
+ ["E6",0x436],
+ ["E7",0x437],
+ ["E8",0x438],
+ ["E9",0x439],
+ ["EA",0x43A],
+ ["EB",0x43B],
+ ["EC",0x43C],
+ ["ED",0x43D],
+ ["EE",0x43E],
+ ["EF",0x43F],
+ ["F0",0x440],
+ ["F1",0x441],
+ ["F2",0x442],
+ ["F3",0x443],
+ ["F4",0x444],
+ ["F5",0x445],
+ ["F6",0x446],
+ ["F7",0x447],
+ ["F8",0x448],
+ ["F9",0x449],
+ ["FA",0x44A],
+ ["FB",0x44B],
+ ["FC",0x44C],
+ ["FD",0x44D],
+ ["FE",0x44E],
+ ["DF",0x44F],
+ ["DE",0x451],
+ ["AC",0x452],
+ ["AF",0x453],
+ ["B9",0x454],
+ ["CF",0x455],
+ ["B4",0x456],
+ ["BB",0x457],
+ ["C0",0x458],
+ ["BD",0x459],
+ ["BF",0x45A],
+ ["CC",0x45B],
+ ["CE",0x45C],
+ ["D9",0x45E],
+ ["DB",0x45F],
+ ["D0",0x2013],
+ ["D1",0x2014],
+ ["D4",0x2018],
+ ["D5",0x2019],
+ ["D2",0x201C],
+ ["D3",0x201D],
+ ["D7",0x201E],
+ ["A0",0x2020],
+ ["A5",0x2022],
+ ["C9",0x2026],
+ ["DC",0x2116],
+ ["AA",0x2122],
+ ["B6",0x2202],
+ ["C6",0x2206],
+ ["C3",0x221A],
+ ["B0",0x221E],
+ ["C5",0x2248],
+ ["AD",0x2260],
+ ["B2",0x2264],
+ ["B3",0x2265],
+] \ No newline at end of file
diff --git a/enc/trans/macgreek-tbl.rb b/enc/trans/macgreek-tbl.rb
new file mode 100644
index 0000000000..7f75fde6d2
--- /dev/null
+++ b/enc/trans/macgreek-tbl.rb
@@ -0,0 +1,129 @@
+MACGREEK_TO_UCS_TBL = [
+ ["CA",0xA0],
+ ["92",0xA3],
+ ["B4",0xA5],
+ ["9B",0xA6],
+ ["AC",0xA7],
+ ["8C",0xA8],
+ ["A9",0xA9],
+ ["C7",0xAB],
+ ["C2",0xAC],
+ ["9C",0xAD],
+ ["A8",0xAE],
+ ["AE",0xB0],
+ ["B1",0xB1],
+ ["82",0xB2],
+ ["84",0xB3],
+ ["81",0xB9],
+ ["C8",0xBB],
+ ["97",0xBD],
+ ["80",0xC4],
+ ["83",0xC9],
+ ["85",0xD6],
+ ["86",0xDC],
+ ["A7",0xDF],
+ ["88",0xE0],
+ ["89",0xE2],
+ ["8A",0xE4],
+ ["8D",0xE7],
+ ["8F",0xE8],
+ ["8E",0xE9],
+ ["90",0xEA],
+ ["91",0xEB],
+ ["94",0xEE],
+ ["95",0xEF],
+ ["99",0xF4],
+ ["9A",0xF6],
+ ["D6",0xF7],
+ ["9D",0xF9],
+ ["9E",0xFB],
+ ["9F",0xFC],
+ ["CF",0x153],
+ ["8B",0x384],
+ ["87",0x385],
+ ["CD",0x386],
+ ["AF",0x387],
+ ["CE",0x388],
+ ["D7",0x389],
+ ["D8",0x38A],
+ ["D9",0x38C],
+ ["DA",0x38E],
+ ["DF",0x38F],
+ ["FD",0x390],
+ ["B0",0x391],
+ ["B5",0x392],
+ ["A1",0x393],
+ ["A2",0x394],
+ ["B6",0x395],
+ ["B7",0x396],
+ ["B8",0x397],
+ ["A3",0x398],
+ ["B9",0x399],
+ ["BA",0x39A],
+ ["A4",0x39B],
+ ["BB",0x39C],
+ ["C1",0x39D],
+ ["A5",0x39E],
+ ["C3",0x39F],
+ ["A6",0x3A0],
+ ["C4",0x3A1],
+ ["AA",0x3A3],
+ ["C6",0x3A4],
+ ["CB",0x3A5],
+ ["BC",0x3A6],
+ ["CC",0x3A7],
+ ["BE",0x3A8],
+ ["BF",0x3A9],
+ ["AB",0x3AA],
+ ["BD",0x3AB],
+ ["C0",0x3AC],
+ ["DB",0x3AD],
+ ["DC",0x3AE],
+ ["DD",0x3AF],
+ ["FE",0x3B0],
+ ["E1",0x3B1],
+ ["E2",0x3B2],
+ ["E7",0x3B3],
+ ["E4",0x3B4],
+ ["E5",0x3B5],
+ ["FA",0x3B6],
+ ["E8",0x3B7],
+ ["F5",0x3B8],
+ ["E9",0x3B9],
+ ["EB",0x3BA],
+ ["EC",0x3BB],
+ ["ED",0x3BC],
+ ["EE",0x3BD],
+ ["EA",0x3BE],
+ ["EF",0x3BF],
+ ["F0",0x3C0],
+ ["F2",0x3C1],
+ ["F7",0x3C2],
+ ["F3",0x3C3],
+ ["F4",0x3C4],
+ ["F9",0x3C5],
+ ["E6",0x3C6],
+ ["F8",0x3C7],
+ ["E3",0x3C8],
+ ["F6",0x3C9],
+ ["FB",0x3CA],
+ ["FC",0x3CB],
+ ["DE",0x3CC],
+ ["E0",0x3CD],
+ ["F1",0x3CE],
+ ["D0",0x2013],
+ ["D1",0x2015],
+ ["D4",0x2018],
+ ["D5",0x2019],
+ ["D2",0x201C],
+ ["D3",0x201D],
+ ["A0",0x2020],
+ ["96",0x2022],
+ ["C9",0x2026],
+ ["98",0x2030],
+ ["93",0x2122],
+ ["C5",0x2248],
+ ["AD",0x2260],
+ ["B2",0x2264],
+ ["B3",0x2265],
+] \ No newline at end of file
diff --git a/enc/trans/maciceland-tbl.rb b/enc/trans/maciceland-tbl.rb
new file mode 100644
index 0000000000..818d992274
--- /dev/null
+++ b/enc/trans/maciceland-tbl.rb
@@ -0,0 +1,129 @@
+MACICELAND_TO_UCS_TBL = [
+ ["CA",0xA0],
+ ["C1",0xA1],
+ ["A2",0xA2],
+ ["A3",0xA3],
+ ["DB",0xA4],
+ ["B4",0xA5],
+ ["A4",0xA7],
+ ["AC",0xA8],
+ ["A9",0xA9],
+ ["BB",0xAA],
+ ["C7",0xAB],
+ ["C2",0xAC],
+ ["A8",0xAE],
+ ["F8",0xAF],
+ ["A1",0xB0],
+ ["B1",0xB1],
+ ["AB",0xB4],
+ ["B5",0xB5],
+ ["A6",0xB6],
+ ["E1",0xB7],
+ ["FC",0xB8],
+ ["BC",0xBA],
+ ["C8",0xBB],
+ ["C0",0xBF],
+ ["CB",0xC0],
+ ["E7",0xC1],
+ ["E5",0xC2],
+ ["CC",0xC3],
+ ["80",0xC4],
+ ["81",0xC5],
+ ["AE",0xC6],
+ ["82",0xC7],
+ ["E9",0xC8],
+ ["83",0xC9],
+ ["E6",0xCA],
+ ["E8",0xCB],
+ ["ED",0xCC],
+ ["EA",0xCD],
+ ["EB",0xCE],
+ ["EC",0xCF],
+ ["DC",0xD0],
+ ["84",0xD1],
+ ["F1",0xD2],
+ ["EE",0xD3],
+ ["EF",0xD4],
+ ["CD",0xD5],
+ ["85",0xD6],
+ ["AF",0xD8],
+ ["F4",0xD9],
+ ["F2",0xDA],
+ ["F3",0xDB],
+ ["86",0xDC],
+ ["A0",0xDD],
+ ["DE",0xDE],
+ ["A7",0xDF],
+ ["88",0xE0],
+ ["87",0xE1],
+ ["89",0xE2],
+ ["8B",0xE3],
+ ["8A",0xE4],
+ ["8C",0xE5],
+ ["BE",0xE6],
+ ["8D",0xE7],
+ ["8F",0xE8],
+ ["8E",0xE9],
+ ["90",0xEA],
+ ["91",0xEB],
+ ["93",0xEC],
+ ["92",0xED],
+ ["94",0xEE],
+ ["95",0xEF],
+ ["DD",0xF0],
+ ["96",0xF1],
+ ["98",0xF2],
+ ["97",0xF3],
+ ["99",0xF4],
+ ["9B",0xF5],
+ ["9A",0xF6],
+ ["D6",0xF7],
+ ["BF",0xF8],
+ ["9D",0xF9],
+ ["9C",0xFA],
+ ["9E",0xFB],
+ ["9F",0xFC],
+ ["E0",0xFD],
+ ["DF",0xFE],
+ ["D8",0xFF],
+ ["F5",0x131],
+ ["CE",0x152],
+ ["CF",0x153],
+ ["D9",0x178],
+ ["C4",0x192],
+ ["F6",0x2C6],
+ ["FF",0x2C7],
+ ["F9",0x2D8],
+ ["FA",0x2D9],
+ ["FB",0x2DA],
+ ["FE",0x2DB],
+ ["F7",0x2DC],
+ ["FD",0x2DD],
+ ["B9",0x3C0],
+ ["D0",0x2013],
+ ["D1",0x2014],
+ ["D4",0x2018],
+ ["D5",0x2019],
+ ["E2",0x201A],
+ ["D2",0x201C],
+ ["D3",0x201D],
+ ["E3",0x201E],
+ ["A5",0x2022],
+ ["C9",0x2026],
+ ["E4",0x2030],
+ ["DA",0x2044],
+ ["AA",0x2122],
+ ["BD",0x2126],
+ ["B6",0x2202],
+ ["C6",0x2206],
+ ["B8",0x220F],
+ ["B7",0x2211],
+ ["C3",0x221A],
+ ["B0",0x221E],
+ ["BA",0x222B],
+ ["C5",0x2248],
+ ["AD",0x2260],
+ ["B2",0x2264],
+ ["B3",0x2265],
+ ["D7",0x25CA],
+] \ No newline at end of file
diff --git a/enc/trans/macroman-tbl.rb b/enc/trans/macroman-tbl.rb
new file mode 100644
index 0000000000..8f74eea27f
--- /dev/null
+++ b/enc/trans/macroman-tbl.rb
@@ -0,0 +1,129 @@
+MACROMAN_TO_UCS_TBL = [
+ ["CA",0xA0],
+ ["C1",0xA1],
+ ["A2",0xA2],
+ ["A3",0xA3],
+ ["DB",0xA4],
+ ["B4",0xA5],
+ ["A4",0xA7],
+ ["AC",0xA8],
+ ["A9",0xA9],
+ ["BB",0xAA],
+ ["C7",0xAB],
+ ["C2",0xAC],
+ ["A8",0xAE],
+ ["F8",0xAF],
+ ["A1",0xB0],
+ ["B1",0xB1],
+ ["AB",0xB4],
+ ["B5",0xB5],
+ ["A6",0xB6],
+ ["E1",0xB7],
+ ["FC",0xB8],
+ ["BC",0xBA],
+ ["C8",0xBB],
+ ["C0",0xBF],
+ ["CB",0xC0],
+ ["E7",0xC1],
+ ["E5",0xC2],
+ ["CC",0xC3],
+ ["80",0xC4],
+ ["81",0xC5],
+ ["AE",0xC6],
+ ["82",0xC7],
+ ["E9",0xC8],
+ ["83",0xC9],
+ ["E6",0xCA],
+ ["E8",0xCB],
+ ["ED",0xCC],
+ ["EA",0xCD],
+ ["EB",0xCE],
+ ["EC",0xCF],
+ ["84",0xD1],
+ ["F1",0xD2],
+ ["EE",0xD3],
+ ["EF",0xD4],
+ ["CD",0xD5],
+ ["85",0xD6],
+ ["AF",0xD8],
+ ["F4",0xD9],
+ ["F2",0xDA],
+ ["F3",0xDB],
+ ["86",0xDC],
+ ["A7",0xDF],
+ ["88",0xE0],
+ ["87",0xE1],
+ ["89",0xE2],
+ ["8B",0xE3],
+ ["8A",0xE4],
+ ["8C",0xE5],
+ ["BE",0xE6],
+ ["8D",0xE7],
+ ["8F",0xE8],
+ ["8E",0xE9],
+ ["90",0xEA],
+ ["91",0xEB],
+ ["93",0xEC],
+ ["92",0xED],
+ ["94",0xEE],
+ ["95",0xEF],
+ ["96",0xF1],
+ ["98",0xF2],
+ ["97",0xF3],
+ ["99",0xF4],
+ ["9B",0xF5],
+ ["9A",0xF6],
+ ["D6",0xF7],
+ ["BF",0xF8],
+ ["9D",0xF9],
+ ["9C",0xFA],
+ ["9E",0xFB],
+ ["9F",0xFC],
+ ["D8",0xFF],
+ ["F5",0x131],
+ ["CE",0x152],
+ ["CF",0x153],
+ ["D9",0x178],
+ ["C4",0x192],
+ ["F6",0x2C6],
+ ["FF",0x2C7],
+ ["F9",0x2D8],
+ ["FA",0x2D9],
+ ["FB",0x2DA],
+ ["FE",0x2DB],
+ ["F7",0x2DC],
+ ["FD",0x2DD],
+ ["B9",0x3C0],
+ ["D0",0x2013],
+ ["D1",0x2014],
+ ["D4",0x2018],
+ ["D5",0x2019],
+ ["E2",0x201A],
+ ["D2",0x201C],
+ ["D3",0x201D],
+ ["E3",0x201E],
+ ["A0",0x2020],
+ ["E0",0x2021],
+ ["A5",0x2022],
+ ["C9",0x2026],
+ ["E4",0x2030],
+ ["DC",0x2039],
+ ["DD",0x203A],
+ ["DA",0x2044],
+ ["AA",0x2122],
+ ["BD",0x2126],
+ ["B6",0x2202],
+ ["C6",0x2206],
+ ["B8",0x220F],
+ ["B7",0x2211],
+ ["C3",0x221A],
+ ["B0",0x221E],
+ ["BA",0x222B],
+ ["C5",0x2248],
+ ["AD",0x2260],
+ ["B2",0x2264],
+ ["B3",0x2265],
+ ["D7",0x25CA],
+ ["DE",0xFB01],
+ ["DF",0xFB02],
+] \ No newline at end of file
diff --git a/enc/trans/macromania-tbl.rb b/enc/trans/macromania-tbl.rb
new file mode 100644
index 0000000000..ff95c5e957
--- /dev/null
+++ b/enc/trans/macromania-tbl.rb
@@ -0,0 +1,129 @@
+MACROMANIA_TO_UCS_TBL = [
+ ["CA",0xA0],
+ ["C1",0xA1],
+ ["A2",0xA2],
+ ["A3",0xA3],
+ ["DB",0xA4],
+ ["B4",0xA5],
+ ["A4",0xA7],
+ ["AC",0xA8],
+ ["A9",0xA9],
+ ["BB",0xAA],
+ ["C7",0xAB],
+ ["C2",0xAC],
+ ["A8",0xAE],
+ ["F8",0xAF],
+ ["A1",0xB0],
+ ["B1",0xB1],
+ ["AB",0xB4],
+ ["B5",0xB5],
+ ["A6",0xB6],
+ ["E1",0xB7],
+ ["FC",0xB8],
+ ["BC",0xBA],
+ ["C8",0xBB],
+ ["C0",0xBF],
+ ["CB",0xC0],
+ ["E7",0xC1],
+ ["E5",0xC2],
+ ["CC",0xC3],
+ ["80",0xC4],
+ ["81",0xC5],
+ ["82",0xC7],
+ ["E9",0xC8],
+ ["83",0xC9],
+ ["E6",0xCA],
+ ["E8",0xCB],
+ ["ED",0xCC],
+ ["EA",0xCD],
+ ["EB",0xCE],
+ ["EC",0xCF],
+ ["84",0xD1],
+ ["F1",0xD2],
+ ["EE",0xD3],
+ ["EF",0xD4],
+ ["CD",0xD5],
+ ["85",0xD6],
+ ["F4",0xD9],
+ ["F2",0xDA],
+ ["F3",0xDB],
+ ["86",0xDC],
+ ["A7",0xDF],
+ ["88",0xE0],
+ ["87",0xE1],
+ ["89",0xE2],
+ ["8B",0xE3],
+ ["8A",0xE4],
+ ["8C",0xE5],
+ ["8D",0xE7],
+ ["8F",0xE8],
+ ["8E",0xE9],
+ ["90",0xEA],
+ ["91",0xEB],
+ ["93",0xEC],
+ ["92",0xED],
+ ["94",0xEE],
+ ["95",0xEF],
+ ["96",0xF1],
+ ["98",0xF2],
+ ["97",0xF3],
+ ["99",0xF4],
+ ["9B",0xF5],
+ ["9A",0xF6],
+ ["D6",0xF7],
+ ["9D",0xF9],
+ ["9C",0xFA],
+ ["9E",0xFB],
+ ["9F",0xFC],
+ ["D8",0xFF],
+ ["AE",0x102],
+ ["BE",0x103],
+ ["F5",0x131],
+ ["CE",0x152],
+ ["CF",0x153],
+ ["AF",0x15E],
+ ["BF",0x15F],
+ ["DE",0x162],
+ ["DF",0x163],
+ ["D9",0x178],
+ ["C4",0x192],
+ ["F6",0x2C6],
+ ["FF",0x2C7],
+ ["F9",0x2D8],
+ ["FA",0x2D9],
+ ["FB",0x2DA],
+ ["FE",0x2DB],
+ ["F7",0x2DC],
+ ["FD",0x2DD],
+ ["B9",0x3C0],
+ ["D0",0x2013],
+ ["D1",0x2014],
+ ["D4",0x2018],
+ ["D5",0x2019],
+ ["E2",0x201A],
+ ["D2",0x201C],
+ ["D3",0x201D],
+ ["E3",0x201E],
+ ["A0",0x2020],
+ ["E0",0x2021],
+ ["A5",0x2022],
+ ["C9",0x2026],
+ ["E4",0x2030],
+ ["DC",0x2039],
+ ["DD",0x203A],
+ ["DA",0x2044],
+ ["AA",0x2122],
+ ["BD",0x2126],
+ ["B6",0x2202],
+ ["C6",0x2206],
+ ["B8",0x220F],
+ ["B7",0x2211],
+ ["C3",0x221A],
+ ["B0",0x221E],
+ ["BA",0x222B],
+ ["C5",0x2248],
+ ["AD",0x2260],
+ ["B2",0x2264],
+ ["B3",0x2265],
+ ["D7",0x25CA],
+] \ No newline at end of file
diff --git a/enc/trans/macturkish-tbl.rb b/enc/trans/macturkish-tbl.rb
new file mode 100644
index 0000000000..2358672ed6
--- /dev/null
+++ b/enc/trans/macturkish-tbl.rb
@@ -0,0 +1,128 @@
+MACTURKISH_TO_UCS_TBL = [
+ ["CA",0xA0],
+ ["C1",0xA1],
+ ["A2",0xA2],
+ ["A3",0xA3],
+ ["B4",0xA5],
+ ["A4",0xA7],
+ ["AC",0xA8],
+ ["A9",0xA9],
+ ["BB",0xAA],
+ ["C7",0xAB],
+ ["C2",0xAC],
+ ["A8",0xAE],
+ ["F8",0xAF],
+ ["A1",0xB0],
+ ["B1",0xB1],
+ ["AB",0xB4],
+ ["B5",0xB5],
+ ["A6",0xB6],
+ ["E1",0xB7],
+ ["FC",0xB8],
+ ["BC",0xBA],
+ ["C8",0xBB],
+ ["C0",0xBF],
+ ["CB",0xC0],
+ ["E7",0xC1],
+ ["E5",0xC2],
+ ["CC",0xC3],
+ ["80",0xC4],
+ ["81",0xC5],
+ ["AE",0xC6],
+ ["82",0xC7],
+ ["E9",0xC8],
+ ["83",0xC9],
+ ["E6",0xCA],
+ ["E8",0xCB],
+ ["ED",0xCC],
+ ["EA",0xCD],
+ ["EB",0xCE],
+ ["EC",0xCF],
+ ["84",0xD1],
+ ["F1",0xD2],
+ ["EE",0xD3],
+ ["EF",0xD4],
+ ["CD",0xD5],
+ ["85",0xD6],
+ ["AF",0xD8],
+ ["F4",0xD9],
+ ["F2",0xDA],
+ ["F3",0xDB],
+ ["86",0xDC],
+ ["A7",0xDF],
+ ["88",0xE0],
+ ["87",0xE1],
+ ["89",0xE2],
+ ["8B",0xE3],
+ ["8A",0xE4],
+ ["8C",0xE5],
+ ["BE",0xE6],
+ ["8D",0xE7],
+ ["8F",0xE8],
+ ["8E",0xE9],
+ ["90",0xEA],
+ ["91",0xEB],
+ ["93",0xEC],
+ ["92",0xED],
+ ["94",0xEE],
+ ["95",0xEF],
+ ["96",0xF1],
+ ["98",0xF2],
+ ["97",0xF3],
+ ["99",0xF4],
+ ["9B",0xF5],
+ ["9A",0xF6],
+ ["D6",0xF7],
+ ["BF",0xF8],
+ ["9D",0xF9],
+ ["9C",0xFA],
+ ["9E",0xFB],
+ ["9F",0xFC],
+ ["D8",0xFF],
+ ["DA",0x11E],
+ ["DB",0x11F],
+ ["DC",0x130],
+ ["DD",0x131],
+ ["CE",0x152],
+ ["CF",0x153],
+ ["DE",0x15E],
+ ["DF",0x15F],
+ ["D9",0x178],
+ ["C4",0x192],
+ ["F6",0x2C6],
+ ["FF",0x2C7],
+ ["F9",0x2D8],
+ ["FA",0x2D9],
+ ["FB",0x2DA],
+ ["FE",0x2DB],
+ ["F7",0x2DC],
+ ["FD",0x2DD],
+ ["B9",0x3C0],
+ ["D0",0x2013],
+ ["D1",0x2014],
+ ["D4",0x2018],
+ ["D5",0x2019],
+ ["E2",0x201A],
+ ["D2",0x201C],
+ ["D3",0x201D],
+ ["E3",0x201E],
+ ["A0",0x2020],
+ ["E0",0x2021],
+ ["A5",0x2022],
+ ["C9",0x2026],
+ ["E4",0x2030],
+ ["AA",0x2122],
+ ["BD",0x2126],
+ ["B6",0x2202],
+ ["C6",0x2206],
+ ["B8",0x220F],
+ ["B7",0x2211],
+ ["C3",0x221A],
+ ["B0",0x221E],
+ ["BA",0x222B],
+ ["C5",0x2248],
+ ["AD",0x2260],
+ ["B2",0x2264],
+ ["B3",0x2265],
+ ["D7",0x25CA],
+] \ No newline at end of file
diff --git a/enc/trans/macukraine-tbl.rb b/enc/trans/macukraine-tbl.rb
new file mode 100644
index 0000000000..6941af654d
--- /dev/null
+++ b/enc/trans/macukraine-tbl.rb
@@ -0,0 +1,130 @@
+MACUKRAINE_TO_UCS_TBL = [
+ ["CA",0xA0],
+ ["A3",0xA3],
+ ["FF",0xA4],
+ ["A4",0xA7],
+ ["A9",0xA9],
+ ["C7",0xAB],
+ ["C2",0xAC],
+ ["A8",0xAE],
+ ["A1",0xB0],
+ ["B1",0xB1],
+ ["B5",0xB5],
+ ["A6",0xB6],
+ ["C8",0xBB],
+ ["D6",0xF7],
+ ["C4",0x192],
+ ["DD",0x401],
+ ["AB",0x402],
+ ["AE",0x403],
+ ["B8",0x404],
+ ["C1",0x405],
+ ["A7",0x406],
+ ["BA",0x407],
+ ["B7",0x408],
+ ["BC",0x409],
+ ["BE",0x40A],
+ ["CB",0x40B],
+ ["CD",0x40C],
+ ["D8",0x40E],
+ ["DA",0x40F],
+ ["80",0x410],
+ ["81",0x411],
+ ["82",0x412],
+ ["83",0x413],
+ ["84",0x414],
+ ["85",0x415],
+ ["86",0x416],
+ ["87",0x417],
+ ["88",0x418],
+ ["89",0x419],
+ ["8A",0x41A],
+ ["8B",0x41B],
+ ["8C",0x41C],
+ ["8D",0x41D],
+ ["8E",0x41E],
+ ["8F",0x41F],
+ ["90",0x420],
+ ["91",0x421],
+ ["92",0x422],
+ ["93",0x423],
+ ["94",0x424],
+ ["95",0x425],
+ ["96",0x426],
+ ["97",0x427],
+ ["98",0x428],
+ ["99",0x429],
+ ["9A",0x42A],
+ ["9B",0x42B],
+ ["9C",0x42C],
+ ["9D",0x42D],
+ ["9E",0x42E],
+ ["9F",0x42F],
+ ["E0",0x430],
+ ["E1",0x431],
+ ["E2",0x432],
+ ["E3",0x433],
+ ["E4",0x434],
+ ["E5",0x435],
+ ["E6",0x436],
+ ["E7",0x437],
+ ["E8",0x438],
+ ["E9",0x439],
+ ["EA",0x43A],
+ ["EB",0x43B],
+ ["EC",0x43C],
+ ["ED",0x43D],
+ ["EE",0x43E],
+ ["EF",0x43F],
+ ["F0",0x440],
+ ["F1",0x441],
+ ["F2",0x442],
+ ["F3",0x443],
+ ["F4",0x444],
+ ["F5",0x445],
+ ["F6",0x446],
+ ["F7",0x447],
+ ["F8",0x448],
+ ["F9",0x449],
+ ["FA",0x44A],
+ ["FB",0x44B],
+ ["FC",0x44C],
+ ["FD",0x44D],
+ ["FE",0x44E],
+ ["DF",0x44F],
+ ["DE",0x451],
+ ["AC",0x452],
+ ["AF",0x453],
+ ["B9",0x454],
+ ["CF",0x455],
+ ["B4",0x456],
+ ["BB",0x457],
+ ["C0",0x458],
+ ["BD",0x459],
+ ["BF",0x45A],
+ ["CC",0x45B],
+ ["CE",0x45C],
+ ["D9",0x45E],
+ ["DB",0x45F],
+ ["A2",0x490],
+ ["B6",0x491],
+ ["D0",0x2013],
+ ["D1",0x2014],
+ ["D4",0x2018],
+ ["D5",0x2019],
+ ["D2",0x201C],
+ ["D3",0x201D],
+ ["D7",0x201E],
+ ["A0",0x2020],
+ ["A5",0x2022],
+ ["C9",0x2026],
+ ["DC",0x2116],
+ ["AA",0x2122],
+ ["C6",0x2206],
+ ["C3",0x221A],
+ ["B0",0x221E],
+ ["C5",0x2248],
+ ["AD",0x2260],
+ ["B2",0x2264],
+ ["B3",0x2265],
+] \ No newline at end of file
diff --git a/enc/trans/newline.trans b/enc/trans/newline.trans
index db49a9f003..d62034aa49 100644
--- a/enc/trans/newline.trans
+++ b/enc/trans/newline.trans
@@ -40,8 +40,8 @@ universal_newline_init(void *statep)
return 0;
}
-static int
-fun_so_universal_newline(void *statep, const unsigned char *s, size_t l, unsigned char *o)
+static ssize_t
+fun_so_universal_newline(void *statep, const unsigned char *s, size_t l, unsigned char *o, size_t osize)
{
unsigned char *sp = statep;
int len;
@@ -75,8 +75,8 @@ fun_so_universal_newline(void *statep, const unsigned char *s, size_t l, unsigne
return len;
}
-static int
-universal_newline_finish(void *statep, unsigned char *o)
+static ssize_t
+universal_newline_finish(void *statep, unsigned char *o, size_t osize)
{
unsigned char *sp = statep;
if (STATE == JUST_AFTER_CR)
@@ -87,7 +87,7 @@ universal_newline_finish(void *statep, unsigned char *o)
static const rb_transcoder
rb_universal_newline = {
- "universal_newline", "", universal_newline,
+ "", "universal_newline", universal_newline,
TRANSCODE_TABLE_INFO,
1, /* input_unit_length */
1, /* max_input */
@@ -129,4 +129,3 @@ Init_newline(void)
rb_register_transcoder(&rb_crlf_newline);
rb_register_transcoder(&rb_cr_newline);
}
-
diff --git a/enc/trans/single_byte.trans b/enc/trans/single_byte.trans
index 57254bf3d5..80bd3f9ae2 100644
--- a/enc/trans/single_byte.trans
+++ b/enc/trans/single_byte.trans
@@ -3,31 +3,26 @@
<%
us_ascii_map = [["{00-7f}", :nomap]]
- ISO_8859_1_TO_UCS_TBL = (0x80..0xff).map {|c| ["%02X" % c, c] }
- CONTROL1_TO_UCS_TBL = (0x80..0x9f).map {|c| ["%02X" % c, c] }
-
- require 'iso-8859-2-tbl'
- require 'iso-8859-3-tbl'
- require 'iso-8859-4-tbl'
- require 'iso-8859-5-tbl'
- require 'iso-8859-6-tbl'
- require 'iso-8859-7-tbl'
- require 'iso-8859-8-tbl'
- require 'iso-8859-9-tbl'
- require 'iso-8859-10-tbl'
- require 'iso-8859-11-tbl'
- require 'iso-8859-13-tbl'
- require 'iso-8859-14-tbl'
- require 'iso-8859-15-tbl'
-
transcode_tblgen "US-ASCII", "UTF-8", us_ascii_map
transcode_tblgen "UTF-8", "US-ASCII", us_ascii_map
transcode_tblgen "ASCII-8BIT", "UTF-8", us_ascii_map
transcode_tblgen "UTF-8", "ASCII-8BIT", us_ascii_map
- def transcode_tblgen_iso8859(name, tbl_to_ucs)
- tbl_to_ucs = CONTROL1_TO_UCS_TBL + tbl_to_ucs
- name_ident = name.tr('-','_')
+ CONTROL1_TO_UCS_TBL = (0x80..0x9f).map {|c| ["%02X" % c, c] }
+
+ # Generate transcoding tables for single byte encoding from
+ # encoding name using table file.
+ #
+ # Conventions:
+ # name: encoding name as string, UPPER case, hyphens (e.g. 'ISO-8859-3')
+ # file name: lower case, hyphens, -tbl.rb suffix (e.g. iso-8859-3-tbl.rb)
+ # variable name: UPPER case, underscores, _TO_UCS_TBL suffix (e.g. ISO_8859_3_TO_UCS_TBL)
+ # If the name starts with "ISO-8859", the C1 control code area is added automatically.
+ def transcode_tblgen_singlebyte (name)
+ 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])
code << "\n"
@@ -35,20 +30,49 @@
code
end
- transcode_tblgen_iso8859("ISO-8859-1", ISO_8859_1_TO_UCS_TBL)
- transcode_tblgen_iso8859("ISO-8859-2", ISO_8859_2_TO_UCS_TBL)
- transcode_tblgen_iso8859("ISO-8859-3", ISO_8859_3_TO_UCS_TBL)
- transcode_tblgen_iso8859("ISO-8859-4", ISO_8859_4_TO_UCS_TBL)
- transcode_tblgen_iso8859("ISO-8859-5", ISO_8859_5_TO_UCS_TBL)
- transcode_tblgen_iso8859("ISO-8859-6", ISO_8859_6_TO_UCS_TBL)
- transcode_tblgen_iso8859("ISO-8859-7", ISO_8859_7_TO_UCS_TBL)
- transcode_tblgen_iso8859("ISO-8859-8", ISO_8859_8_TO_UCS_TBL)
- transcode_tblgen_iso8859("ISO-8859-9", ISO_8859_9_TO_UCS_TBL)
- transcode_tblgen_iso8859("ISO-8859-10", ISO_8859_10_TO_UCS_TBL)
- transcode_tblgen_iso8859("ISO-8859-11", ISO_8859_11_TO_UCS_TBL)
- transcode_tblgen_iso8859("ISO-8859-13", ISO_8859_13_TO_UCS_TBL)
- transcode_tblgen_iso8859("ISO-8859-14", ISO_8859_14_TO_UCS_TBL)
- transcode_tblgen_iso8859("ISO-8859-15", ISO_8859_15_TO_UCS_TBL)
+ transcode_tblgen_singlebyte "ISO-8859-1"
+ transcode_tblgen_singlebyte "ISO-8859-2"
+ transcode_tblgen_singlebyte "ISO-8859-3"
+ transcode_tblgen_singlebyte "ISO-8859-4"
+ transcode_tblgen_singlebyte "ISO-8859-5"
+ transcode_tblgen_singlebyte "ISO-8859-6"
+ transcode_tblgen_singlebyte "ISO-8859-7"
+ transcode_tblgen_singlebyte "ISO-8859-8"
+ transcode_tblgen_singlebyte "ISO-8859-9"
+ transcode_tblgen_singlebyte "ISO-8859-10"
+ transcode_tblgen_singlebyte "ISO-8859-11"
+ transcode_tblgen_singlebyte "ISO-8859-13"
+ transcode_tblgen_singlebyte "ISO-8859-14"
+ transcode_tblgen_singlebyte "ISO-8859-15"
+ transcode_tblgen_singlebyte "WINDOWS-874"
+ transcode_tblgen_singlebyte "WINDOWS-1250"
+ transcode_tblgen_singlebyte "WINDOWS-1251"
+ transcode_tblgen_singlebyte "WINDOWS-1252"
+ transcode_tblgen_singlebyte "WINDOWS-1253"
+ transcode_tblgen_singlebyte "WINDOWS-1254"
+ transcode_tblgen_singlebyte "WINDOWS-1255"
+ transcode_tblgen_singlebyte "WINDOWS-1256"
+ transcode_tblgen_singlebyte "WINDOWS-1257"
+ transcode_tblgen_singlebyte "IBM437"
+ transcode_tblgen_singlebyte "IBM775"
+ transcode_tblgen_singlebyte "IBM852"
+ transcode_tblgen_singlebyte "IBM855"
+ transcode_tblgen_singlebyte "IBM857"
+ transcode_tblgen_singlebyte "IBM860"
+ transcode_tblgen_singlebyte "IBM861"
+ transcode_tblgen_singlebyte "IBM862"
+ transcode_tblgen_singlebyte "IBM863"
+ transcode_tblgen_singlebyte "IBM865"
+ transcode_tblgen_singlebyte "IBM866"
+ transcode_tblgen_singlebyte "IBM869"
+ transcode_tblgen_singlebyte "MACCROATIAN"
+ transcode_tblgen_singlebyte "MACCYRILLIC"
+ transcode_tblgen_singlebyte "MACGREEK"
+ transcode_tblgen_singlebyte "MACICELAND"
+ transcode_tblgen_singlebyte "MACROMAN"
+ transcode_tblgen_singlebyte "MACROMANIA"
+ transcode_tblgen_singlebyte "MACTURKISH"
+ transcode_tblgen_singlebyte "MACUKRAINE"
%>
<%= transcode_generated_code %>
diff --git a/enc/trans/utf_16_32.trans b/enc/trans/utf_16_32.trans
index 88648266c6..1bf6ed0975 100644
--- a/enc/trans/utf_16_32.trans
+++ b/enc/trans/utf_16_32.trans
@@ -37,8 +37,8 @@
<%= transcode_generated_code %>
-static int
-fun_so_from_utf_16be(void *statep, const unsigned char *s, size_t l, unsigned char *o)
+static ssize_t
+fun_so_from_utf_16be(void *statep, const unsigned char *s, size_t l, unsigned char *o, size_t osize)
{
if (!s[0] && s[1]<0x80) {
o[0] = s[1];
@@ -65,8 +65,8 @@ fun_so_from_utf_16be(void *statep, const unsigned char *s, size_t l, unsigned ch
}
}
-static int
-fun_so_to_utf_16be(void *statep, const unsigned char *s, size_t l, unsigned char *o)
+static ssize_t
+fun_so_to_utf_16be(void *statep, const unsigned char *s, size_t l, unsigned char *o, size_t osize)
{
if (!(s[0]&0x80)) {
o[0] = 0x00;
@@ -93,8 +93,8 @@ fun_so_to_utf_16be(void *statep, const unsigned char *s, size_t l, unsigned char
}
}
-static int
-fun_so_from_utf_16le(void *statep, const unsigned char *s, size_t l, unsigned char *o)
+static ssize_t
+fun_so_from_utf_16le(void *statep, const unsigned char *s, size_t l, unsigned char *o, size_t osize)
{
if (!s[1] && s[0]<0x80) {
o[0] = s[0];
@@ -121,8 +121,8 @@ fun_so_from_utf_16le(void *statep, const unsigned char *s, size_t l, unsigned ch
}
}
-static int
-fun_so_to_utf_16le(void *statep, const unsigned char *s, size_t l, unsigned char *o)
+static ssize_t
+fun_so_to_utf_16le(void *statep, const unsigned char *s, size_t l, unsigned char *o, size_t osize)
{
if (!(s[0]&0x80)) {
o[1] = 0x00;
@@ -149,8 +149,8 @@ fun_so_to_utf_16le(void *statep, const unsigned char *s, size_t l, unsigned char
}
}
-static int
-fun_so_from_utf_32be(void *statep, const unsigned char *s, size_t l, unsigned char *o)
+static ssize_t
+fun_so_from_utf_32be(void *statep, const unsigned char *s, size_t l, unsigned char *o, size_t osize)
{
if (!s[1]) {
if (s[2]==0 && s[3]<0x80) {
@@ -178,8 +178,8 @@ fun_so_from_utf_32be(void *statep, const unsigned char *s, size_t l, unsigned ch
}
}
-static int
-fun_so_to_utf_32be(void *statep, const unsigned char *s, size_t l, unsigned char *o)
+static ssize_t
+fun_so_to_utf_32be(void *statep, const unsigned char *s, size_t l, unsigned char *o, size_t osize)
{
o[0] = 0;
if (!(s[0]&0x80)) {
@@ -204,8 +204,8 @@ fun_so_to_utf_32be(void *statep, const unsigned char *s, size_t l, unsigned char
return 4;
}
-static int
-fun_so_from_utf_32le(void *statep, const unsigned char *s, size_t l, unsigned char *o)
+static ssize_t
+fun_so_from_utf_32le(void *statep, const unsigned char *s, size_t l, unsigned char *o, size_t osize)
{
if (!s[2]) {
if (s[1]==0 && s[0]<0x80) {
@@ -233,8 +233,8 @@ fun_so_from_utf_32le(void *statep, const unsigned char *s, size_t l, unsigned ch
}
}
-static int
-fun_so_to_utf_32le(void *statep, const unsigned char *s, size_t l, unsigned char *o)
+static ssize_t
+fun_so_to_utf_32le(void *statep, const unsigned char *s, size_t l, unsigned char *o, size_t osize)
{
o[3] = 0;
if (!(s[0]&0x80)) {
diff --git a/enc/trans/windows-1250-tbl.rb b/enc/trans/windows-1250-tbl.rb
new file mode 100644
index 0000000000..52063e17b1
--- /dev/null
+++ b/enc/trans/windows-1250-tbl.rb
@@ -0,0 +1,125 @@
+WINDOWS_1250_TO_UCS_TBL = [
+ ["A0",0xA0],
+ ["A4",0xA4],
+ ["A6",0xA6],
+ ["A7",0xA7],
+ ["A8",0xA8],
+ ["A9",0xA9],
+ ["AB",0xAB],
+ ["AC",0xAC],
+ ["AD",0xAD],
+ ["AE",0xAE],
+ ["B0",0xB0],
+ ["B1",0xB1],
+ ["B4",0xB4],
+ ["B5",0xB5],
+ ["B6",0xB6],
+ ["B7",0xB7],
+ ["B8",0xB8],
+ ["BB",0xBB],
+ ["C1",0xC1],
+ ["C2",0xC2],
+ ["C4",0xC4],
+ ["C7",0xC7],
+ ["C9",0xC9],
+ ["CB",0xCB],
+ ["CD",0xCD],
+ ["CE",0xCE],
+ ["D3",0xD3],
+ ["D4",0xD4],
+ ["D6",0xD6],
+ ["D7",0xD7],
+ ["DA",0xDA],
+ ["DC",0xDC],
+ ["DD",0xDD],
+ ["DF",0xDF],
+ ["E1",0xE1],
+ ["E2",0xE2],
+ ["E4",0xE4],
+ ["E7",0xE7],
+ ["E9",0xE9],
+ ["EB",0xEB],
+ ["ED",0xED],
+ ["EE",0xEE],
+ ["F3",0xF3],
+ ["F4",0xF4],
+ ["F6",0xF6],
+ ["F7",0xF7],
+ ["FA",0xFA],
+ ["FC",0xFC],
+ ["FD",0xFD],
+ ["C3",0x102],
+ ["E3",0x103],
+ ["A5",0x104],
+ ["B9",0x105],
+ ["C6",0x106],
+ ["E6",0x107],
+ ["C8",0x10C],
+ ["E8",0x10D],
+ ["CF",0x10E],
+ ["EF",0x10F],
+ ["D0",0x110],
+ ["F0",0x111],
+ ["CA",0x118],
+ ["EA",0x119],
+ ["CC",0x11A],
+ ["EC",0x11B],
+ ["C5",0x139],
+ ["E5",0x13A],
+ ["BC",0x13D],
+ ["BE",0x13E],
+ ["A3",0x141],
+ ["B3",0x142],
+ ["D1",0x143],
+ ["F1",0x144],
+ ["D2",0x147],
+ ["F2",0x148],
+ ["D5",0x150],
+ ["F5",0x151],
+ ["C0",0x154],
+ ["E0",0x155],
+ ["D8",0x158],
+ ["F8",0x159],
+ ["8C",0x15A],
+ ["9C",0x15B],
+ ["AA",0x15E],
+ ["BA",0x15F],
+ ["8A",0x160],
+ ["9A",0x161],
+ ["DE",0x162],
+ ["FE",0x163],
+ ["8D",0x164],
+ ["9D",0x165],
+ ["D9",0x16E],
+ ["F9",0x16F],
+ ["DB",0x170],
+ ["FB",0x171],
+ ["8F",0x179],
+ ["9F",0x17A],
+ ["AF",0x17B],
+ ["BF",0x17C],
+ ["8E",0x17D],
+ ["9E",0x17E],
+ ["A1",0x2C7],
+ ["A2",0x2D8],
+ ["FF",0x2D9],
+ ["B2",0x2DB],
+ ["BD",0x2DD],
+ ["96",0x2013],
+ ["97",0x2014],
+ ["91",0x2018],
+ ["92",0x2019],
+ ["82",0x201A],
+ ["93",0x201C],
+ ["94",0x201D],
+ ["84",0x201E],
+ ["86",0x2020],
+ ["87",0x2021],
+ ["95",0x2022],
+ ["85",0x2026],
+ ["89",0x2030],
+ ["8B",0x2039],
+ ["9B",0x203A],
+ ["80",0x20AC],
+ ["99",0x2122],
+] \ No newline at end of file
diff --git a/enc/trans/windows-1251-tbl.rb b/enc/trans/windows-1251-tbl.rb
new file mode 100644
index 0000000000..870c718b72
--- /dev/null
+++ b/enc/trans/windows-1251-tbl.rb
@@ -0,0 +1,129 @@
+WINDOWS_1251_TO_UCS_TBL = [
+ ["A0",0xA0],
+ ["A4",0xA4],
+ ["A6",0xA6],
+ ["A7",0xA7],
+ ["A9",0xA9],
+ ["AB",0xAB],
+ ["AC",0xAC],
+ ["AD",0xAD],
+ ["AE",0xAE],
+ ["B0",0xB0],
+ ["B1",0xB1],
+ ["B5",0xB5],
+ ["B6",0xB6],
+ ["B7",0xB7],
+ ["BB",0xBB],
+ ["A8",0x401],
+ ["80",0x402],
+ ["81",0x403],
+ ["AA",0x404],
+ ["BD",0x405],
+ ["B2",0x406],
+ ["AF",0x407],
+ ["A3",0x408],
+ ["8A",0x409],
+ ["8C",0x40A],
+ ["8E",0x40B],
+ ["8D",0x40C],
+ ["A1",0x40E],
+ ["8F",0x40F],
+ ["C0",0x410],
+ ["C1",0x411],
+ ["C2",0x412],
+ ["C3",0x413],
+ ["C4",0x414],
+ ["C5",0x415],
+ ["C6",0x416],
+ ["C7",0x417],
+ ["C8",0x418],
+ ["C9",0x419],
+ ["CA",0x41A],
+ ["CB",0x41B],
+ ["CC",0x41C],
+ ["CD",0x41D],
+ ["CE",0x41E],
+ ["CF",0x41F],
+ ["D0",0x420],
+ ["D1",0x421],
+ ["D2",0x422],
+ ["D3",0x423],
+ ["D4",0x424],
+ ["D5",0x425],
+ ["D6",0x426],
+ ["D7",0x427],
+ ["D8",0x428],
+ ["D9",0x429],
+ ["DA",0x42A],
+ ["DB",0x42B],
+ ["DC",0x42C],
+ ["DD",0x42D],
+ ["DE",0x42E],
+ ["DF",0x42F],
+ ["E0",0x430],
+ ["E1",0x431],
+ ["E2",0x432],
+ ["E3",0x433],
+ ["E4",0x434],
+ ["E5",0x435],
+ ["E6",0x436],
+ ["E7",0x437],
+ ["E8",0x438],
+ ["E9",0x439],
+ ["EA",0x43A],
+ ["EB",0x43B],
+ ["EC",0x43C],
+ ["ED",0x43D],
+ ["EE",0x43E],
+ ["EF",0x43F],
+ ["F0",0x440],
+ ["F1",0x441],
+ ["F2",0x442],
+ ["F3",0x443],
+ ["F4",0x444],
+ ["F5",0x445],
+ ["F6",0x446],
+ ["F7",0x447],
+ ["F8",0x448],
+ ["F9",0x449],
+ ["FA",0x44A],
+ ["FB",0x44B],
+ ["FC",0x44C],
+ ["FD",0x44D],
+ ["FE",0x44E],
+ ["FF",0x44F],
+ ["B8",0x451],
+ ["90",0x452],
+ ["83",0x453],
+ ["BA",0x454],
+ ["BE",0x455],
+ ["B3",0x456],
+ ["BF",0x457],
+ ["BC",0x458],
+ ["9A",0x459],
+ ["9C",0x45A],
+ ["9E",0x45B],
+ ["9D",0x45C],
+ ["A2",0x45E],
+ ["9F",0x45F],
+ ["A5",0x490],
+ ["B4",0x491],
+ ["96",0x2013],
+ ["97",0x2014],
+ ["91",0x2018],
+ ["92",0x2019],
+ ["82",0x201A],
+ ["93",0x201C],
+ ["94",0x201D],
+ ["84",0x201E],
+ ["86",0x2020],
+ ["87",0x2021],
+ ["95",0x2022],
+ ["85",0x2026],
+ ["89",0x2030],
+ ["8B",0x2039],
+ ["9B",0x203A],
+ ["88",0x20AC],
+ ["B9",0x2116],
+ ["99",0x2122],
+] \ No newline at end of file
diff --git a/enc/trans/windows-1252-tbl.rb b/enc/trans/windows-1252-tbl.rb
new file mode 100644
index 0000000000..cefc72dff2
--- /dev/null
+++ b/enc/trans/windows-1252-tbl.rb
@@ -0,0 +1,125 @@
+WINDOWS_1252_TO_UCS_TBL = [
+ ["A0",0xA0],
+ ["A1",0xA1],
+ ["A2",0xA2],
+ ["A3",0xA3],
+ ["A4",0xA4],
+ ["A5",0xA5],
+ ["A6",0xA6],
+ ["A7",0xA7],
+ ["A8",0xA8],
+ ["A9",0xA9],
+ ["AA",0xAA],
+ ["AB",0xAB],
+ ["AC",0xAC],
+ ["AD",0xAD],
+ ["AE",0xAE],
+ ["AF",0xAF],
+ ["B0",0xB0],
+ ["B1",0xB1],
+ ["B2",0xB2],
+ ["B3",0xB3],
+ ["B4",0xB4],
+ ["B5",0xB5],
+ ["B6",0xB6],
+ ["B7",0xB7],
+ ["B8",0xB8],
+ ["B9",0xB9],
+ ["BA",0xBA],
+ ["BB",0xBB],
+ ["BC",0xBC],
+ ["BD",0xBD],
+ ["BE",0xBE],
+ ["BF",0xBF],
+ ["C0",0xC0],
+ ["C1",0xC1],
+ ["C2",0xC2],
+ ["C3",0xC3],
+ ["C4",0xC4],
+ ["C5",0xC5],
+ ["C6",0xC6],
+ ["C7",0xC7],
+ ["C8",0xC8],
+ ["C9",0xC9],
+ ["CA",0xCA],
+ ["CB",0xCB],
+ ["CC",0xCC],
+ ["CD",0xCD],
+ ["CE",0xCE],
+ ["CF",0xCF],
+ ["D0",0xD0],
+ ["D1",0xD1],
+ ["D2",0xD2],
+ ["D3",0xD3],
+ ["D4",0xD4],
+ ["D5",0xD5],
+ ["D6",0xD6],
+ ["D7",0xD7],
+ ["D8",0xD8],
+ ["D9",0xD9],
+ ["DA",0xDA],
+ ["DB",0xDB],
+ ["DC",0xDC],
+ ["DD",0xDD],
+ ["DE",0xDE],
+ ["DF",0xDF],
+ ["E0",0xE0],
+ ["E1",0xE1],
+ ["E2",0xE2],
+ ["E3",0xE3],
+ ["E4",0xE4],
+ ["E5",0xE5],
+ ["E6",0xE6],
+ ["E7",0xE7],
+ ["E8",0xE8],
+ ["E9",0xE9],
+ ["EA",0xEA],
+ ["EB",0xEB],
+ ["EC",0xEC],
+ ["ED",0xED],
+ ["EE",0xEE],
+ ["EF",0xEF],
+ ["F0",0xF0],
+ ["F1",0xF1],
+ ["F2",0xF2],
+ ["F3",0xF3],
+ ["F4",0xF4],
+ ["F5",0xF5],
+ ["F6",0xF6],
+ ["F7",0xF7],
+ ["F8",0xF8],
+ ["F9",0xF9],
+ ["FA",0xFA],
+ ["FB",0xFB],
+ ["FC",0xFC],
+ ["FD",0xFD],
+ ["FE",0xFE],
+ ["FF",0xFF],
+ ["8C",0x152],
+ ["9C",0x153],
+ ["8A",0x160],
+ ["9A",0x161],
+ ["9F",0x178],
+ ["8E",0x17D],
+ ["9E",0x17E],
+ ["83",0x192],
+ ["88",0x2C6],
+ ["98",0x2DC],
+ ["96",0x2013],
+ ["97",0x2014],
+ ["91",0x2018],
+ ["92",0x2019],
+ ["82",0x201A],
+ ["93",0x201C],
+ ["94",0x201D],
+ ["84",0x201E],
+ ["86",0x2020],
+ ["87",0x2021],
+ ["95",0x2022],
+ ["85",0x2026],
+ ["89",0x2030],
+ ["8B",0x2039],
+ ["9B",0x203A],
+ ["80",0x20AC],
+ ["99",0x2122],
+] \ No newline at end of file
diff --git a/enc/trans/windows-1253-tbl.rb b/enc/trans/windows-1253-tbl.rb
new file mode 100644
index 0000000000..132edb60ba
--- /dev/null
+++ b/enc/trans/windows-1253-tbl.rb
@@ -0,0 +1,113 @@
+WINDOWS_1253_TO_UCS_TBL = [
+ ["A0",0xA0],
+ ["A3",0xA3],
+ ["A4",0xA4],
+ ["A5",0xA5],
+ ["A6",0xA6],
+ ["A7",0xA7],
+ ["A8",0xA8],
+ ["A9",0xA9],
+ ["AB",0xAB],
+ ["AC",0xAC],
+ ["AD",0xAD],
+ ["AE",0xAE],
+ ["B0",0xB0],
+ ["B1",0xB1],
+ ["B2",0xB2],
+ ["B3",0xB3],
+ ["B5",0xB5],
+ ["B6",0xB6],
+ ["B7",0xB7],
+ ["BB",0xBB],
+ ["BD",0xBD],
+ ["83",0x192],
+ ["B4",0x384],
+ ["A1",0x385],
+ ["A2",0x386],
+ ["B8",0x388],
+ ["B9",0x389],
+ ["BA",0x38A],
+ ["BC",0x38C],
+ ["BE",0x38E],
+ ["BF",0x38F],
+ ["C0",0x390],
+ ["C1",0x391],
+ ["C2",0x392],
+ ["C3",0x393],
+ ["C4",0x394],
+ ["C5",0x395],
+ ["C6",0x396],
+ ["C7",0x397],
+ ["C8",0x398],
+ ["C9",0x399],
+ ["CA",0x39A],
+ ["CB",0x39B],
+ ["CC",0x39C],
+ ["CD",0x39D],
+ ["CE",0x39E],
+ ["CF",0x39F],
+ ["D0",0x3A0],
+ ["D1",0x3A1],
+ ["D3",0x3A3],
+ ["D4",0x3A4],
+ ["D5",0x3A5],
+ ["D6",0x3A6],
+ ["D7",0x3A7],
+ ["D8",0x3A8],
+ ["D9",0x3A9],
+ ["DA",0x3AA],
+ ["DB",0x3AB],
+ ["DC",0x3AC],
+ ["DD",0x3AD],
+ ["DE",0x3AE],
+ ["DF",0x3AF],
+ ["E0",0x3B0],
+ ["E1",0x3B1],
+ ["E2",0x3B2],
+ ["E3",0x3B3],
+ ["E4",0x3B4],
+ ["E5",0x3B5],
+ ["E6",0x3B6],
+ ["E7",0x3B7],
+ ["E8",0x3B8],
+ ["E9",0x3B9],
+ ["EA",0x3BA],
+ ["EB",0x3BB],
+ ["EC",0x3BC],
+ ["ED",0x3BD],
+ ["EE",0x3BE],
+ ["EF",0x3BF],
+ ["F0",0x3C0],
+ ["F1",0x3C1],
+ ["F2",0x3C2],
+ ["F3",0x3C3],
+ ["F4",0x3C4],
+ ["F5",0x3C5],
+ ["F6",0x3C6],
+ ["F7",0x3C7],
+ ["F8",0x3C8],
+ ["F9",0x3C9],
+ ["FA",0x3CA],
+ ["FB",0x3CB],
+ ["FC",0x3CC],
+ ["FD",0x3CD],
+ ["FE",0x3CE],
+ ["96",0x2013],
+ ["97",0x2014],
+ ["AF",0x2015],
+ ["91",0x2018],
+ ["92",0x2019],
+ ["82",0x201A],
+ ["93",0x201C],
+ ["94",0x201D],
+ ["84",0x201E],
+ ["86",0x2020],
+ ["87",0x2021],
+ ["95",0x2022],
+ ["85",0x2026],
+ ["89",0x2030],
+ ["8B",0x2039],
+ ["9B",0x203A],
+ ["80",0x20AC],
+ ["99",0x2122],
+] \ No newline at end of file
diff --git a/enc/trans/windows-1254-tbl.rb b/enc/trans/windows-1254-tbl.rb
new file mode 100644
index 0000000000..81a747afaa
--- /dev/null
+++ b/enc/trans/windows-1254-tbl.rb
@@ -0,0 +1,123 @@
+WINDOWS_1254_TO_UCS_TBL = [
+ ["A0",0xA0],
+ ["A1",0xA1],
+ ["A2",0xA2],
+ ["A3",0xA3],
+ ["A4",0xA4],
+ ["A5",0xA5],
+ ["A6",0xA6],
+ ["A7",0xA7],
+ ["A8",0xA8],
+ ["A9",0xA9],
+ ["AA",0xAA],
+ ["AB",0xAB],
+ ["AC",0xAC],
+ ["AD",0xAD],
+ ["AE",0xAE],
+ ["AF",0xAF],
+ ["B0",0xB0],
+ ["B1",0xB1],
+ ["B2",0xB2],
+ ["B3",0xB3],
+ ["B4",0xB4],
+ ["B5",0xB5],
+ ["B6",0xB6],
+ ["B7",0xB7],
+ ["B8",0xB8],
+ ["B9",0xB9],
+ ["BA",0xBA],
+ ["BB",0xBB],
+ ["BC",0xBC],
+ ["BD",0xBD],
+ ["BE",0xBE],
+ ["BF",0xBF],
+ ["C0",0xC0],
+ ["C1",0xC1],
+ ["C2",0xC2],
+ ["C3",0xC3],
+ ["C4",0xC4],
+ ["C5",0xC5],
+ ["C6",0xC6],
+ ["C7",0xC7],
+ ["C8",0xC8],
+ ["C9",0xC9],
+ ["CA",0xCA],
+ ["CB",0xCB],
+ ["CC",0xCC],
+ ["CD",0xCD],
+ ["CE",0xCE],
+ ["CF",0xCF],
+ ["D1",0xD1],
+ ["D2",0xD2],
+ ["D3",0xD3],
+ ["D4",0xD4],
+ ["D5",0xD5],
+ ["D6",0xD6],
+ ["D7",0xD7],
+ ["D8",0xD8],
+ ["D9",0xD9],
+ ["DA",0xDA],
+ ["DB",0xDB],
+ ["DC",0xDC],
+ ["DF",0xDF],
+ ["E0",0xE0],
+ ["E1",0xE1],
+ ["E2",0xE2],
+ ["E3",0xE3],
+ ["E4",0xE4],
+ ["E5",0xE5],
+ ["E6",0xE6],
+ ["E7",0xE7],
+ ["E8",0xE8],
+ ["E9",0xE9],
+ ["EA",0xEA],
+ ["EB",0xEB],
+ ["EC",0xEC],
+ ["ED",0xED],
+ ["EE",0xEE],
+ ["EF",0xEF],
+ ["F1",0xF1],
+ ["F2",0xF2],
+ ["F3",0xF3],
+ ["F4",0xF4],
+ ["F5",0xF5],
+ ["F6",0xF6],
+ ["F7",0xF7],
+ ["F8",0xF8],
+ ["F9",0xF9],
+ ["FA",0xFA],
+ ["FB",0xFB],
+ ["FC",0xFC],
+ ["FF",0xFF],
+ ["D0",0x11E],
+ ["F0",0x11F],
+ ["DD",0x130],
+ ["FD",0x131],
+ ["8C",0x152],
+ ["9C",0x153],
+ ["DE",0x15E],
+ ["FE",0x15F],
+ ["8A",0x160],
+ ["9A",0x161],
+ ["9F",0x178],
+ ["83",0x192],
+ ["88",0x2C6],
+ ["98",0x2DC],
+ ["96",0x2013],
+ ["97",0x2014],
+ ["91",0x2018],
+ ["92",0x2019],
+ ["82",0x201A],
+ ["93",0x201C],
+ ["94",0x201D],
+ ["84",0x201E],
+ ["86",0x2020],
+ ["87",0x2021],
+ ["95",0x2022],
+ ["85",0x2026],
+ ["89",0x2030],
+ ["8B",0x2039],
+ ["9B",0x203A],
+ ["80",0x20AC],
+ ["99",0x2122],
+] \ No newline at end of file
diff --git a/enc/trans/windows-1255-tbl.rb b/enc/trans/windows-1255-tbl.rb
new file mode 100644
index 0000000000..9084a56a10
--- /dev/null
+++ b/enc/trans/windows-1255-tbl.rb
@@ -0,0 +1,141 @@
+WINDOWS_1255_TO_UCS_TBL = [
+ ["A0",0xA0],
+ ["A1",0xA1],
+ ["A2",0xA2],
+ ["A3",0xA3],
+ ["A5",0xA5],
+ ["A6",0xA6],
+ ["A7",0xA7],
+ ["A8",0xA8],
+ ["A9",0xA9],
+ ["AB",0xAB],
+ ["AC",0xAC],
+ ["AD",0xAD],
+ ["AE",0xAE],
+ ["AF",0xAF],
+ ["B0",0xB0],
+ ["B1",0xB1],
+ ["B2",0xB2],
+ ["B3",0xB3],
+ ["B4",0xB4],
+ ["B5",0xB5],
+ ["B6",0xB6],
+ ["B7",0xB7],
+ ["B8",0xB8],
+ ["B9",0xB9],
+ ["BB",0xBB],
+ ["BC",0xBC],
+ ["BD",0xBD],
+ ["BE",0xBE],
+ ["BF",0xBF],
+ ["AA",0xD7],
+ ["BA",0xF7],
+ ["83",0x192],
+ ["88",0x2C6],
+ ["98",0x2DC],
+ ["C0",0x5B0],
+ ["C1",0x5B1],
+ ["C2",0x5B2],
+ ["C3",0x5B3],
+ ["C4",0x5B4],
+ ["C5",0x5B5],
+ ["C6",0x5B6],
+ ["C7",0x5B7],
+ ["C8",0x5B8],
+ ["C9",0x5B9],
+ ["CB",0x5BB],
+ ["CC",0x5BC],
+ ["CD",0x5BD],
+ ["CE",0x5BE],
+ ["CF",0x5BF],
+ ["D0",0x5C0],
+ ["D1",0x5C1],
+ ["D2",0x5C2],
+ ["D3",0x5C3],
+ ["E0",0x5D0],
+ ["E1",0x5D1],
+ ["E2",0x5D2],
+ ["E3",0x5D3],
+ ["E4",0x5D4],
+ ["E5",0x5D5],
+ ["E6",0x5D6],
+ ["E7",0x5D7],
+ ["E8",0x5D8],
+ ["E9",0x5D9],
+ ["EA",0x5DA],
+ ["EB",0x5DB],
+ ["EC",0x5DC],
+ ["ED",0x5DD],
+ ["EE",0x5DE],
+ ["EF",0x5DF],
+ ["F0",0x5E0],
+ ["F1",0x5E1],
+ ["F2",0x5E2],
+ ["F3",0x5E3],
+ ["F4",0x5E4],
+ ["F5",0x5E5],
+ ["F6",0x5E6],
+ ["F7",0x5E7],
+ ["F8",0x5E8],
+ ["F9",0x5E9],
+ ["FA",0x5EA],
+ ["D4",0x5F0],
+ ["D5",0x5F1],
+ ["D6",0x5F2],
+ ["D7",0x5F3],
+ ["D8",0x5F4],
+ ["FD",0x200E],
+ ["FE",0x200F],
+ ["96",0x2013],
+ ["97",0x2014],
+ ["91",0x2018],
+ ["92",0x2019],
+ ["82",0x201A],
+ ["93",0x201C],
+ ["94",0x201D],
+ ["84",0x201E],
+ ["86",0x2020],
+ ["87",0x2021],
+ ["95",0x2022],
+ ["85",0x2026],
+ ["89",0x2030],
+ ["8B",0x2039],
+ ["9B",0x203A],
+ ["A4",0x20AA],
+ ["80",0x20AC],
+ ["99",0x2122],
+ ["E9C4",0xFB1D],
+ ["D6C7",0xFB1F],
+ ["F9D1",0xFB2A],
+ ["F9D2",0xFB2B],
+ ["F9CCD1",0xFB2C],
+ ["F9CCD2",0xFB2D],
+ ["E0C7",0xFB2E],
+ ["E0C8",0xFB2F],
+ ["E0CC",0xFB30],
+ ["E1CC",0xFB31],
+ ["E2CC",0xFB32],
+ ["E3CC",0xFB33],
+ ["E4CC",0xFB34],
+ ["E5CC",0xFB35],
+ ["E6CC",0xFB36],
+ ["E8CC",0xFB38],
+ ["E9CC",0xFB39],
+ ["EACC",0xFB3A],
+ ["EBCC",0xFB3B],
+ ["ECCC",0xFB3C],
+ ["EECC",0xFB3E],
+ ["F0CC",0xFB40],
+ ["F1CC",0xFB41],
+ ["F3CC",0xFB43],
+ ["F4CC",0xFB44],
+ ["F6CC",0xFB46],
+ ["F7CC",0xFB47],
+ ["F8CC",0xFB48],
+ ["F9CC",0xFB49],
+ ["FACC",0xFB4A],
+ ["E5C9",0xFB4B],
+ ["E1CF",0xFB4C],
+ ["EBCF",0xFB4D],
+ ["F4CF",0xFB4E],
+] \ No newline at end of file
diff --git a/enc/trans/windows-1256-tbl.rb b/enc/trans/windows-1256-tbl.rb
new file mode 100644
index 0000000000..25c5874fb0
--- /dev/null
+++ b/enc/trans/windows-1256-tbl.rb
@@ -0,0 +1,130 @@
+WINDOWS_1256_TO_UCS_TBL = [
+ ["A0",0xA0],
+ ["A2",0xA2],
+ ["A3",0xA3],
+ ["A4",0xA4],
+ ["A5",0xA5],
+ ["A6",0xA6],
+ ["A7",0xA7],
+ ["A8",0xA8],
+ ["A9",0xA9],
+ ["AB",0xAB],
+ ["AC",0xAC],
+ ["AD",0xAD],
+ ["AE",0xAE],
+ ["AF",0xAF],
+ ["B0",0xB0],
+ ["B1",0xB1],
+ ["B2",0xB2],
+ ["B3",0xB3],
+ ["B4",0xB4],
+ ["B5",0xB5],
+ ["B6",0xB6],
+ ["B7",0xB7],
+ ["B8",0xB8],
+ ["B9",0xB9],
+ ["BB",0xBB],
+ ["BC",0xBC],
+ ["BD",0xBD],
+ ["BE",0xBE],
+ ["D7",0xD7],
+ ["E0",0xE0],
+ ["E2",0xE2],
+ ["E7",0xE7],
+ ["E8",0xE8],
+ ["E9",0xE9],
+ ["EA",0xEA],
+ ["EB",0xEB],
+ ["EE",0xEE],
+ ["EF",0xEF],
+ ["F4",0xF4],
+ ["F7",0xF7],
+ ["F9",0xF9],
+ ["FB",0xFB],
+ ["FC",0xFC],
+ ["8C",0x152],
+ ["9C",0x153],
+ ["83",0x192],
+ ["88",0x2C6],
+ ["A1",0x60C],
+ ["BA",0x61B],
+ ["BF",0x61F],
+ ["C1",0x621],
+ ["C2",0x622],
+ ["C3",0x623],
+ ["C4",0x624],
+ ["C5",0x625],
+ ["C6",0x626],
+ ["C7",0x627],
+ ["C8",0x628],
+ ["C9",0x629],
+ ["CA",0x62A],
+ ["CB",0x62B],
+ ["CC",0x62C],
+ ["CD",0x62D],
+ ["CE",0x62E],
+ ["CF",0x62F],
+ ["D0",0x630],
+ ["D1",0x631],
+ ["D2",0x632],
+ ["D3",0x633],
+ ["D4",0x634],
+ ["D5",0x635],
+ ["D6",0x636],
+ ["D8",0x637],
+ ["D9",0x638],
+ ["DA",0x639],
+ ["DB",0x63A],
+ ["DC",0x640],
+ ["DD",0x641],
+ ["DE",0x642],
+ ["DF",0x643],
+ ["E1",0x644],
+ ["E3",0x645],
+ ["E4",0x646],
+ ["E5",0x647],
+ ["E6",0x648],
+ ["EC",0x649],
+ ["ED",0x64A],
+ ["F0",0x64B],
+ ["F1",0x64C],
+ ["F2",0x64D],
+ ["F3",0x64E],
+ ["F5",0x64F],
+ ["F6",0x650],
+ ["F8",0x651],
+ ["FA",0x652],
+ ["8A",0x679],
+ ["81",0x67E],
+ ["8D",0x686],
+ ["8F",0x688],
+ ["9A",0x691],
+ ["8E",0x698],
+ ["98",0x6A9],
+ ["90",0x6AF],
+ ["9F",0x6BA],
+ ["AA",0x6BE],
+ ["C0",0x6C1],
+ ["FF",0x6D2],
+ ["9D",0x200C],
+ ["9E",0x200D],
+ ["FD",0x200E],
+ ["FE",0x200F],
+ ["96",0x2013],
+ ["97",0x2014],
+ ["91",0x2018],
+ ["92",0x2019],
+ ["82",0x201A],
+ ["93",0x201C],
+ ["94",0x201D],
+ ["84",0x201E],
+ ["86",0x2020],
+ ["87",0x2021],
+ ["95",0x2022],
+ ["85",0x2026],
+ ["89",0x2030],
+ ["8B",0x2039],
+ ["9B",0x203A],
+ ["80",0x20AC],
+ ["99",0x2122],
+] \ No newline at end of file
diff --git a/enc/trans/windows-1257-tbl.rb b/enc/trans/windows-1257-tbl.rb
new file mode 100644
index 0000000000..9e89b2b0b5
--- /dev/null
+++ b/enc/trans/windows-1257-tbl.rb
@@ -0,0 +1,118 @@
+WINDOWS_1257_TO_UCS_TBL = [
+ ["A0",0xA0],
+ ["A2",0xA2],
+ ["A3",0xA3],
+ ["A4",0xA4],
+ ["A6",0xA6],
+ ["A7",0xA7],
+ ["8D",0xA8],
+ ["A9",0xA9],
+ ["AB",0xAB],
+ ["AC",0xAC],
+ ["AD",0xAD],
+ ["AE",0xAE],
+ ["9D",0xAF],
+ ["B0",0xB0],
+ ["B1",0xB1],
+ ["B2",0xB2],
+ ["B3",0xB3],
+ ["B4",0xB4],
+ ["B5",0xB5],
+ ["B6",0xB6],
+ ["B7",0xB7],
+ ["8F",0xB8],
+ ["B9",0xB9],
+ ["BB",0xBB],
+ ["BC",0xBC],
+ ["BD",0xBD],
+ ["BE",0xBE],
+ ["C4",0xC4],
+ ["C5",0xC5],
+ ["AF",0xC6],
+ ["C9",0xC9],
+ ["D3",0xD3],
+ ["D5",0xD5],
+ ["D6",0xD6],
+ ["D7",0xD7],
+ ["A8",0xD8],
+ ["DC",0xDC],
+ ["DF",0xDF],
+ ["E4",0xE4],
+ ["E5",0xE5],
+ ["BF",0xE6],
+ ["E9",0xE9],
+ ["F3",0xF3],
+ ["F5",0xF5],
+ ["F6",0xF6],
+ ["F7",0xF7],
+ ["B8",0xF8],
+ ["FC",0xFC],
+ ["C2",0x100],
+ ["E2",0x101],
+ ["C0",0x104],
+ ["E0",0x105],
+ ["C3",0x106],
+ ["E3",0x107],
+ ["C8",0x10C],
+ ["E8",0x10D],
+ ["C7",0x112],
+ ["E7",0x113],
+ ["CB",0x116],
+ ["EB",0x117],
+ ["C6",0x118],
+ ["E6",0x119],
+ ["CC",0x122],
+ ["EC",0x123],
+ ["CE",0x12A],
+ ["EE",0x12B],
+ ["C1",0x12E],
+ ["E1",0x12F],
+ ["CD",0x136],
+ ["ED",0x137],
+ ["CF",0x13B],
+ ["EF",0x13C],
+ ["D9",0x141],
+ ["F9",0x142],
+ ["D1",0x143],
+ ["F1",0x144],
+ ["D2",0x145],
+ ["F2",0x146],
+ ["D4",0x14C],
+ ["F4",0x14D],
+ ["AA",0x156],
+ ["BA",0x157],
+ ["DA",0x15A],
+ ["FA",0x15B],
+ ["D0",0x160],
+ ["F0",0x161],
+ ["DB",0x16A],
+ ["FB",0x16B],
+ ["D8",0x172],
+ ["F8",0x173],
+ ["CA",0x179],
+ ["EA",0x17A],
+ ["DD",0x17B],
+ ["FD",0x17C],
+ ["DE",0x17D],
+ ["FE",0x17E],
+ ["8E",0x2C7],
+ ["FF",0x2D9],
+ ["9E",0x2DB],
+ ["96",0x2013],
+ ["97",0x2014],
+ ["91",0x2018],
+ ["92",0x2019],
+ ["82",0x201A],
+ ["93",0x201C],
+ ["94",0x201D],
+ ["84",0x201E],
+ ["86",0x2020],
+ ["87",0x2021],
+ ["95",0x2022],
+ ["85",0x2026],
+ ["89",0x2030],
+ ["8B",0x2039],
+ ["9B",0x203A],
+ ["80",0x20AC],
+ ["99",0x2122],
+] \ No newline at end of file
diff --git a/enc/trans/windows-874-tbl.rb b/enc/trans/windows-874-tbl.rb
new file mode 100644
index 0000000000..0552df3d28
--- /dev/null
+++ b/enc/trans/windows-874-tbl.rb
@@ -0,0 +1,99 @@
+WINDOWS_874_TO_UCS_TBL = [
+ ["A0",0xA0],
+ ["A1",0xE01],
+ ["A2",0xE02],
+ ["A3",0xE03],
+ ["A4",0xE04],
+ ["A5",0xE05],
+ ["A6",0xE06],
+ ["A7",0xE07],
+ ["A8",0xE08],
+ ["A9",0xE09],
+ ["AA",0xE0A],
+ ["AB",0xE0B],
+ ["AC",0xE0C],
+ ["AD",0xE0D],
+ ["AE",0xE0E],
+ ["AF",0xE0F],
+ ["B0",0xE10],
+ ["B1",0xE11],
+ ["B2",0xE12],
+ ["B3",0xE13],
+ ["B4",0xE14],
+ ["B5",0xE15],
+ ["B6",0xE16],
+ ["B7",0xE17],
+ ["B8",0xE18],
+ ["B9",0xE19],
+ ["BA",0xE1A],
+ ["BB",0xE1B],
+ ["BC",0xE1C],
+ ["BD",0xE1D],
+ ["BE",0xE1E],
+ ["BF",0xE1F],
+ ["C0",0xE20],
+ ["C1",0xE21],
+ ["C2",0xE22],
+ ["C3",0xE23],
+ ["C4",0xE24],
+ ["C5",0xE25],
+ ["C6",0xE26],
+ ["C7",0xE27],
+ ["C8",0xE28],
+ ["C9",0xE29],
+ ["CA",0xE2A],
+ ["CB",0xE2B],
+ ["CC",0xE2C],
+ ["CD",0xE2D],
+ ["CE",0xE2E],
+ ["CF",0xE2F],
+ ["D0",0xE30],
+ ["D1",0xE31],
+ ["D2",0xE32],
+ ["D3",0xE33],
+ ["D4",0xE34],
+ ["D5",0xE35],
+ ["D6",0xE36],
+ ["D7",0xE37],
+ ["D8",0xE38],
+ ["D9",0xE39],
+ ["DA",0xE3A],
+ ["DF",0xE3F],
+ ["E0",0xE40],
+ ["E1",0xE41],
+ ["E2",0xE42],
+ ["E3",0xE43],
+ ["E4",0xE44],
+ ["E5",0xE45],
+ ["E6",0xE46],
+ ["E7",0xE47],
+ ["E8",0xE48],
+ ["E9",0xE49],
+ ["EA",0xE4A],
+ ["EB",0xE4B],
+ ["EC",0xE4C],
+ ["ED",0xE4D],
+ ["EE",0xE4E],
+ ["EF",0xE4F],
+ ["F0",0xE50],
+ ["F1",0xE51],
+ ["F2",0xE52],
+ ["F3",0xE53],
+ ["F4",0xE54],
+ ["F5",0xE55],
+ ["F6",0xE56],
+ ["F7",0xE57],
+ ["F8",0xE58],
+ ["F9",0xE59],
+ ["FA",0xE5A],
+ ["FB",0xE5B],
+ ["96",0x2013],
+ ["97",0x2014],
+ ["91",0x2018],
+ ["92",0x2019],
+ ["93",0x201C],
+ ["94",0x201D],
+ ["95",0x2022],
+ ["85",0x2026],
+ ["80",0x20AC],
+] \ No newline at end of file
diff --git a/enc/us_ascii.c b/enc/us_ascii.c
index 39e2b26088..2e96dd3846 100644
--- a/enc/us_ascii.c
+++ b/enc/us_ascii.c
@@ -1,6 +1,6 @@
#include "regenc.h"
-extern int
+static int
us_ascii_mbc_enc_len(const UChar* p, const UChar* e, OnigEncoding enc)
{
if (*p & 0x80)
diff --git a/enc/utf_16be.c b/enc/utf_16be.c
index ccae9397bb..8d7c8e9b11 100644
--- a/enc/utf_16be.c
+++ b/enc/utf_16be.c
@@ -212,7 +212,7 @@ utf16be_is_mbc_ambiguous(OnigCaseFoldType flag, const UChar** pp, const UChar* e
#endif
static UChar*
-utf16be_left_adjust_char_head(const UChar* start, const UChar* s,
+utf16be_left_adjust_char_head(const UChar* start, const UChar* s, const UChar* end,
OnigEncoding enc ARG_UNUSED)
{
if (s <= start) return (UChar* )s;
diff --git a/enc/utf_16le.c b/enc/utf_16le.c
index c3712f4e18..c8a1e7a10a 100644
--- a/enc/utf_16le.c
+++ b/enc/utf_16le.c
@@ -204,7 +204,7 @@ utf16le_is_mbc_ambiguous(OnigCaseFoldType flag, const UChar** pp,
#endif
static UChar*
-utf16le_left_adjust_char_head(const UChar* start, const UChar* s,
+utf16le_left_adjust_char_head(const UChar* start, const UChar* s, const UChar* end,
OnigEncoding enc ARG_UNUSED)
{
if (s <= start) return (UChar* )s;
diff --git a/enc/utf_32be.c b/enc/utf_32be.c
index ed6c9b7f3b..61e7d0f1b5 100644
--- a/enc/utf_32be.c
+++ b/enc/utf_32be.c
@@ -152,7 +152,7 @@ utf32be_is_mbc_ambiguous(OnigCaseFoldType flag, const UChar** pp, const UChar* e
#endif
static UChar*
-utf32be_left_adjust_char_head(const UChar* start, const UChar* s,
+utf32be_left_adjust_char_head(const UChar* start, const UChar* s, const UChar* end,
OnigEncoding enc ARG_UNUSED)
{
int rem;
diff --git a/enc/utf_32le.c b/enc/utf_32le.c
index 53e3522070..3a0a41bba7 100644
--- a/enc/utf_32le.c
+++ b/enc/utf_32le.c
@@ -152,7 +152,7 @@ utf32le_is_mbc_ambiguous(OnigCaseFoldType flag, const UChar** pp, const UChar* e
#endif
static UChar*
-utf32le_left_adjust_char_head(const UChar* start, const UChar* s,
+utf32le_left_adjust_char_head(const UChar* start, const UChar* s, const UChar* end,
OnigEncoding enc ARG_UNUSED)
{
int rem;
diff --git a/enc/utf_8.c b/enc/utf_8.c
index b8ee92feb4..3b9387c613 100644
--- a/enc/utf_8.c
+++ b/enc/utf_8.c
@@ -405,7 +405,7 @@ get_ctype_code_range(OnigCtype ctype, OnigCodePoint *sb_out,
static UChar*
-left_adjust_char_head(const UChar* start, const UChar* s, OnigEncoding enc ARG_UNUSED)
+left_adjust_char_head(const UChar* start, const UChar* s, const UChar* end, OnigEncoding enc ARG_UNUSED)
{
const UChar *p;
diff --git a/encoding.c b/encoding.c
index 9b5c2b3e32..c0c4936c7a 100644
--- a/encoding.c
+++ b/encoding.c
@@ -19,7 +19,7 @@
#endif
#include "ruby/util.h"
-static ID id_encoding, id_base_encoding;
+static ID id_encoding;
struct rb_encoding_entry {
const char *name;
@@ -41,7 +41,6 @@ void rb_enc_init(void);
#define enc_autoload_p(enc) (!rb_enc_mbmaxlen(enc))
static int load_encoding(const char *name);
-static VALUE enc_base_encoding(VALUE self);
static void
enc_mark(void *ptr)
@@ -544,14 +543,31 @@ rb_id_encoding(void)
int
rb_enc_get_index(VALUE obj)
{
- int i;
-
- i = ENCODING_GET_INLINED(obj);
- if (i == ENCODING_INLINE_MAX) {
- VALUE iv;
+ int i = -1;
+ VALUE tmp;
- iv = rb_ivar_get(obj, rb_id_encoding());
- i = NUM2INT(iv);
+ switch (BUILTIN_TYPE(obj)) {
+ default:
+ case T_STRING:
+ case T_REGEXP:
+ i = ENCODING_GET_INLINED(obj);
+ if (i == ENCODING_INLINE_MAX) {
+ VALUE iv;
+
+ iv = rb_ivar_get(obj, rb_id_encoding());
+ i = NUM2INT(iv);
+ }
+ break;
+ case T_FILE:
+ tmp = rb_funcall(obj, rb_intern("internal_encoding"), 0, 0);
+ if (NIL_P(tmp)) obj = rb_funcall(obj, rb_intern("external_encoding"), 0, 0);
+ else obj = tmp;
+ if (NIL_P(obj)) break;
+ case T_DATA:
+ if (RDATA(obj)->dmark == enc_mark) {
+ i = enc_check_encoding(obj);
+ }
+ break;
}
return i;
}
@@ -630,9 +646,11 @@ rb_enc_compatible(VALUE str1, VALUE str2)
if (!rb_enc_asciicompat(enc1) || !rb_enc_asciicompat(enc2)) {
return 0;
}
- if (BUILTIN_TYPE(str2) == T_REGEXP && idx2 == ENCINDEX_US_ASCII)
+
+ /* objects whose encoding is the same of contents */
+ if (BUILTIN_TYPE(str2) != T_STRING && idx2 == ENCINDEX_US_ASCII)
return enc1;
- if (BUILTIN_TYPE(str1) == T_REGEXP && idx1 == ENCINDEX_US_ASCII)
+ if (BUILTIN_TYPE(str1) != T_STRING && idx1 == ENCINDEX_US_ASCII)
return enc2;
if (BUILTIN_TYPE(str1) != T_STRING) {
@@ -716,7 +734,7 @@ rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc)
int
rb_enc_ascget(const char *p, const char *e, int *len, rb_encoding *enc)
{
- int c, l;
+ unsigned int c, l;
if (e <= p)
return -1;
if (rb_enc_asciicompat(enc)) {
@@ -736,7 +754,7 @@ rb_enc_ascget(const char *p, const char *e, int *len, rb_encoding *enc)
return c;
}
-int
+unsigned int
rb_enc_codepoint(const char *p, const char *e, rb_encoding *enc)
{
int r;
@@ -804,12 +822,36 @@ enc_name(VALUE self)
return rb_usascii_str_new2(rb_enc_name((rb_encoding*)DATA_PTR(self)));
}
+static int
+enc_names_i(st_data_t name, st_data_t idx, st_data_t args)
+{
+ VALUE *arg = (VALUE *)args;
+
+ if ((int)idx == (int)arg[0]) {
+ VALUE str = rb_usascii_str_new2((char *)name);
+ OBJ_FREEZE(str);
+ rb_ary_push(arg[1], str);
+ }
+ return ST_CONTINUE;
+}
+
+/*
+ * call-seq:
+ * enc.names => array
+ *
+ * Returns the list of name and aliases of the encoding.
+ *
+ * Encoding::WINDOWS_31J.names => ["Windows-31J", "CP932", "csWindows31J"]
+ */
static VALUE
-enc_base_encoding(VALUE self)
+enc_names(VALUE self)
{
- rb_encoding *base = enc_table.list[must_encoding(self)].base;
- if (!base) return Qnil;
- return ENC_FROM_ENCODING(base);
+ VALUE args[2];
+
+ args[0] = (VALUE)rb_to_encoding_index(self);
+ args[1] = rb_ary_new2(0);
+ st_foreach(enc_table.names, enc_names_i, (st_data_t)args);
+ return args[1];
}
/*
@@ -879,14 +921,6 @@ enc_compatible_p(VALUE klass, VALUE str1, VALUE str2)
{
rb_encoding *enc;
- if (SPECIAL_CONST_P(str1) || TYPE(str1) != T_STRING && TYPE(str1) != T_REGEXP) {
- rb_raise(rb_eTypeError, "wrong argument type %s (expected String or Regexp)",
- rb_obj_classname(str1));
- }
- if (SPECIAL_CONST_P(str2) || TYPE(str2) != T_STRING && TYPE(str2) != T_REGEXP) {
- rb_raise(rb_eTypeError, "wrong argument type %s (expected String or Regexp)",
- rb_obj_classname(str2));
- }
if (!enc_capable(str1)) return Qnil;
if (!enc_capable(str2)) return Qnil;
enc = rb_enc_compatible(str1, str2);
@@ -961,11 +995,11 @@ rb_locale_encoding(void)
int idx;
if (NIL_P(charmap))
- return rb_usascii_encoding();
- else
- idx = rb_enc_find_index(StringValueCStr(charmap));
- if (idx < 0)
- return rb_ascii8bit_encoding();
+ idx = rb_usascii_encindex();
+ else if ((idx = rb_enc_find_index(StringValueCStr(charmap))) < 0)
+ idx = rb_ascii8bit_encindex();
+
+ if (rb_enc_registered("locale") < 0) enc_alias("locale", idx);
return rb_enc_from_index(idx);
}
@@ -985,11 +1019,15 @@ rb_filesystem_encoding(void)
}
static int default_external_index;
+static rb_encoding *default_external;
rb_encoding *
rb_default_external_encoding(void)
{
- return rb_enc_from_index(default_external_index);
+ if (!default_external) {
+ default_external = rb_enc_from_index(default_external_index);
+ }
+ return default_external;
}
VALUE
@@ -1004,7 +1042,8 @@ rb_enc_default_external(void)
*
* Returns default external encoding.
*
- * It is initialized by the locale or -E option.
+ * It is initialized by the locale or -E option,
+ * and can't be modified after that.
*/
static VALUE
get_default_external(VALUE klass)
@@ -1016,6 +1055,63 @@ void
rb_enc_set_default_external(VALUE encoding)
{
default_external_index = rb_enc_to_index(rb_to_encoding(encoding));
+ default_external = 0;
+ enc_alias("external", default_external_index);
+}
+
+/* -2 => not yet set, -1 => nil */
+static int default_internal_index = -2;
+static rb_encoding *default_internal;
+
+rb_encoding *
+rb_default_internal_encoding(void)
+{
+ if (!default_internal && default_internal_index >= 0) {
+ default_internal = rb_enc_from_index(default_internal_index);
+ }
+ return default_internal;
+}
+
+VALUE
+rb_enc_default_internal(void)
+{
+ /* Note: These functions cope with default_internal not being set */
+ return rb_enc_from_encoding(rb_default_internal_encoding());
+}
+
+/*
+ * call-seq:
+ * Encoding.default_internal => enc
+ *
+ * Returns default internal encoding.
+ *
+ * It is initialized by the source internal_encoding or -E option,
+ * and can't be modified after that.
+ */
+static VALUE
+get_default_internal(VALUE klass)
+{
+ return rb_enc_default_internal();
+}
+
+void
+rb_enc_set_default_internal(VALUE encoding)
+{
+ if (default_internal_index != -2)
+ /* Already set */
+ return;
+ if (NIL_P(encoding)) {
+ default_internal_index = -1;
+ default_internal = 0;
+ return;
+ }
+
+ default_internal_index = rb_enc_to_index(rb_to_encoding(encoding));
+ /* Convert US-ASCII => UTF-8 */
+ if (default_internal_index == rb_usascii_encindex())
+ default_internal_index = rb_utf8_encindex();
+ default_internal = 0;
+ enc_alias("internal", default_internal_index);
}
/*
@@ -1184,8 +1280,6 @@ Init_Encoding(void)
{
#undef rb_intern
#define rb_intern(str) rb_intern_const(str)
-
- id_base_encoding = rb_intern("#base_encoding");
}
void
@@ -1199,7 +1293,7 @@ InitVM_Encoding(rb_vm_t *vm)
rb_define_method(rb_cEncoding, "to_s", enc_name, 0);
rb_define_method(rb_cEncoding, "inspect", enc_inspect, 0);
rb_define_method(rb_cEncoding, "name", enc_name, 0);
- rb_define_method(rb_cEncoding, "base_encoding", enc_base_encoding, 0);
+ rb_define_method(rb_cEncoding, "names", enc_names, 0);
rb_define_method(rb_cEncoding, "dummy?", enc_dummy_p, 0);
rb_define_singleton_method(rb_cEncoding, "list", enc_list, 0);
rb_define_singleton_method(rb_cEncoding, "name_list", rb_enc_name_list, 0);
@@ -1211,11 +1305,14 @@ InitVM_Encoding(rb_vm_t *vm)
rb_define_singleton_method(rb_cEncoding, "_load", enc_load, 1);
rb_define_singleton_method(rb_cEncoding, "default_external", get_default_external, 0);
+ rb_define_singleton_method(rb_cEncoding, "default_internal", get_default_internal, 0);
rb_define_singleton_method(rb_cEncoding, "locale_charmap", rb_locale_charmap, 0);
list = rb_ary_new2(enc_table.count);
RBASIC(list)->klass = 0;
rb_encoding_list = list;
+ rb_gc_register_mark_object(list);
+
for (i = 0; i < enc_table.count; ++i) {
rb_ary_push(list, enc_new(enc_table.list[i].enc));
}
diff --git a/enum.c b/enum.c
index c57092a7e6..f96c8d4578 100644
--- a/enum.c
+++ b/enum.c
@@ -10,8 +10,8 @@
**********************************************************************/
#include "ruby/ruby.h"
-#include "ruby/node.h"
#include "ruby/util.h"
+#include "node.h"
static ID id_each, id_eqq, id_cmp, id_next, id_size;
diff --git a/enumerator.c b/enumerator.c
index d325e97da4..8186b6ea53 100644
--- a/enumerator.c
+++ b/enumerator.c
@@ -13,7 +13,6 @@
************************************************/
#include "ruby/ruby.h"
-#include "debug.h"
/*
* Document-class: Enumerator
diff --git a/error.c b/error.c
index 021293e7e3..151da09c7d 100644
--- a/error.c
+++ b/error.c
@@ -310,6 +310,37 @@ rb_check_type(VALUE x, int t)
/* exception classes */
#include <errno.h>
+#if 0
+VALUE rb_eException;
+VALUE rb_eSystemExit;
+VALUE rb_eInterrupt;
+VALUE rb_eSignal;
+VALUE rb_eFatal;
+VALUE rb_eStandardError;
+VALUE rb_eRuntimeError;
+VALUE rb_eTypeError;
+VALUE rb_eArgError;
+VALUE rb_eIndexError;
+VALUE rb_eKeyError;
+VALUE rb_eRangeError;
+VALUE rb_eNameError;
+VALUE rb_eEncodingError;
+VALUE rb_eEncCompatError;
+VALUE rb_eNoMethodError;
+VALUE rb_eSecurityError;
+VALUE rb_eNotImpError;
+VALUE rb_eNoMemError;
+VALUE rb_cNameErrorMesg;
+
+VALUE rb_eScriptError;
+VALUE rb_eSyntaxError;
+VALUE rb_eLoadError;
+
+VALUE rb_eSystemCallError;
+VALUE rb_mErrno;
+static VALUE rb_eNOERROR;
+#endif
+
VALUE
rb_exc_new(VALUE etype, const char *ptr, long len)
{
@@ -529,7 +560,7 @@ exc_equal(VALUE exc, VALUE obj)
if (exc == obj) return Qtrue;
if (rb_obj_class(exc) != rb_obj_class(obj))
- return rb_equal(obj, exc);
+ return Qfalse;
CONST_ID(id_mesg, "mesg");
if (!rb_equal(rb_attr_get(exc, id_mesg), rb_attr_get(obj, id_mesg)))
return Qfalse;
@@ -869,7 +900,7 @@ get_syserr(int n)
static VALUE
syserr_initialize(int argc, VALUE *argv, VALUE self)
{
-#if !defined(_WIN32) && !defined(__VMS)
+#if !defined(_WIN32)
char *strerror();
#endif
const char *err;
@@ -956,18 +987,6 @@ syserr_eqq(VALUE self, VALUE exc)
}
/*
- * call-seq:
- * Errno.const_missing => SystemCallError
- *
- * Returns default SystemCallError class.
- */
-static VALUE
-errno_missing(VALUE self, VALUE id)
-{
- return rb_eNOERROR;
-}
-
-/*
* Descendants of class <code>Exception</code> are used to communicate
* between <code>raise</code> methods and <code>rescue</code>
* statements in <code>begin/end</code> blocks. <code>Exception</code>
@@ -1011,7 +1030,6 @@ InitVM_Exception(rb_vm_t *vm)
rb_eIndexError = rb_define_class("IndexError", rb_eStandardError);
rb_eKeyError = rb_define_class("KeyError", rb_eIndexError);
rb_eRangeError = rb_define_class("RangeError", rb_eStandardError);
- rb_eEncCompatError = rb_define_class("EncodingCompatibilityError", rb_eStandardError);
rb_eScriptError = rb_define_class("ScriptError", rb_eException);
rb_eSyntaxError = rb_define_class("SyntaxError", rb_eScriptError);
@@ -1035,6 +1053,8 @@ InitVM_Exception(rb_vm_t *vm)
rb_eRuntimeError = rb_define_class("RuntimeError", rb_eStandardError);
rb_eSecurityError = rb_define_class("SecurityError", rb_eException);
rb_eNoMemError = rb_define_class("NoMemoryError", rb_eException);
+ rb_eEncodingError = rb_define_class("EncodingError", rb_eStandardError);
+ rb_eEncCompatError = rb_define_class_under(rb_cEncoding, "CompatibilityError", rb_eEncodingError);
rb_syserr_tbl = rb_wrap_st_table(st_init_numtable());
rb_eSystemCallError = rb_define_class("SystemCallError", rb_eStandardError);
@@ -1043,7 +1063,6 @@ InitVM_Exception(rb_vm_t *vm)
rb_define_singleton_method(rb_eSystemCallError, "===", syserr_eqq, 1);
rb_mErrno = rb_define_module("Errno");
- rb_define_singleton_method(rb_mErrno, "const_missing", errno_missing, 1);
rb_define_global_function("warn", rb_warn_m, 1);
}
@@ -1146,381 +1165,15 @@ rb_check_frozen(VALUE obj)
if (OBJ_FROZEN(obj)) rb_error_frozen(rb_obj_classname(obj));
}
-void
-Init_syserr(void)
+void Init_syserr(void)
{
}
void
InitVM_syserr(rb_vm_t *vm)
{
-#ifdef EPERM
- set_syserr(EPERM, "EPERM");
-#endif
-#ifdef ENOENT
- set_syserr(ENOENT, "ENOENT");
-#endif
-#ifdef ESRCH
- set_syserr(ESRCH, "ESRCH");
-#endif
-#ifdef EINTR
- set_syserr(EINTR, "EINTR");
-#endif
-#ifdef EIO
- set_syserr(EIO, "EIO");
-#endif
-#ifdef ENXIO
- set_syserr(ENXIO, "ENXIO");
-#endif
-#ifdef E2BIG
- set_syserr(E2BIG, "E2BIG");
-#endif
-#ifdef ENOEXEC
- set_syserr(ENOEXEC, "ENOEXEC");
-#endif
-#ifdef EBADF
- set_syserr(EBADF, "EBADF");
-#endif
-#ifdef ECHILD
- set_syserr(ECHILD, "ECHILD");
-#endif
-#ifdef EAGAIN
- set_syserr(EAGAIN, "EAGAIN");
-#endif
-#ifdef ENOMEM
- set_syserr(ENOMEM, "ENOMEM");
-#endif
-#ifdef EACCES
- set_syserr(EACCES, "EACCES");
-#endif
-#ifdef EFAULT
- set_syserr(EFAULT, "EFAULT");
-#endif
-#ifdef ENOTBLK
- set_syserr(ENOTBLK, "ENOTBLK");
-#endif
-#ifdef EBUSY
- set_syserr(EBUSY, "EBUSY");
-#endif
-#ifdef EEXIST
- set_syserr(EEXIST, "EEXIST");
-#endif
-#ifdef EXDEV
- set_syserr(EXDEV, "EXDEV");
-#endif
-#ifdef ENODEV
- set_syserr(ENODEV, "ENODEV");
-#endif
-#ifdef ENOTDIR
- set_syserr(ENOTDIR, "ENOTDIR");
-#endif
-#ifdef EISDIR
- set_syserr(EISDIR, "EISDIR");
-#endif
-#ifdef EINVAL
- set_syserr(EINVAL, "EINVAL");
-#endif
-#ifdef ENFILE
- set_syserr(ENFILE, "ENFILE");
-#endif
-#ifdef EMFILE
- set_syserr(EMFILE, "EMFILE");
-#endif
-#ifdef ENOTTY
- set_syserr(ENOTTY, "ENOTTY");
-#endif
-#ifdef ETXTBSY
- set_syserr(ETXTBSY, "ETXTBSY");
-#endif
-#ifdef EFBIG
- set_syserr(EFBIG, "EFBIG");
-#endif
-#ifdef ENOSPC
- set_syserr(ENOSPC, "ENOSPC");
-#endif
-#ifdef ESPIPE
- set_syserr(ESPIPE, "ESPIPE");
-#endif
-#ifdef EROFS
- set_syserr(EROFS, "EROFS");
-#endif
-#ifdef EMLINK
- set_syserr(EMLINK, "EMLINK");
-#endif
-#ifdef EPIPE
- set_syserr(EPIPE, "EPIPE");
-#endif
-#ifdef EDOM
- set_syserr(EDOM, "EDOM");
-#endif
-#ifdef ERANGE
- set_syserr(ERANGE, "ERANGE");
-#endif
-#ifdef EDEADLK
- set_syserr(EDEADLK, "EDEADLK");
-#endif
-#ifdef ENAMETOOLONG
- set_syserr(ENAMETOOLONG, "ENAMETOOLONG");
-#endif
-#ifdef ENOLCK
- set_syserr(ENOLCK, "ENOLCK");
-#endif
-#ifdef ENOSYS
- set_syserr(ENOSYS, "ENOSYS");
-#endif
-#ifdef ENOTEMPTY
- set_syserr(ENOTEMPTY, "ENOTEMPTY");
-#endif
-#ifdef ELOOP
- set_syserr(ELOOP, "ELOOP");
-#endif
-#ifdef EWOULDBLOCK
- set_syserr(EWOULDBLOCK, "EWOULDBLOCK");
-#endif
-#ifdef ENOMSG
- set_syserr(ENOMSG, "ENOMSG");
-#endif
-#ifdef EIDRM
- set_syserr(EIDRM, "EIDRM");
-#endif
-#ifdef ECHRNG
- set_syserr(ECHRNG, "ECHRNG");
-#endif
-#ifdef EL2NSYNC
- set_syserr(EL2NSYNC, "EL2NSYNC");
-#endif
-#ifdef EL3HLT
- set_syserr(EL3HLT, "EL3HLT");
-#endif
-#ifdef EL3RST
- set_syserr(EL3RST, "EL3RST");
-#endif
-#ifdef ELNRNG
- set_syserr(ELNRNG, "ELNRNG");
-#endif
-#ifdef EUNATCH
- set_syserr(EUNATCH, "EUNATCH");
-#endif
-#ifdef ENOCSI
- set_syserr(ENOCSI, "ENOCSI");
-#endif
-#ifdef EL2HLT
- set_syserr(EL2HLT, "EL2HLT");
-#endif
-#ifdef EBADE
- set_syserr(EBADE, "EBADE");
-#endif
-#ifdef EBADR
- set_syserr(EBADR, "EBADR");
-#endif
-#ifdef EXFULL
- set_syserr(EXFULL, "EXFULL");
-#endif
-#ifdef ENOANO
- set_syserr(ENOANO, "ENOANO");
-#endif
-#ifdef EBADRQC
- set_syserr(EBADRQC, "EBADRQC");
-#endif
-#ifdef EBADSLT
- set_syserr(EBADSLT, "EBADSLT");
-#endif
-#ifdef EDEADLOCK
- set_syserr(EDEADLOCK, "EDEADLOCK");
-#endif
-#ifdef EBFONT
- set_syserr(EBFONT, "EBFONT");
-#endif
-#ifdef ENOSTR
- set_syserr(ENOSTR, "ENOSTR");
-#endif
-#ifdef ENODATA
- set_syserr(ENODATA, "ENODATA");
-#endif
-#ifdef ETIME
- set_syserr(ETIME, "ETIME");
-#endif
-#ifdef ENOSR
- set_syserr(ENOSR, "ENOSR");
-#endif
-#ifdef ENONET
- set_syserr(ENONET, "ENONET");
-#endif
-#ifdef ENOPKG
- set_syserr(ENOPKG, "ENOPKG");
-#endif
-#ifdef EREMOTE
- set_syserr(EREMOTE, "EREMOTE");
-#endif
-#ifdef ENOLINK
- set_syserr(ENOLINK, "ENOLINK");
-#endif
-#ifdef EADV
- set_syserr(EADV, "EADV");
-#endif
-#ifdef ESRMNT
- set_syserr(ESRMNT, "ESRMNT");
-#endif
-#ifdef ECOMM
- set_syserr(ECOMM, "ECOMM");
-#endif
-#ifdef EPROTO
- set_syserr(EPROTO, "EPROTO");
-#endif
-#ifdef EMULTIHOP
- set_syserr(EMULTIHOP, "EMULTIHOP");
-#endif
-#ifdef EDOTDOT
- set_syserr(EDOTDOT, "EDOTDOT");
-#endif
-#ifdef EBADMSG
- set_syserr(EBADMSG, "EBADMSG");
-#endif
-#ifdef EOVERFLOW
- set_syserr(EOVERFLOW, "EOVERFLOW");
-#endif
-#ifdef ENOTUNIQ
- set_syserr(ENOTUNIQ, "ENOTUNIQ");
-#endif
-#ifdef EBADFD
- set_syserr(EBADFD, "EBADFD");
-#endif
-#ifdef EREMCHG
- set_syserr(EREMCHG, "EREMCHG");
-#endif
-#ifdef ELIBACC
- set_syserr(ELIBACC, "ELIBACC");
-#endif
-#ifdef ELIBBAD
- set_syserr(ELIBBAD, "ELIBBAD");
-#endif
-#ifdef ELIBSCN
- set_syserr(ELIBSCN, "ELIBSCN");
-#endif
-#ifdef ELIBMAX
- set_syserr(ELIBMAX, "ELIBMAX");
-#endif
-#ifdef ELIBEXEC
- set_syserr(ELIBEXEC, "ELIBEXEC");
-#endif
-#ifdef EILSEQ
- set_syserr(EILSEQ, "EILSEQ");
-#endif
-#ifdef ERESTART
- set_syserr(ERESTART, "ERESTART");
-#endif
-#ifdef ESTRPIPE
- set_syserr(ESTRPIPE, "ESTRPIPE");
-#endif
-#ifdef EUSERS
- set_syserr(EUSERS, "EUSERS");
-#endif
-#ifdef ENOTSOCK
- set_syserr(ENOTSOCK, "ENOTSOCK");
-#endif
-#ifdef EDESTADDRREQ
- set_syserr(EDESTADDRREQ, "EDESTADDRREQ");
-#endif
-#ifdef EMSGSIZE
- set_syserr(EMSGSIZE, "EMSGSIZE");
-#endif
-#ifdef EPROTOTYPE
- set_syserr(EPROTOTYPE, "EPROTOTYPE");
-#endif
-#ifdef ENOPROTOOPT
- set_syserr(ENOPROTOOPT, "ENOPROTOOPT");
-#endif
-#ifdef EPROTONOSUPPORT
- set_syserr(EPROTONOSUPPORT, "EPROTONOSUPPORT");
-#endif
-#ifdef ESOCKTNOSUPPORT
- set_syserr(ESOCKTNOSUPPORT, "ESOCKTNOSUPPORT");
-#endif
-#ifdef EOPNOTSUPP
- set_syserr(EOPNOTSUPP, "EOPNOTSUPP");
-#endif
-#ifdef EPFNOSUPPORT
- set_syserr(EPFNOSUPPORT, "EPFNOSUPPORT");
-#endif
-#ifdef EAFNOSUPPORT
- set_syserr(EAFNOSUPPORT, "EAFNOSUPPORT");
-#endif
-#ifdef EADDRINUSE
- set_syserr(EADDRINUSE, "EADDRINUSE");
-#endif
-#ifdef EADDRNOTAVAIL
- set_syserr(EADDRNOTAVAIL, "EADDRNOTAVAIL");
-#endif
-#ifdef ENETDOWN
- set_syserr(ENETDOWN, "ENETDOWN");
-#endif
-#ifdef ENETUNREACH
- set_syserr(ENETUNREACH, "ENETUNREACH");
-#endif
-#ifdef ENETRESET
- set_syserr(ENETRESET, "ENETRESET");
-#endif
-#ifdef ECONNABORTED
- set_syserr(ECONNABORTED, "ECONNABORTED");
-#endif
-#ifdef ECONNRESET
- set_syserr(ECONNRESET, "ECONNRESET");
-#endif
-#ifdef ENOBUFS
- set_syserr(ENOBUFS, "ENOBUFS");
-#endif
-#ifdef EISCONN
- set_syserr(EISCONN, "EISCONN");
-#endif
-#ifdef ENOTCONN
- set_syserr(ENOTCONN, "ENOTCONN");
-#endif
-#ifdef ESHUTDOWN
- set_syserr(ESHUTDOWN, "ESHUTDOWN");
-#endif
-#ifdef ETOOMANYREFS
- set_syserr(ETOOMANYREFS, "ETOOMANYREFS");
-#endif
-#ifdef ETIMEDOUT
- set_syserr(ETIMEDOUT, "ETIMEDOUT");
-#endif
-#ifdef ECONNREFUSED
- set_syserr(ECONNREFUSED, "ECONNREFUSED");
-#endif
-#ifdef EHOSTDOWN
- set_syserr(EHOSTDOWN, "EHOSTDOWN");
-#endif
-#ifdef EHOSTUNREACH
- set_syserr(EHOSTUNREACH, "EHOSTUNREACH");
-#endif
-#ifdef EALREADY
- set_syserr(EALREADY, "EALREADY");
-#endif
-#ifdef EINPROGRESS
- set_syserr(EINPROGRESS, "EINPROGRESS");
-#endif
-#ifdef ESTALE
- set_syserr(ESTALE, "ESTALE");
-#endif
-#ifdef EUCLEAN
- set_syserr(EUCLEAN, "EUCLEAN");
-#endif
-#ifdef ENOTNAM
- set_syserr(ENOTNAM, "ENOTNAM");
-#endif
-#ifdef ENAVAIL
- set_syserr(ENAVAIL, "ENAVAIL");
-#endif
-#ifdef EISNAM
- set_syserr(EISNAM, "EISNAM");
-#endif
-#ifdef EREMOTEIO
- set_syserr(EREMOTEIO, "EREMOTEIO");
-#endif
-#ifdef EDQUOT
- set_syserr(EDQUOT, "EDQUOT");
-#endif
rb_eNOERROR = set_syserr(0, "NOERROR");
+#include "known_errors.inc"
}
static void
diff --git a/eval.c b/eval.c
index d39adfb970..3d9a6ad8c4 100644
--- a/eval.c
+++ b/eval.c
@@ -12,16 +12,16 @@
**********************************************************************/
#include "eval_intern.h"
+#include "iseq.h"
#define exception_error rb_errReenterError
#include "eval_error.c"
-#include "eval_safe.c"
#include "eval_jump.c"
#if defined(__APPLE__)
#define environ (*_NSGetEnviron())
-#elif !defined(_WIN32) && !defined(__MACOS__) || defined(_WIN32_WCE)
+#elif !defined(_WIN32)
extern char **environ;
#endif
char **rb_origenviron;
@@ -56,11 +56,7 @@ ruby_init(void)
return;
initialized = 1;
-#ifdef __MACOS__
- rb_origenviron = 0;
-#else
rb_origenviron = environ;
-#endif
Init_stack((void *)&state);
Init_BareVM();
@@ -68,12 +64,7 @@ ruby_init(void)
PUSH_TAG();
if ((state = EXEC_TAG()) == 0) {
rb_call_inits();
-
-#ifdef __MACOS__
- _macruby_init();
-#elif defined(__VMS)
- _vmsruby_init();
-#endif
+ ruby_prog_init();
}
POP_TAG();
@@ -1170,7 +1161,6 @@ InitVM_eval(rb_vm_t *vm)
rb_define_virtual_variable("$@", errat_getter, errat_setter);
rb_define_virtual_variable("$!", errinfo_getter, 0);
- rb_define_global_function("eval", rb_f_eval, -1);
rb_define_global_function("iterator?", rb_f_block_given_p, 0);
rb_define_global_function("block_given?", rb_f_block_given_p, 0);
@@ -1186,8 +1176,6 @@ InitVM_eval(rb_vm_t *vm)
rb_define_private_method(rb_cModule, "append_features", rb_mod_append_features, 1);
rb_define_private_method(rb_cModule, "extend_object", rb_mod_extend_object, 1);
rb_define_private_method(rb_cModule, "include", rb_mod_include, -1);
- rb_define_method(rb_cModule, "module_eval", rb_mod_module_eval, -1);
- rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval, -1);
rb_undef_method(rb_cClass, "module_function");
@@ -1208,64 +1196,9 @@ InitVM_eval(rb_vm_t *vm)
rb_define_global_function("trace_var", rb_f_trace_var, -1); /* in variable.c */
rb_define_global_function("untrace_var", rb_f_untrace_var, -1); /* in variable.c */
- rb_define_virtual_variable("$SAFE", safe_getter, safe_setter);
-
exception_error = rb_exc_new3(rb_eFatal,
rb_obj_freeze(rb_str_new2("exception reentered")));
rb_ivar_set(exception_error, idThrowState, INT2FIX(TAG_FATAL));
OBJ_TAINT(exception_error);
OBJ_FREEZE(exception_error);
}
-
-
-/* for parser */
-
-int
-rb_dvar_defined(ID id)
-{
- rb_thread_t *th = GET_THREAD();
- rb_iseq_t *iseq;
- if (th->base_block && (iseq = th->base_block->iseq)) {
- while (iseq->type == ISEQ_TYPE_BLOCK ||
- iseq->type == ISEQ_TYPE_RESCUE ||
- iseq->type == ISEQ_TYPE_ENSURE ||
- iseq->type == ISEQ_TYPE_EVAL) {
- int i;
-
- for (i = 0; i < iseq->local_table_size; i++) {
- if (iseq->local_table[i] == id) {
- return 1;
- }
- }
- iseq = iseq->parent_iseq;
- }
- }
- return 0;
-}
-
-int
-rb_local_defined(ID id)
-{
- rb_thread_t *th = GET_THREAD();
- rb_iseq_t *iseq;
-
- if (th->base_block && th->base_block->iseq) {
- int i;
- iseq = th->base_block->iseq->local_iseq;
-
- for (i=0; i<iseq->local_table_size; i++) {
- if (iseq->local_table[i] == id) {
- return 1;
- }
- }
- }
- return 0;
-}
-
-int
-rb_parse_in_eval(void)
-{
- return GET_THREAD()->parse_in_eval != 0;
-}
-
-
diff --git a/eval_intern.h b/eval_intern.h
index bfd42da572..68436951e7 100644
--- a/eval_intern.h
+++ b/eval_intern.h
@@ -1,7 +1,9 @@
-
#ifndef RUBY_EVAL_INTERN_H
#define RUBY_EVAL_INTERN_H
+#include "ruby/ruby.h"
+#include "vm_core.h"
+
#define PASS_PASSED_BLOCK_TH(th) do { \
(th)->passed_block = GC_GUARDED_PTR_REF((rb_block_t *)(th)->cfp->lfp[0]); \
(th)->cfp->flag |= VM_FRAME_FLAG_PASSED; \
@@ -12,11 +14,6 @@
PASS_PASSED_BLOCK_TH(__th__); \
} while (0)
-#include "ruby/ruby.h"
-#include "ruby/node.h"
-#include "ruby/util.h"
-#include "vm_core.h"
-
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
@@ -30,9 +27,6 @@
#include <stdio.h>
#include <setjmp.h>
-#include "ruby/st.h"
-#include "dln.h"
-
#ifdef __APPLE__
#include <crt_externs.h>
#endif
@@ -58,14 +52,6 @@ void *alloca();
# endif /* HAVE_ALLOCA_H */
#endif /* __GNUC__ */
-#ifdef HAVE_STDARG_PROTOTYPES
-#include <stdarg.h>
-#define va_init_list(a,b) va_start(a,b)
-#else
-#include <varargs.h>
-#define va_init_list(a,b) va_start(a)
-#endif
-
#ifndef HAVE_STRING_H
char *strrchr(const char *, const char);
#endif
@@ -78,14 +64,6 @@ char *strrchr(const char *, const char);
#include <net/socket.h>
#endif
-#ifdef __MACOS__
-#include "macruby_private.h"
-#endif
-
-#ifdef __VMS
-#include "vmsruby_private.h"
-#endif
-
#define ruby_setjmp(env) RUBY_SETJMP(env)
#define ruby_longjmp(env,val) RUBY_LONGJMP(env,val)
#ifdef __CYGWIN__
@@ -96,10 +74,6 @@ int _setjmp(), _longjmp();
#include <signal.h>
#include <errno.h>
-#if defined(__VMS)
-#pragma nostandard
-#endif
-
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
diff --git a/ext/Setup.dj b/ext/Setup.dj
deleted file mode 100644
index 5276b125a1..0000000000
--- a/ext/Setup.dj
+++ /dev/null
@@ -1,33 +0,0 @@
-option nodynamic
-
-#Win32API
-bigdecimal
-curses
-dbm
-digest
-digest/md5
-digest/rmd160
-digest/sha1
-digest/sha2
-#dl
-etc
-enumerator
-fcntl
-gdbm
-#iconv
-#io/wait
-nkf
-#openssl
-#pty
-racc/cparse
-readline
-ripper
-sdbm
-#socket
-stringio
-strscan
-syck
-#syslog
-#tk
-#win32ole
-zlib
diff --git a/ext/Setup.x68 b/ext/Setup.x68
deleted file mode 100644
index 03f5d2d50d..0000000000
--- a/ext/Setup.x68
+++ /dev/null
@@ -1,33 +0,0 @@
-option nodynamic
-
-#Win32API
-bigdecimal
-#curses
-dbm
-digest
-digest/md5
-digest/rmd160
-digest/sha1
-digest/sha2
-#dl
-#etc
-enumerator
-fcntl
-#gdbm
-#iconv
-#io/wait
-nkf
-#openssl
-#pty
-racc/cparse
-#readline
-#ripper
-#sdbm
-#socket
-stringio
-strscan
-#syck
-#syslog
-#tk
-#win32ole
-#zlib
diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c
index 754c319991..96bd88160c 100644
--- a/ext/bigdecimal/bigdecimal.c
+++ b/ext/bigdecimal/bigdecimal.c
@@ -579,13 +579,6 @@ BigDecimal_to_i(VALUE self)
return rb_cstr2inum(psz,10);
}
-static VALUE
-BigDecimal_induced_from(VALUE self, VALUE x)
-{
- Real *p = GetVpValue(x,1);
- return p->obj;
-}
-
/* Returns a new Float object having approximately the same value as the
* BigDecimal number. Normal accuracy limits and built-in errors of binary
* Float arithmetic apply.
@@ -613,6 +606,41 @@ BigDecimal_to_f(VALUE self)
return rb_float_new(d);
}
+
+static VALUE BigDecimal_split(VALUE self);
+
+/* Converts a BigDecimal to a Rational.
+ */
+static VALUE
+BigDecimal_to_r(VALUE self)
+{
+ Real *p;
+ S_LONG sign, power, denomi_power;
+ VALUE a, digits, numerator;
+
+ p = GetVpValue(self,1);
+ sign = VpGetSign(p);
+ power = VpExponent10(p);
+ a = BigDecimal_split(self);
+ digits = RARRAY_PTR(a)[1];
+ denomi_power = power - RSTRING_LEN(digits);
+ numerator = rb_funcall(digits, rb_intern("to_i"), 0);
+
+ if (sign < 0) {
+ numerator = rb_funcall(numerator, '*', 1, INT2FIX(-1));
+ }
+ if (denomi_power < 0) {
+ return rb_Rational(numerator,
+ rb_funcall(INT2FIX(10), rb_intern("**"), 1,
+ INT2FIX(-denomi_power)));
+ }
+ else {
+ return rb_Rational1(rb_funcall(numerator, '*', 1,
+ rb_funcall(INT2FIX(10), rb_intern("**"), 1,
+ INT2FIX(denomi_power))));
+ }
+}
+
/* The coerce method provides support for Ruby type coercion. It is not
* enabled by default.
*
@@ -1807,7 +1835,6 @@ Init_bigdecimal(void)
rb_define_singleton_method(rb_cBigDecimal, "mode", BigDecimal_mode, -1);
rb_define_singleton_method(rb_cBigDecimal, "limit", BigDecimal_limit, -1);
rb_define_singleton_method(rb_cBigDecimal, "double_fig", BigDecimal_double_fig, 0);
- rb_define_singleton_method(rb_cBigDecimal, "induced_from",BigDecimal_induced_from, 1);
rb_define_singleton_method(rb_cBigDecimal, "_load", BigDecimal_load, 1);
rb_define_singleton_method(rb_cBigDecimal, "ver", BigDecimal_version, 0);
@@ -1926,6 +1953,7 @@ Init_bigdecimal(void)
rb_define_method(rb_cBigDecimal, "to_s", BigDecimal_to_s, -1);
rb_define_method(rb_cBigDecimal, "to_i", BigDecimal_to_i, 0);
rb_define_method(rb_cBigDecimal, "to_int", BigDecimal_to_i, 0);
+ rb_define_method(rb_cBigDecimal, "to_r", BigDecimal_to_r, 0);
rb_define_method(rb_cBigDecimal, "split", BigDecimal_split, 0);
rb_define_method(rb_cBigDecimal, "+", BigDecimal_add, 1);
rb_define_method(rb_cBigDecimal, "-", BigDecimal_sub, 1);
@@ -3944,7 +3972,12 @@ VpCtoV(Real *a, const char *int_chr, U_LONG ni, const char *frac, U_LONG nf, con
es = e*((S_INT)BASE_FIG);
e = e * 10 + exp_chr[i] - '0';
if(es>e*((S_INT)BASE_FIG)) {
- return VpException(VP_EXCEPTION_INFINITY,"exponent overflow",0);
+ VpException(VP_EXCEPTION_INFINITY,"exponent overflow",0);
+ sign = 1;
+ if(int_chr[0] == '-') sign = -1;
+ if(signe > 0) VpSetInf(a, sign);
+ else VpSetZero(a, sign);
+ return 1;
}
++i;
}
@@ -4633,8 +4666,20 @@ VpPower(Real *y, Real *x, S_INT n)
}
goto Exit;
}
- if(!VpIsDef(x)) {
- VpSetNaN(y); /* Not sure !!! */
+ if(VpIsNaN(x)) {
+ VpSetNaN(y);
+ goto Exit;
+ }
+ if(VpIsInf(x)) {
+ if(n==0) {
+ VpSetOne(y);
+ goto Exit;
+ }
+ if(n>0) {
+ VpSetInf(y, (n%2==0 || VpIsPosInf(x)) ? 1 : -1);
+ goto Exit;
+ }
+ VpSetZero(y, (n%2==0 || VpIsPosInf(x)) ? 1 : -1);
goto Exit;
}
diff --git a/ext/bigdecimal/lib/bigdecimal/util.rb b/ext/bigdecimal/lib/bigdecimal/util.rb
index 09e926acd5..257781f035 100644
--- a/ext/bigdecimal/lib/bigdecimal/util.rb
+++ b/ext/bigdecimal/lib/bigdecimal/util.rb
@@ -39,18 +39,6 @@ class BigDecimal < Numeric
i + "." + ("0"*(-z)) + f
end
end
-
- # Converts a BigDecimal to a Rational.
- def to_r
- sign,digits,base,power = self.split
- numerator = sign*digits.to_i
- denomi_power = power - digits.size # base is always 10
- if denomi_power < 0
- Rational(numerator,base ** (-denomi_power))
- else
- Rational(numerator * (base ** denomi_power),1)
- end
- end
end
class Rational < Numeric
diff --git a/ext/curses/curses.c b/ext/curses/curses.c
index 7d4ed87478..778bee4da9 100644
--- a/ext/curses/curses.c
+++ b/ext/curses/curses.c
@@ -14,7 +14,7 @@
*/
#include "ruby.h"
-#include "rubyio.h"
+#include "ruby/io.h"
#if defined(HAVE_NCURSES_H)
# include <ncurses.h>
@@ -307,13 +307,35 @@ curses_flash(VALUE obj)
return Qnil;
}
+static int
+curses_char(VALUE c)
+{
+ if (FIXNUM_P(c)) {
+ return NUM2INT(c);
+ }
+ else {
+ int cc;
+
+ StringValue(c);
+ if (RSTRING_LEN(c) == 0 || RSTRING_LEN(c) > 1) {
+ rb_raise(rb_eArgError, "string not corresponding a character");
+ }
+ cc = RSTRING_PTR(c)[0];
+ if (cc > 0x7f) {
+ rb_raise(rb_eArgError, "no multibyte string supported (yet)");
+ }
+ return cc;
+ }
+}
+
/* def ungetch */
static VALUE
curses_ungetch(VALUE obj, VALUE ch)
{
#ifdef HAVE_UNGETCH
+ int c = curses_char(ch);
curses_stdscr();
- ungetch(NUM2INT(ch));
+ ungetch(c);
#else
rb_notimplement();
#endif
@@ -375,9 +397,11 @@ curses_insch(VALUE obj, VALUE ch)
static VALUE
curses_addstr(VALUE obj, VALUE str)
{
+ StringValue(str);
+ str = rb_str_export_locale(str);
curses_stdscr();
if (!NIL_P(str)) {
- addstr(STR2CSTR(str));
+ addstr(StringValueCStr(str));
}
return Qnil;
}
@@ -386,9 +410,18 @@ curses_addstr(VALUE obj, VALUE str)
static VALUE
curses_getch(VALUE obj)
{
+ int c;
+
rb_read_check(stdin);
curses_stdscr();
- return UINT2NUM(getch());
+ c = getch();
+ if (c == EOF) return Qnil;
+ if (ISPRINT(c)) {
+ char ch = (char)c;
+
+ return rb_locale_str_new(&ch, 1);
+ }
+ return UINT2NUM(c);
}
/* def getstr */
@@ -403,7 +436,7 @@ curses_getstr(VALUE obj)
#else
getstr(rtn);
#endif
- return rb_tainted_str_new2(rtn);
+ return rb_locale_str_new_cstr(rtn);
}
/* def delch */
@@ -439,16 +472,18 @@ static VALUE
curses_keyname(VALUE obj, VALUE c)
{
#ifdef HAVE_KEYNAME
- const char *name;
+ int cc = curses_char(c);
+ const char *name;
- name = keyname(NUM2INT(c));
- if (name) {
- return rb_str_new2(name);
- } else {
- return Qnil;
- }
+ name = keyname(cc);
+ if (name) {
+ return rb_str_new_cstr(name);
+ }
+ else {
+ return Qnil;
+ }
#else
- return Qnil;
+ return Qnil;
#endif
}
@@ -1048,8 +1083,10 @@ window_addstr(VALUE obj, VALUE str)
if (!NIL_P(str)) {
struct windata *winp;
+ StringValue(str);
+ str = rb_str_export_locale(str);
GetWINDOW(obj, winp);
- waddstr(winp->window, STR2CSTR(str));
+ waddstr(winp->window, StringValueCStr(str));
}
return Qnil;
}
@@ -1067,10 +1104,18 @@ static VALUE
window_getch(VALUE obj)
{
struct windata *winp;
-
+ int c;
+
rb_read_check(stdin);
GetWINDOW(obj, winp);
- return UINT2NUM(wgetch(winp->window));
+ c = wgetch(winp->window);
+ if (c == EOF) return Qnil;
+ if (ISPRINT(c)) {
+ char ch = (char)c;
+
+ return rb_locale_str_new(&ch, 1);
+ }
+ return UINT2NUM(c);
}
/* def getstr */
@@ -1087,7 +1132,7 @@ window_getstr(VALUE obj)
#else
wgetstr(winp->window, rtn);
#endif
- return rb_tainted_str_new2(rtn);
+ return rb_locale_str_new_cstr(rtn);
}
/* def delch */
diff --git a/ext/curses/view.rb b/ext/curses/view.rb
index d9a82a57db..239f414b84 100644
--- a/ext/curses/view.rb
+++ b/ext/curses/view.rb
@@ -48,7 +48,7 @@ while TRUE
explicit = FALSE
n = 0
while TRUE
- c = getch.chr
+ c = getch
if c =~ /[0-9]/
n = 10 * n + c.to_i
else
diff --git a/ext/dbm/dbm.c b/ext/dbm/dbm.c
index 42bd4ff057..7a78f8dad0 100644
--- a/ext/dbm/dbm.c
+++ b/ext/dbm/dbm.c
@@ -109,7 +109,7 @@ fdbm_initialize(int argc, VALUE *argv, VALUE obj)
if (!NIL_P(vflags))
flags = NUM2INT(vflags);
- SafeStringValue(file);
+ FilePathValue(file);
if (flags & RUBY_DBM_RW_BIT) {
flags &= ~RUBY_DBM_RW_BIT;
@@ -164,7 +164,7 @@ fdbm_fetch(VALUE obj, VALUE keystr, VALUE ifnone)
struct dbmdata *dbmp;
DBM *dbm;
- StringValue(keystr);
+ ExportStringValue(keystr);
key.dptr = RSTRING_PTR(keystr);
key.dsize = RSTRING_LEN(keystr);
@@ -198,13 +198,13 @@ fdbm_fetch_m(int argc, VALUE *argv, VALUE obj)
}
static VALUE
-fdbm_index(VALUE obj, VALUE valstr)
+fdbm_key(VALUE obj, VALUE valstr)
{
datum key, val;
struct dbmdata *dbmp;
DBM *dbm;
- StringValue(valstr);
+ ExportStringValue(valstr);
val.dptr = RSTRING_PTR(valstr);
val.dsize = RSTRING_LEN(valstr);
@@ -220,6 +220,13 @@ fdbm_index(VALUE obj, VALUE valstr)
}
static VALUE
+fdbm_index(VALUE hash, VALUE value)
+{
+ rb_warn("DBM#index is deprecated; use DBM#key");
+ return fdbm_key(hash, value);
+}
+
+static VALUE
fdbm_select(VALUE obj)
{
VALUE new = rb_ary_new();
@@ -272,7 +279,7 @@ fdbm_delete(VALUE obj, VALUE keystr)
VALUE valstr;
fdbm_modify(obj);
- StringValue(keystr);
+ ExportStringValue(keystr);
key.dptr = RSTRING_PTR(keystr);
key.dsize = RSTRING_LEN(keystr);
@@ -346,7 +353,7 @@ fdbm_delete_if(VALUE obj)
for (i = 0; i < RARRAY_LEN(ary); i++) {
keystr = RARRAY_PTR(ary)[i];
- StringValue(keystr);
+ ExportStringValue(keystr);
key.dptr = RSTRING_PTR(keystr);
key.dsize = RSTRING_LEN(keystr);
if (dbm_delete(dbm, key)) {
@@ -599,7 +606,7 @@ fdbm_has_key(VALUE obj, VALUE keystr)
struct dbmdata *dbmp;
DBM *dbm;
- StringValue(keystr);
+ ExportStringValue(keystr);
key.dptr = RSTRING_PTR(keystr);
key.dsize = RSTRING_LEN(keystr);
@@ -616,7 +623,7 @@ fdbm_has_value(VALUE obj, VALUE valstr)
struct dbmdata *dbmp;
DBM *dbm;
- StringValue(valstr);
+ ExportStringValue(valstr);
val.dptr = RSTRING_PTR(valstr);
val.dsize = RSTRING_LEN(valstr);
@@ -692,6 +699,7 @@ Init_dbm(void)
rb_define_method(rb_cDBM, "[]=", fdbm_store, 2);
rb_define_method(rb_cDBM, "store", fdbm_store, 2);
rb_define_method(rb_cDBM, "index", fdbm_index, 1);
+ rb_define_method(rb_cDBM, "key", fdbm_key, 1);
rb_define_method(rb_cDBM, "select", fdbm_select, 0);
rb_define_method(rb_cDBM, "values_at", fdbm_values_at, -1);
rb_define_method(rb_cDBM, "length", fdbm_length, 0);
diff --git a/ext/dl/extconf.rb b/ext/dl/extconf.rb
index 8ba6c53d0d..c0b8ffd0a1 100644
--- a/ext/dl/extconf.rb
+++ b/ext/dl/extconf.rb
@@ -4,10 +4,14 @@ if( RbConfig::CONFIG['CC'] =~ /gcc/ )
$CFLAGS << " -fno-defer-pop -fno-omit-frame-pointer"
end
+CALLBACKS = (0..8).map{|i| "callback-#{i}"}
+CALLBACK_SRCS = CALLBACKS.map{|basename| "#{basename}.c"}
+CALLBACK_OBJS = CALLBACKS.map{|basename| "#{basename}.o"}
+
$INSTALLFILES = [
["dl.h", "$(HDRDIR)"],
]
-$distcleanfiles << "callback.h"
+$distcleanfiles += [ "callback.h", *CALLBACK_SRCS ]
check = true
@@ -25,12 +29,7 @@ else
check = false
end
-$objs = %w[
- cfunc.o dl.o cptr.o handle.o
- callback-0.o callback-1.o callback-2.o callback-3.o
- callback-4.o callback-5.o callback-6.o callback-7.o
- callback-8.o
-]
+$objs = %w[ cfunc.o dl.o cptr.o handle.o ] + CALLBACK_OBJS
if check
$defs << %[-DRUBY_VERSION=\\"#{RUBY_VERSION}\\"]
diff --git a/ext/etc/etc.c b/ext/etc/etc.c
index f09c8d76db..cb850f6987 100644
--- a/ext/etc/etc.c
+++ b/ext/etc/etc.c
@@ -26,7 +26,10 @@
#define uid_t int
#endif
-static VALUE sPasswd, sGroup;
+static VALUE sPasswd;
+#ifdef HAVE_GETGRENT
+static VALUE sGroup;
+#endif
#ifndef _WIN32
char *getenv();
@@ -132,7 +135,7 @@ etc_getpwuid(int argc, VALUE *argv, VALUE obj)
uid = getuid();
}
pwd = getpwuid(uid);
- if (pwd == 0) rb_raise(rb_eArgError, "can't find user for %d", uid);
+ if (pwd == 0) rb_raise(rb_eArgError, "can't find user for %d", (int)uid);
return setup_passwd(pwd);
#else
return Qnil;
@@ -333,7 +336,7 @@ etc_getgrgid(int argc, VALUE *argv, VALUE obj)
gid = getgid();
}
grp = getgrgid(gid);
- if (grp == 0) rb_raise(rb_eArgError, "can't find group for %d", gid);
+ if (grp == 0) rb_raise(rb_eArgError, "can't find group for %d", (int)gid);
return setup_group(grp);
#else
return Qnil;
diff --git a/ext/extmk.rb b/ext/extmk.rb
index 52f10defea..be3ad8d248 100644
--- a/ext/extmk.rb
+++ b/ext/extmk.rb
@@ -39,7 +39,7 @@ load File.expand_path("lib/mkmf.rb", srcdir)
require 'optparse/shellwords'
def sysquote(x)
- @quote ||= /human|os2|macos/ =~ (CROSS_COMPILING || RUBY_PLATFORM)
+ @quote ||= /os2/ =~ (CROSS_COMPILING || RUBY_PLATFORM)
@quote ? x.quote : x
end
@@ -343,7 +343,6 @@ unless CROSS_COMPILING
ENV["RUBYLIB"] = "-"
ENV["RUBYOPT"] = "-r#{File.expand_path('ext/purelib.rb', $top_srcdir)}"
end
-$config_h = '$(arch_hdrdir)/ruby/config.h'
$mflags << "ruby=#$ruby"
MTIMES = [__FILE__, 'rbconfig.rb', srcdir+'/lib/mkmf.rb'].collect {|f| File.mtime(f)}
@@ -507,7 +506,7 @@ void Init_ext _((void))\n{\n#$extinit}
end
$extobjs = "ext/#{extinit.o} #{$extobjs}"
- if RUBY_PLATFORM =~ /m68k-human|beos/
+ if RUBY_PLATFORM =~ /beos/
$extflags.delete("-L/usr/local/lib")
end
$extpath.delete("$(topdir)")
diff --git a/ext/gdbm/gdbm.c b/ext/gdbm/gdbm.c
index e6a6e0d039..1e83608132 100644
--- a/ext/gdbm/gdbm.c
+++ b/ext/gdbm/gdbm.c
@@ -396,13 +396,13 @@ fgdbm_fetch_m(int argc, VALUE *argv, VALUE obj)
/*
* call-seq:
- * gdbm.index(value) -> key
+ * gdbm.key(value) -> key
*
* Returns the _key_ for a given _value_. If several keys may map to the
* same value, the key that is found first will be returned.
*/
static VALUE
-fgdbm_index(VALUE obj, VALUE valstr)
+fgdbm_key(VALUE obj, VALUE valstr)
{
struct dbmdata *dbmp;
GDBM_FILE dbm;
@@ -424,6 +424,14 @@ fgdbm_index(VALUE obj, VALUE valstr)
return Qnil;
}
+/* :nodoc: */
+static VALUE
+fgdbm_index(VALUE obj, VALUE value)
+{
+ rb_warn("GDBM#index is deprecated; use GDBM#key");
+ return fgdbm_key(obj, value);
+}
+
/*
* call-seq:
* gdbm.select { |value| block } -> array
@@ -1180,6 +1188,7 @@ Init_gdbm(void)
rb_define_method(rb_cGDBM, "[]=", fgdbm_store, 2);
rb_define_method(rb_cGDBM, "store", fgdbm_store, 2);
rb_define_method(rb_cGDBM, "index", fgdbm_index, 1);
+ rb_define_method(rb_cGDBM, "key", fgdbm_key, 1);
rb_define_method(rb_cGDBM, "select", fgdbm_select, 0);
rb_define_method(rb_cGDBM, "values_at", fgdbm_values_at, -1);
rb_define_method(rb_cGDBM, "length", fgdbm_length, 0);
diff --git a/ext/iconv/iconv.c b/ext/iconv/iconv.c
index 14ef9ae380..6ff49e5b5c 100644
--- a/ext/iconv/iconv.c
+++ b/ext/iconv/iconv.c
@@ -66,6 +66,12 @@
* 4. Shorthand for (3).
*
* Iconv.iconv(to, from, *input.to_a)
+ *
+ * == Attentions
+ *
+ * Even if some extentions of implementation dependent are useful,
+ * DON'T USE those extentions in libraries and scripts to widely distribute.
+ * If you want to use those feature, use String#encode.
*/
/* Invalid value for iconv_t is -1 but 0 for VALUE, I hope VALUE is
@@ -138,9 +144,10 @@ charset_map_get(void)
static VALUE
strip_glibc_option(VALUE *code)
{
- VALUE val = *code;
+ VALUE val = StringValue(*code);
const char *ptr = RSTRING_PTR(val), *pend = RSTRING_END(val);
const char *slash = memchr(ptr, '/', pend - ptr);
+
if (slash && slash < pend - 1 && slash[1] == '/') {
VALUE opt = rb_str_subseq(val, slash - ptr, pend - slash);
val = rb_str_subseq(val, 0, slash - ptr);
@@ -153,7 +160,7 @@ strip_glibc_option(VALUE *code)
static char *
map_charset(VALUE *code)
{
- VALUE val = *code;
+ VALUE val = StringValue(*code);
if (RHASH_SIZE(charset_map)) {
VALUE key = rb_funcall2(val, rb_intern("downcase"), 0, 0);
diff --git a/ext/io/wait/extconf.rb b/ext/io/wait/extconf.rb
index 1a0edbd846..eed3543124 100644
--- a/ext/io/wait/extconf.rb
+++ b/ext/io/wait/extconf.rb
@@ -2,8 +2,9 @@ require 'mkmf'
target = "io/wait"
unless macro_defined?("DOSISH", "#include <ruby.h>")
+ have_header(ioctl_h = "sys/ioctl.h") or ioctl_h = nil
fionread = %w[sys/ioctl.h sys/filio.h sys/socket.h].find do |h|
- have_macro("FIONREAD", h)
+ have_macro("FIONREAD", [h, ioctl_h].compact)
end
if fionread
$defs << "-DFIONREAD_HEADER=\"<#{fionread}>\""
diff --git a/ext/io/wait/wait.c b/ext/io/wait/wait.c
index 5986f61b39..42f5e8fc48 100644
--- a/ext/io/wait/wait.c
+++ b/ext/io/wait/wait.c
@@ -11,9 +11,12 @@
**********************************************************************/
#include "ruby.h"
-#include "rubyio.h"
+#include "ruby/io.h"
#include <sys/types.h>
+#if defined(HAVE_SYS_IOCTL_H)
+#include <sys/ioctl.h>
+#endif
#if defined(FIONREAD_HEADER)
#include FIONREAD_HEADER
#endif
diff --git a/ext/json/ext/generator/extconf.rb b/ext/json/ext/generator/extconf.rb
index 86ed7e6367..55741516f4 100644
--- a/ext/json/ext/generator/extconf.rb
+++ b/ext/json/ext/generator/extconf.rb
@@ -2,9 +2,8 @@ require 'mkmf'
require 'rbconfig'
if CONFIG['CC'] =~ /gcc/
- #$CFLAGS += ' -Wall -ggdb'
$CFLAGS += ' -Wall'
+ #$CFLAGS += ' -O0 -ggdb'
end
-have_header 'st.h'
create_makefile 'json/ext/generator'
diff --git a/ext/json/ext/generator/generator.c b/ext/json/ext/generator/generator.c
index b8a1ea16d1..1f48d3c780 100644
--- a/ext/json/ext/generator/generator.c
+++ b/ext/json/ext/generator/generator.c
@@ -1,15 +1,8 @@
-/* vim: set cin et sw=4 ts=4: */
-
+#include <string.h>
#include "ruby.h"
-#include "ruby/st.h"
#include "unicode.h"
-#include <string.h>
#include <math.h>
-#ifdef HAVE_IEEEFP_H
-#include <ieeefp.h>
-#endif
-
#define check_max_nesting(state, depth) do { \
long current_nesting = 1 + depth; \
if (state->max_nesting != 0 && current_nesting > state->max_nesting) \
@@ -297,14 +290,14 @@ static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self)
return rb_funcall(self, i_to_s, 0);
} else {
tmp = rb_funcall(self, i_to_s, 0);
- rb_raise(eGeneratorError, "%s not allowed in JSON", StringValueCStr(tmp));
+ rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
}
} else if (isnan(value)) {
if (!state || state->allow_nan) {
return rb_funcall(self, i_to_s, 0);
} else {
tmp = rb_funcall(self, i_to_s, 0);
- rb_raise(eGeneratorError, "%s not allowed in JSON", StringValueCStr(tmp));
+ rb_raise(eGeneratorError, "%u: %s not allowed in JSON", __LINE__, StringValueCStr(tmp));
}
} else {
return rb_funcall(self, i_to_s, 0);
diff --git a/ext/json/ext/generator/unicode.c b/ext/json/ext/generator/unicode.c
index 44e1f41f98..76834eadc5 100644
--- a/ext/json/ext/generator/unicode.c
+++ b/ext/json/ext/generator/unicode.c
@@ -1,5 +1,3 @@
-/* vim: set cin et sw=4 ts=4: */
-
#include "unicode.h"
#define unicode_escape(buffer, character) \
diff --git a/ext/json/ext/parser/extconf.rb b/ext/json/ext/parser/extconf.rb
index b2e7b051a4..b56c4e66d7 100644
--- a/ext/json/ext/parser/extconf.rb
+++ b/ext/json/ext/parser/extconf.rb
@@ -2,9 +2,8 @@ require 'mkmf'
require 'rbconfig'
if CONFIG['CC'] =~ /gcc/
- #$CFLAGS += ' -Wall -ggdb'
$CFLAGS += ' -Wall'
+ #$CFLAGS += ' -O0 -ggdb'
end
-have_header 'st.h'
create_makefile 'json/ext/parser'
diff --git a/ext/json/ext/parser/parser.c b/ext/json/ext/parser/parser.c
index 8734de2f5b..9de618d0e6 100644
--- a/ext/json/ext/parser/parser.c
+++ b/ext/json/ext/parser/parser.c
@@ -1,9 +1,5 @@
#line 1 "parser.rl"
-/* vim: set cin et sw=4 ts=4: */
-
#include "ruby.h"
-#include "ruby/re.h"
-#include "ruby/st.h"
#include "ruby/encoding.h"
#include "unicode.h"
@@ -39,18 +35,18 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
JSON_Parser *json; \
Data_Get_Struct(self, JSON_Parser, json);
-#line 67 "parser.rl"
+#line 64 "parser.rl"
-#line 47 "parser.c"
+#line 44 "parser.c"
static const int JSON_object_start = 1;
static const int JSON_object_first_final = 27;
static const int JSON_object_error = 0;
static const int JSON_object_en_main = 1;
-#line 100 "parser.rl"
+#line 97 "parser.rl"
static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -65,16 +61,16 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
*result = rb_hash_new();
-#line 69 "parser.c"
+#line 66 "parser.c"
{
cs = JSON_object_start;
}
-#line 114 "parser.rl"
+#line 111 "parser.rl"
-#line 75 "parser.c"
+#line 72 "parser.c"
{
if ( p == pe )
- goto _out;
+ goto _test_eof;
switch ( cs )
{
case 1:
@@ -82,10 +78,11 @@ case 1:
goto st2;
goto st0;
st0:
- goto _out0;
+cs = 0;
+ goto _out;
st2:
if ( ++p == pe )
- goto _out2;
+ goto _test_eof2;
case 2:
switch( (*p) ) {
case 13: goto st2;
@@ -98,17 +95,17 @@ case 2:
goto st2;
goto st0;
tr2:
-#line 86 "parser.rl"
+#line 83 "parser.rl"
{
char *np = JSON_parse_string(json, p, pe, &last_name);
- if (np == NULL) goto _out3; else {p = (( np))-1;}
+ if (np == NULL) { p--; {p++; cs = 3; goto _out;} } else {p = (( np))-1;}
}
goto st3;
st3:
if ( ++p == pe )
- goto _out3;
+ goto _test_eof3;
case 3:
-#line 112 "parser.c"
+#line 110 "parser.c"
switch( (*p) ) {
case 13: goto st3;
case 32: goto st3;
@@ -120,7 +117,7 @@ case 3:
goto st0;
st4:
if ( ++p == pe )
- goto _out4;
+ goto _test_eof4;
case 4:
switch( (*p) ) {
case 42: goto st5;
@@ -129,14 +126,14 @@ case 4:
goto st0;
st5:
if ( ++p == pe )
- goto _out5;
+ goto _test_eof5;
case 5:
if ( (*p) == 42 )
goto st6;
goto st5;
st6:
if ( ++p == pe )
- goto _out6;
+ goto _test_eof6;
case 6:
switch( (*p) ) {
case 42: goto st6;
@@ -145,14 +142,14 @@ case 6:
goto st5;
st7:
if ( ++p == pe )
- goto _out7;
+ goto _test_eof7;
case 7:
if ( (*p) == 10 )
goto st3;
goto st7;
st8:
if ( ++p == pe )
- goto _out8;
+ goto _test_eof8;
case 8:
switch( (*p) ) {
case 13: goto st8;
@@ -175,12 +172,12 @@ case 8:
goto st8;
goto st0;
tr11:
-#line 75 "parser.rl"
+#line 72 "parser.rl"
{
VALUE v = Qnil;
char *np = JSON_parse_value(json, p, pe, &v);
if (np == NULL) {
- goto _out9;
+ p--; {p++; cs = 9; goto _out;}
} else {
rb_hash_aset(*result, last_name, v);
{p = (( np))-1;}
@@ -189,9 +186,9 @@ tr11:
goto st9;
st9:
if ( ++p == pe )
- goto _out9;
+ goto _test_eof9;
case 9:
-#line 195 "parser.c"
+#line 193 "parser.c"
switch( (*p) ) {
case 13: goto st9;
case 32: goto st9;
@@ -204,7 +201,7 @@ case 9:
goto st0;
st10:
if ( ++p == pe )
- goto _out10;
+ goto _test_eof10;
case 10:
switch( (*p) ) {
case 13: goto st10;
@@ -217,7 +214,7 @@ case 10:
goto st0;
st11:
if ( ++p == pe )
- goto _out11;
+ goto _test_eof11;
case 11:
switch( (*p) ) {
case 42: goto st12;
@@ -226,14 +223,14 @@ case 11:
goto st0;
st12:
if ( ++p == pe )
- goto _out12;
+ goto _test_eof12;
case 12:
if ( (*p) == 42 )
goto st13;
goto st12;
st13:
if ( ++p == pe )
- goto _out13;
+ goto _test_eof13;
case 13:
switch( (*p) ) {
case 42: goto st13;
@@ -242,14 +239,14 @@ case 13:
goto st12;
st14:
if ( ++p == pe )
- goto _out14;
+ goto _test_eof14;
case 14:
if ( (*p) == 10 )
goto st10;
goto st14;
st15:
if ( ++p == pe )
- goto _out15;
+ goto _test_eof15;
case 15:
switch( (*p) ) {
case 42: goto st16;
@@ -258,14 +255,14 @@ case 15:
goto st0;
st16:
if ( ++p == pe )
- goto _out16;
+ goto _test_eof16;
case 16:
if ( (*p) == 42 )
goto st17;
goto st16;
st17:
if ( ++p == pe )
- goto _out17;
+ goto _test_eof17;
case 17:
switch( (*p) ) {
case 42: goto st17;
@@ -274,24 +271,24 @@ case 17:
goto st16;
st18:
if ( ++p == pe )
- goto _out18;
+ goto _test_eof18;
case 18:
if ( (*p) == 10 )
goto st9;
goto st18;
tr4:
-#line 91 "parser.rl"
- { goto _out27; }
+#line 88 "parser.rl"
+ { p--; {p++; cs = 27; goto _out;} }
goto st27;
st27:
if ( ++p == pe )
- goto _out27;
+ goto _test_eof27;
case 27:
-#line 291 "parser.c"
+#line 289 "parser.c"
goto st0;
st19:
if ( ++p == pe )
- goto _out19;
+ goto _test_eof19;
case 19:
switch( (*p) ) {
case 42: goto st20;
@@ -300,14 +297,14 @@ case 19:
goto st0;
st20:
if ( ++p == pe )
- goto _out20;
+ goto _test_eof20;
case 20:
if ( (*p) == 42 )
goto st21;
goto st20;
st21:
if ( ++p == pe )
- goto _out21;
+ goto _test_eof21;
case 21:
switch( (*p) ) {
case 42: goto st21;
@@ -316,14 +313,14 @@ case 21:
goto st20;
st22:
if ( ++p == pe )
- goto _out22;
+ goto _test_eof22;
case 22:
if ( (*p) == 10 )
goto st8;
goto st22;
st23:
if ( ++p == pe )
- goto _out23;
+ goto _test_eof23;
case 23:
switch( (*p) ) {
case 42: goto st24;
@@ -332,14 +329,14 @@ case 23:
goto st0;
st24:
if ( ++p == pe )
- goto _out24;
+ goto _test_eof24;
case 24:
if ( (*p) == 42 )
goto st25;
goto st24;
st25:
if ( ++p == pe )
- goto _out25;
+ goto _test_eof25;
case 25:
switch( (*p) ) {
case 42: goto st25;
@@ -348,43 +345,43 @@ case 25:
goto st24;
st26:
if ( ++p == pe )
- goto _out26;
+ goto _test_eof26;
case 26:
if ( (*p) == 10 )
goto st2;
goto st26;
}
- _out0: cs = 0; goto _out;
- _out2: cs = 2; goto _out;
- _out3: cs = 3; goto _out;
- _out4: cs = 4; goto _out;
- _out5: cs = 5; goto _out;
- _out6: cs = 6; goto _out;
- _out7: cs = 7; goto _out;
- _out8: cs = 8; goto _out;
- _out9: cs = 9; goto _out;
- _out10: cs = 10; goto _out;
- _out11: cs = 11; goto _out;
- _out12: cs = 12; goto _out;
- _out13: cs = 13; goto _out;
- _out14: cs = 14; goto _out;
- _out15: cs = 15; goto _out;
- _out16: cs = 16; goto _out;
- _out17: cs = 17; goto _out;
- _out18: cs = 18; goto _out;
- _out27: cs = 27; goto _out;
- _out19: cs = 19; goto _out;
- _out20: cs = 20; goto _out;
- _out21: cs = 21; goto _out;
- _out22: cs = 22; goto _out;
- _out23: cs = 23; goto _out;
- _out24: cs = 24; goto _out;
- _out25: cs = 25; goto _out;
- _out26: cs = 26; goto _out;
-
+ _test_eof2: cs = 2; goto _test_eof;
+ _test_eof3: cs = 3; goto _test_eof;
+ _test_eof4: cs = 4; goto _test_eof;
+ _test_eof5: cs = 5; goto _test_eof;
+ _test_eof6: cs = 6; goto _test_eof;
+ _test_eof7: cs = 7; goto _test_eof;
+ _test_eof8: cs = 8; goto _test_eof;
+ _test_eof9: cs = 9; goto _test_eof;
+ _test_eof10: cs = 10; goto _test_eof;
+ _test_eof11: cs = 11; goto _test_eof;
+ _test_eof12: cs = 12; goto _test_eof;
+ _test_eof13: cs = 13; goto _test_eof;
+ _test_eof14: cs = 14; goto _test_eof;
+ _test_eof15: cs = 15; goto _test_eof;
+ _test_eof16: cs = 16; goto _test_eof;
+ _test_eof17: cs = 17; goto _test_eof;
+ _test_eof18: cs = 18; goto _test_eof;
+ _test_eof27: cs = 27; goto _test_eof;
+ _test_eof19: cs = 19; goto _test_eof;
+ _test_eof20: cs = 20; goto _test_eof;
+ _test_eof21: cs = 21; goto _test_eof;
+ _test_eof22: cs = 22; goto _test_eof;
+ _test_eof23: cs = 23; goto _test_eof;
+ _test_eof24: cs = 24; goto _test_eof;
+ _test_eof25: cs = 25; goto _test_eof;
+ _test_eof26: cs = 26; goto _test_eof;
+
+ _test_eof: {}
_out: {}
}
-#line 115 "parser.rl"
+#line 112 "parser.rl"
if (cs >= JSON_object_first_final) {
if (RTEST(json->create_id)) {
@@ -403,14 +400,14 @@ case 26:
}
-#line 407 "parser.c"
+#line 405 "parser.c"
static const int JSON_value_start = 1;
static const int JSON_value_first_final = 21;
static const int JSON_value_error = 0;
static const int JSON_value_en_main = 1;
-#line 213 "parser.rl"
+#line 210 "parser.rl"
static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -418,16 +415,16 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
int cs = EVIL;
-#line 422 "parser.c"
+#line 420 "parser.c"
{
cs = JSON_value_start;
}
-#line 220 "parser.rl"
+#line 217 "parser.rl"
-#line 428 "parser.c"
+#line 426 "parser.c"
{
if ( p == pe )
- goto _out;
+ goto _test_eof;
switch ( cs )
{
case 1:
@@ -446,259 +443,260 @@ case 1:
goto tr2;
goto st0;
st0:
- goto _out0;
+cs = 0;
+ goto _out;
tr0:
-#line 161 "parser.rl"
+#line 158 "parser.rl"
{
char *np = JSON_parse_string(json, p, pe, result);
- if (np == NULL) goto _out21; else {p = (( np))-1;}
+ if (np == NULL) { p--; {p++; cs = 21; goto _out;} } else {p = (( np))-1;}
}
goto st21;
tr2:
-#line 166 "parser.rl"
+#line 163 "parser.rl"
{
char *np;
if(pe > p + 9 && !strncmp(MinusInfinity, p, 9)) {
if (json->allow_nan) {
*result = CMinusInfinity;
{p = (( p + 10))-1;}
- goto _out21;
+ p--; {p++; cs = 21; goto _out;}
} else {
- rb_raise(eParserError, "unexpected token at '%s'", p);
+ rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
}
}
np = JSON_parse_float(json, p, pe, result);
if (np != NULL) {p = (( np))-1;}
np = JSON_parse_integer(json, p, pe, result);
if (np != NULL) {p = (( np))-1;}
- goto _out21;
+ p--; {p++; cs = 21; goto _out;}
}
goto st21;
tr5:
-#line 184 "parser.rl"
+#line 181 "parser.rl"
{
char *np;
- json->current_nesting += 1;
+ json->current_nesting++;
np = JSON_parse_array(json, p, pe, result);
- json->current_nesting -= 1;
- if (np == NULL) goto _out21; else {p = (( np))-1;}
+ json->current_nesting--;
+ if (np == NULL) { p--; {p++; cs = 21; goto _out;} } else {p = (( np))-1;}
}
goto st21;
tr9:
-#line 192 "parser.rl"
+#line 189 "parser.rl"
{
char *np;
- json->current_nesting += 1;
+ json->current_nesting++;
np = JSON_parse_object(json, p, pe, result);
- json->current_nesting -= 1;
- if (np == NULL) goto _out21; else {p = (( np))-1;}
+ json->current_nesting--;
+ if (np == NULL) { p--; {p++; cs = 21; goto _out;} } else {p = (( np))-1;}
}
goto st21;
tr16:
-#line 154 "parser.rl"
+#line 151 "parser.rl"
{
if (json->allow_nan) {
*result = CInfinity;
} else {
- rb_raise(eParserError, "unexpected token at '%s'", p - 8);
+ rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p - 8);
}
}
goto st21;
tr18:
-#line 147 "parser.rl"
+#line 144 "parser.rl"
{
if (json->allow_nan) {
*result = CNaN;
} else {
- rb_raise(eParserError, "unexpected token at '%s'", p - 2);
+ rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p - 2);
}
}
goto st21;
tr22:
-#line 141 "parser.rl"
+#line 138 "parser.rl"
{
*result = Qfalse;
}
goto st21;
tr25:
-#line 138 "parser.rl"
+#line 135 "parser.rl"
{
*result = Qnil;
}
goto st21;
tr28:
-#line 144 "parser.rl"
+#line 141 "parser.rl"
{
*result = Qtrue;
}
goto st21;
st21:
if ( ++p == pe )
- goto _out21;
+ goto _test_eof21;
case 21:
-#line 200 "parser.rl"
- { goto _out21; }
-#line 542 "parser.c"
+#line 197 "parser.rl"
+ { p--; {p++; cs = 21; goto _out;} }
+#line 541 "parser.c"
goto st0;
st2:
if ( ++p == pe )
- goto _out2;
+ goto _test_eof2;
case 2:
if ( (*p) == 110 )
goto st3;
goto st0;
st3:
if ( ++p == pe )
- goto _out3;
+ goto _test_eof3;
case 3:
if ( (*p) == 102 )
goto st4;
goto st0;
st4:
if ( ++p == pe )
- goto _out4;
+ goto _test_eof4;
case 4:
if ( (*p) == 105 )
goto st5;
goto st0;
st5:
if ( ++p == pe )
- goto _out5;
+ goto _test_eof5;
case 5:
if ( (*p) == 110 )
goto st6;
goto st0;
st6:
if ( ++p == pe )
- goto _out6;
+ goto _test_eof6;
case 6:
if ( (*p) == 105 )
goto st7;
goto st0;
st7:
if ( ++p == pe )
- goto _out7;
+ goto _test_eof7;
case 7:
if ( (*p) == 116 )
goto st8;
goto st0;
st8:
if ( ++p == pe )
- goto _out8;
+ goto _test_eof8;
case 8:
if ( (*p) == 121 )
goto tr16;
goto st0;
st9:
if ( ++p == pe )
- goto _out9;
+ goto _test_eof9;
case 9:
if ( (*p) == 97 )
goto st10;
goto st0;
st10:
if ( ++p == pe )
- goto _out10;
+ goto _test_eof10;
case 10:
if ( (*p) == 78 )
goto tr18;
goto st0;
st11:
if ( ++p == pe )
- goto _out11;
+ goto _test_eof11;
case 11:
if ( (*p) == 97 )
goto st12;
goto st0;
st12:
if ( ++p == pe )
- goto _out12;
+ goto _test_eof12;
case 12:
if ( (*p) == 108 )
goto st13;
goto st0;
st13:
if ( ++p == pe )
- goto _out13;
+ goto _test_eof13;
case 13:
if ( (*p) == 115 )
goto st14;
goto st0;
st14:
if ( ++p == pe )
- goto _out14;
+ goto _test_eof14;
case 14:
if ( (*p) == 101 )
goto tr22;
goto st0;
st15:
if ( ++p == pe )
- goto _out15;
+ goto _test_eof15;
case 15:
if ( (*p) == 117 )
goto st16;
goto st0;
st16:
if ( ++p == pe )
- goto _out16;
+ goto _test_eof16;
case 16:
if ( (*p) == 108 )
goto st17;
goto st0;
st17:
if ( ++p == pe )
- goto _out17;
+ goto _test_eof17;
case 17:
if ( (*p) == 108 )
goto tr25;
goto st0;
st18:
if ( ++p == pe )
- goto _out18;
+ goto _test_eof18;
case 18:
if ( (*p) == 114 )
goto st19;
goto st0;
st19:
if ( ++p == pe )
- goto _out19;
+ goto _test_eof19;
case 19:
if ( (*p) == 117 )
goto st20;
goto st0;
st20:
if ( ++p == pe )
- goto _out20;
+ goto _test_eof20;
case 20:
if ( (*p) == 101 )
goto tr28;
goto st0;
}
- _out0: cs = 0; goto _out;
- _out21: cs = 21; goto _out;
- _out2: cs = 2; goto _out;
- _out3: cs = 3; goto _out;
- _out4: cs = 4; goto _out;
- _out5: cs = 5; goto _out;
- _out6: cs = 6; goto _out;
- _out7: cs = 7; goto _out;
- _out8: cs = 8; goto _out;
- _out9: cs = 9; goto _out;
- _out10: cs = 10; goto _out;
- _out11: cs = 11; goto _out;
- _out12: cs = 12; goto _out;
- _out13: cs = 13; goto _out;
- _out14: cs = 14; goto _out;
- _out15: cs = 15; goto _out;
- _out16: cs = 16; goto _out;
- _out17: cs = 17; goto _out;
- _out18: cs = 18; goto _out;
- _out19: cs = 19; goto _out;
- _out20: cs = 20; goto _out;
-
+ _test_eof21: cs = 21; goto _test_eof;
+ _test_eof2: cs = 2; goto _test_eof;
+ _test_eof3: cs = 3; goto _test_eof;
+ _test_eof4: cs = 4; goto _test_eof;
+ _test_eof5: cs = 5; goto _test_eof;
+ _test_eof6: cs = 6; goto _test_eof;
+ _test_eof7: cs = 7; goto _test_eof;
+ _test_eof8: cs = 8; goto _test_eof;
+ _test_eof9: cs = 9; goto _test_eof;
+ _test_eof10: cs = 10; goto _test_eof;
+ _test_eof11: cs = 11; goto _test_eof;
+ _test_eof12: cs = 12; goto _test_eof;
+ _test_eof13: cs = 13; goto _test_eof;
+ _test_eof14: cs = 14; goto _test_eof;
+ _test_eof15: cs = 15; goto _test_eof;
+ _test_eof16: cs = 16; goto _test_eof;
+ _test_eof17: cs = 17; goto _test_eof;
+ _test_eof18: cs = 18; goto _test_eof;
+ _test_eof19: cs = 19; goto _test_eof;
+ _test_eof20: cs = 20; goto _test_eof;
+
+ _test_eof: {}
_out: {}
}
-#line 221 "parser.rl"
+#line 218 "parser.rl"
if (cs >= JSON_value_first_final) {
return p;
@@ -708,14 +706,14 @@ case 20:
}
-#line 712 "parser.c"
+#line 711 "parser.c"
static const int JSON_integer_start = 1;
static const int JSON_integer_first_final = 5;
static const int JSON_integer_error = 0;
static const int JSON_integer_en_main = 1;
-#line 237 "parser.rl"
+#line 234 "parser.rl"
static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -723,17 +721,17 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
int cs = EVIL;
-#line 727 "parser.c"
+#line 726 "parser.c"
{
cs = JSON_integer_start;
}
-#line 244 "parser.rl"
+#line 241 "parser.rl"
json->memo = p;
-#line 734 "parser.c"
+#line 733 "parser.c"
{
if ( p == pe )
- goto _out;
+ goto _test_eof;
switch ( cs )
{
case 1:
@@ -745,10 +743,11 @@ case 1:
goto st4;
goto st0;
st0:
- goto _out0;
+cs = 0;
+ goto _out;
st2:
if ( ++p == pe )
- goto _out2;
+ goto _test_eof2;
case 2:
if ( (*p) == 48 )
goto st3;
@@ -757,38 +756,38 @@ case 2:
goto st0;
st3:
if ( ++p == pe )
- goto _out3;
+ goto _test_eof3;
case 3:
if ( 48 <= (*p) && (*p) <= 57 )
goto st0;
goto tr4;
tr4:
-#line 234 "parser.rl"
- { goto _out5; }
+#line 231 "parser.rl"
+ { p--; {p++; cs = 5; goto _out;} }
goto st5;
st5:
if ( ++p == pe )
- goto _out5;
+ goto _test_eof5;
case 5:
#line 774 "parser.c"
goto st0;
st4:
if ( ++p == pe )
- goto _out4;
+ goto _test_eof4;
case 4:
if ( 48 <= (*p) && (*p) <= 57 )
goto st4;
goto tr4;
}
- _out0: cs = 0; goto _out;
- _out2: cs = 2; goto _out;
- _out3: cs = 3; goto _out;
- _out5: cs = 5; goto _out;
- _out4: cs = 4; goto _out;
+ _test_eof2: cs = 2; goto _test_eof;
+ _test_eof3: cs = 3; goto _test_eof;
+ _test_eof5: cs = 5; goto _test_eof;
+ _test_eof4: cs = 4; goto _test_eof;
+ _test_eof: {}
_out: {}
}
-#line 246 "parser.rl"
+#line 243 "parser.rl"
if (cs >= JSON_integer_first_final) {
long len = p - json->memo;
@@ -807,7 +806,7 @@ static const int JSON_float_error = 0;
static const int JSON_float_en_main = 1;
-#line 268 "parser.rl"
+#line 265 "parser.rl"
static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -819,13 +818,13 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
{
cs = JSON_float_start;
}
-#line 275 "parser.rl"
+#line 272 "parser.rl"
json->memo = p;
#line 826 "parser.c"
{
if ( p == pe )
- goto _out;
+ goto _test_eof;
switch ( cs )
{
case 1:
@@ -837,10 +836,11 @@ case 1:
goto st9;
goto st0;
st0:
- goto _out0;
+cs = 0;
+ goto _out;
st2:
if ( ++p == pe )
- goto _out2;
+ goto _test_eof2;
case 2:
if ( (*p) == 48 )
goto st3;
@@ -849,7 +849,7 @@ case 2:
goto st0;
st3:
if ( ++p == pe )
- goto _out3;
+ goto _test_eof3;
case 3:
switch( (*p) ) {
case 46: goto st4;
@@ -859,14 +859,14 @@ case 3:
goto st0;
st4:
if ( ++p == pe )
- goto _out4;
+ goto _test_eof4;
case 4:
if ( 48 <= (*p) && (*p) <= 57 )
goto st5;
goto st0;
st5:
if ( ++p == pe )
- goto _out5;
+ goto _test_eof5;
case 5:
switch( (*p) ) {
case 69: goto st6;
@@ -879,18 +879,18 @@ case 5:
goto st0;
goto tr7;
tr7:
-#line 262 "parser.rl"
- { goto _out10; }
+#line 259 "parser.rl"
+ { p--; {p++; cs = 10; goto _out;} }
goto st10;
st10:
if ( ++p == pe )
- goto _out10;
+ goto _test_eof10;
case 10:
-#line 890 "parser.c"
+#line 891 "parser.c"
goto st0;
st6:
if ( ++p == pe )
- goto _out6;
+ goto _test_eof6;
case 6:
switch( (*p) ) {
case 43: goto st7;
@@ -901,14 +901,14 @@ case 6:
goto st0;
st7:
if ( ++p == pe )
- goto _out7;
+ goto _test_eof7;
case 7:
if ( 48 <= (*p) && (*p) <= 57 )
goto st8;
goto st0;
st8:
if ( ++p == pe )
- goto _out8;
+ goto _test_eof8;
case 8:
switch( (*p) ) {
case 69: goto st0;
@@ -922,7 +922,7 @@ case 8:
goto tr7;
st9:
if ( ++p == pe )
- goto _out9;
+ goto _test_eof9;
case 9:
switch( (*p) ) {
case 46: goto st4;
@@ -933,20 +933,20 @@ case 9:
goto st9;
goto st0;
}
- _out0: cs = 0; goto _out;
- _out2: cs = 2; goto _out;
- _out3: cs = 3; goto _out;
- _out4: cs = 4; goto _out;
- _out5: cs = 5; goto _out;
- _out10: cs = 10; goto _out;
- _out6: cs = 6; goto _out;
- _out7: cs = 7; goto _out;
- _out8: cs = 8; goto _out;
- _out9: cs = 9; goto _out;
-
+ _test_eof2: cs = 2; goto _test_eof;
+ _test_eof3: cs = 3; goto _test_eof;
+ _test_eof4: cs = 4; goto _test_eof;
+ _test_eof5: cs = 5; goto _test_eof;
+ _test_eof10: cs = 10; goto _test_eof;
+ _test_eof6: cs = 6; goto _test_eof;
+ _test_eof7: cs = 7; goto _test_eof;
+ _test_eof8: cs = 8; goto _test_eof;
+ _test_eof9: cs = 9; goto _test_eof;
+
+ _test_eof: {}
_out: {}
}
-#line 277 "parser.rl"
+#line 274 "parser.rl"
if (cs >= JSON_float_first_final) {
long len = p - json->memo;
@@ -959,14 +959,14 @@ case 9:
-#line 963 "parser.c"
+#line 964 "parser.c"
static const int JSON_array_start = 1;
static const int JSON_array_first_final = 17;
static const int JSON_array_error = 0;
static const int JSON_array_en_main = 1;
-#line 313 "parser.rl"
+#line 310 "parser.rl"
static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -979,16 +979,16 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
*result = rb_ary_new();
-#line 983 "parser.c"
+#line 984 "parser.c"
{
cs = JSON_array_start;
}
-#line 325 "parser.rl"
+#line 322 "parser.rl"
-#line 989 "parser.c"
+#line 990 "parser.c"
{
if ( p == pe )
- goto _out;
+ goto _test_eof;
switch ( cs )
{
case 1:
@@ -996,10 +996,11 @@ case 1:
goto st2;
goto st0;
st0:
- goto _out0;
+cs = 0;
+ goto _out;
st2:
if ( ++p == pe )
- goto _out2;
+ goto _test_eof2;
case 2:
switch( (*p) ) {
case 13: goto st2;
@@ -1023,12 +1024,12 @@ case 2:
goto st2;
goto st0;
tr2:
-#line 294 "parser.rl"
+#line 291 "parser.rl"
{
VALUE v = Qnil;
char *np = JSON_parse_value(json, p, pe, &v);
if (np == NULL) {
- goto _out3;
+ p--; {p++; cs = 3; goto _out;}
} else {
rb_ary_push(*result, v);
{p = (( np))-1;}
@@ -1037,9 +1038,9 @@ tr2:
goto st3;
st3:
if ( ++p == pe )
- goto _out3;
+ goto _test_eof3;
case 3:
-#line 1043 "parser.c"
+#line 1045 "parser.c"
switch( (*p) ) {
case 13: goto st3;
case 32: goto st3;
@@ -1052,7 +1053,7 @@ case 3:
goto st0;
st4:
if ( ++p == pe )
- goto _out4;
+ goto _test_eof4;
case 4:
switch( (*p) ) {
case 13: goto st4;
@@ -1076,7 +1077,7 @@ case 4:
goto st0;
st5:
if ( ++p == pe )
- goto _out5;
+ goto _test_eof5;
case 5:
switch( (*p) ) {
case 42: goto st6;
@@ -1085,14 +1086,14 @@ case 5:
goto st0;
st6:
if ( ++p == pe )
- goto _out6;
+ goto _test_eof6;
case 6:
if ( (*p) == 42 )
goto st7;
goto st6;
st7:
if ( ++p == pe )
- goto _out7;
+ goto _test_eof7;
case 7:
switch( (*p) ) {
case 42: goto st7;
@@ -1101,14 +1102,14 @@ case 7:
goto st6;
st8:
if ( ++p == pe )
- goto _out8;
+ goto _test_eof8;
case 8:
if ( (*p) == 10 )
goto st4;
goto st8;
st9:
if ( ++p == pe )
- goto _out9;
+ goto _test_eof9;
case 9:
switch( (*p) ) {
case 42: goto st10;
@@ -1117,14 +1118,14 @@ case 9:
goto st0;
st10:
if ( ++p == pe )
- goto _out10;
+ goto _test_eof10;
case 10:
if ( (*p) == 42 )
goto st11;
goto st10;
st11:
if ( ++p == pe )
- goto _out11;
+ goto _test_eof11;
case 11:
switch( (*p) ) {
case 42: goto st11;
@@ -1133,24 +1134,24 @@ case 11:
goto st10;
st12:
if ( ++p == pe )
- goto _out12;
+ goto _test_eof12;
case 12:
if ( (*p) == 10 )
goto st3;
goto st12;
tr4:
-#line 305 "parser.rl"
- { goto _out17; }
+#line 302 "parser.rl"
+ { p--; {p++; cs = 17; goto _out;} }
goto st17;
st17:
if ( ++p == pe )
- goto _out17;
+ goto _test_eof17;
case 17:
-#line 1150 "parser.c"
+#line 1152 "parser.c"
goto st0;
st13:
if ( ++p == pe )
- goto _out13;
+ goto _test_eof13;
case 13:
switch( (*p) ) {
case 42: goto st14;
@@ -1159,14 +1160,14 @@ case 13:
goto st0;
st14:
if ( ++p == pe )
- goto _out14;
+ goto _test_eof14;
case 14:
if ( (*p) == 42 )
goto st15;
goto st14;
st15:
if ( ++p == pe )
- goto _out15;
+ goto _test_eof15;
case 15:
switch( (*p) ) {
case 42: goto st15;
@@ -1175,44 +1176,44 @@ case 15:
goto st14;
st16:
if ( ++p == pe )
- goto _out16;
+ goto _test_eof16;
case 16:
if ( (*p) == 10 )
goto st2;
goto st16;
}
- _out0: cs = 0; goto _out;
- _out2: cs = 2; goto _out;
- _out3: cs = 3; goto _out;
- _out4: cs = 4; goto _out;
- _out5: cs = 5; goto _out;
- _out6: cs = 6; goto _out;
- _out7: cs = 7; goto _out;
- _out8: cs = 8; goto _out;
- _out9: cs = 9; goto _out;
- _out10: cs = 10; goto _out;
- _out11: cs = 11; goto _out;
- _out12: cs = 12; goto _out;
- _out17: cs = 17; goto _out;
- _out13: cs = 13; goto _out;
- _out14: cs = 14; goto _out;
- _out15: cs = 15; goto _out;
- _out16: cs = 16; goto _out;
-
+ _test_eof2: cs = 2; goto _test_eof;
+ _test_eof3: cs = 3; goto _test_eof;
+ _test_eof4: cs = 4; goto _test_eof;
+ _test_eof5: cs = 5; goto _test_eof;
+ _test_eof6: cs = 6; goto _test_eof;
+ _test_eof7: cs = 7; goto _test_eof;
+ _test_eof8: cs = 8; goto _test_eof;
+ _test_eof9: cs = 9; goto _test_eof;
+ _test_eof10: cs = 10; goto _test_eof;
+ _test_eof11: cs = 11; goto _test_eof;
+ _test_eof12: cs = 12; goto _test_eof;
+ _test_eof17: cs = 17; goto _test_eof;
+ _test_eof13: cs = 13; goto _test_eof;
+ _test_eof14: cs = 14; goto _test_eof;
+ _test_eof15: cs = 15; goto _test_eof;
+ _test_eof16: cs = 16; goto _test_eof;
+
+ _test_eof: {}
_out: {}
}
-#line 326 "parser.rl"
+#line 323 "parser.rl"
if(cs >= JSON_array_first_final) {
return p + 1;
} else {
- rb_raise(eParserError, "unexpected token at '%s'", p);
+ rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
}
}
static VALUE json_string_unescape(char *p, char *pe)
{
- VALUE result = rb_enc_str_new("", 0, rb_utf8_encoding());
+ VALUE result = rb_str_buf_new(pe - p + 1);
while (p < pe) {
if (*p == '\\') {
@@ -1267,33 +1268,33 @@ static VALUE json_string_unescape(char *p, char *pe)
}
-#line 1271 "parser.c"
+#line 1273 "parser.c"
static const int JSON_string_start = 1;
static const int JSON_string_first_final = 8;
static const int JSON_string_error = 0;
static const int JSON_string_en_main = 1;
-#line 404 "parser.rl"
+#line 401 "parser.rl"
static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result)
{
int cs = EVIL;
- *result = rb_enc_str_new("", 0, rb_utf8_encoding());
+ *result = rb_str_new("", 0);
-#line 1287 "parser.c"
+#line 1289 "parser.c"
{
cs = JSON_string_start;
}
-#line 412 "parser.rl"
+#line 409 "parser.rl"
json->memo = p;
-#line 1294 "parser.c"
+#line 1296 "parser.c"
{
if ( p == pe )
- goto _out;
+ goto _test_eof;
switch ( cs )
{
case 1:
@@ -1301,10 +1302,11 @@ case 1:
goto st2;
goto st0;
st0:
- goto _out0;
+cs = 0;
+ goto _out;
st2:
if ( ++p == pe )
- goto _out2;
+ goto _test_eof2;
case 2:
switch( (*p) ) {
case 34: goto tr2;
@@ -1314,23 +1316,23 @@ case 2:
goto st0;
goto st2;
tr2:
-#line 396 "parser.rl"
+#line 393 "parser.rl"
{
*result = json_string_unescape(json->memo + 1, p);
- if (NIL_P(*result)) goto _out8; else {p = (( p + 1))-1;}
+ if (NIL_P(*result)) { p--; {p++; cs = 8; goto _out;} } else {p = (( p + 1))-1;}
}
-#line 401 "parser.rl"
- { goto _out8; }
+#line 398 "parser.rl"
+ { p--; {p++; cs = 8; goto _out;} }
goto st8;
st8:
if ( ++p == pe )
- goto _out8;
+ goto _test_eof8;
case 8:
-#line 1330 "parser.c"
+#line 1333 "parser.c"
goto st0;
st3:
if ( ++p == pe )
- goto _out3;
+ goto _test_eof3;
case 3:
if ( (*p) == 117 )
goto st4;
@@ -1339,7 +1341,7 @@ case 3:
goto st2;
st4:
if ( ++p == pe )
- goto _out4;
+ goto _test_eof4;
case 4:
if ( (*p) < 65 ) {
if ( 48 <= (*p) && (*p) <= 57 )
@@ -1352,7 +1354,7 @@ case 4:
goto st0;
st5:
if ( ++p == pe )
- goto _out5;
+ goto _test_eof5;
case 5:
if ( (*p) < 65 ) {
if ( 48 <= (*p) && (*p) <= 57 )
@@ -1365,7 +1367,7 @@ case 5:
goto st0;
st6:
if ( ++p == pe )
- goto _out6;
+ goto _test_eof6;
case 6:
if ( (*p) < 65 ) {
if ( 48 <= (*p) && (*p) <= 57 )
@@ -1378,7 +1380,7 @@ case 6:
goto st0;
st7:
if ( ++p == pe )
- goto _out7;
+ goto _test_eof7;
case 7:
if ( (*p) < 65 ) {
if ( 48 <= (*p) && (*p) <= 57 )
@@ -1390,21 +1392,22 @@ case 7:
goto st2;
goto st0;
}
- _out0: cs = 0; goto _out;
- _out2: cs = 2; goto _out;
- _out8: cs = 8; goto _out;
- _out3: cs = 3; goto _out;
- _out4: cs = 4; goto _out;
- _out5: cs = 5; goto _out;
- _out6: cs = 6; goto _out;
- _out7: cs = 7; goto _out;
-
+ _test_eof2: cs = 2; goto _test_eof;
+ _test_eof8: cs = 8; goto _test_eof;
+ _test_eof3: cs = 3; goto _test_eof;
+ _test_eof4: cs = 4; goto _test_eof;
+ _test_eof5: cs = 5; goto _test_eof;
+ _test_eof6: cs = 6; goto _test_eof;
+ _test_eof7: cs = 7; goto _test_eof;
+
+ _test_eof: {}
_out: {}
}
-#line 414 "parser.rl"
+#line 411 "parser.rl"
if (cs >= JSON_string_first_final) {
- return p + 1;
+ rb_enc_associate(*result, rb_utf8_encoding());
+ return p + 1;
} else {
return NULL;
}
@@ -1412,14 +1415,14 @@ case 7:
-#line 1416 "parser.c"
+#line 1419 "parser.c"
static const int JSON_start = 1;
static const int JSON_first_final = 10;
static const int JSON_error = 0;
static const int JSON_en_main = 1;
-#line 448 "parser.rl"
+#line 445 "parser.rl"
/*
@@ -1542,23 +1545,23 @@ static VALUE cParser_parse(VALUE self)
GET_STRUCT;
-#line 1546 "parser.c"
+#line 1549 "parser.c"
{
cs = JSON_start;
}
-#line 570 "parser.rl"
+#line 567 "parser.rl"
p = json->source;
pe = p + json->len;
-#line 1554 "parser.c"
+#line 1557 "parser.c"
{
if ( p == pe )
- goto _out;
+ goto _test_eof;
switch ( cs )
{
st1:
if ( ++p == pe )
- goto _out1;
+ goto _test_eof1;
case 1:
switch( (*p) ) {
case 13: goto st1;
@@ -1571,10 +1574,11 @@ case 1:
goto st1;
goto st0;
st0:
- goto _out0;
+cs = 0;
+ goto _out;
st2:
if ( ++p == pe )
- goto _out2;
+ goto _test_eof2;
case 2:
switch( (*p) ) {
case 42: goto st3;
@@ -1583,14 +1587,14 @@ case 2:
goto st0;
st3:
if ( ++p == pe )
- goto _out3;
+ goto _test_eof3;
case 3:
if ( (*p) == 42 )
goto st4;
goto st3;
st4:
if ( ++p == pe )
- goto _out4;
+ goto _test_eof4;
case 4:
switch( (*p) ) {
case 42: goto st4;
@@ -1599,34 +1603,34 @@ case 4:
goto st3;
st5:
if ( ++p == pe )
- goto _out5;
+ goto _test_eof5;
case 5:
if ( (*p) == 10 )
goto st1;
goto st5;
tr3:
-#line 437 "parser.rl"
+#line 434 "parser.rl"
{
char *np;
json->current_nesting = 1;
np = JSON_parse_array(json, p, pe, &result);
- if (np == NULL) goto _out10; else {p = (( np))-1;}
+ if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;}
}
goto st10;
tr4:
-#line 430 "parser.rl"
+#line 427 "parser.rl"
{
char *np;
json->current_nesting = 1;
np = JSON_parse_object(json, p, pe, &result);
- if (np == NULL) goto _out10; else {p = (( np))-1;}
+ if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;}
}
goto st10;
st10:
if ( ++p == pe )
- goto _out10;
+ goto _test_eof10;
case 10:
-#line 1630 "parser.c"
+#line 1634 "parser.c"
switch( (*p) ) {
case 13: goto st10;
case 32: goto st10;
@@ -1637,7 +1641,7 @@ case 10:
goto st0;
st6:
if ( ++p == pe )
- goto _out6;
+ goto _test_eof6;
case 6:
switch( (*p) ) {
case 42: goto st7;
@@ -1646,14 +1650,14 @@ case 6:
goto st0;
st7:
if ( ++p == pe )
- goto _out7;
+ goto _test_eof7;
case 7:
if ( (*p) == 42 )
goto st8;
goto st7;
st8:
if ( ++p == pe )
- goto _out8;
+ goto _test_eof8;
case 8:
switch( (*p) ) {
case 42: goto st8;
@@ -1662,32 +1666,32 @@ case 8:
goto st7;
st9:
if ( ++p == pe )
- goto _out9;
+ goto _test_eof9;
case 9:
if ( (*p) == 10 )
goto st10;
goto st9;
}
- _out1: cs = 1; goto _out;
- _out0: cs = 0; goto _out;
- _out2: cs = 2; goto _out;
- _out3: cs = 3; goto _out;
- _out4: cs = 4; goto _out;
- _out5: cs = 5; goto _out;
- _out10: cs = 10; goto _out;
- _out6: cs = 6; goto _out;
- _out7: cs = 7; goto _out;
- _out8: cs = 8; goto _out;
- _out9: cs = 9; goto _out;
-
+ _test_eof1: cs = 1; goto _test_eof;
+ _test_eof2: cs = 2; goto _test_eof;
+ _test_eof3: cs = 3; goto _test_eof;
+ _test_eof4: cs = 4; goto _test_eof;
+ _test_eof5: cs = 5; goto _test_eof;
+ _test_eof10: cs = 10; goto _test_eof;
+ _test_eof6: cs = 6; goto _test_eof;
+ _test_eof7: cs = 7; goto _test_eof;
+ _test_eof8: cs = 8; goto _test_eof;
+ _test_eof9: cs = 9; goto _test_eof;
+
+ _test_eof: {}
_out: {}
}
-#line 573 "parser.rl"
+#line 570 "parser.rl"
if (cs >= JSON_first_final && p == pe) {
return result;
} else {
- rb_raise(eParserError, "unexpected token at '%s'", p);
+ rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
}
}
@@ -1729,6 +1733,7 @@ static VALUE cParser_source(VALUE self)
void Init_parser()
{
+ rb_require("json/common");
mJSON = rb_define_module("JSON");
mExt = rb_define_module_under(mJSON, "Ext");
cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
diff --git a/ext/json/ext/parser/parser.rl b/ext/json/ext/parser/parser.rl
index c25b1278f7..8325a93795 100644
--- a/ext/json/ext/parser/parser.rl
+++ b/ext/json/ext/parser/parser.rl
@@ -1,9 +1,4 @@
-/* vim: set cin et sw=4 ts=4: */
-
#include "ruby.h"
-#include "ruby/re.h"
-#include "ruby/st.h"
-#include "ruby/encoding.h"
#include "unicode.h"
#define EVIL 0x666
@@ -76,7 +71,7 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
VALUE v = Qnil;
char *np = JSON_parse_value(json, fpc, pe, &v);
if (np == NULL) {
- fbreak;
+ fhold; fbreak;
} else {
rb_hash_aset(*result, last_name, v);
fexec np;
@@ -85,10 +80,10 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
action parse_name {
char *np = JSON_parse_string(json, fpc, pe, &last_name);
- if (np == NULL) fbreak; else fexec np;
+ if (np == NULL) { fhold; fbreak; } else fexec np;
}
- action exit { fbreak; }
+ action exit { fhold; fbreak; }
a_pair = ignore* begin_name >parse_name
ignore* name_separator ignore*
@@ -148,19 +143,19 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
if (json->allow_nan) {
*result = CNaN;
} else {
- rb_raise(eParserError, "unexpected token at '%s'", p - 2);
+ rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p - 2);
}
}
action parse_infinity {
if (json->allow_nan) {
*result = CInfinity;
} else {
- rb_raise(eParserError, "unexpected token at '%s'", p - 8);
+ rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p - 8);
}
}
action parse_string {
char *np = JSON_parse_string(json, fpc, pe, result);
- if (np == NULL) fbreak; else fexec np;
+ if (np == NULL) { fhold; fbreak; } else fexec np;
}
action parse_number {
@@ -169,35 +164,35 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
if (json->allow_nan) {
*result = CMinusInfinity;
fexec p + 10;
- fbreak;
+ fhold; fbreak;
} else {
- rb_raise(eParserError, "unexpected token at '%s'", p);
+ rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
}
}
np = JSON_parse_float(json, fpc, pe, result);
if (np != NULL) fexec np;
np = JSON_parse_integer(json, fpc, pe, result);
if (np != NULL) fexec np;
- fbreak;
+ fhold; fbreak;
}
action parse_array {
char *np;
- json->current_nesting += 1;
+ json->current_nesting++;
np = JSON_parse_array(json, fpc, pe, result);
- json->current_nesting -= 1;
- if (np == NULL) fbreak; else fexec np;
+ json->current_nesting--;
+ if (np == NULL) { fhold; fbreak; } else fexec np;
}
action parse_object {
char *np;
- json->current_nesting += 1;
+ json->current_nesting++;
np = JSON_parse_object(json, fpc, pe, result);
- json->current_nesting -= 1;
- if (np == NULL) fbreak; else fexec np;
+ json->current_nesting--;
+ if (np == NULL) { fhold; fbreak; } else fexec np;
}
- action exit { fbreak; }
+ action exit { fhold; fbreak; }
main := (
Vnull @parse_null |
@@ -231,7 +226,7 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
write data;
- action exit { fbreak; }
+ action exit { fhold; fbreak; }
main := '-'? ('0' | [1-9][0-9]*) (^[0-9] @exit);
}%%
@@ -259,7 +254,7 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
write data;
- action exit { fbreak; }
+ action exit { fhold; fbreak; }
main := '-'? (
(('0' | [1-9][0-9]*) '.' [0-9]+ ([Ee] [+\-]?[0-9]+)?)
@@ -295,14 +290,14 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
VALUE v = Qnil;
char *np = JSON_parse_value(json, fpc, pe, &v);
if (np == NULL) {
- fbreak;
+ fhold; fbreak;
} else {
rb_ary_push(*result, v);
fexec np;
}
}
- action exit { fbreak; }
+ action exit { fhold; fbreak; }
next_element = value_separator ignore* begin_value >parse_value;
@@ -327,13 +322,13 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
if(cs >= JSON_array_first_final) {
return p + 1;
} else {
- rb_raise(eParserError, "unexpected token at '%s'", p);
+ rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
}
}
static VALUE json_string_unescape(char *p, char *pe)
{
- VALUE result = rb_enc_str_new(0, pe - p + 1, rb_utf8_encoding());
+ VALUE result = rb_str_buf_new(pe - p + 1);
while (p < pe) {
if (*p == '\\') {
@@ -395,10 +390,10 @@ static VALUE json_string_unescape(char *p, char *pe)
action parse_string {
*result = json_string_unescape(json->memo + 1, p);
- if (NIL_P(*result)) fbreak; else fexec p + 1;
+ if (NIL_P(*result)) { fhold; fbreak; } else fexec p + 1;
}
- action exit { fbreak; }
+ action exit { fhold; fbreak; }
main := '"' ((^(["\\] | 0..0x1f) | '\\'["\\/bfnrt] | '\\u'[0-9a-fA-F]{4} | '\\'^(["\\/bfnrtu]|0..0x1f))* %parse_string) '"' @exit;
}%%
@@ -407,7 +402,7 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
{
int cs = EVIL;
- *result = rb_enc_str_new("", 0, rb_utf8_encoding());
+ *result = rb_str_new("", 0);
%% write init;
json->memo = p;
%% write exec;
@@ -431,14 +426,14 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
char *np;
json->current_nesting = 1;
np = JSON_parse_object(json, fpc, pe, &result);
- if (np == NULL) fbreak; else fexec np;
+ if (np == NULL) { fhold; fbreak; } else fexec np;
}
action parse_array {
char *np;
json->current_nesting = 1;
np = JSON_parse_array(json, fpc, pe, &result);
- if (np == NULL) fbreak; else fexec np;
+ if (np == NULL) { fhold; fbreak; } else fexec np;
}
main := ignore* (
@@ -574,7 +569,7 @@ static VALUE cParser_parse(VALUE self)
if (cs >= JSON_first_final && p == pe) {
return result;
} else {
- rb_raise(eParserError, "unexpected token at '%s'", p);
+ rb_raise(eParserError, "%u: unexpected token at '%s'", __LINE__, p);
}
}
@@ -616,6 +611,7 @@ static VALUE cParser_source(VALUE self)
void Init_parser()
{
+ rb_require("json/common");
mJSON = rb_define_module("JSON");
mExt = rb_define_module_under(mJSON, "Ext");
cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
diff --git a/ext/json/ext/parser/unicode.c b/ext/json/ext/parser/unicode.c
index f196727354..b2f1e58676 100644
--- a/ext/json/ext/parser/unicode.c
+++ b/ext/json/ext/parser/unicode.c
@@ -1,5 +1,3 @@
-/* vim: set cin et sw=4 ts=4: */
-
#include "unicode.h"
/*
@@ -105,7 +103,7 @@ char *JSON_convert_UTF16_to_UTF8 (
+ (ch2 - UNI_SUR_LOW_START) + halfBase;
++tmpPtr;
} else if (flags == strictConversion) { /* it's an unpaired high surrogate */
- ruby_xfree(tmp);
+ ruby_xfree(tmp);
rb_raise(rb_path2class("JSON::ParserError"),
"source sequence is illegal/malformed near %s", source);
}
diff --git a/ext/json/lib/json/add/core.rb b/ext/json/lib/json/add/core.rb
index 630ed6e4b7..7121a77ff1 100644
--- a/ext/json/lib/json/add/core.rb
+++ b/ext/json/lib/json/add/core.rb
@@ -9,14 +9,21 @@ require 'date'
class Time
def self.json_create(object)
- at(*object.values_at('s', 'u'))
+ if usec = object.delete('u') # used to be tv_usec -> tv_nsec
+ object['n'] = usec * 1000
+ end
+ if respond_to?(:tv_nsec)
+ at(*object.values_at('s', 'n'))
+ else
+ at(object['s'], object['n'] / 1000)
+ end
end
def to_json(*args)
{
- 'json_class' => self.class.name.to_s,
+ 'json_class' => self.class.name,
's' => tv_sec,
- 'u' => tv_usec,
+ 'n' => respond_to?(:tv_nsec) ? tv_nsec : tv_usec * 1000
}.to_json(*args)
end
end
@@ -26,13 +33,15 @@ class Date
civil(*object.values_at('y', 'm', 'd', 'sg'))
end
+ alias start sg unless method_defined?(:start)
+
def to_json(*args)
{
- 'json_class' => self.class.name.to_s,
+ 'json_class' => self.class.name,
'y' => year,
'm' => month,
'd' => day,
- 'sg' => @sg,
+ 'sg' => start,
}.to_json(*args)
end
end
@@ -41,14 +50,20 @@ class DateTime
def self.json_create(object)
args = object.values_at('y', 'm', 'd', 'H', 'M', 'S')
of_a, of_b = object['of'].split('/')
- args << Rational(of_a.to_i, of_b.to_i)
+ if of_b and of_b != '0'
+ args << Rational(of_a.to_i, of_b.to_i)
+ else
+ args << of_a
+ end
args << object['sg']
civil(*args)
end
+ alias start sg unless method_defined?(:start)
+
def to_json(*args)
{
- 'json_class' => self.class.name.to_s,
+ 'json_class' => self.class.name,
'y' => year,
'm' => month,
'd' => day,
@@ -56,7 +71,7 @@ class DateTime
'M' => min,
'S' => sec,
'of' => offset.to_s,
- 'sg' => @sg,
+ 'sg' => start,
}.to_json(*args)
end
end
@@ -68,7 +83,7 @@ class Range
def to_json(*args)
{
- 'json_class' => self.class.name.to_s,
+ 'json_class' => self.class.name,
'a' => [ first, last, exclude_end? ]
}.to_json(*args)
end
@@ -80,8 +95,8 @@ class Struct
end
def to_json(*args)
- klass = self.class.name.to_s
- klass.empty? and raise JSON::JSONError, "Only named structs are supported!"
+ klass = self.class.name
+ klass.nil? and raise JSON::JSONError, "Only named structs are supported!"
{
'json_class' => klass,
'v' => values,
@@ -98,7 +113,7 @@ class Exception
def to_json(*args)
{
- 'json_class' => self.class.name.to_s,
+ 'json_class' => self.class.name,
'm' => message,
'b' => backtrace,
}.to_json(*args)
@@ -112,7 +127,7 @@ class Regexp
def to_json(*)
{
- 'json_class' => self.class.name.to_s,
+ 'json_class' => self.class.name,
'o' => options,
's' => source,
}.to_json
diff --git a/ext/json/lib/json/common.rb b/ext/json/lib/json/common.rb
index 7bc5ae0656..499fcc0dae 100644
--- a/ext/json/lib/json/common.rb
+++ b/ext/json/lib/json/common.rb
@@ -2,7 +2,7 @@ require 'json/version'
module JSON
class << self
- # If _object_ is string like parse the string and return the parsed result
+ # If _object_ is string-like parse the string and return the parsed result
# as a Ruby data structure. Otherwise generate a JSON text from the Ruby
# data structure object and return it.
#
@@ -184,7 +184,8 @@ module JSON
end
# :stopdoc:
- # I want to deprecate these later, so I'll first be silent about them, and later delete them.
+ # I want to deprecate these later, so I'll first be silent about them, and
+ # later delete them.
alias unparse generate
module_function :unparse
# :startdoc:
@@ -238,7 +239,7 @@ module JSON
# :startdoc:
# Load a ruby data structure from a JSON _source_ and return it. A source can
- # either be a string like object, an IO like object, or an object responding
+ # either be a string-like object, an IO like object, or an object responding
# to the read method. If _proc_ was given, it will be called with any nested
# Ruby object as an argument recursively in depth first order.
#
@@ -327,7 +328,7 @@ module ::Kernel
nil
end
- # If _object_ is string like parse the string and return the parsed result as
+ # If _object_ is string-like parse the string and return the parsed result as
# a Ruby data structure. Otherwise generate a JSON text from the Ruby data
# structure object and return it.
#
@@ -351,4 +352,3 @@ class ::Class
respond_to?(:json_create)
end
end
- # vim: set et sw=2 ts=2:
diff --git a/ext/json/lib/json/editor.rb b/ext/json/lib/json/editor.rb
index 9a65400622..12a7f94591 100644
--- a/ext/json/lib/json/editor.rb
+++ b/ext/json/lib/json/editor.rb
@@ -1360,4 +1360,3 @@ module JSON
end
end
end
- # vim: set et sw=2 ts=2:
diff --git a/ext/json/lib/json/pure.rb b/ext/json/lib/json/pure.rb
index b86d905523..6af8705c5b 100644
--- a/ext/json/lib/json/pure.rb
+++ b/ext/json/lib/json/pure.rb
@@ -3,59 +3,6 @@ require 'json/pure/parser'
require 'json/pure/generator'
module JSON
- begin
- require 'iconv'
- # An iconv instance to convert from UTF8 to UTF16 Big Endian.
- UTF16toUTF8 = Iconv.new('utf-8', 'utf-16be') # :nodoc:
- # An iconv instance to convert from UTF16 Big Endian to UTF8.
- UTF8toUTF16 = Iconv.new('utf-16be', 'utf-8') # :nodoc:
- UTF8toUTF16.iconv('no bom')
- rescue Errno::EINVAL, Iconv::InvalidEncoding
- # Iconv doesn't support big endian utf-16. Let's try to hack this manually
- # into the converters.
- begin
- old_verbose, $VERBSOSE = $VERBOSE, nil
- # An iconv instance to convert from UTF8 to UTF16 Big Endian.
- UTF16toUTF8 = Iconv.new('utf-8', 'utf-16') # :nodoc:
- # An iconv instance to convert from UTF16 Big Endian to UTF8.
- UTF8toUTF16 = Iconv.new('utf-16', 'utf-8') # :nodoc:
- UTF8toUTF16.iconv('no bom')
- if UTF8toUTF16.iconv("\xe2\x82\xac") == "\xac\x20"
- swapper = Class.new do
- def initialize(iconv) # :nodoc:
- @iconv = iconv
- end
-
- def iconv(string) # :nodoc:
- result = @iconv.iconv(string)
- JSON.swap!(result)
- end
- end
- UTF8toUTF16 = swapper.new(UTF8toUTF16) # :nodoc:
- end
- if UTF16toUTF8.iconv("\xac\x20") == "\xe2\x82\xac"
- swapper = Class.new do
- def initialize(iconv) # :nodoc:
- @iconv = iconv
- end
-
- def iconv(string) # :nodoc:
- string = JSON.swap!(string.dup)
- @iconv.iconv(string)
- end
- end
- UTF16toUTF8 = swapper.new(UTF16toUTF8) # :nodoc:
- end
- rescue Errno::EINVAL, Iconv::InvalidEncoding
- raise MissingUnicodeSupport, "iconv doesn't seem to support UTF-8/UTF-16 conversions"
- ensure
- $VERBOSE = old_verbose
- end
- rescue LoadError
- raise MissingUnicodeSupport,
- "iconv couldn't be loaded, which is required for UTF-8/UTF-16 conversions"
- end
-
# Swap consecutive bytes of _string_ in place.
def self.swap!(string) # :nodoc:
0.upto(string.size / 2) do |i|
diff --git a/ext/json/lib/json/pure/generator.rb b/ext/json/lib/json/pure/generator.rb
index c8bbfd09ee..9c7cfac0a2 100644
--- a/ext/json/lib/json/pure/generator.rb
+++ b/ext/json/lib/json/pure/generator.rb
@@ -40,7 +40,8 @@ module JSON
# Convert a UTF8 encoded Ruby string _string_ to a JSON string, encoded with
# UTF16 big endian characters as \u????, and return it.
def utf8_to_json(string) # :nodoc:
- string = string.gsub(/["\\\/\x0-\x1f]/) { MAP[$&] }
+ string = string.dup.force_encoding(Encoding::ASCII_8BIT)
+ string.gsub!(/["\\\/\x0-\x1f]/) { MAP[$&] }
string.gsub!(/(
(?:
[\xc2-\xdf][\x80-\xbf] |
@@ -50,12 +51,11 @@ module JSON
[\x80-\xc1\xf5-\xff] # invalid
)/nx) { |c|
c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'"
- s = JSON::UTF8toUTF16.iconv(c).unpack('H*')[0]
- s.gsub!(/.{4}/n, '\\\\u\&')
+ c.unpack("U*").map{|c|
+ c>0xFFFF ? ('\ud%03x\ud%03x'%[0x7C0+c/1024,0xC00+c%1024]) : ('\u%04x'%c)
+ }.join("")
}
string
- rescue Iconv::Failure => e
- raise GeneratorError, "Caught #{e.class}: #{e}"
end
module_function :utf8_to_json
diff --git a/ext/json/lib/json/pure/parser.rb b/ext/json/lib/json/pure/parser.rb
index 39bee54269..9c3fea91da 100644
--- a/ext/json/lib/json/pure/parser.rb
+++ b/ext/json/lib/json/pure/parser.rb
@@ -122,25 +122,34 @@ module JSON
def parse_string
if scan(STRING)
return '' if self[1].empty?
- self[1].gsub(%r((?:\\[\\bfnrt"/]|(?:\\u(?:[A-Fa-f\d]{4}))+|\\[\x20-\xff]))n) do
- c = $&
- if u = UNESCAPE_MAP[c[1]]
+ self[1].gsub(%r((?:\\[\\bfnrt"/]|(?:\\u(?:[A-Fa-f\d]{4}))+|\\[\x20-\xff]))n) do |c|
+ if u = UNESCAPE_MAP[$&[1]]
u
else # \uXXXX
- bytes = ''
- i = 0
- while c[6 * i] == ?\\ && c[6 * i + 1] == ?u
- bytes << c[6 * i + 2, 2].to_i(16) << c[6 * i + 4, 2].to_i(16)
- i += 1
+ res = []
+ stack = nil
+ [c.delete!('\\\\u')].pack("H*").unpack("n*").each do |c|
+ case c
+ when 0xD800..0xDBFF
+ raise JSON::ParserError, "partial character in source" if stack
+ stack = c
+ when 0xDC00..0xDFFF
+ raise JSON::ParserError,
+ "partial character in source" unless (0xD800..0xDBFF).include?(stack)
+ res << (stack << 10) - 0x35fdc00 + c
+ stack = nil
+ else
+ raise JSON::ParserError, "partial character in source" if stack
+ res << c
+ end
end
- JSON::UTF16toUTF8.iconv(bytes)
+ raise JSON::ParserError, "partial character in source" if stack
+ res.pack("U*")
end
- end
+ end.force_encoding("UTF-8")
else
UNPARSED
end
- rescue Iconv::Failure => e
- raise GeneratorError, "Caught #{e.class}: #{e}"
end
def parse_value
diff --git a/ext/json/lib/json/version.rb b/ext/json/lib/json/version.rb
index 3d674ac44f..acf8217048 100644
--- a/ext/json/lib/json/version.rb
+++ b/ext/json/lib/json/version.rb
@@ -1,6 +1,6 @@
module JSON
# JSON version
- VERSION = '1.1.2'
+ VERSION = '1.1.3'
VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc:
VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
diff --git a/ext/mathn/complex/complex.c b/ext/mathn/complex/complex.c
new file mode 100644
index 0000000000..5ffa5917e4
--- /dev/null
+++ b/ext/mathn/complex/complex.c
@@ -0,0 +1,7 @@
+extern void nucomp_canonicalize(int);
+
+void
+Init_complex(void)
+{
+ nucomp_canonicalize(1);
+}
diff --git a/ext/mathn/complex/extconf.rb b/ext/mathn/complex/extconf.rb
new file mode 100644
index 0000000000..d4d14ffcb8
--- /dev/null
+++ b/ext/mathn/complex/extconf.rb
@@ -0,0 +1,3 @@
+require "mkmf"
+
+create_makefile "mathn/complex"
diff --git a/ext/mathn/rational/extconf.rb b/ext/mathn/rational/extconf.rb
new file mode 100644
index 0000000000..ba76306b7b
--- /dev/null
+++ b/ext/mathn/rational/extconf.rb
@@ -0,0 +1,3 @@
+require "mkmf"
+
+create_makefile "mathn/rational"
diff --git a/ext/mathn/rational/rational.c b/ext/mathn/rational/rational.c
new file mode 100644
index 0000000000..fe6797454d
--- /dev/null
+++ b/ext/mathn/rational/rational.c
@@ -0,0 +1,7 @@
+extern void nurat_canonicalize(int);
+
+void
+Init_rational(void)
+{
+ nurat_canonicalize(1);
+}
diff --git a/ext/nkf/nkf-utf8/config.h b/ext/nkf/nkf-utf8/config.h
index 50daa891fa..752ed38d59 100644
--- a/ext/nkf/nkf-utf8/config.h
+++ b/ext/nkf/nkf-utf8/config.h
@@ -44,9 +44,8 @@
/* #define DEFAULT_CODE_JIS */
/* #define DEFAULT_CODE_SJIS */
+/* #define DEFAULT_CODE_WINDOWS_31J */
/* #define DEFAULT_CODE_EUC */
/* #define DEFAULT_CODE_UTF8 */
-/* #define DEFAULT_CODE_LOCALE */
#endif /* _CONFIG_H_ */
-
diff --git a/ext/nkf/nkf-utf8/nkf.c b/ext/nkf/nkf-utf8/nkf.c
index a4ad15dcfb..e34ff44a7b 100644
--- a/ext/nkf/nkf-utf8/nkf.c
+++ b/ext/nkf/nkf-utf8/nkf.c
@@ -33,7 +33,7 @@
***********************************************************************/
#define NKF_IDENT "$Id$"
#define NKF_VERSION "2.0.8"
-#define NKF_RELEASE_DATE "2008-02-08"
+#define NKF_RELEASE_DATE "2008-11-07"
#define COPY_RIGHT \
"Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa),2000 S. Kono, COW\n" \
"Copyright (C) 2002-2008 Kono, Furukawa, Naruse, mastodon"
@@ -41,6 +41,15 @@
#include "config.h"
#include "nkf.h"
#include "utf8tbl.h"
+#ifdef __WIN32__
+#include <windows.h>
+#include <locale.h>
+#endif
+#if defined(__OS2__)
+# define INCL_DOS
+# define INCL_DOSERRORS
+# include <os2.h>
+#endif
/* state of output_mode and input_mode
@@ -263,6 +272,8 @@ struct {
#define DEFAULT_ENCIDX ISO_2022_JP
#elif defined(DEFAULT_CODE_SJIS)
#define DEFAULT_ENCIDX SHIFT_JIS
+#elif defined(DEFAULT_CODE_WINDOWS_31J)
+#define DEFAULT_ENCIDX WINDOWS_31J
#elif defined(DEFAULT_CODE_EUC)
#define DEFAULT_ENCIDX EUC_JP
#elif defined(DEFAULT_CODE_UTF8)
@@ -332,7 +343,6 @@ static const char *input_codename = NULL; /* NULL: unestablished, "": BINARY */
static nkf_encoding *input_encoding = NULL;
static nkf_encoding *output_encoding = NULL;
-static int kanji_convert(FILE *f);
#if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
/* UCS Mapping
* 0: Shift_JIS, eucJP-ascii
@@ -421,8 +431,8 @@ static nkf_char (*i_uungetc)(nkf_char c ,FILE *f) = std_ungetc;
#define nkf_char_euc3_new(c) ((c) | PREFIX_EUCG3)
#define nkf_char_unicode_new(c) ((c) | CLASS_UNICODE)
#define nkf_char_unicode_p(c) ((c & CLASS_MASK) == CLASS_UNICODE)
-#define nkf_char_unicode_bmp_p(c) ((c & VALUE_MASK) <= NKF_INT32_C(UNICODE_BMP_MAX))
-#define nkf_char_unicode_value_p(c) ((c & VALUE_MASK) <= NKF_INT32_C(UNICODE_MAX))
+#define nkf_char_unicode_bmp_p(c) ((c & VALUE_MASK) <= UNICODE_BMP_MAX)
+#define nkf_char_unicode_value_p(c) ((c & VALUE_MASK) <= UNICODE_MAX)
#ifdef NUMCHAR_OPTION
static int numchar_f = FALSE;
@@ -719,7 +729,31 @@ nkf_locale_charmap()
#ifdef HAVE_LANGINFO_H
return nl_langinfo(CODESET);
#elif defined(__WIN32__)
- return sprintf("CP%d", GetACP());
+ char buf[16];
+ char *str;
+ int len = sprintf(buf, "CP%d", GetACP());
+ if (len > 0) {
+ str = malloc(len + 1);
+ strcpy(str, buf);
+ str[len] = '\0';
+ return str;
+ }
+ else return NULL;
+#elif defined(__OS2__)
+# if defined(INT_IS_SHORT)
+ /* OS/2 1.x */
+ return NULL;
+# else
+ /* OS/2 32bit */
+ static char buf[16];
+ ULONG ulCP[1], ulncp;
+ DosQueryCp(sizeof(ulCP), ulCP, &ulncp);
+ if (ulCP[0] == 932 || ulCP[0] == 943)
+ strcpy(buf, "Shift_JIS");
+ else
+ sprintf(buf, "CP%lu", ulCP[0]);
+ return buf;
+# endif
#else
return NULL;
#endif
@@ -732,20 +766,26 @@ nkf_locale_encoding()
char *encname = nkf_locale_charmap();
if (encname)
enc = nkf_enc_find(encname);
- if (enc < 0) enc = 0;
return enc;
}
#endif /* DEFAULT_CODE_LOCALE */
static nkf_encoding*
+nkf_utf8_encoding()
+{
+ return &nkf_encoding_table[UTF_8];
+}
+
+static nkf_encoding*
nkf_default_encoding()
{
nkf_encoding *enc = 0;
#ifdef DEFAULT_CODE_LOCALE
enc = nkf_locale_encoding();
-#elif DEFAULT_ENCIDX
+#elif defined(DEFAULT_ENCIDX)
enc = nkf_enc_from_index(DEFAULT_ENCIDX);
#endif
+ if (!enc) enc = nkf_utf8_encoding();
return enc;
}
@@ -843,7 +883,7 @@ show_configuration(void)
" Default output encoding: "
#ifdef DEFAULT_CODE_LOCALE
"LOCALE (%s)\n", nkf_enc_name(nkf_default_encoding())
-#elif DEFAULT_ENCIDX
+#elif defined(DEFAULT_ENCIDX)
"CONFIG (%s)\n", nkf_enc_name(nkf_default_encoding())
#else
"NONE\n"
@@ -915,7 +955,8 @@ get_backup_filename(const char *suffix, const char *filename)
}
backup_filename[j] = '\0';
}else{
- backup_filename = malloc(filename_length + strlen(suffix) + 1);
+ j = filename_length + strlen(suffix);
+ backup_filename = malloc(j + 1);
strcpy(backup_filename, filename);
strcat(backup_filename, suffix);
backup_filename[j] = '\0';
@@ -1472,6 +1513,7 @@ s2e_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1)
nkf_char val;
#endif
static const char shift_jisx0213_s1a3_table[5][2] ={ { 1, 8}, { 3, 4}, { 5,12}, {13,14}, {15, 0} };
+ if (0xFC < c1) return 1;
#ifdef SHIFTJIS_CP932
if (!cp932inv_f && is_ibmext_in_sjis(c2)){
val = shiftjis_cp932[c2 - CP932_TABLE_BEGIN][c1 - 0x40];
@@ -1482,10 +1524,10 @@ s2e_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1)
}
if (cp932inv_f
&& CP932INV_TABLE_BEGIN <= c2 && c2 <= CP932INV_TABLE_END){
- nkf_char c = cp932inv[c2 - CP932INV_TABLE_BEGIN][c1 - 0x40];
- if (c){
- c2 = c >> 8;
- c1 = c & 0xff;
+ val = cp932inv[c2 - CP932INV_TABLE_BEGIN][c1 - 0x40];
+ if (val){
+ c2 = val >> 8;
+ c1 = val & 0xff;
}
}
#endif /* SHIFTJIS_CP932 */
@@ -1537,7 +1579,7 @@ s2e_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1)
#if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE)
static void
-nkf_unicode_to_utf8(nkf_char val, int *p1, int *p2, int *p3, int *p4)
+nkf_unicode_to_utf8(nkf_char val, nkf_char *p1, nkf_char *p2, nkf_char *p3, nkf_char *p4)
{
val &= VALUE_MASK;
if (val < 0x80){
@@ -1569,7 +1611,7 @@ nkf_unicode_to_utf8(nkf_char val, int *p1, int *p2, int *p3, int *p4)
}
static nkf_char
-nkf_utf8_to_unicode(int c1, int c2, int c3, int c4)
+nkf_utf8_to_unicode(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4)
{
nkf_char wc;
if (c1 <= 0x7F) {
@@ -1870,7 +1912,7 @@ w2e_conv(nkf_char c2, nkf_char c1, nkf_char c0, nkf_char *p2, nkf_char *p1)
static nkf_char
w16e_conv(nkf_char val, nkf_char *p2, nkf_char *p1)
{
- int c1, c2, c3, c4;
+ nkf_char c1, c2, c3, c4;
nkf_char ret = 0;
val &= VALUE_MASK;
if (val < 0x80) {
@@ -2087,7 +2129,7 @@ unicode_iconv(nkf_char wc)
#define NKF_ICONV_NEED_TWO_MORE_BYTES -2
#define UTF16_TO_UTF32(lead, trail) (((lead) << 10) + (trail) - NKF_INT32_C(0x35FDC00))
static size_t
-nkf_iconv_utf_16(int c1, int c2, int c3, int c4)
+nkf_iconv_utf_16(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4)
{
nkf_char wc;
@@ -2130,7 +2172,7 @@ w_iconv32(nkf_char c2, nkf_char c1, nkf_char c0)
}
static size_t
-nkf_iconv_utf_32(int c1, int c2, int c3, int c4)
+nkf_iconv_utf_32(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4)
{
nkf_char wc;
@@ -2414,7 +2456,7 @@ s_oconv(nkf_char c2, nkf_char c1)
static void
w_oconv(nkf_char c2, nkf_char c1)
{
- int c3, c4;
+ nkf_char c3, c4;
nkf_char val;
if (output_bom_f) {
@@ -2501,6 +2543,7 @@ w_oconv16(nkf_char c2, nkf_char c1)
c1 = val & 0xff;
if (!val) return;
}
+
if (output_endian == ENDIAN_LITTLE){
(*o_putc)(c1);
(*o_putc)(c2);
@@ -4098,7 +4141,7 @@ numchar_getc(FILE *f)
nkf_char (*g)(FILE *) = i_ngetc;
nkf_char (*u)(nkf_char c ,FILE *f) = i_nungetc;
int i = 0, j;
- nkf_char buf[8];
+ nkf_char buf[12];
long c = -1;
buf[i] = (*g)(f);
@@ -5251,7 +5294,7 @@ kanji_convert(FILE *f)
{
nkf_char c1=0, c2=0, c3=0, c4=0;
int shift_mode = 0; /* 0, 1, 2, 3 */
- char g2 = 0;
+ int g2 = 0;
int is_8bit = FALSE;
if (input_encoding && !nkf_enc_asciicompat(input_encoding)) {
@@ -5326,6 +5369,10 @@ kanji_convert(FILE *f)
SEND;
}
}
+ else if (nkf_char_unicode_p(c1)) {
+ (*oconv)(0, c1);
+ NEXT;
+ }
else {
/* first byte */
if (input_mode == JIS_X_0208 && DEL <= c1 && c1 < 0x92) {
@@ -5550,7 +5597,7 @@ kanji_convert(FILE *f)
C%7 : 0 1 2 3 4 5 6
NUM : 2 0 3 4 5 X 1
*/
- static const int jphone_emoji_first_table[7] =
+ static const nkf_char jphone_emoji_first_table[7] =
{0xE1E0, 0xDFE0, 0xE2E0, 0xE3E0, 0xE4E0, 0xDFE0, 0xE0E0};
c3 = nkf_char_unicode_new(jphone_emoji_first_table[c1 % 7]);
if ((c1 = (*i_getc)(f)) == EOF) LAST;
@@ -5739,7 +5786,8 @@ options(unsigned char *cp)
}
if (strcmp(long_option[i].name, "oc=") == 0){
enc = nkf_enc_find((char *)p);
- if (enc <= 0) continue;
+ /* if (enc <= 0) continue; */
+ if (!enc) continue;
output_encoding = enc;
continue;
}
@@ -6085,9 +6133,9 @@ options(unsigned char *cp)
cp++;
input_endian = ENDIAN_BIG;
}
- enc_idx = enc_idx == UTF_16
+ enc_idx = (enc_idx == UTF_16
? (input_endian == ENDIAN_LITTLE ? UTF_16LE : UTF_16BE)
- : (input_endian == ENDIAN_LITTLE ? UTF_32LE : UTF_32BE);
+ : (input_endian == ENDIAN_LITTLE ? UTF_32LE : UTF_32BE));
input_encoding = nkf_enc_from_index(enc_idx);
}
continue;
diff --git a/ext/nkf/nkf-utf8/nkf.h b/ext/nkf/nkf-utf8/nkf.h
index 1dbae54f20..49f3b7ff34 100644
--- a/ext/nkf/nkf-utf8/nkf.h
+++ b/ext/nkf/nkf-utf8/nkf.h
@@ -51,7 +51,7 @@ typedef int nkf_char;
#define NKF_INT32_C(n) (n)
#endif
-#if (defined(__TURBOC__) || defined(_MSC_VER) || defined(LSI_C) || defined(__MINGW32__) || defined(__EMX__) || defined(__MSDOS__) || defined(__WINDOWS__) || defined(__DOS__) || defined(__OS2__)) && !defined(MSDOS)
+#if (defined(__TURBOC__) || defined(_MSC_VER) || defined(LSI_C) || (defined(__WATCOMC__) && defined(__386__) && !defined(__LINUX__)) || defined(__MINGW32__) || defined(__EMX__) || defined(__MSDOS__) || defined(__WINDOWS__) || defined(__DOS__) || defined(__OS2__)) && !defined(MSDOS)
#define MSDOS
#if (defined(__Win32__) || defined(_WIN32)) && !defined(__WIN32__)
#define __WIN32__
@@ -143,15 +143,34 @@ void setbinmode(FILE *fp)
#endif
#endif
+#if !defined(DEFAULT_CODE_JIS) && !defined(DEFAULT_CODE_SJIS) && \
+ !defined(DEFAULT_CODE_WINDOWS_31J) && !defined(DEFAULT_CODE_EUC) && \
+ !defined(DEFAULT_CODE_UTF8) && !defined(DEFAULT_CODE_LOCALE)
+#define DEFAULT_CODE_LOCALE
+#endif
+
#ifdef DEFAULT_CODE_LOCALE
-#ifndef __WIN32__ /* not win32 is posix */
-#ifndef HAVE_LANGINFO_H
-#define HAVE_LANGINFO_H
-#endif
-#ifndef HAVE_LOCALE_H
-#define HAVE_LOCALE_H
-#endif
+#if defined(__WIN32__) /* not win32 should be posix */
+# ifndef HAVE_LOCALE_H
+# define HAVE_LOCALE_H
+# endif
+#elif defined(__OS2__)
+# undef HAVE_LANGINFO_H /* We do not use kLIBC's langinfo. */
+# ifndef HAVE_LOCALE_H
+# define HAVE_LOCALE_H
+# endif
+#elif defined(MSDOS)
+# ifndef HAVE_LOCALE_H
+# define HAVE_LOCALE_H
+# endif
+#else
+# ifndef HAVE_LANGINFO_H
+# define HAVE_LANGINFO_H
+# endif
+# ifndef HAVE_LOCALE_H
+# define HAVE_LOCALE_H
+# endif
#endif
#ifdef HAVE_LANGINFO_H
@@ -171,4 +190,3 @@ void setbinmode(FILE *fp)
#endif
#endif /* NKF_H */
-
diff --git a/ext/nkf/nkf-utf8/utf8tbl.c b/ext/nkf/nkf-utf8/utf8tbl.c
index fbcd86b442..10eec60c5d 100644
--- a/ext/nkf/nkf-utf8/utf8tbl.c
+++ b/ext/nkf/nkf-utf8/utf8tbl.c
@@ -2464,8 +2464,8 @@ static const unsigned short utf8_to_euc_C2_mac[] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 0x0220, 0xA242, 0x2171, 0x2172, 0xA270, 0x5C, 0xA243, 0x2178,
- 0x212F, 0x027D, 0xA26C, 0, 0x224C, 0, 0xA26E, 0xA234,
+ 0x00A0, 0xA242, 0x2171, 0x2172, 0xA270, 0x5C, 0xA243, 0x2178,
+ 0x212F, 0x00FD, 0xA26C, 0, 0x224C, 0, 0xA26E, 0xA234,
0x216B, 0x215E, 0, 0, 0x212D, 0, 0x2279, 0,
0xA231, 0, 0xA26B, 0, 0, 0, 0, 0xA244,
};
@@ -2624,7 +2624,7 @@ static const unsigned short utf8_to_euc_E284_mac[] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0x2B7B, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0x2B7D, 0x027E, 0, 0, 0, 0, 0,
+ 0, 0x2B7D, 0x00FE, 0, 0, 0, 0, 0,
0, 0, 0, 0x2272, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
diff --git a/ext/nkf/nkf.c b/ext/nkf/nkf.c
index 24761449d2..82327bf356 100644
--- a/ext/nkf/nkf.c
+++ b/ext/nkf/nkf.c
@@ -69,9 +69,6 @@ rb_encoding* rb_nkf_enc_get(const char *name)
idx = rb_enc_find_index(nkf_enc_name(nkf_enc_to_base_encoding(nkf_enc)));
if (idx < 0) {
idx = rb_define_dummy_encoding(name);
- } else {
- rb_encoding *rb_enc = rb_enc_from_index(idx);
- idx = rb_enc_replicate(name, rb_enc);
}
}
return rb_enc_from_index(idx);
@@ -138,6 +135,7 @@ int nkf_split_options(const char *arg)
static VALUE
rb_nkf_convert(VALUE obj, VALUE opt, VALUE src)
{
+ volatile VALUE tmp;
reinit();
StringValue(opt);
nkf_split_options(RSTRING_PTR(opt));
@@ -158,7 +156,7 @@ rb_nkf_convert(VALUE obj, VALUE opt, VALUE src)
StringValue(src);
input = (unsigned char *)RSTRING_PTR(src);
i_len = RSTRING_LEN(src);
- result = rb_str_new(0, i_len*3 + 10);
+ tmp = result = rb_str_new(0, i_len*3 + 10);
output_ctr = 0;
output = (unsigned char *)RSTRING_PTR(result);
diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h
index 33b0373c53..9734249db1 100644
--- a/ext/openssl/ossl.h
+++ b/ext/openssl/ossl.h
@@ -29,7 +29,7 @@ extern "C" {
# undef RFILE
#endif
#include <ruby.h>
-#include <rubyio.h>
+#include <ruby/io.h>
/*
* Check the OpenSSL version
diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c
index d4285f2069..caa140dc4b 100644
--- a/ext/openssl/ossl_pkey_ec.c
+++ b/ext/openssl/ossl_pkey_ec.c
@@ -463,8 +463,10 @@ static VALUE ossl_ec_key_to_string(VALUE self, int format)
BIO *out;
int i = -1;
int private = 0;
+#if 0 /* unused now */
EVP_CIPHER *cipher = NULL;
char *password = NULL;
+#endif
VALUE str;
Require_EC_KEY(self, ec);
@@ -484,13 +486,18 @@ static VALUE ossl_ec_key_to_string(VALUE self, int format)
switch(format) {
case EXPORT_PEM:
if (private) {
+#if 0 /* unused now */
if (cipher || password)
/* BUG: finish cipher/password key export */
rb_notimplement();
i = PEM_write_bio_ECPrivateKey(out, ec, cipher, NULL, 0, NULL, password);
+#endif
+ i = PEM_write_bio_ECPrivateKey(out, ec, NULL, NULL, 0, NULL, NULL);
} else {
+#if 0 /* unused now */
if (cipher || password)
rb_raise(rb_eArgError, "encryption is not supported when exporting this key type");
+#endif
i = PEM_write_bio_EC_PUBKEY(out, ec);
}
@@ -498,13 +505,17 @@ static VALUE ossl_ec_key_to_string(VALUE self, int format)
break;
case EXPORT_DER:
if (private) {
+#if 0 /* unused now */
if (cipher || password)
rb_raise(rb_eArgError, "encryption is not supported when exporting this key type");
+#endif
i = i2d_ECPrivateKey_bio(out, ec);
} else {
+#if 0 /* unused now */
if (cipher || password)
rb_raise(rb_eArgError, "encryption is not supported when exporting this key type");
+#endif
i = i2d_EC_PUBKEY_bio(out, ec);
}
diff --git a/ext/readline/readline.c b/ext/readline/readline.c
index 1bfec15eac..5e30aa3046 100644
--- a/ext/readline/readline.c
+++ b/ext/readline/readline.c
@@ -63,6 +63,11 @@ static int (*history_get_offset_func)(int);
static char **readline_attempted_completion_function(const char *text,
int start, int end);
+#define OutputStringValue(str) do {\
+ SafeStringValue(str);\
+ str = rb_str_conv_enc(str, rb_enc_get(str), rb_locale_encoding());\
+} while (0)\
+
#ifdef HAVE_RL_EVENT_HOOK
#define BUSY_WAIT 0
@@ -214,7 +219,7 @@ readline_readline(int argc, VALUE *argv, VALUE self)
rb_secure(4);
if (rb_scan_args(argc, argv, "02", &tmp, &add_hist) > 0) {
- SafeStringValue(tmp);
+ OutputStringValue(tmp);
prompt = RSTRING_PTR(tmp);
}
@@ -241,8 +246,7 @@ readline_readline(int argc, VALUE *argv, VALUE self)
add_history(buff);
}
if (buff) {
- result = rb_tainted_str_new2(buff);
- rb_enc_associate(result, rb_locale_encoding());
+ result = rb_locale_str_new_cstr(buff);
}
else
result = Qnil;
@@ -381,7 +385,7 @@ readline_attempted_completion_function(const char *text, int start, int end)
rl_attempted_completion_over = 1;
#endif
case_fold = RTEST(rb_attr_get(mReadline, completion_case_fold));
- ary = rb_funcall(proc, rb_intern("call"), 1, rb_tainted_str_new2(text));
+ ary = rb_funcall(proc, rb_intern("call"), 1, rb_locale_str_new_cstr(text));
if (TYPE(ary) != T_ARRAY)
ary = rb_Array(ary);
matches = RARRAY_LEN(ary);
@@ -569,7 +573,7 @@ readline_s_set_completion_append_character(VALUE self, VALUE str)
rl_completion_append_character = '\0';
}
else {
- SafeStringValue(str);
+ OutputStringValue(str);
if (RSTRING_LEN(str) == 0) {
rl_completion_append_character = '\0';
} else {
@@ -604,7 +608,7 @@ readline_s_get_completion_append_character(VALUE self)
if (rl_completion_append_character == '\0')
return Qnil;
- str = rb_str_new("", 1);
+ str = rb_str_new(0, 1);
RSTRING_PTR(str)[0] = rl_completion_append_character;
return str;
#else
@@ -632,7 +636,7 @@ readline_s_set_basic_word_break_characters(VALUE self, VALUE str)
static char *basic_word_break_characters = NULL;
rb_secure(4);
- SafeStringValue(str);
+ OutputStringValue(str);
if (basic_word_break_characters == NULL) {
basic_word_break_characters =
ALLOC_N(char, RSTRING_LEN(str) + 1);
@@ -669,7 +673,7 @@ readline_s_get_basic_word_break_characters(VALUE self, VALUE str)
rb_secure(4);
if (rl_basic_word_break_characters == NULL)
return Qnil;
- return rb_tainted_str_new2(rl_basic_word_break_characters);
+ return rb_locale_str_new_cstr(rl_basic_word_break_characters);
#else
rb_notimplement();
return Qnil; /* not reached */
@@ -695,7 +699,7 @@ readline_s_set_completer_word_break_characters(VALUE self, VALUE str)
static char *completer_word_break_characters = NULL;
rb_secure(4);
- SafeStringValue(str);
+ OutputStringValue(str);
if (completer_word_break_characters == NULL) {
completer_word_break_characters =
ALLOC_N(char, RSTRING_LEN(str) + 1);
@@ -732,7 +736,7 @@ readline_s_get_completer_word_break_characters(VALUE self, VALUE str)
rb_secure(4);
if (rl_completer_word_break_characters == NULL)
return Qnil;
- return rb_tainted_str_new2(rl_completer_word_break_characters);
+ return rb_locale_str_new_cstr(rl_completer_word_break_characters);
#else
rb_notimplement();
return Qnil; /* not reached */
@@ -756,7 +760,7 @@ readline_s_set_basic_quote_characters(VALUE self, VALUE str)
static char *basic_quote_characters = NULL;
rb_secure(4);
- SafeStringValue(str);
+ OutputStringValue(str);
if (basic_quote_characters == NULL) {
basic_quote_characters =
ALLOC_N(char, RSTRING_LEN(str) + 1);
@@ -793,7 +797,7 @@ readline_s_get_basic_quote_characters(VALUE self, VALUE str)
rb_secure(4);
if (rl_basic_quote_characters == NULL)
return Qnil;
- return rb_tainted_str_new2(rl_basic_quote_characters);
+ return rb_locale_str_new_cstr(rl_basic_quote_characters);
#else
rb_notimplement();
return Qnil; /* not reached */
@@ -820,7 +824,7 @@ readline_s_set_completer_quote_characters(VALUE self, VALUE str)
static char *completer_quote_characters = NULL;
rb_secure(4);
- SafeStringValue(str);
+ OutputStringValue(str);
if (completer_quote_characters == NULL) {
completer_quote_characters =
ALLOC_N(char, RSTRING_LEN(str) + 1);
@@ -857,7 +861,7 @@ readline_s_get_completer_quote_characters(VALUE self, VALUE str)
rb_secure(4);
if (rl_completer_quote_characters == NULL)
return Qnil;
- return rb_tainted_str_new2(rl_completer_quote_characters);
+ return rb_locale_str_new_cstr(rl_completer_quote_characters);
#else
rb_notimplement();
return Qnil; /* not reached */
@@ -882,7 +886,7 @@ readline_s_set_filename_quote_characters(VALUE self, VALUE str)
static char *filename_quote_characters = NULL;
rb_secure(4);
- SafeStringValue(str);
+ OutputStringValue(str);
if (filename_quote_characters == NULL) {
filename_quote_characters =
ALLOC_N(char, RSTRING_LEN(str) + 1);
@@ -919,7 +923,7 @@ readline_s_get_filename_quote_characters(VALUE self, VALUE str)
rb_secure(4);
if (rl_filename_quote_characters == NULL)
return Qnil;
- return rb_tainted_str_new2(rl_filename_quote_characters);
+ return rb_locale_str_new_cstr(rl_filename_quote_characters);
#else
rb_notimplement();
return Qnil; /* not reached */
@@ -929,7 +933,7 @@ readline_s_get_filename_quote_characters(VALUE self, VALUE str)
static VALUE
hist_to_s(VALUE self)
{
- return rb_str_new2("HISTORY");
+ return rb_str_new_cstr("HISTORY");
}
static int
@@ -961,7 +965,7 @@ hist_get(VALUE self, VALUE index)
if (entry == NULL) {
rb_raise(rb_eIndexError, "invalid index");
}
- return rb_tainted_str_new2(entry->line);
+ return rb_locale_str_new_cstr(entry->line);
}
static VALUE
@@ -973,7 +977,7 @@ hist_set(VALUE self, VALUE index, VALUE str)
rb_secure(4);
i = NUM2INT(index);
- SafeStringValue(str);
+ OutputStringValue(str);
if (i < 0) {
i += history_length;
}
@@ -994,7 +998,7 @@ static VALUE
hist_push(VALUE self, VALUE str)
{
rb_secure(4);
- SafeStringValue(str);
+ OutputStringValue(str);
add_history(RSTRING_PTR(str));
return self;
}
@@ -1007,7 +1011,7 @@ hist_push_method(int argc, VALUE *argv, VALUE self)
rb_secure(4);
while (argc--) {
str = *argv++;
- SafeStringValue(str);
+ OutputStringValue(str);
add_history(RSTRING_PTR(str));
}
return self;
@@ -1023,7 +1027,7 @@ rb_remove_history(int index)
rb_secure(4);
entry = remove_history(index);
if (entry) {
- val = rb_tainted_str_new2(entry->line);
+ val = rb_locale_str_new_cstr(entry->line);
free((void *) entry->line);
free(entry);
return val;
@@ -1070,7 +1074,7 @@ hist_each(VALUE self)
entry = history_get(history_get_offset_func(i));
if (entry == NULL)
break;
- rb_yield(rb_tainted_str_new2(entry->line));
+ rb_yield(rb_locale_str_new_cstr(entry->line));
}
return self;
}
@@ -1129,7 +1133,7 @@ filename_completion_proc_call(VALUE self, VALUE str)
if (matches) {
result = rb_ary_new();
for (i = 0; matches[i]; i++) {
- rb_ary_push(result, rb_tainted_str_new2(matches[i]));
+ rb_ary_push(result, rb_locale_str_new_cstr(matches[i]));
free(matches[i]);
}
free(matches);
@@ -1154,7 +1158,7 @@ username_completion_proc_call(VALUE self, VALUE str)
if (matches) {
result = rb_ary_new();
for (i = 0; matches[i]; i++) {
- rb_ary_push(result, rb_tainted_str_new2(matches[i]));
+ rb_ary_push(result, rb_locale_str_new_cstr(matches[i]));
free(matches[i]);
}
free(matches);
@@ -1271,19 +1275,27 @@ Init_readline()
rb_define_const(mReadline, "USERNAME_COMPLETION_PROC", ucomp);
history_get_offset_func = history_get_offset_history_base;
#if defined HAVE_RL_LIBRARY_VERSION
- version = rb_str_new2(rl_library_version);
-#if defined HAVE_CLEAR_HISTORY
+ version = rb_str_new_cstr(rl_library_version);
+#if defined HAVE_CLEAR_HISTORY || defined HAVE_REMOVE_HISTORY
if (strncmp(rl_library_version, EDIT_LINE_LIBRARY_VERSION,
strlen(EDIT_LINE_LIBRARY_VERSION)) == 0) {
add_history("1");
if (history_get(history_get_offset_func(0)) == NULL) {
history_get_offset_func = history_get_offset_0;
}
+#if !defined HAVE_CLEAR_HISTORY
clear_history();
+#else
+ {
+ HIST_ENTRY *entry = remove_history(0);
+ free(entry->line);
+ free(entry);
+ }
+#endif
}
#endif
#else
- version = rb_str_new2("2.0 or prior version");
+ version = rb_str_new_cstr("2.0 or prior version");
#endif
/* Version string of GNU Readline or libedit. */
rb_define_const(mReadline, "VERSION", version);
diff --git a/ext/ripper/depend b/ext/ripper/depend
index 120fdc58e7..e8a53e436b 100644
--- a/ext/ripper/depend
+++ b/ext/ripper/depend
@@ -5,7 +5,12 @@ BISON = bison
src: ripper.c eventids1.c eventids2table.c
-ripper.o: ripper.c lex.c eventids1.c eventids2.c eventids2table.c
+ripper.o: ripper.c lex.c eventids1.c eventids2.c eventids2table.c \
+ $(hdrdir)/ruby/ruby.h $(arch_hdrdir)/ruby/config.h \
+ $(hdrdir)/ruby/defines.h $(hdrdir)/ruby/intern.h \
+ $(hdrdir)/ruby/encoding.h $(hdrdir)/missing.h \
+ $(hdrdir)/../node.h $(hdrdir)/oniguruma.h \
+ $(hdrdir)/regex.h $(hdrdir)/st.h $(hdrdir)/util.h
.y.c:
$(BISON) -t -v -oy.tab.c $<
diff --git a/ext/ripper/eventids2.c b/ext/ripper/eventids2.c
index 47e195d084..2439631496 100644
--- a/ext/ripper/eventids2.c
+++ b/ext/ripper/eventids2.c
@@ -180,6 +180,7 @@ static const struct token_assoc {
{keyword_yield, &ripper_id_kw},
{keyword__FILE__, &ripper_id_kw},
{keyword__LINE__, &ripper_id_kw},
+ {keyword__ENCODING__, &ripper_id_kw},
{keyword_BEGIN, &ripper_id_kw},
{keyword_END, &ripper_id_kw},
{tAMPER, &ripper_id_op},
diff --git a/ext/sdbm/_sdbm.c b/ext/sdbm/_sdbm.c
index 1d81778193..5668c2c184 100644
--- a/ext/sdbm/_sdbm.c
+++ b/ext/sdbm/_sdbm.c
@@ -103,7 +103,7 @@ static int duppair proto((char *, datum));
/*
* externals
*/
-#if !defined sun && !defined MSDOS && !defined _WIN32 && !defined __CYGWIN__ && !defined(errno)
+#if !defined sun && !defined _WIN32 && !defined __CYGWIN__ && !defined(errno)
extern int errno;
#endif
@@ -338,7 +338,7 @@ makroom(register DBM *db, long int hash, int need)
{
long newp;
char twin[PBLKSIZ];
-#if defined MSDOS || (defined _WIN32 && !defined __CYGWIN__)
+#if defined _WIN32 && !defined __CYGWIN__
char zer[PBLKSIZ];
long oldtail;
#endif
@@ -365,7 +365,7 @@ makroom(register DBM *db, long int hash, int need)
* here, as sdbm_store will do so, after it inserts the incoming pair.
*/
-#if defined MSDOS || (defined _WIN32 && !defined __CYGWIN__)
+#if defined _WIN32 && !defined __CYGWIN__
/*
* Fill hole with 0 if made it.
* (hole is NOT read as 0)
diff --git a/ext/sdbm/init.c b/ext/sdbm/init.c
index 70480f462b..2e4f75cfbf 100644
--- a/ext/sdbm/init.c
+++ b/ext/sdbm/init.c
@@ -96,7 +96,7 @@ fsdbm_initialize(int argc, VALUE *argv, VALUE obj)
else {
mode = NUM2INT(vmode);
}
- SafeStringValue(file);
+ FilePathValue(file);
dbm = 0;
if (mode >= 0)
@@ -142,7 +142,7 @@ fsdbm_fetch(VALUE obj, VALUE keystr, VALUE ifnone)
struct dbmdata *dbmp;
DBM *dbm;
- StringValue(keystr);
+ ExportStringValue(keystr);
key.dptr = RSTRING_PTR(keystr);
key.dsize = RSTRING_LEN(keystr);
@@ -150,10 +150,10 @@ fsdbm_fetch(VALUE obj, VALUE keystr, VALUE ifnone)
value = sdbm_fetch(dbm, key);
if (value.dptr == 0) {
if (ifnone == Qnil && rb_block_given_p())
- return rb_yield(rb_tainted_str_new(key.dptr, key.dsize));
+ return rb_yield(rb_external_str_new(key.dptr, key.dsize));
return ifnone;
}
- return rb_tainted_str_new(value.dptr, value.dsize);
+ return rb_external_str_new(value.dptr, value.dsize);
}
static VALUE
@@ -176,13 +176,13 @@ fsdbm_fetch_m(int argc, VALUE *argv, VALUE obj)
}
static VALUE
-fsdbm_index(VALUE obj, VALUE valstr)
+fsdbm_key(VALUE obj, VALUE valstr)
{
datum key, val;
struct dbmdata *dbmp;
DBM *dbm;
- StringValue(valstr);
+ ExportStringValue(valstr);
val.dptr = RSTRING_PTR(valstr);
val.dsize = RSTRING_LEN(valstr);
@@ -191,12 +191,19 @@ fsdbm_index(VALUE obj, VALUE valstr)
val = sdbm_fetch(dbm, key);
if (val.dsize == RSTRING_LEN(valstr) &&
memcmp(val.dptr, RSTRING_PTR(valstr), val.dsize) == 0)
- return rb_tainted_str_new(key.dptr, key.dsize);
+ return rb_external_str_new(key.dptr, key.dsize);
}
return Qnil;
}
static VALUE
+fsdbm_index(VALUE hash, VALUE value)
+{
+ rb_warn("SDBM#index is deprecated; use SDBM#key");
+ return fsdbm_key(hash, value);
+}
+
+static VALUE
fsdbm_select(VALUE obj)
{
VALUE new = rb_ary_new();
@@ -208,8 +215,8 @@ fsdbm_select(VALUE obj)
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
VALUE assoc, v;
val = sdbm_fetch(dbm, key);
- assoc = rb_assoc_new(rb_tainted_str_new(key.dptr, key.dsize),
- rb_tainted_str_new(val.dptr, val.dsize));
+ assoc = rb_assoc_new(rb_external_str_new(key.dptr, key.dsize),
+ rb_external_str_new(val.dptr, val.dsize));
v = rb_yield(assoc);
if (RTEST(v)) {
rb_ary_push(new, assoc);
@@ -249,7 +256,7 @@ fsdbm_delete(VALUE obj, VALUE keystr)
VALUE valstr;
fdbm_modify(obj);
- StringValue(keystr);
+ ExportStringValue(keystr);
key.dptr = RSTRING_PTR(keystr);
key.dsize = RSTRING_LEN(keystr);
@@ -263,7 +270,7 @@ fsdbm_delete(VALUE obj, VALUE keystr)
}
/* need to save value before sdbm_delete() */
- valstr = rb_tainted_str_new(value.dptr, value.dsize);
+ valstr = rb_external_str_new(value.dptr, value.dsize);
if (sdbm_delete(dbm, key)) {
dbmp->di_size = -1;
@@ -288,8 +295,8 @@ fsdbm_shift(VALUE obj)
key = sdbm_firstkey(dbm);
if (!key.dptr) return Qnil;
val = sdbm_fetch(dbm, key);
- keystr = rb_tainted_str_new(key.dptr, key.dsize);
- valstr = rb_tainted_str_new(val.dptr, val.dsize);
+ keystr = rb_external_str_new(key.dptr, key.dsize);
+ valstr = rb_external_str_new(val.dptr, val.dsize);
sdbm_delete(dbm, key);
if (dbmp->di_size >= 0) {
dbmp->di_size--;
@@ -314,8 +321,8 @@ fsdbm_delete_if(VALUE obj)
dbmp->di_size = -1;
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
val = sdbm_fetch(dbm, key);
- keystr = rb_tainted_str_new(key.dptr, key.dsize);
- valstr = rb_tainted_str_new(val.dptr, val.dsize);
+ keystr = rb_external_str_new(key.dptr, key.dsize);
+ valstr = rb_external_str_new(val.dptr, val.dsize);
ret = rb_protect(rb_yield, rb_assoc_new(rb_str_dup(keystr), valstr), &status);
if (status != 0) break;
if (RTEST(ret)) rb_ary_push(ary, keystr);
@@ -324,7 +331,7 @@ fsdbm_delete_if(VALUE obj)
for (i = 0; i < RARRAY_LEN(ary); i++) {
keystr = RARRAY_PTR(ary)[i];
- StringValue(keystr);
+ ExportStringValue(keystr);
key.dptr = RSTRING_PTR(keystr);
key.dsize = RSTRING_LEN(keystr);
if (sdbm_delete(dbm, key)) {
@@ -369,8 +376,8 @@ fsdbm_invert(VALUE obj)
GetDBM2(obj, dbmp, dbm);
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
val = sdbm_fetch(dbm, key);
- keystr = rb_tainted_str_new(key.dptr, key.dsize);
- valstr = rb_tainted_str_new(val.dptr, val.dsize);
+ keystr = rb_external_str_new(key.dptr, key.dsize);
+ valstr = rb_external_str_new(val.dptr, val.dsize);
rb_hash_aset(hash, valstr, keystr);
}
return hash;
@@ -389,8 +396,8 @@ fsdbm_store(VALUE obj, VALUE keystr, VALUE valstr)
}
fdbm_modify(obj);
- StringValue(keystr);
- StringValue(valstr);
+ ExportStringValue(keystr);
+ ExportStringValue(valstr);
key.dptr = RSTRING_PTR(keystr);
key.dsize = RSTRING_LEN(keystr);
@@ -491,7 +498,7 @@ fsdbm_each_value(VALUE obj)
GetDBM2(obj, dbmp, dbm);
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
val = sdbm_fetch(dbm, key);
- rb_yield(rb_tainted_str_new(val.dptr, val.dsize));
+ rb_yield(rb_external_str_new(val.dptr, val.dsize));
GetDBM2(obj, dbmp, dbm);
}
return obj;
@@ -508,7 +515,7 @@ fsdbm_each_key(VALUE obj)
GetDBM2(obj, dbmp, dbm);
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
- rb_yield(rb_tainted_str_new(key.dptr, key.dsize));
+ rb_yield(rb_external_str_new(key.dptr, key.dsize));
GetDBM2(obj, dbmp, dbm);
}
return obj;
@@ -527,8 +534,8 @@ fsdbm_each_pair(VALUE obj)
GetDBM2(obj, dbmp, dbm);
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
val = sdbm_fetch(dbm, key);
- keystr = rb_tainted_str_new(key.dptr, key.dsize);
- valstr = rb_tainted_str_new(val.dptr, val.dsize);
+ keystr = rb_external_str_new(key.dptr, key.dsize);
+ valstr = rb_external_str_new(val.dptr, val.dsize);
rb_yield(rb_assoc_new(keystr, valstr));
GetDBM2(obj, dbmp, dbm);
}
@@ -547,7 +554,7 @@ fsdbm_keys(VALUE obj)
GetDBM2(obj, dbmp, dbm);
ary = rb_ary_new();
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
- rb_ary_push(ary, rb_tainted_str_new(key.dptr, key.dsize));
+ rb_ary_push(ary, rb_external_str_new(key.dptr, key.dsize));
}
return ary;
@@ -565,7 +572,7 @@ fsdbm_values(VALUE obj)
ary = rb_ary_new();
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
val = sdbm_fetch(dbm, key);
- rb_ary_push(ary, rb_tainted_str_new(val.dptr, val.dsize));
+ rb_ary_push(ary, rb_external_str_new(val.dptr, val.dsize));
}
return ary;
@@ -578,7 +585,7 @@ fsdbm_has_key(VALUE obj, VALUE keystr)
struct dbmdata *dbmp;
DBM *dbm;
- StringValue(keystr);
+ ExportStringValue(keystr);
key.dptr = RSTRING_PTR(keystr);
key.dsize = RSTRING_LEN(keystr);
@@ -595,7 +602,7 @@ fsdbm_has_value(VALUE obj, VALUE valstr)
struct dbmdata *dbmp;
DBM *dbm;
- StringValue(valstr);
+ ExportStringValue(valstr);
val.dptr = RSTRING_PTR(valstr);
val.dsize = RSTRING_LEN(valstr);
@@ -621,8 +628,8 @@ fsdbm_to_a(VALUE obj)
ary = rb_ary_new();
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
val = sdbm_fetch(dbm, key);
- rb_ary_push(ary, rb_assoc_new(rb_tainted_str_new(key.dptr, key.dsize),
- rb_tainted_str_new(val.dptr, val.dsize)));
+ rb_ary_push(ary, rb_assoc_new(rb_external_str_new(key.dptr, key.dsize),
+ rb_external_str_new(val.dptr, val.dsize)));
}
return ary;
@@ -640,8 +647,8 @@ fsdbm_to_hash(VALUE obj)
hash = rb_hash_new();
for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
val = sdbm_fetch(dbm, key);
- rb_hash_aset(hash, rb_tainted_str_new(key.dptr, key.dsize),
- rb_tainted_str_new(val.dptr, val.dsize));
+ rb_hash_aset(hash, rb_external_str_new(key.dptr, key.dsize),
+ rb_external_str_new(val.dptr, val.dsize));
}
return hash;
@@ -671,6 +678,7 @@ Init_sdbm()
rb_define_method(rb_cDBM, "[]=", fsdbm_store, 2);
rb_define_method(rb_cDBM, "store", fsdbm_store, 2);
rb_define_method(rb_cDBM, "index", fsdbm_index, 1);
+ rb_define_method(rb_cDBM, "key", fsdbm_key, 1);
rb_define_method(rb_cDBM, "select", fsdbm_select, 0);
rb_define_method(rb_cDBM, "values_at", fsdbm_values_at, -1);
rb_define_method(rb_cDBM, "length", fsdbm_length, 0);
diff --git a/ext/sdbm/sdbm.h b/ext/sdbm/sdbm.h
index ce8f54c4d4..0c7ed1ba9b 100644
--- a/ext/sdbm/sdbm.h
+++ b/ext/sdbm/sdbm.h
@@ -52,7 +52,7 @@ typedef struct {
extern datum nullitem;
-#if defined(__STDC__) || defined(MSDOS)
+#if defined(__STDC__)
#define proto(p) p
#else
#define proto(p) ()
diff --git a/ext/socket/getaddrinfo.c b/ext/socket/getaddrinfo.c
index e99c4e462b..837a506a72 100644
--- a/ext/socket/getaddrinfo.c
+++ b/ext/socket/getaddrinfo.c
@@ -42,7 +42,7 @@
#include <sys/types.h>
#ifndef _WIN32
#include <sys/param.h>
-#if defined(__BEOS__) && !defined(__HAIKU__)
+#if defined(__BEOS__) && !defined(__HAIKU__) && !defined(BONE)
# include <net/socket.h>
#else
# include <sys/socket.h>
diff --git a/ext/socket/getnameinfo.c b/ext/socket/getnameinfo.c
index 37f60fc83f..aee81b5356 100644
--- a/ext/socket/getnameinfo.c
+++ b/ext/socket/getnameinfo.c
@@ -38,7 +38,7 @@
#include <stdio.h>
#include <sys/types.h>
#ifndef _WIN32
-#if defined(__BEOS__) && !defined(__HAIKU__)
+#if defined(__BEOS__) && !defined(__HAIKU__) && !defined(BONE)
# include <net/socket.h>
#else
# include <sys/socket.h>
diff --git a/ext/socket/mkconstants.rb b/ext/socket/mkconstants.rb
index 46a6655bfc..bb05250805 100644
--- a/ext/socket/mkconstants.rb
+++ b/ext/socket/mkconstants.rb
@@ -143,6 +143,16 @@ IPPROTO_TP
IPPROTO_XTP
IPPROTO_EON
IPPROTO_BIP
+IPPROTO_AH
+IPPROTO_DSTOPTS
+IPPROTO_ESP
+IPPROTO_FRAGMENT
+IPPROTO_HOPOPTS
+IPPROTO_ICMPV6
+IPPROTO_IPV6
+IPPROTO_NONE
+IPPROTO_ROUTING
+
IPPROTO_RAW 255
IPPROTO_MAX
@@ -232,6 +242,7 @@ EAI_FAMILY
EAI_MEMORY
EAI_NODATA
EAI_NONAME
+EAI_OVERFLOW
EAI_SERVICE
EAI_SOCKTYPE
EAI_SYSTEM
@@ -242,6 +253,7 @@ EAI_MAX
AI_PASSIVE
AI_CANONNAME
AI_NUMERICHOST
+AI_NUMERICSERV
AI_MASK
AI_ALL
AI_V4MAPPED_CFG
@@ -288,3 +300,6 @@ IPV6_RTHDR_TYPE_0
IPV6_RECVPATHMTU
IPV6_TCLASS
IPV6_USE_MIN_MTU
+
+INET_ADDRSTRLEN
+INET6_ADDRSTRLEN
diff --git a/ext/socket/socket.c b/ext/socket/socket.c
index c753f19de3..09abc88c18 100644
--- a/ext/socket/socket.c
+++ b/ext/socket/socket.c
@@ -28,7 +28,7 @@
#endif
#ifndef _WIN32
-#if defined(__BEOS__) && !defined(__HAIKU__)
+#if defined(__BEOS__) && !defined(__HAIKU__) && !defined(BONE)
# include <net/socket.h>
#else
# include <sys/socket.h>
@@ -241,9 +241,7 @@ init_sock(VALUE sock, int fd)
MakeOpenFile(sock, fp);
fp->fd = fd;
fp->mode = FMODE_READWRITE|FMODE_DUPLEX;
-#if defined(_WIN32) || defined(DJGPP) || defined(__CYGWIN__) || defined(__human68k__) || defined(__EMX__)
- fp->mode |= FMODE_BINMODE;
-#endif
+ rb_io_ascii8bit_binmode(sock);
if (do_not_reverse_lookup) {
fp->mode |= FMODE_NOREVLOOKUP;
}
@@ -772,7 +770,7 @@ bsock_recv(int argc, VALUE *argv, VALUE sock)
* c = TCPSocket.new(addr, port)
* s = serv.accept
* c.send "aaa", 0
- * IO.select([s])
+ * IO.select([s]) # emulate blocking recv.
* p s.recv_nonblock(10) #=> "aaa"
*
* Refer to Socket#recvfrom for the exceptions that may be thrown if the call
@@ -869,7 +867,7 @@ host_str(VALUE host, char *hbuf, size_t len)
return NULL;
}
else if (rb_obj_is_kind_of(host, rb_cInteger)) {
- long i = NUM2LONG(host);
+ unsigned long i = NUM2ULONG(host);
make_inetaddr(htonl(i), hbuf, len);
return hbuf;
@@ -1598,7 +1596,7 @@ tcp_accept(VALUE sock)
* === Example
* require 'socket'
* serv = TCPServer.new(2202)
- * begin
+ * begin # emulate blocking accept
* sock = serv.accept_nonblock
* rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
* IO.select([serv])
@@ -1899,7 +1897,7 @@ udp_send(int argc, VALUE *argv, VALUE sock)
* s2.connect(*s1.addr.values_at(3,1))
* s1.connect(*s2.addr.values_at(3,1))
* s1.send "aaa", 0
- * IO.select([s2])
+ * IO.select([s2]) # emulate blocking recvfrom
* p s2.recvfrom_nonblock(10) #=> ["aaa", ["AF_INET", 33302, "localhost.localdomain", "127.0.0.1"]]
*
* Refer to Socket#recvfrom for the exceptions that may be thrown if the call
@@ -2187,7 +2185,7 @@ unix_accept(VALUE sock)
* === Example
* require 'socket'
* serv = UNIXServer.new("/tmp/sock")
- * begin
+ * begin # emulate blocking accept
* sock = serv.accept_nonblock
* rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
* IO.select([serv])
@@ -2560,7 +2558,7 @@ sock_connect(VALUE sock, VALUE addr)
* include Socket::Constants
* socket = Socket.new(AF_INET, SOCK_STREAM, 0)
* sockaddr = Socket.sockaddr_in(80, 'www.google.com')
- * begin
+ * begin # emulate blocking connect
* socket.connect_nonblock(sockaddr)
* rescue Errno::EINPROGRESS
* IO.select(nil, [socket])
@@ -2916,7 +2914,7 @@ sock_recvfrom(int argc, VALUE *argv, VALUE sock)
* socket.bind(sockaddr)
* socket.listen(5)
* client, client_sockaddr = socket.accept
- * begin
+ * begin # emulate blocking recvfrom
* pair = client.recvfrom_nonblock(20)
* rescue Errno::EAGAIN, Errno::EWOULDBLOCK
* IO.select([client])
@@ -2984,7 +2982,7 @@ sock_accept(VALUE sock)
* sockaddr = Socket.sockaddr_in(2200, 'localhost')
* socket.bind(sockaddr)
* socket.listen(5)
- * begin
+ * begin # emulate blocking accept
* client_socket, client_sockaddr = socket.accept_nonblock
* rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::ECONNABORTED, Errno::EPROTO, Errno::EINTR
* IO.select([socket])
@@ -3224,23 +3222,23 @@ sock_s_getservbyname(int argc, VALUE *argv)
VALUE service, proto;
struct servent *sp;
int port;
+ const char *servicename, *protoname = "tcp";
rb_scan_args(argc, argv, "11", &service, &proto);
- if (NIL_P(proto)) proto = rb_str_new2("tcp");
StringValue(service);
- StringValue(proto);
-
- sp = getservbyname(StringValueCStr(service), StringValueCStr(proto));
+ if (!NIL_P(proto)) StringValue(proto);
+ servicename = StringValueCStr(service);
+ if (!NIL_P(proto)) protoname = StringValueCStr(proto);
+ sp = getservbyname(servicename, protoname);
if (sp) {
port = ntohs(sp->s_port);
}
else {
- char *s = RSTRING_PTR(service);
char *end;
- port = STRTOUL(s, &end, 0);
+ port = STRTOUL(servicename, &end, 0);
if (*end != '\0') {
- rb_raise(rb_eSocket, "no such service %s/%s", s, RSTRING_PTR(proto));
+ rb_raise(rb_eSocket, "no such service %s/%s", servicename, protoname);
}
}
return INT2FIX(port);
@@ -3251,14 +3249,20 @@ sock_s_getservbyport(int argc, VALUE *argv)
{
VALUE port, proto;
struct servent *sp;
+ long portnum;
+ const char *protoname = "tcp";
rb_scan_args(argc, argv, "11", &port, &proto);
- if (NIL_P(proto)) proto = rb_str_new2("tcp");
- StringValue(proto);
+ portnum = NUM2LONG(port);
+ if (portnum != (uint16_t)portnum) {
+ const char *s = portnum > 0 ? "big" : "small";
+ rb_raise(rb_eRangeError, "integer %ld too %s to convert into `int16_t'", portnum, s);
+ }
+ if (!NIL_P(proto)) protoname = StringValueCStr(proto);
- sp = getservbyport(NUM2INT(port), StringValueCStr(proto));
+ sp = getservbyport((int)htons((uint16_t)portnum), protoname);
if (!sp) {
- rb_raise(rb_eSocket, "no such service for port %d/%s", NUM2INT(port), RSTRING_PTR(proto));
+ rb_raise(rb_eSocket, "no such service for port %d/%s", (int)portnum, protoname);
}
return rb_tainted_str_new2(sp->s_name);
}
diff --git a/ext/stringio/stringio.c b/ext/stringio/stringio.c
index db243c4e7e..4c997dcd04 100644
--- a/ext/stringio/stringio.c
+++ b/ext/stringio/stringio.c
@@ -13,6 +13,7 @@
#include "ruby.h"
#include "ruby/io.h"
+#include "ruby/encoding.h"
#if defined(HAVE_FCNTL_H) || defined(_WIN32)
#include <fcntl.h>
#elif defined(HAVE_SYS_FCNTL_H)
@@ -700,7 +701,7 @@ strio_ungetc(VALUE self, VALUE c)
struct StringIO *ptr = readable(StringIO(self));
long lpos, clen;
char *p, *pend;
- rb_encoding *enc;
+ rb_encoding *enc, *enc2;
if (NIL_P(c)) return Qnil;
if (FIXNUM_P(c)) {
@@ -713,10 +714,14 @@ strio_ungetc(VALUE self, VALUE c)
}
else {
SafeStringValue(c);
- enc = rb_enc_check(ptr->string, c);
+ enc = rb_enc_get(ptr->string);
+ enc2 = rb_enc_get(c);
+ if (enc != enc2 && enc != rb_ascii8bit_encoding()) {
+ c = rb_str_conv_enc(c, enc2, enc);
+ }
}
/* get logical position */
- lpos = 0; p = RSTRING_PTR(ptr->string); pend = p + ptr->pos - 1;
+ lpos = 0; p = RSTRING_PTR(ptr->string); pend = p + ptr->pos;
for (;;) {
clen = rb_enc_mbclen(p, pend, enc);
if (p+clen >= pend) break;
@@ -731,6 +736,19 @@ strio_ungetc(VALUE self, VALUE c)
/*
* call-seq:
+ * strio.ungetbyte(fixnum) -> nil
+ *
+ * See IO#ungetbyte
+ */
+static VALUE
+strio_ungetbyte(VALUE self, VALUE c)
+{
+ NUM2INT(c);
+ return strio_ungetc(self, c);
+}
+
+/*
+ * call-seq:
* strio.readchar -> fixnum
*
* See IO#readchar.
@@ -992,9 +1010,15 @@ strio_write(VALUE self, VALUE str)
{
struct StringIO *ptr = writable(StringIO(self));
long len, olen;
+ rb_encoding *enc, *enc2;
if (TYPE(str) != T_STRING)
str = rb_obj_as_string(str);
+ enc = rb_enc_get(ptr->string);
+ enc2 = rb_enc_get(str);
+ if (enc != enc2 && enc != rb_ascii8bit_encoding()) {
+ str = rb_str_conv_enc(str, enc2, enc);
+ }
len = RSTRING_LEN(str);
if (len == 0) return INT2FIX(0);
check_modifiable(ptr);
@@ -1217,6 +1241,51 @@ strio_truncate(VALUE self, VALUE len)
}
/*
+ * call-seq:
+ * strio.external_encoding => encoding
+ *
+ * Returns the Encoding object that represents the encoding of the file.
+ * If strio is write mode and no encoding is specified, returns <code>nil</code>.
+ */
+
+static VALUE
+strio_external_encoding(VALUE self)
+{
+ return rb_enc_from_encoding(rb_enc_get(StringIO(self)->string));
+}
+
+/*
+ * call-seq:
+ * strio.internal_encoding => encoding
+ *
+ * Returns the Encoding of the internal string if conversion is
+ * specified. Otherwise returns nil.
+ */
+
+static VALUE
+strio_internal_encoding(VALUE self)
+{
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * strio.set_encoding(ext_enc) => strio
+ *
+ * Tagged with the encoding specified.
+ */
+
+static VALUE
+strio_set_encoding(VALUE self, VALUE ext_enc)
+{
+ rb_encoding* enc;
+ VALUE str = StringIO(self)->string;
+ enc = rb_to_encoding(ext_enc);
+ rb_enc_associate(str, enc);
+ return self;
+}
+
+/*
* Pseudo I/O on String object.
*/
void
@@ -1266,6 +1335,7 @@ Init_stringio()
rb_define_method(StringIO, "chars", strio_each_char, 0);
rb_define_method(StringIO, "getc", strio_getc, 0);
rb_define_method(StringIO, "ungetc", strio_ungetc, 1);
+ rb_define_method(StringIO, "ungetbyte", strio_ungetbyte, 1);
rb_define_method(StringIO, "readchar", strio_readchar, 0);
rb_define_method(StringIO, "getbyte", strio_getbyte, 0);
rb_define_method(StringIO, "readbyte", strio_readbyte, 0);
@@ -1291,4 +1361,8 @@ Init_stringio()
rb_define_method(StringIO, "size", strio_size, 0);
rb_define_method(StringIO, "length", strio_size, 0);
rb_define_method(StringIO, "truncate", strio_truncate, 1);
+
+ rb_define_method(StringIO, "external_encoding", strio_external_encoding, 0);
+ rb_define_method(StringIO, "internal_encoding", strio_internal_encoding, 0);
+ rb_define_method(StringIO, "set_encoding", strio_set_encoding, 1);
}
diff --git a/ext/syck/node.c b/ext/syck/node.c
index 890eba9d58..fb98f655cc 100644
--- a/ext/syck/node.c
+++ b/ext/syck/node.c
@@ -128,7 +128,7 @@ syck_replace_str( SyckNode *n, char *str, enum scalar_style style )
void
syck_replace_str2( SyckNode *n, char *str, long len, enum scalar_style style )
{
- if ( n->data.str != NULL )
+ if ( n->data.str->ptr != NULL )
{
S_FREE( n->data.str->ptr );
n->data.str->ptr = NULL;
diff --git a/ext/syck/syck.c b/ext/syck/syck.c
index 92b7566d1a..e0fc2bc244 100644
--- a/ext/syck/syck.c
+++ b/ext/syck/syck.c
@@ -192,11 +192,11 @@ syck_add_sym( SyckParser *p, void *data )
int
syck_lookup_sym( SyckParser *p, SYMID id, void **datap )
{
- st_data_t data = (st_data_t)*datap;
+ st_data_t data;
int ret;
if ( p->syms == NULL ) return 0;
ret = st_lookup( p->syms, id, &data );
- *datap = (void *)data;
+ if(ret) *datap = (void *)data;
return ret;
}
diff --git a/ext/tk/extconf.rb b/ext/tk/extconf.rb
index be3781251e..419c79ceda 100644
--- a/ext/tk/extconf.rb
+++ b/ext/tk/extconf.rb
@@ -2,7 +2,7 @@
require 'mkmf'
-is_win32 = (/mswin|mingw|cygwin|bccwin|wince/ =~ RUBY_PLATFORM)
+is_win32 = (/mswin|mingw|cygwin|bccwin/ =~ RUBY_PLATFORM)
#is_macosx = (/darwin/ =~ RUBY_PLATFORM)
have_func("ruby_native_thread_p", "ruby.h")
@@ -64,6 +64,18 @@ tcltk_version = with_config("tcltkversion")
use_X = with_config("X11", (! is_win32))
+def parse_tclConfig(file)
+ # check tclConfig.sh/tkConfig.sh
+ tbl = {}
+ IO.foreach(file){|line|
+ line.strip!
+ next if line !~ /^([^\#=][^=]*)=(['"]|)(.*)\2$/
+ key, val = $1, $3
+ tbl[key] = val.gsub(/\$\{([^}]+)\}/){|s| tbl[$1]} rescue nil
+ }
+ tbl
+end
+
def check_tcltk_version(version)
return [nil, nil] unless version
@@ -118,7 +130,7 @@ def find_tcl(tcllib, stubs, version, *opt_paths)
if version && ! version.empty?
versions = [version]
else
- versions = %w[8.6 8.5 8.4 8.3 8.2 8.1 8.0 7.6]
+ versions = %w[8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0 7.6]
end
if tcllib
@@ -161,7 +173,7 @@ def find_tk(tklib, stubs, version, *opt_paths)
if version && ! version.empty?
versions = [version]
else
- versions = %w[8.6 8.5 8.4 8.3 8.2 8.1 8.0 4.2]
+ versions = %w[8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0 4.2]
end
if tklib
@@ -185,6 +197,35 @@ def find_tk(tklib, stubs, version, *opt_paths)
st
end
+def find_tcltk_header(tclver, tkver)
+ base_dir = ['/usr/local/include', '/usr/pkg/include', '/usr/include']
+ base_dir << '/Tcl/include' # default for ActiveTcl
+
+ unless have_tcl_h = have_header('tcl.h')
+ if tclver && ! tclver.empty?
+ versions = [tclver]
+ else
+ versions = %w[8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0 7.6]
+ end
+ paths = base_dir.dup
+ versions.each{|ver| paths.concat(base_dir.map{|dir| dir + '/tcl' + ver})}
+ have_tcl_h = find_header('tcl.h', *paths)
+ end
+
+ unless have_tk_h = have_header("tk.h")
+ if tkver && ! tkver.empty?
+ versions = [tkver]
+ else
+ versions = %w[8.7 8.6 8.5 8.4 8.3 8.2 8.1 8.0 4.2]
+ end
+ paths = base_dir.dup
+ versions.each{|ver| paths.concat(base_dir.map{|dir| dir + '/tk' + ver})}
+ have_tk_h = find_header('tk.h', *paths)
+ end
+
+ have_tcl_h && have_tk_h
+end
+
def find_X11(*opt_paths)
default_paths =
[ "/usr/X11/lib", "/usr/lib/X11", "/usr/X11R6/lib", "/usr/openwin/lib" ]
@@ -218,37 +259,19 @@ def pthread_check()
else
# tcl-thread is unknown and tclConfig.sh is given
begin
- open(tclConfig, "r") do |cfg|
- while line = cfg.gets()
- if line =~ /^\s*TCL_THREADS=(0|1)/
- tcl_enable_thread = ($1 == "1")
- break
- end
-
- if line =~ /^\s*TCL_MAJOR_VERSION=("|')(\d+)\1/
- tcl_major_ver = $2
- if tcl_major_ver =~ /^[1-7]$/
- tcl_enable_thread = false
- break
- end
- if tcl_major_ver == "8" && tcl_minor_ver == "0"
- tcl_enable_thread = false
- break
- end
- end
-
- if line =~ /^\s*TCL_MINOR_VERSION=("|')(\d+)\1/
- tcl_minor_ver = $2
- if tcl_major_ver == "8" && tcl_minor_ver == "0"
- tcl_enable_thread = false
- break
- end
- end
+ tbl = parse_tclConfig(tclConfig)
+ if tbl['TCL_THREADS']
+ tcl_enable_thread = (tbl['TCL_THREADS'] == "1")
+ else
+ tcl_major_ver = tbl['TCL_MAJOR_VERSION'].to_i
+ tcl_minor_ver = tbl['TCL_MINOR_VERSION'].to_i
+ if tcl_major_ver < 8 || (tcl_major_ver == 8 && tcl_minor_ver == 0)
+ tcl_enable_thread = false
end
end
if tcl_enable_thread == nil
- # not find definition
+ # cannot find definition
if tcl_major_ver
puts("Warning: '#{tclConfig}' doesn't include TCL_THREADS definition.")
else
@@ -376,11 +399,11 @@ end
tclver, tkver = check_tcltk_version(tcltk_version)
-if have_header("tcl.h") && have_header("tk.h") &&
- ( tcltk_framework ||
- ( ( !use_X || find_X11(x11_ldir2, x11_ldir) ) &&
- find_tcl(tcllib, stubs, tclver, *tcl_ldir_list) &&
- find_tk(tklib, stubs, tkver, *tk_ldir_list) ) )
+if ( tcltk_framework ||
+ ( find_tcltk_header(tclver, tkver) &&
+ ( !use_X || find_X11(x11_ldir2, x11_ldir) ) &&
+ find_tcl(tcllib, stubs, tclver, *tcl_ldir_list) &&
+ find_tk(tklib, stubs, tkver, *tk_ldir_list) ) )
$CPPFLAGS += ' -DUSE_TCL_STUBS -DUSE_TK_STUBS' if stubs
$CPPFLAGS += ' -D_WIN32' if /cygwin/ =~ RUBY_PLATFORM
diff --git a/ext/tk/lib/tk.rb b/ext/tk/lib/tk.rb
index c3401dfadb..67069abc32 100644
--- a/ext/tk/lib/tk.rb
+++ b/ext/tk/lib/tk.rb
@@ -1112,7 +1112,15 @@ module TkCore
WITH_RUBY_VM = Object.const_defined?(:VM) && ::VM.class == Class
WITH_ENCODING = defined?(::Encoding.default_external) && true
#WITH_ENCODING = Object.const_defined?(:Encoding) && ::Encoding.class == Class
-
+ #if TclTkLib::WINDOWING_SYSTEM == 'aqua'
+ # if (TclTkLib.get_version <=> [8, 4, TclTkLib::RELEASE_TYPE::FINAL, 9]) > 0
+ # # *** KNOWN BUG ***
+ # # Main event loop thread of TkAqua (> Tk8.4.9) must be the main
+ # # application thread. So, ruby1.9 users must call Tk.mainloop on
+ # # the main application thread.
+ # RUN_EVENTLOOP_ON_MAIN_THREAD = true
+ # end
+ #end
unless self.const_defined? :RUN_EVENTLOOP_ON_MAIN_THREAD
### Ruby 1.9 !!!!!!!!!!!!!!!!!!!!!!!!!!
RUN_EVENTLOOP_ON_MAIN_THREAD = false
@@ -1671,8 +1679,18 @@ module TkCore
end
def mainloop(check_root = true)
- if !TkCore::WITH_RUBY_VM || TkCore::RUN_EVENTLOOP_ON_MAIN_THREAD
+ if !TkCore::WITH_RUBY_VM
TclTkLib.mainloop(check_root)
+
+ elsif TkCore::RUN_EVENTLOOP_ON_MAIN_THREAD
+ #if TclTkLib::WINDOWING_SYSTEM == 'aqua' &&
+ # Thread.current != Thread.main &&
+ # (TclTkLib.get_version <=> [8,4,TclTkLib::RELEASE_TYPE::FINAL,9]) > 0
+ # raise RuntimeError,
+ # "eventloop on TkAqua ( > Tk8.4.9 ) works on the main thread only"
+ #end
+ TclTkLib.mainloop(check_root)
+
else ### Ruby 1.9 !!!!!
unless TkCore::INTERP.default_master?
# [MultiTkIp] slave interp ?
@@ -2389,6 +2407,7 @@ if (/^(8\.[1-9]|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK)
BINARY_NAME = 'binary'.freeze
UTF8_NAME = 'utf-8'.freeze
DEFAULT_EXTERNAL_NAME = RubyEncoding.default_external.name.freeze
+ DEFAULT_INTERNAL_NAME = RubyEncoding.default_internal.name.freeze rescue nil
BINARY = RubyEncoding.find(BINARY_NAME)
UNKNOWN = RubyEncoding.find('ASCII-8BIT')
@@ -2528,7 +2547,7 @@ if (/^(8\.[1-9]|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK)
def tk_encoding_names
#TkComm.simplelist(TkCore::INTERP._invoke_without_enc(Tk::Encoding::ENCNAMES_CMD[0], Tk::Encoding::ENCNAMES_CMD[1]))
TkComm.simplelist(TkCore::INTERP._invoke_without_enc('encoding', 'names'))
- end
+ end
def encoding_names
self.tk_encoding_names.find_all{|name|
Tk::Encoding::ENCODING_TABLE.get_name(name) rescue false
@@ -2721,7 +2740,12 @@ if (/^(8\.[1-9]|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK)
enc_name ||=
Tk::Encoding::ENCODING_TABLE.get_name(str.encoding) rescue nil
- unless enc_name
+ if enc_name
+ # str has its encoding information
+ encstr = __toUTF8(str, enc_name)
+ encstr.force_encoding(Tk::Encoding::UTF8_NAME)
+ return encstr
+ else
# str.encoding isn't supported by Tk -> try to convert on Ruby
begin
return str.encode(Tk::Encoding::UTF8_NAME) # new string
@@ -2976,6 +3000,7 @@ if (/^(8\.[1-9]|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK)
else ### Ruby 1.9 !!!!!!!!!!!!
loc_enc_obj = ::Encoding.find(::Encoding.locale_charmap)
ext_enc_obj = ::Encoding.default_external
+ int_enc_obj = ::Encoding.default_internal || ext_enc_obj
tksys_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(Tk.encoding_system)
# p [Tk.encoding, Tk.encoding_system, loc_enc_obj, ext_enc_obj]
@@ -3052,7 +3077,8 @@ if (/^(8\.[1-9]|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK)
end
unless enc_name
- if ext_enc_obj == Tk::Encoding::UNKNOWN
+ #if ext_enc_obj == Tk::Encoding::UNKNOWN
+ if int_enc_obj == Tk::Encoding::UNKNOWN
if loc_enc_obj == Tk::Encoding::UNKNOWN
# use Tk.encoding_system
enc_name = tksys_enc_name
@@ -3060,7 +3086,7 @@ if (/^(8\.[1-9]|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK)
# use locale_charmap
begin
loc_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(loc_enc_obj)
- if loc_enc_name && loc_enc_name != tksys_enc_name
+ if loc_enc_name
# use locale_charmap
enc_name = loc_enc_name
else
@@ -3074,10 +3100,12 @@ if (/^(8\.[1-9]|9\.|[1-9][0-9])/ =~ Tk::TCL_VERSION && !Tk::JAPANIZED_TK)
end
else
begin
- ext_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(ext_enc_obj)
- if ext_enc_name && ext_enc_name != tksys_enc_name
+ #ext_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(ext_enc_obj)
+ #if ext_enc_name && ext_enc_name != tksys_enc_name
+ int_enc_name = Tk::Encoding::ENCODING_TABLE.get_name(int_enc_obj)
+ if int_enc_name
# use default_external
- enc_name = ext_enc_name
+ enc_name = int_enc_name
else
# use Tk.encoding_system
enc_name = tksys_enc_name
@@ -5501,7 +5529,7 @@ TkWidget = TkWindow
#Tk.freeze
module Tk
- RELEASE_DATE = '2008-06-17'.freeze
+ RELEASE_DATE = '2008-10-20'.freeze
autoload :AUTO_PATH, 'tk/variable'
autoload :TCL_PACKAGE_PATH, 'tk/variable'
diff --git a/ext/tk/lib/tk/autoload.rb b/ext/tk/lib/tk/autoload.rb
index 0773f7708d..79b6e01eb8 100644
--- a/ext/tk/lib/tk/autoload.rb
+++ b/ext/tk/lib/tk/autoload.rb
@@ -394,7 +394,7 @@ Tk.default_widget_set = :Tk
############################################
# depend on the version of Tcl/Tk
-# major, minor, type, type_name, patchlevel = TclTkLib.get_version
+# major, minor, type, patchlevel = TclTkLib.get_version
############################################
# Ttk (Tile) support
diff --git a/ext/tk/lib/tk/variable.rb b/ext/tk/lib/tk/variable.rb
index f738a96ee7..b73a4677da 100644
--- a/ext/tk/lib/tk/variable.rb
+++ b/ext/tk/lib/tk/variable.rb
@@ -26,7 +26,7 @@ class TkVariable
TkVar_ID_TBL.mutex.synchronize{ TkVar_ID_TBL.clear }
}
- major, minor, type, type_name, patchlevel = TclTkLib.get_version
+ major, minor, type, patchlevel = TclTkLib.get_version
USE_OLD_TRACE_OPTION_STYLE = (major < 8) || (major == 8 && minor < 4)
#TkCore::INTERP.add_tk_procs('rb_var', 'args',
diff --git a/ext/tk/sample/tkextlib/treectrl/demo.rb b/ext/tk/sample/tkextlib/treectrl/demo.rb
index eed95d0e1c..a1b4661197 100644
--- a/ext/tk/sample/tkextlib/treectrl/demo.rb
+++ b/ext/tk/sample/tkextlib/treectrl/demo.rb
@@ -156,8 +156,6 @@ class TkTreeCtrl_demo
@src_top = TkToplevel.new
f = TkFrame.new(@src_top, :borderwidth=>0)
case @thisPlatform
- when 'macintosh', 'macos'
- font = TkFont.new(['Geneva', 9])
when 'unix'
font = TkFont.new(['Courier', -12])
else
@@ -198,10 +196,6 @@ class TkTreeCtrl_demo
def tree_plus_scrollbars_in_a_frame(parent, h, v)
f = TkFrame.new(parent, :borderwidth=>1, :relief=>:sunken)
case @thisPlatform
- when 'macintosh'
- font = TkFont.new(['Geneva', 9])
- when 'macos'
- font = TkFont.new(['Lucida Grande', 11])
when 'unix'
font = TkFont.new(['Helvetica', -12])
else
@@ -244,7 +238,7 @@ class TkTreeCtrl_demo
Tk.root.title('Tk::TreeCtrl Demo')
case @thisPlatform
- when 'macintosh', 'macosx'
+ when 'macosx'
Tk.root.geometry('+40+40')
else
Tk.root.geometry('+0+30')
diff --git a/ext/tk/stubs.c b/ext/tk/stubs.c
index 4388fb294d..e7ef79dda8 100644
--- a/ext/tk/stubs.c
+++ b/ext/tk/stubs.c
@@ -11,25 +11,6 @@
/*------------------------------*/
-#ifdef __MACOS__
-# include <tkMac.h>
-# include <Quickdraw.h>
-
-static int call_macinit = 0;
-
-static void
-_macinit()
-{
- if (!call_macinit) {
- tcl_macQdPtr = &qd; /* setup QuickDraw globals */
- Tcl_MacSetEventProc(TkMacConvertEvent); /* setup event handler */
- call_macinit = 1;
- }
-}
-#endif
-
-/*------------------------------*/
-
static int nativethread_checked = 0;
static void
@@ -320,10 +301,6 @@ ruby_tk_stubs_init(tcl_ip)
if (!Tk_InitStubs(tcl_ip, (char *)"8.1", 0))
return FAIL_Tk_InitStubs;
-
-#ifdef __MACOS__
- _macinit();
-#endif
}
return TCLTK_STUBS_OK;
@@ -359,10 +336,6 @@ ruby_tk_stubs_safeinit(tcl_ip)
if (!Tk_InitStubs(tcl_ip, (char *)"8.1", 0))
return FAIL_Tk_InitStubs;
-
-#ifdef __MACOS__
- _macinit();
-#endif
}
return TCLTK_STUBS_OK;
@@ -517,9 +490,6 @@ ruby_tk_stubs_init(tcl_ip)
return FAIL_Tk_Init;
if (!call_tk_stubs_init) {
-#ifdef __MACOS__
- _macinit();
-#endif
call_tk_stubs_init = 1;
}
@@ -539,9 +509,6 @@ ruby_tk_stubs_safeinit(tcl_ip)
return FAIL_Tk_Init;
if (!call_tk_stubs_init) {
-#ifdef __MACOS__
- _macinit();
-#endif
call_tk_stubs_init = 1;
}
diff --git a/ext/tk/tcltklib.c b/ext/tk/tcltklib.c
index 1946272340..34b66f76e6 100644
--- a/ext/tk/tcltklib.c
+++ b/ext/tk/tcltklib.c
@@ -4,7 +4,7 @@
* Oct. 24, 1997 Y. Matsumoto
*/
-#define TCLTKLIB_RELEASE_DATE "2008-06-17"
+#define TCLTKLIB_RELEASE_DATE "2008-10-20"
#include "ruby.h"
@@ -44,9 +44,9 @@
#include "stubs.h"
#ifndef TCL_ALPHA_RELEASE
-#define TCL_ALPHA_RELEASE 0
-#define TCL_BETA_RELEASE 1
-#define TCL_FINAL_RELEASE 2
+#define TCL_ALPHA_RELEASE 0 /* "alpha" */
+#define TCL_BETA_RELEASE 1 /* "beta" */
+#define TCL_FINAL_RELEASE 2 /* "final" */
#endif
static VALUE rb_thread_critical; /* dummy */
@@ -55,8 +55,8 @@ int rb_thread_check_trap_pending();
static struct {
int major;
int minor;
+ int type; /* ALPHA==0, BETA==1, FINAL==2 */
int patchlevel;
- int type;
} tcltk_version = {0, 0, 0, 0};
static void
@@ -3089,9 +3089,6 @@ ip_ruby_cmd(clientData, interp, argc, argv)
/* get args */
args = rb_ary_new2(argc - 2);
-#ifdef HAVE_STRUCT_RARRAY_LEN
- RARRAY(args)->len = 0;
-#endif
for(i = 3; i < argc; i++) {
#if TCL_MAJOR_VERSION >= 8
str = Tcl_GetStringFromObj(argv[i], &len);
@@ -3099,14 +3096,14 @@ ip_ruby_cmd(clientData, interp, argc, argv)
#ifndef HAVE_STRUCT_RARRAY_LEN
rb_ary_push(args, rb_tainted_str_new(str, len));
#else
- RARRAY(args)->ptr[RARRAY(args)->len++] = rb_tainted_str_new(str, len);
+ RARRAY(args)->as.heap.ptr[RARRAY(args)->as.heap.len++] = rb_tainted_str_new(str, len);
#endif
#else /* TCL_MAJOR_VERSION < 8 */
DUMP2("arg:%s",argv[i]);
#ifndef HAVE_STRUCT_RARRAY_LEN
rb_ary_push(args, rb_tainted_str_new2(argv[i]));
#else
- RARRAY(args)->ptr[RARRAY(args)->len++] = rb_tainted_str_new2(argv[i]);
+ RARRAY(args)->as.heap.ptr[RARRAY(args)->as.heap.len++] = rb_tainted_str_new2(argv[i]);
#endif
#endif
}
@@ -8298,7 +8295,7 @@ ip_invoke_with_position(argc, argv, obj, position)
DUMP2("back from handler (current thread:%lx)", current);
/* get result & free allocated memory */
- ret = RARRAY(result)->ptr[0];
+ ret = RARRAY(result)->as.heap.ptr[0];
#if 0 /* use Tcl_EventuallyFree */
Tcl_EventuallyFree((ClientData)alloc_done, TCL_DYNAMIC); /* XXXXXXXX */
#else
@@ -9073,28 +9070,30 @@ static VALUE
lib_getversion(self)
VALUE self;
{
- volatile VALUE type_name;
+ set_tcltk_version();
+ return rb_ary_new3(4, INT2NUM(tcltk_version.major),
+ INT2NUM(tcltk_version.minor),
+ INT2NUM(tcltk_version.type),
+ INT2NUM(tcltk_version.patchlevel));
+}
+
+static VALUE
+lib_get_reltype_name(self)
+ VALUE self;
+{
set_tcltk_version();
switch(tcltk_version.type) {
case TCL_ALPHA_RELEASE:
- type_name = rb_str_new2("alpha");
- break;
+ return rb_str_new2("alpha");
case TCL_BETA_RELEASE:
- type_name = rb_str_new2("beta");
- break;
+ return rb_str_new2("beta");
case TCL_FINAL_RELEASE:
- type_name = rb_str_new2("final");
- break;
+ return rb_str_new2("final");
default:
- type_name = rb_str_new2("unknown");
+ rb_raise(rb_eRuntimeError, "tcltklib has invalid release type number");
}
-
- return rb_ary_new3(5, INT2NUM(tcltk_version.major),
- INT2NUM(tcltk_version.minor),
- INT2NUM(tcltk_version.type), type_name,
- INT2NUM(tcltk_version.patchlevel));
}
@@ -9297,14 +9296,22 @@ encoding_table_get_name_core(table, enc_arg, error_mode)
enc = rb_funcall(interp, ID_encoding_name, 0, 0);
}
}
- /* 2nd: encoding system of Tcl/Tk */
+ /* 2nd: Encoding.default_internal */
+ if (NIL_P(enc)) {
+ enc = rb_enc_default_internal();
+ }
+ /* 3rd: encoding system of Tcl/Tk */
if (NIL_P(enc)) {
enc = rb_str_new2(Tcl_GetEncodingName((Tcl_Encoding)NULL));
}
- /* 3rd: Encoding.default_external */
+ /* 4th: Encoding.default_external */
if (NIL_P(enc)) {
enc = rb_enc_default_external();
}
+ /* 5th: Encoding.locale_charmap */
+ if (NIL_P(enc)) {
+ enc = rb_locale_charmap(rb_cEncoding);
+ }
if (RTEST(rb_obj_is_kind_of(enc, cRubyEncoding))) {
/* Ruby's Encoding object */
@@ -9873,6 +9880,24 @@ Init_tcltklib()
/* --------------------------------------------------------------- */
+#ifdef __WIN32__
+#define TK_WINDOWING_SYSTEM "win32"
+#else
+#ifdef MAC_TCL
+#define TK_WINDOWING_SYSTEM "classic"
+#else
+#ifdef MAC_OSX_TK
+#define TK_WINDOWING_SYSTEM "aqua"
+#else
+#define TK_WINDOWING_SYSTEM "x11"
+#endif
+#endif
+#endif
+ rb_define_const(lib, "WINDOWING_SYSTEM",
+ rb_obj_freeze(rb_str_new2(TK_WINDOWING_SYSTEM)));
+
+ /* --------------------------------------------------------------- */
+
rb_define_const(ev_flag, "NONE", INT2FIX(0));
rb_define_const(ev_flag, "WINDOW", INT2FIX(TCL_WINDOW_EVENTS));
rb_define_const(ev_flag, "FILE", INT2FIX(TCL_FILE_EVENTS));
@@ -9902,6 +9927,8 @@ Init_tcltklib()
/* --------------------------------------------------------------- */
rb_define_module_function(lib, "get_version", lib_getversion, -1);
+ rb_define_module_function(lib, "get_release_type_name",
+ lib_get_reltype_name, -1);
rb_define_const(release_type, "ALPHA", INT2FIX(TCL_ALPHA_RELEASE));
rb_define_const(release_type, "BETA", INT2FIX(TCL_BETA_RELEASE));
diff --git a/ext/win32ole/extconf.rb b/ext/win32ole/extconf.rb
index d8534291e4..06a3f14c43 100644
--- a/ext/win32ole/extconf.rb
+++ b/ext/win32ole/extconf.rb
@@ -24,6 +24,9 @@ def create_win32ole_makefile
have_library("kernel32") and
have_library("advapi32") and
have_header("windows.h")
+ unless have_type("IMultiLanguage2", "mlang.h")
+ have_type("IMultiLanguage", "mlang.h")
+ end
create_makefile("win32ole")
create_docfile(SRCFILES)
else
diff --git a/ext/win32ole/win32ole.c b/ext/win32ole/win32ole.c
index 8b20e62b0c..da9421a421 100644
--- a/ext/win32ole/win32ole.c
+++ b/ext/win32ole/win32ole.c
@@ -23,6 +23,7 @@
#include <ocidl.h>
#include <olectl.h>
#include <ole2.h>
+#include <mlang.h>
#include <stdlib.h>
#include <math.h>
#ifdef HAVE_STDARG_PROTOTYPES
@@ -81,6 +82,15 @@
#define V_UINTREF(X) V_UNION(X, puintVal)
#endif
+/*
+ * unfortunately IID_IMultiLanguage2 is not included in any libXXX.a
+ * in Cygwin(mingw32).
+ */
+#if defined(__CYGWIN__) || defined(__MINGW32__)
+#undef IID_IMultiLanguage2
+const IID IID_IMultiLanguage2 = {0xDCCFC164, 0x2B38, 0x11d2, {0xB7, 0xEC, 0x00, 0xC0, 0x4F, 0x8F, 0x5D, 0x9A}};
+#endif
+
#define OLE_RELEASE(X) (X) ? ((X)->lpVtbl->Release(X)) : 0
#define OLE_ADDREF(X) (X) ? ((X)->lpVtbl->AddRef(X)) : 0
@@ -118,7 +128,7 @@
#define WC2VSTR(x) ole_wc2vstr((x), TRUE)
-#define WIN32OLE_VERSION "1.3.1"
+#define WIN32OLE_VERSION "1.3.9"
typedef HRESULT (STDAPICALLTYPE FNCOCREATEINSTANCEEX)
(REFCLSID, IUnknown*, DWORD, COSERVERINFO*, DWORD, MULTI_QI*);
@@ -208,6 +218,14 @@ static IMessageFilterVtbl message_filter;
static IMessageFilter imessage_filter = { &message_filter };
static IMessageFilter* previous_filter;
+#if defined(HAVE_TYPE_IMULTILANGUAGE2)
+static IMultiLanguage2 *pIMultiLanguage = NULL;
+#elif defined(HAVE_TYPE_IMULTILANGUAGE)
+static IMultiLanguage *pIMultiLanguage = NULL;
+#else
+static void *pIMultiLanguage = NULL; /* dummy */
+#endif
+
struct oledata {
IDispatch *pDispatch;
};
@@ -267,6 +285,7 @@ static double time_object2date(VALUE tmobj);
static VALUE date2time_str(double date);
static rb_encoding *ole_cp2encoding(UINT cp);
static UINT ole_encoding2cp(rb_encoding *enc);
+static void load_conv_function51932();
static UINT ole_init_cp();
static char *ole_wc2mb(LPWSTR pw);
static VALUE ole_hresult2msg(HRESULT hr);
@@ -956,16 +975,69 @@ static UINT ole_encoding2cp(rb_encoding *enc)
return CP_ACP;
}
+static void
+load_conv_function51932()
+{
+ HRESULT hr = E_NOINTERFACE;
+ void *p;
+ if (!pIMultiLanguage) {
+#if defined(HAVE_TYPE_IMULTILANGUAGE2)
+ hr = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IMultiLanguage2, &p);
+#elif defined(HAVE_TYPE_IMULTILANGUAGE)
+ hr = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IMultiLanguage, &p);
+#else
+ hr = E_NOINTERFACE;
+ p = NULL;
+#endif
+ if (FAILED(hr)) {
+ rb_raise(eWIN32OLERuntimeError, "fail to load convert function for CP51932");
+ }
+ pIMultiLanguage = p;
+ }
+}
+
+static void
+set_ole_codepage(UINT cp)
+{
+ if (code_page_installed(cp)) {
+ cWIN32OLE_cp = cp;
+ } else {
+ switch(cp) {
+ case CP_ACP:
+ case CP_OEMCP:
+ case CP_MACCP:
+ case CP_THREAD_ACP:
+ case CP_SYMBOL:
+ case CP_UTF7:
+ case CP_UTF8:
+ case 51932:
+ cWIN32OLE_cp = cp;
+ if (cp == 51932) {
+ load_conv_function51932();
+ }
+ break;
+ default:
+ rb_raise(eWIN32OLERuntimeError, "codepage should be WIN32OLE::CP_ACP, WIN32OLE::CP_OEMCP, WIN32OLE::CP_MACCP, WIN32OLE::CP_THREAD_ACP, WIN32OLE::CP_SYMBOL, WIN32OLE::CP_UTF7, WIN32OLE::CP_UTF8, or installed codepage.");
+ break;
+ }
+ }
+ cWIN32OLE_enc = ole_cp2encoding(cWIN32OLE_cp);
+}
+
+
static UINT
ole_init_cp()
{
UINT cp;
rb_encoding *encdef;
- encdef = rb_default_external_encoding();
- cp = ole_encoding2cp(encdef);
- if (code_page_installed(cp)) {
- cWIN32OLE_cp = cp;
+ encdef = rb_default_internal_encoding();
+ if (!encdef) {
+ encdef = rb_default_external_encoding();
}
+ cp = ole_encoding2cp(encdef);
+ set_ole_codepage(cp);
return cp;
}
@@ -1015,7 +1087,9 @@ ole_cp2encoding(UINT cp)
case CP_SYMBOL:
case CP_UTF7:
case CP_UTF8:
- // nothing ToDo
+ break;
+ case 51932:
+ load_conv_function51932();
break;
default:
rb_raise(eWIN32OLERuntimeError, "codepage should be WIN32OLE::CP_ACP, WIN32OLE::CP_OEMCP, WIN32OLE::CP_MACCP, WIN32OLE::CP_THREAD_ACP, WIN32OLE::CP_SYMBOL, WIN32OLE::CP_UTF7, WIN32OLE::CP_UTF8, or installed codepage.");
@@ -1033,8 +1107,26 @@ ole_cp2encoding(UINT cp)
static char *
ole_wc2mb(LPWSTR pw)
{
- int size;
LPSTR pm;
+ HRESULT hr;
+ int size = 0;
+ DWORD dw = 0;
+ if (cWIN32OLE_cp == 51932) {
+ load_conv_function51932();
+ hr = pIMultiLanguage->lpVtbl->ConvertStringFromUnicode(pIMultiLanguage,
+ &dw, cWIN32OLE_cp, pw, NULL, NULL, &size);
+ if (FAILED(hr)) {
+ ole_raise(hr, eWIN32OLERuntimeError, "fail to convert Unicode to CP%d", cWIN32OLE_cp);
+ }
+ pm = ALLOC_N(char, size + 1);
+ hr = pIMultiLanguage->lpVtbl->ConvertStringFromUnicode(pIMultiLanguage,
+ &dw, cWIN32OLE_cp, pw, NULL, pm, &size);
+ if (FAILED(hr)) {
+ ole_raise(hr, eWIN32OLERuntimeError, "fail to convert Unicode to CP%d", cWIN32OLE_cp);
+ }
+ pm[size] = '\0';
+ return pm;
+ }
size = WideCharToMultiByte(cWIN32OLE_cp, 0, pw, -1, NULL, 0, NULL, NULL);
if (size) {
pm = ALLOC_N(char, size + 1);
@@ -1227,15 +1319,20 @@ oleparam_free(struct oleparamdata *pole)
free(pole);
}
+
static LPWSTR
ole_vstr2wc(VALUE vstr)
{
rb_encoding *enc;
int cp;
- int size;
+ int size = 0;
LPWSTR pw;
+ int len = 0;
+ DWORD dw = 0;
+ HRESULT hr;
st_data_t data;
enc = rb_enc_get(vstr);
+
if (st_lookup(enc2cp_table, (st_data_t)enc, &data)) {
cp = data;
} else {
@@ -1247,23 +1344,62 @@ ole_vstr2wc(VALUE vstr)
cp == CP_THREAD_ACP ||
cp == CP_SYMBOL ||
cp == CP_UTF7 ||
- cp == CP_UTF8 ) {
+ cp == CP_UTF8 ||
+ cp == 51932) {
st_insert(enc2cp_table, (st_data_t)enc, (st_data_t)cp);
} else {
rb_raise(eWIN32OLERuntimeError, "not installed Windows codepage(%d) according to `%s'", cp, rb_enc_name(enc));
}
}
- size = MultiByteToWideChar(cp, 0, StringValuePtr(vstr), -1, NULL, 0);
- pw = SysAllocStringLen(NULL, size - 1);
- MultiByteToWideChar(cp, 0, StringValuePtr(vstr), -1, pw, size);
+ if (cp == 51932) {
+ load_conv_function51932();
+ len = RSTRING_LEN(vstr);
+ size = 0;
+ hr = pIMultiLanguage->lpVtbl->ConvertStringToUnicode(pIMultiLanguage,
+ &dw, cp, RSTRING_PTR(vstr), &len, NULL, &size);
+ if (FAILED(hr)) {
+ ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cp);
+ }
+ pw = SysAllocStringLen(NULL, size);
+ len = RSTRING_LEN(vstr);
+ hr = pIMultiLanguage->lpVtbl->ConvertStringToUnicode(pIMultiLanguage,
+ &dw, cp, RSTRING_PTR(vstr), &len, pw, &size);
+ if (FAILED(hr)) {
+ ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cp);
+ }
+ return pw;
+ }
+ size = MultiByteToWideChar(cp, 0, RSTRING_PTR(vstr), RSTRING_LEN(vstr), NULL, 0);
+ pw = SysAllocStringLen(NULL, size);
+ MultiByteToWideChar(cp, 0, RSTRING_PTR(vstr), RSTRING_LEN(vstr), pw, size);
return pw;
}
static LPWSTR
ole_mb2wc(char *pm, int len)
{
- int size;
+ int size = 0;
LPWSTR pw;
+ HRESULT hr;
+ DWORD dw = 0;
+ int n = len;
+
+ if (cWIN32OLE_cp == 51932) {
+ load_conv_function51932();
+ size = 0;
+ hr = pIMultiLanguage->lpVtbl->ConvertStringToUnicode(pIMultiLanguage,
+ &dw, cWIN32OLE_cp, pm, &n, NULL, &size);
+ if (FAILED(hr)) {
+ ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cWIN32OLE_cp);
+ }
+ pw = SysAllocStringLen(NULL, size);
+ hr = pIMultiLanguage->lpVtbl->ConvertStringToUnicode(pIMultiLanguage,
+ &dw, cWIN32OLE_cp, pm, &n, pw, &size);
+ if (FAILED(hr)) {
+ ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cWIN32OLE_cp);
+ }
+ return pw;
+ }
size = MultiByteToWideChar(cWIN32OLE_cp, 0, pm, len, NULL, 0);
pw = SysAllocStringLen(NULL, size - 1);
MultiByteToWideChar(cWIN32OLE_cp, 0, pm, len, pw, size);
@@ -2597,6 +2733,7 @@ fole_s_connect(int argc, VALUE *argv, VALUE self)
ole_initialize();
rb_scan_args(argc, argv, "1*", &svr_name, &others);
+ Check_SafeStr(svr_name);
if (rb_safe_level() > 0 && OBJ_TAINTED(svr_name)) {
rb_raise(rb_eSecurityError, "Insecure Object Connection - %s",
StringValuePtr(svr_name));
@@ -2908,34 +3045,20 @@ code_page_installed(UINT cp)
* call-seq:
* WIN32OLE.codepage = CP
*
- * Sets current codepage.
+ * Sets current codepage.
+ * The WIN32OLE.codepage is initialized according to
+ * Encoding.default_internal.
+ * If Encoding.default_internal is nil then WIN32OLE.codepage
+ * is initialized according to Encoding.default_external.
+ *
* WIN32OLE.codepage = WIN32OLE::CP_UTF8
- * WIN32OLE.codepage = 20932
+ * WIN32OLE.codepage = 65001
*/
static VALUE
fole_s_set_code_page(VALUE self, VALUE vcp)
{
UINT cp = FIX2INT(vcp);
-
- if (code_page_installed(cp)) {
- cWIN32OLE_cp = cp;
- } else {
- switch(cp) {
- case CP_ACP:
- case CP_OEMCP:
- case CP_MACCP:
- case CP_THREAD_ACP:
- case CP_SYMBOL:
- case CP_UTF7:
- case CP_UTF8:
- cWIN32OLE_cp = cp;
- break;
- default:
- rb_raise(eWIN32OLERuntimeError, "codepage should be WIN32OLE::CP_ACP, WIN32OLE::CP_OEMCP, WIN32OLE::CP_MACCP, WIN32OLE::CP_THREAD_ACP, WIN32OLE::CP_SYMBOL, WIN32OLE::CP_UTF7, WIN32OLE::CP_UTF8, or installed codepage.");
- break;
- }
- }
- cWIN32OLE_enc = ole_cp2encoding(cWIN32OLE_cp);
+ set_ole_codepage(cp);
/*
* Should this method return old codepage?
*/
@@ -3094,16 +3217,17 @@ fole_initialize(int argc, VALUE *argv, VALUE self)
OLECHAR *pBuf;
IDispatch *pDispatch;
void *p;
-
rb_secure(4);
rb_call_super(0, 0);
rb_scan_args(argc, argv, "11*", &svr_name, &host, &others);
+ Check_SafeStr(svr_name);
if (rb_safe_level() > 0 && OBJ_TAINTED(svr_name)) {
rb_raise(rb_eSecurityError, "Insecure Object Creation - %s",
StringValuePtr(svr_name));
}
if (!NIL_P(host)) {
+ Check_SafeStr(host);
if (rb_safe_level() > 0 && OBJ_TAINTED(host)) {
rb_raise(rb_eSecurityError, "Insecure Object Creation - %s",
StringValuePtr(svr_name));
@@ -7542,11 +7666,13 @@ static VALUE
rescue_callback(VALUE arg)
{
+ VALUE error;
VALUE e = rb_errinfo();
VALUE bt = rb_funcall(e, rb_intern("backtrace"), 0);
VALUE msg = rb_funcall(e, rb_intern("message"), 0);
bt = rb_ary_entry(bt, 0);
- fprintf(stdout, "%s: %s (%s)\n", StringValuePtr(bt), StringValuePtr(msg), rb_obj_classname(e));
+ error = rb_sprintf("%s: %s (%s)\n", StringValuePtr(bt), StringValuePtr(msg), rb_obj_classname(e));
+ rb_write_error(StringValuePtr(error));
rb_backtrace();
ruby_finalize();
exit(-1);
@@ -8001,7 +8127,11 @@ find_default_source(VALUE ole, IID *piid, ITypeInfo **ppTypeInfo)
static void
ole_event_free(struct oleeventdata *poleev)
{
- OLE_FREE(poleev->pConnectionPoint);
+ if (poleev->pConnectionPoint) {
+ poleev->pConnectionPoint->lpVtbl->Unadvise(poleev->pConnectionPoint, poleev->dwCookie);
+ OLE_RELEASE(poleev->pConnectionPoint);
+ poleev->pConnectionPoint = NULL;
+ }
free(poleev);
}
@@ -8114,6 +8244,7 @@ fev_initialize(int argc, VALUE *argv, VALUE self)
ev_advise(argc, argv, self);
evs_push(self);
rb_ivar_set(self, id_events, rb_ary_new());
+ fev_set_handler(self, Qnil);
return self;
}
@@ -8493,6 +8624,26 @@ folevariant_initialize(VALUE self, VALUE args)
}
VariantInit(&var);
val = rb_ary_entry(args, 0);
+
+ if(!rb_obj_is_kind_of(val, cWIN32OLE) &&
+ !rb_obj_is_kind_of(val, cWIN32OLE_VARIANT) &&
+ !rb_obj_is_kind_of(val, rb_cTime)) {
+ switch (TYPE(val)) {
+ case T_ARRAY:
+ case T_STRING:
+ case T_FIXNUM:
+ case T_BIGNUM:
+ case T_FLOAT:
+ case T_TRUE:
+ case T_FALSE:
+ case T_NIL:
+ break;
+ default:
+ rb_raise(rb_eTypeError, "can not convert WIN32OLE_VARIANT from type %s",
+ rb_obj_classname(val));
+ }
+ }
+
Data_Get_Struct(self, struct olevariantdata, pvar);
if (len == 1) {
ole_val2variant(val, &(pvar->var));
@@ -8797,7 +8948,7 @@ void
Init_win32ole()
{
ary_ole_event = rb_ary_new();
- rb_register_mark_object(ary_ole_event);
+ rb_gc_register_mark_object(ary_ole_event);
id_events = rb_intern("events");
com_vtbl.QueryInterface = QueryInterface;
@@ -8816,7 +8967,7 @@ Init_win32ole()
message_filter.MessagePending = mf_MessagePending;
com_hash = Data_Wrap_Struct(rb_cData, rb_mark_hash, st_free_table, st_init_numtable());
- rb_register_mark_object(com_hash);
+ rb_gc_register_mark_object(com_hash);
cWIN32OLE = rb_define_class("WIN32OLE", rb_cObject);
@@ -9030,5 +9181,4 @@ Init_win32ole()
init_enc2cp();
atexit((void (*)(void))free_enc2cp);
ole_init_cp();
- cWIN32OLE_enc = ole_cp2encoding(cWIN32OLE_cp);
}
diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c
index 9bb8f33344..30c3241674 100644
--- a/ext/zlib/zlib.c
+++ b/ext/zlib/zlib.c
@@ -9,6 +9,7 @@
#include <ruby.h>
#include <zlib.h>
#include <time.h>
+#include <ruby/encoding.h>
#define RUBY_ZLIB_VERSION "0.6.0"
@@ -31,165 +32,169 @@
/*--------- Prototypes --------*/
-static NORETURN(void raise_zlib_error _((int, const char*)));
-static VALUE rb_zlib_version _((VALUE));
-static VALUE do_checksum _((int, VALUE*, uLong (*) _((uLong, const Bytef*, uInt))));
-static VALUE rb_zlib_adler32 _((int, VALUE*, VALUE));
-static VALUE rb_zlib_crc32 _((int, VALUE*, VALUE));
-static VALUE rb_zlib_crc_table _((VALUE));
-static voidpf zlib_mem_alloc _((voidpf, uInt, uInt));
-static void zlib_mem_free _((voidpf, voidpf));
-static void finalizer_warn _((const char*));
+static NORETURN(void raise_zlib_error(int, const char*));
+static VALUE rb_zlib_version(VALUE);
+static VALUE do_checksum(int, VALUE*, uLong (*)(uLong, const Bytef*, uInt));
+static VALUE rb_zlib_adler32(int, VALUE*, VALUE);
+static VALUE rb_zlib_crc32(int, VALUE*, VALUE);
+static VALUE rb_zlib_crc_table(VALUE);
+static voidpf zlib_mem_alloc(voidpf, uInt, uInt);
+static void zlib_mem_free(voidpf, voidpf);
+static void finalizer_warn(const char*);
struct zstream;
struct zstream_funcs;
-static void zstream_init _((struct zstream*, const struct zstream_funcs*));
-static void zstream_expand_buffer _((struct zstream*));
-static void zstream_expand_buffer_into _((struct zstream*, int));
-static void zstream_append_buffer _((struct zstream*, const Bytef*, int));
-static VALUE zstream_detach_buffer _((struct zstream*));
-static VALUE zstream_shift_buffer _((struct zstream*, int));
-static void zstream_buffer_ungetc _((struct zstream*, int));
-static void zstream_append_input _((struct zstream*, const Bytef*, unsigned int));
-static void zstream_discard_input _((struct zstream*, unsigned int));
-static void zstream_reset_input _((struct zstream*));
-static void zstream_passthrough_input _((struct zstream*));
-static VALUE zstream_detach_input _((struct zstream*));
-static void zstream_reset _((struct zstream*));
-static VALUE zstream_end _((struct zstream*));
-static void zstream_run _((struct zstream*, Bytef*, uInt, int));
-static VALUE zstream_sync _((struct zstream*, Bytef*, uInt));
-static void zstream_mark _((struct zstream*));
-static void zstream_free _((struct zstream*));
-static VALUE zstream_new _((VALUE, const struct zstream_funcs*));
-static struct zstream *get_zstream _((VALUE));
-static void zstream_finalize _((struct zstream*));
-
-static VALUE rb_zstream_end _((VALUE));
-static VALUE rb_zstream_reset _((VALUE));
-static VALUE rb_zstream_finish _((VALUE));
-static VALUE rb_zstream_flush_next_in _((VALUE));
-static VALUE rb_zstream_flush_next_out _((VALUE));
-static VALUE rb_zstream_avail_out _((VALUE));
-static VALUE rb_zstream_set_avail_out _((VALUE, VALUE));
-static VALUE rb_zstream_avail_in _((VALUE));
-static VALUE rb_zstream_total_in _((VALUE));
-static VALUE rb_zstream_total_out _((VALUE));
-static VALUE rb_zstream_data_type _((VALUE));
-static VALUE rb_zstream_adler _((VALUE));
-static VALUE rb_zstream_finished_p _((VALUE));
-static VALUE rb_zstream_closed_p _((VALUE));
-
-static VALUE rb_deflate_s_allocate _((VALUE));
-static VALUE rb_deflate_initialize _((int, VALUE*, VALUE));
-static VALUE rb_deflate_init_copy _((VALUE, VALUE));
-static VALUE deflate_run _((VALUE));
-static VALUE rb_deflate_s_deflate _((int, VALUE*, VALUE));
-static void do_deflate _((struct zstream*, VALUE, int));
-static VALUE rb_deflate_deflate _((int, VALUE*, VALUE));
-static VALUE rb_deflate_addstr _((VALUE, VALUE));
-static VALUE rb_deflate_flush _((int, VALUE*, VALUE));
-static VALUE rb_deflate_params _((VALUE, VALUE, VALUE));
-static VALUE rb_deflate_set_dictionary _((VALUE, VALUE));
-
-static VALUE inflate_run _((VALUE));
-static VALUE rb_inflate_s_allocate _((VALUE));
-static VALUE rb_inflate_initialize _((int, VALUE*, VALUE));
-static VALUE rb_inflate_s_inflate _((VALUE, VALUE));
-static void do_inflate _((struct zstream*, VALUE));
-static VALUE rb_inflate_inflate _((VALUE, VALUE));
-static VALUE rb_inflate_addstr _((VALUE, VALUE));
-static VALUE rb_inflate_sync _((VALUE, VALUE));
-static VALUE rb_inflate_sync_point_p _((VALUE));
-static VALUE rb_inflate_set_dictionary _((VALUE, VALUE));
+static void zstream_init(struct zstream*, const struct zstream_funcs*);
+static void zstream_expand_buffer(struct zstream*);
+static void zstream_expand_buffer_into(struct zstream*, int);
+static void zstream_append_buffer(struct zstream*, const Bytef*, int);
+static VALUE zstream_detach_buffer(struct zstream*);
+static VALUE zstream_shift_buffer(struct zstream*, int);
+static void zstream_buffer_ungets(struct zstream*, const Bytef*, int);
+static void zstream_buffer_ungetbyte(struct zstream*, int);
+static void zstream_append_input(struct zstream*, const Bytef*, unsigned int);
+static void zstream_discard_input(struct zstream*, unsigned int);
+static void zstream_reset_input(struct zstream*);
+static void zstream_passthrough_input(struct zstream*);
+static VALUE zstream_detach_input(struct zstream*);
+static void zstream_reset(struct zstream*);
+static VALUE zstream_end(struct zstream*);
+static void zstream_run(struct zstream*, Bytef*, uInt, int);
+static VALUE zstream_sync(struct zstream*, Bytef*, uInt);
+static void zstream_mark(struct zstream*);
+static void zstream_free(struct zstream*);
+static VALUE zstream_new(VALUE, const struct zstream_funcs*);
+static struct zstream *get_zstream(VALUE);
+static void zstream_finalize(struct zstream*);
+
+static VALUE rb_zstream_end(VALUE);
+static VALUE rb_zstream_reset(VALUE);
+static VALUE rb_zstream_finish(VALUE);
+static VALUE rb_zstream_flush_next_in(VALUE);
+static VALUE rb_zstream_flush_next_out(VALUE);
+static VALUE rb_zstream_avail_out(VALUE);
+static VALUE rb_zstream_set_avail_out(VALUE, VALUE);
+static VALUE rb_zstream_avail_in(VALUE);
+static VALUE rb_zstream_total_in(VALUE);
+static VALUE rb_zstream_total_out(VALUE);
+static VALUE rb_zstream_data_type(VALUE);
+static VALUE rb_zstream_adler(VALUE);
+static VALUE rb_zstream_finished_p(VALUE);
+static VALUE rb_zstream_closed_p(VALUE);
+
+static VALUE rb_deflate_s_allocate(VALUE);
+static VALUE rb_deflate_initialize(int, VALUE*, VALUE);
+static VALUE rb_deflate_init_copy(VALUE, VALUE);
+static VALUE deflate_run(VALUE);
+static VALUE rb_deflate_s_deflate(int, VALUE*, VALUE);
+static void do_deflate(struct zstream*, VALUE, int);
+static VALUE rb_deflate_deflate(int, VALUE*, VALUE);
+static VALUE rb_deflate_addstr(VALUE, VALUE);
+static VALUE rb_deflate_flush(int, VALUE*, VALUE);
+static VALUE rb_deflate_params(VALUE, VALUE, VALUE);
+static VALUE rb_deflate_set_dictionary(VALUE, VALUE);
+
+static VALUE inflate_run(VALUE);
+static VALUE rb_inflate_s_allocate(VALUE);
+static VALUE rb_inflate_initialize(int, VALUE*, VALUE);
+static VALUE rb_inflate_s_inflate(VALUE, VALUE);
+static void do_inflate(struct zstream*, VALUE);
+static VALUE rb_inflate_inflate(VALUE, VALUE);
+static VALUE rb_inflate_addstr(VALUE, VALUE);
+static VALUE rb_inflate_sync(VALUE, VALUE);
+static VALUE rb_inflate_sync_point_p(VALUE);
+static VALUE rb_inflate_set_dictionary(VALUE, VALUE);
#if GZIP_SUPPORT
struct gzfile;
-static void gzfile_mark _((struct gzfile*));
-static void gzfile_free _((struct gzfile*));
-static VALUE gzfile_new _((VALUE, const struct zstream_funcs*, void (*) _((struct gzfile*))));
-static void gzfile_reset _((struct gzfile*));
-static void gzfile_close _((struct gzfile*, int));
-static void gzfile_write_raw _((struct gzfile*));
-static VALUE gzfile_read_raw_partial _((VALUE));
-static VALUE gzfile_read_raw_rescue _((VALUE));
-static VALUE gzfile_read_raw _((struct gzfile*));
-static int gzfile_read_raw_ensure _((struct gzfile*, int));
-static char *gzfile_read_raw_until_zero _((struct gzfile*, long));
-static unsigned int gzfile_get16 _((const unsigned char*));
-static unsigned long gzfile_get32 _((const unsigned char*));
-static void gzfile_set32 _((unsigned long n, unsigned char*));
-static void gzfile_make_header _((struct gzfile*));
-static void gzfile_make_footer _((struct gzfile*));
-static void gzfile_read_header _((struct gzfile*));
-static void gzfile_check_footer _((struct gzfile*));
-static void gzfile_write _((struct gzfile*, Bytef*, uInt));
-static long gzfile_read_more _((struct gzfile*));
-static void gzfile_calc_crc _((struct gzfile*, VALUE));
-static VALUE gzfile_read _((struct gzfile*, int));
-static VALUE gzfile_read_all _((struct gzfile*));
-static void gzfile_ungetc _((struct gzfile*, int));
-static VALUE gzfile_writer_end_run _((VALUE));
-static void gzfile_writer_end _((struct gzfile*));
-static VALUE gzfile_reader_end_run _((VALUE));
-static void gzfile_reader_end _((struct gzfile*));
-static void gzfile_reader_rewind _((struct gzfile*));
-static VALUE gzfile_reader_get_unused _((struct gzfile*));
-static struct gzfile *get_gzfile _((VALUE));
-static VALUE gzfile_ensure_close _((VALUE));
-static VALUE rb_gzfile_s_wrap _((int, VALUE*, VALUE));
-static VALUE gzfile_s_open _((int, VALUE*, VALUE, const char*));
-
-static VALUE rb_gzfile_to_io _((VALUE));
-static VALUE rb_gzfile_crc _((VALUE));
-static VALUE rb_gzfile_mtime _((VALUE));
-static VALUE rb_gzfile_level _((VALUE));
-static VALUE rb_gzfile_os_code _((VALUE));
-static VALUE rb_gzfile_orig_name _((VALUE));
-static VALUE rb_gzfile_comment _((VALUE));
-static VALUE rb_gzfile_lineno _((VALUE));
-static VALUE rb_gzfile_set_lineno _((VALUE, VALUE));
-static VALUE rb_gzfile_set_mtime _((VALUE, VALUE));
-static VALUE rb_gzfile_set_orig_name _((VALUE, VALUE));
-static VALUE rb_gzfile_set_comment _((VALUE, VALUE));
-static VALUE rb_gzfile_close _((VALUE));
-static VALUE rb_gzfile_finish _((VALUE));
-static VALUE rb_gzfile_closed_p _((VALUE));
-static VALUE rb_gzfile_eof_p _((VALUE));
-static VALUE rb_gzfile_sync _((VALUE));
-static VALUE rb_gzfile_set_sync _((VALUE, VALUE));
-static VALUE rb_gzfile_total_in _((VALUE));
-static VALUE rb_gzfile_total_out _((VALUE));
-
-static VALUE rb_gzwriter_s_allocate _((VALUE));
-static VALUE rb_gzwriter_s_open _((int, VALUE*, VALUE));
-static VALUE rb_gzwriter_initialize _((int, VALUE*, VALUE));
-static VALUE rb_gzwriter_flush _((int, VALUE*, VALUE));
-static VALUE rb_gzwriter_write _((VALUE, VALUE));
-static VALUE rb_gzwriter_putc _((VALUE, VALUE));
-
-static VALUE rb_gzreader_s_allocate _((VALUE));
-static VALUE rb_gzreader_s_open _((int, VALUE*, VALUE));
-static VALUE rb_gzreader_initialize _((VALUE, VALUE));
-static VALUE rb_gzreader_rewind _((VALUE));
-static VALUE rb_gzreader_unused _((VALUE));
-static VALUE rb_gzreader_read _((int, VALUE*, VALUE));
-static VALUE rb_gzreader_getc _((VALUE));
-static VALUE rb_gzreader_readchar _((VALUE));
-static VALUE rb_gzreader_each_byte _((VALUE));
-static VALUE rb_gzreader_ungetc _((VALUE, VALUE));
-static void gzreader_skip_linebreaks _((struct gzfile*));
-static VALUE gzreader_gets _((int, VALUE*, VALUE));
-static VALUE rb_gzreader_gets _((int, VALUE*, VALUE));
-static VALUE rb_gzreader_readline _((int, VALUE*, VALUE));
-static VALUE rb_gzreader_each _((int, VALUE*, VALUE));
-static VALUE rb_gzreader_readlines _((int, VALUE*, VALUE));
+static void gzfile_mark(struct gzfile*);
+static void gzfile_free(struct gzfile*);
+static VALUE gzfile_new(VALUE, const struct zstream_funcs*, void (*) _((struct gzfile*)));
+static void gzfile_reset(struct gzfile*);
+static void gzfile_close(struct gzfile*, int);
+static void gzfile_write_raw(struct gzfile*);
+static VALUE gzfile_read_raw_partial(VALUE);
+static VALUE gzfile_read_raw_rescue(VALUE);
+static VALUE gzfile_read_raw(struct gzfile*);
+static int gzfile_read_raw_ensure(struct gzfile*, int);
+static char *gzfile_read_raw_until_zero(struct gzfile*, long);
+static unsigned int gzfile_get16(const unsigned char*);
+static unsigned long gzfile_get32(const unsigned char*);
+static void gzfile_set32(unsigned long n, unsigned char*);
+static void gzfile_make_header(struct gzfile*);
+static void gzfile_make_footer(struct gzfile*);
+static void gzfile_read_header(struct gzfile*);
+static void gzfile_check_footer(struct gzfile*);
+static void gzfile_write(struct gzfile*, Bytef*, uInt);
+static long gzfile_read_more(struct gzfile*);
+static void gzfile_calc_crc(struct gzfile*, VALUE);
+static VALUE gzfile_read(struct gzfile*, int);
+static VALUE gzfile_read_all(struct gzfile*);
+static void gzfile_ungets(struct gzfile*, const Bytef*, int);
+static void gzfile_ungetbyte(struct gzfile*, int);
+static VALUE gzfile_writer_end_run(VALUE);
+static void gzfile_writer_end(struct gzfile*);
+static VALUE gzfile_reader_end_run(VALUE);
+static void gzfile_reader_end(struct gzfile*);
+static void gzfile_reader_rewind(struct gzfile*);
+static VALUE gzfile_reader_get_unused(struct gzfile*);
+static struct gzfile *get_gzfile(VALUE);
+static VALUE gzfile_ensure_close(VALUE);
+static VALUE rb_gzfile_s_wrap(int, VALUE*, VALUE);
+static VALUE gzfile_s_open(int, VALUE*, VALUE, const char*);
+
+static VALUE rb_gzfile_to_io(VALUE);
+static VALUE rb_gzfile_crc(VALUE);
+static VALUE rb_gzfile_mtime(VALUE);
+static VALUE rb_gzfile_level(VALUE);
+static VALUE rb_gzfile_os_code(VALUE);
+static VALUE rb_gzfile_orig_name(VALUE);
+static VALUE rb_gzfile_comment(VALUE);
+static VALUE rb_gzfile_lineno(VALUE);
+static VALUE rb_gzfile_set_lineno(VALUE, VALUE);
+static VALUE rb_gzfile_set_mtime(VALUE, VALUE);
+static VALUE rb_gzfile_set_orig_name(VALUE, VALUE);
+static VALUE rb_gzfile_set_comment(VALUE, VALUE);
+static VALUE rb_gzfile_close(VALUE);
+static VALUE rb_gzfile_finish(VALUE);
+static VALUE rb_gzfile_closed_p(VALUE);
+static VALUE rb_gzfile_eof_p(VALUE);
+static VALUE rb_gzfile_sync(VALUE);
+static VALUE rb_gzfile_set_sync(VALUE, VALUE);
+static VALUE rb_gzfile_total_in(VALUE);
+static VALUE rb_gzfile_total_out(VALUE);
+
+static VALUE rb_gzwriter_s_allocate(VALUE);
+static VALUE rb_gzwriter_s_open(int, VALUE*, VALUE);
+static VALUE rb_gzwriter_initialize(int, VALUE*, VALUE);
+static VALUE rb_gzwriter_flush(int, VALUE*, VALUE);
+static VALUE rb_gzwriter_write(VALUE, VALUE);
+static VALUE rb_gzwriter_putc(VALUE, VALUE);
+
+static VALUE rb_gzreader_s_allocate(VALUE);
+static VALUE rb_gzreader_s_open(int, VALUE*, VALUE);
+static VALUE rb_gzreader_initialize(int, VALUE*, VALUE);
+static VALUE rb_gzreader_rewind(VALUE);
+static VALUE rb_gzreader_unused(VALUE);
+static VALUE rb_gzreader_read(int, VALUE*, VALUE);
+static VALUE rb_gzreader_getc(VALUE);
+static VALUE rb_gzreader_readchar(VALUE);
+static VALUE rb_gzreader_each_byte(VALUE);
+static VALUE rb_gzreader_ungetc(VALUE, VALUE);
+static VALUE rb_gzreader_ungetbyte(VALUE, VALUE);
+static void gzreader_skip_linebreaks(struct gzfile*);
+static VALUE gzreader_gets(int, VALUE*, VALUE);
+static VALUE rb_gzreader_gets(int, VALUE*, VALUE);
+static VALUE rb_gzreader_readline(int, VALUE*, VALUE);
+static VALUE rb_gzreader_each(int, VALUE*, VALUE);
+static VALUE rb_gzreader_readlines(int, VALUE*, VALUE);
#endif /* GZIP_SUPPORT */
-void Init_zlib _((void));
-
+void Init_zlib(void);
+int rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p);
+VALUE rb_str_conv_enc_opts(VALUE, rb_encoding*, rb_encoding*, int, VALUE);
/*--------- Exceptions --------*/
@@ -270,7 +275,7 @@ static VALUE
do_checksum(argc, argv, func)
int argc;
VALUE *argv;
- uLong (*func) _((uLong, const Bytef*, uInt));
+ uLong (*func)(uLong, const Bytef*, uInt);
{
VALUE str, vsum;
unsigned long sum;
@@ -357,9 +362,9 @@ struct zstream {
VALUE input;
z_stream stream;
const struct zstream_funcs {
- int (*reset) _((z_streamp));
- int (*end) _((z_streamp));
- int (*run) _((z_streamp, int));
+ int (*reset)(z_streamp);
+ int (*end)(z_streamp);
+ int (*run)(z_streamp, int);
} *func;
};
@@ -536,7 +541,7 @@ zstream_shift_buffer(struct zstream *z, int len)
return zstream_detach_buffer(z);
}
- dst = rb_str_substr(z->buf, 0, len);
+ dst = rb_str_subseq(z->buf, 0, len);
RBASIC(dst)->klass = rb_cString;
z->buf_filled -= len;
memmove(RSTRING_PTR(z->buf), RSTRING_PTR(z->buf) + len,
@@ -551,7 +556,23 @@ zstream_shift_buffer(struct zstream *z, int len)
}
static void
-zstream_buffer_ungetc(struct zstream *z, int c)
+zstream_buffer_ungets(struct zstream *z, const Bytef *b, int len)
+{
+ if (NIL_P(z->buf) || RSTRING_LEN(z->buf) - z->buf_filled == 0) {
+ zstream_expand_buffer_into(z, len);
+ }
+
+ memmove(RSTRING_PTR(z->buf) + len, RSTRING_PTR(z->buf), z->buf_filled);
+ memmove(RSTRING_PTR(z->buf), b, len);
+ z->buf_filled+=len;
+ if (z->stream.avail_out > 0) {
+ z->stream.next_out+=len;
+ z->stream.avail_out-=len;
+ }
+}
+
+static void
+zstream_buffer_ungetbyte(struct zstream *z, int c)
{
if (NIL_P(z->buf) || RSTRING_LEN(z->buf) - z->buf_filled == 0) {
zstream_expand_buffer(z);
@@ -1648,7 +1669,14 @@ struct gzfile {
int lineno;
int ungetc;
void (*end)(struct gzfile *);
+ rb_encoding *enc;
+ rb_encoding *enc2;
+ rb_econv_t *ec;
+ int ecflags;
+ VALUE ecopts;
+ char *cbuf;
};
+#define GZFILE_CBUF_CAPA 10
#define GZFILE_FLAG_SYNC ZSTREAM_FLAG_UNUSED
#define GZFILE_FLAG_HEADER_FINISHED (ZSTREAM_FLAG_UNUSED << 1)
@@ -1667,6 +1695,7 @@ gzfile_mark(struct gzfile *gz)
rb_gc_mark(gz->orig_name);
rb_gc_mark(gz->comment);
zstream_mark(&gz->z);
+ rb_gc_mark(gz->ecopts);
}
static void
@@ -1680,6 +1709,9 @@ gzfile_free(struct gzfile *gz)
}
zstream_finalize(z);
}
+ if (gz->cbuf) {
+ xfree(gz->cbuf);
+ }
xfree(gz);
}
@@ -1687,7 +1719,7 @@ static VALUE
gzfile_new(klass, funcs, endfunc)
VALUE klass;
const struct zstream_funcs *funcs;
- void (*endfunc) _((struct gzfile *));
+ void (*endfunc)(struct gzfile *);
{
VALUE obj;
struct gzfile *gz;
@@ -1704,6 +1736,12 @@ gzfile_new(klass, funcs, endfunc)
gz->lineno = 0;
gz->ungetc = 0;
gz->end = endfunc;
+ gz->enc = rb_default_external_encoding();
+ gz->enc2 = 0;
+ gz->ec = NULL;
+ gz->ecflags = 0;
+ gz->ecopts = Qnil;
+ gz->cbuf = 0;
return obj;
}
@@ -1718,6 +1756,11 @@ gzfile_reset(struct gzfile *gz)
gz->crc = crc32(0, Z_NULL, 0);
gz->lineno = 0;
gz->ungetc = 0;
+ if (gz->ec) {
+ rb_econv_close(gz->ec);
+ gz->ec = rb_econv_open_opts(gz->enc2->name, gz->enc->name,
+ gz->ecflags, gz->ecopts);
+ }
}
static void
@@ -2050,6 +2093,24 @@ gzfile_calc_crc(struct gzfile *gz, VALUE str)
}
static VALUE
+gzfile_newstr(struct gzfile *gz, VALUE str)
+{
+ if (!gz->enc2) {
+ rb_enc_associate(str, gz->enc);
+ OBJ_TAINT(str); /* for safe */
+ return str;
+ }
+ if (gz->ec && rb_enc_dummy_p(gz->enc2)) {
+ str = rb_econv_str_convert(gz->ec, str, ECONV_PARTIAL_INPUT);
+ rb_enc_associate(str, gz->enc);
+ OBJ_TAINT(str);
+ return str;
+ }
+ return rb_str_conv_enc_opts(str, gz->enc2, gz->enc,
+ gz->ecflags, gz->ecopts);
+}
+
+static VALUE
gzfile_read(struct gzfile *gz, int len)
{
VALUE dst;
@@ -2070,8 +2131,6 @@ gzfile_read(struct gzfile *gz, int len)
dst = zstream_shift_buffer(&gz->z, len);
gzfile_calc_crc(gz, dst);
-
- OBJ_TAINT(dst); /* for safe */
return dst;
}
@@ -2109,15 +2168,13 @@ gzfile_readpartial(struct gzfile *gz, int len, VALUE outbuf)
dst = zstream_shift_buffer(&gz->z, len);
gzfile_calc_crc(gz, dst);
- if (NIL_P(outbuf)) {
- OBJ_TAINT(dst); /* for safe */
- return dst;
- }
- else {
+ if (!NIL_P(outbuf)) {
rb_str_resize(outbuf, RSTRING_LEN(dst));
memcpy(RSTRING_PTR(outbuf), RSTRING_PTR(dst), RSTRING_LEN(dst));
- return outbuf;
+ dst = outbuf;
}
+ OBJ_TAINT(dst); /* for safe */
+ return dst;
}
static VALUE
@@ -2137,15 +2194,67 @@ gzfile_read_all(struct gzfile *gz)
dst = zstream_detach_buffer(&gz->z);
gzfile_calc_crc(gz, dst);
-
- OBJ_TAINT(dst); /* for safe */
+ OBJ_TAINT(dst);
return dst;
}
+static VALUE
+gzfile_getc(struct gzfile *gz)
+{
+ VALUE buf, dst = 0;
+ int len;
+
+ len = rb_enc_mbmaxlen(gz->enc);
+ while (!ZSTREAM_IS_FINISHED(&gz->z) && gz->z.buf_filled < len) {
+ gzfile_read_more(gz);
+ }
+ if (GZFILE_IS_FINISHED(gz)) {
+ if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) {
+ gzfile_check_footer(gz);
+ }
+ return Qnil;
+ }
+
+ if (gz->ec && rb_enc_dummy_p(gz->enc2)) {
+ const unsigned char *ss, *sp, *se;
+ unsigned char *ds, *dp, *de;
+ rb_econv_result_t res;
+
+ if (!gz->cbuf) {
+ gz->cbuf = ALLOC_N(char, GZFILE_CBUF_CAPA);
+ }
+ ss = sp = (const unsigned char*)RSTRING_PTR(gz->z.buf);
+ se = sp + gz->z.buf_filled;
+ ds = dp = (unsigned char *)gz->cbuf;
+ de = (unsigned char *)ds + GZFILE_CBUF_CAPA;
+ res = rb_econv_convert(gz->ec, &sp, se, &dp, de, ECONV_PARTIAL_INPUT|ECONV_AFTER_OUTPUT);
+ rb_econv_check_error(gz->ec);
+ dst = zstream_shift_buffer(&gz->z, sp - ss);
+ gzfile_calc_crc(gz, dst);
+ dst = rb_str_new(gz->cbuf, dp - ds);
+ rb_enc_associate(dst, gz->enc);
+ OBJ_TAINT(dst);
+ return dst;
+ }
+ else {
+ buf = gz->z.buf;
+ len = rb_enc_mbclen(RSTRING_PTR(buf), RSTRING_END(buf), gz->enc);
+ dst = gzfile_read(gz, len);
+ return gzfile_newstr(gz, dst);
+ }
+}
+
+static void
+gzfile_ungets(struct gzfile *gz, const Bytef *b, int len)
+{
+ zstream_buffer_ungets(&gz->z, b, len);
+ gz->ungetc+=len;
+}
+
static void
-gzfile_ungetc(struct gzfile *gz, int c)
+gzfile_ungetbyte(struct gzfile *gz, int c)
{
- zstream_buffer_ungetc(&gz->z, c);
+ zstream_buffer_ungetbyte(&gz->z, c);
gz->ungetc++;
}
@@ -2293,9 +2402,7 @@ gzfile_s_open(int argc, VALUE *argv, VALUE klass, const char *mode)
rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)");
}
filename = argv[0];
- FilePathValue(filename);
io = rb_file_open_str(filename, mode);
-
argv[0] = io;
return rb_gzfile_s_wrap(argc, argv, klass);
}
@@ -2564,6 +2671,20 @@ rb_gzfile_total_out(VALUE obj)
}
+static void
+rb_gzfile_ecopts(struct gzfile *gz, VALUE opts)
+{
+ if (!NIL_P(opts)) {
+ rb_io_extract_encoding_option(opts, &gz->enc, &gz->enc2);
+ }
+ if (gz->enc2) {
+ gz->ecflags = rb_econv_prepare_opts(opts, &opts);
+ gz->ec = rb_econv_open_opts(gz->enc2->name, gz->enc->name,
+ gz->ecflags, opts);
+ gz->ecopts = opts;
+ }
+}
+
/* ------------------------------------------------------------------------- */
/*
@@ -2624,9 +2745,14 @@ static VALUE
rb_gzwriter_initialize(int argc, VALUE *argv, VALUE obj)
{
struct gzfile *gz;
- VALUE io, level, strategy;
+ VALUE io, level, strategy, opt = Qnil;
int err;
+ if (argc > 1) {
+ opt = rb_check_convert_type(argv[argc-1], T_HASH, "Hash", "to_hash");
+ if (!NIL_P(opt)) argc--;
+ }
+
rb_scan_args(argc, argv, "12", &io, &level, &strategy);
Data_Get_Struct(obj, struct gzfile, gz);
@@ -2639,6 +2765,7 @@ rb_gzwriter_initialize(int argc, VALUE *argv, VALUE obj)
}
gz->io = io;
ZSTREAM_READY(&gz->z);
+ rb_gzfile_ecopts(gz, opt);
return obj;
}
@@ -2679,8 +2806,10 @@ rb_gzwriter_write(VALUE obj, VALUE str)
{
struct gzfile *gz = get_gzfile(obj);
- if (TYPE(str) != T_STRING) {
+ if (TYPE(str) != T_STRING)
str = rb_obj_as_string(str);
+ if (gz->enc2 && gz->enc2 != rb_ascii8bit_encoding()) {
+ str = rb_str_conv_enc(str, rb_enc_get(str), gz->enc2);
}
gzfile_write(gz, (Bytef*)RSTRING_PTR(str), RSTRING_LEN(str));
return INT2FIX(RSTRING_LEN(str));
@@ -2810,12 +2939,18 @@ rb_gzreader_s_open(int argc, VALUE *argv, VALUE klass)
* exception.
*/
static VALUE
-rb_gzreader_initialize(VALUE obj, VALUE io)
+rb_gzreader_initialize(int argc, VALUE *argv, VALUE obj)
{
+ VALUE io, opt = Qnil;
struct gzfile *gz;
int err;
Data_Get_Struct(obj, struct gzfile, gz);
+ if (argc > 1) {
+ opt = rb_check_convert_type(argv[argc-1], T_HASH, "Hash", "to_hash");
+ if (!NIL_P(opt)) argc--;
+ }
+ rb_scan_args(argc, argv, "1", &io);
/* this is undocumented feature of zlib */
err = inflateInit2(&gz->z.stream, -MAX_WBITS);
@@ -2825,6 +2960,7 @@ rb_gzreader_initialize(VALUE obj, VALUE io)
gz->io = io;
ZSTREAM_READY(&gz->z);
gzfile_read_header(gz);
+ rb_gzfile_ecopts(gz, opt);
return obj;
}
@@ -2910,6 +3046,31 @@ static VALUE
rb_gzreader_getc(VALUE obj)
{
struct gzfile *gz = get_gzfile(obj);
+
+ return gzfile_getc(gz);
+}
+
+/*
+ * See Zlib::GzipReader documentation for a description.
+ */
+static VALUE
+rb_gzreader_readchar(VALUE obj)
+{
+ VALUE dst;
+ dst = rb_gzreader_getc(obj);
+ if (NIL_P(dst)) {
+ rb_raise(rb_eEOFError, "end of file reached");
+ }
+ return dst;
+}
+
+/*
+ * See Zlib::GzipReader documentation for a description.
+ */
+static VALUE
+rb_gzreader_getbyte(VALUE obj)
+{
+ struct gzfile *gz = get_gzfile(obj);
VALUE dst;
dst = gzfile_read(gz, 1);
@@ -2923,10 +3084,10 @@ rb_gzreader_getc(VALUE obj)
* See Zlib::GzipReader documentation for a description.
*/
static VALUE
-rb_gzreader_readchar(VALUE obj)
+rb_gzreader_readbyte(VALUE obj)
{
VALUE dst;
- dst = rb_gzreader_getc(obj);
+ dst = rb_gzreader_getbyte(obj);
if (NIL_P(dst)) {
rb_raise(rb_eEOFError, "end of file reached");
}
@@ -2937,7 +3098,7 @@ rb_gzreader_readchar(VALUE obj)
* See Zlib::GzipReader documentation for a description.
*/
static VALUE
-rb_gzreader_each_byte(VALUE obj)
+rb_gzreader_each_char(VALUE obj)
{
VALUE c;
@@ -2953,10 +3114,45 @@ rb_gzreader_each_byte(VALUE obj)
* See Zlib::GzipReader documentation for a description.
*/
static VALUE
-rb_gzreader_ungetc(VALUE obj, VALUE ch)
+rb_gzreader_each_byte(VALUE obj)
+{
+ VALUE c;
+
+ RETURN_ENUMERATOR(obj, 0, 0);
+
+ while (!NIL_P(c = rb_gzreader_getbyte(obj))) {
+ rb_yield(c);
+ }
+ return Qnil;
+}
+
+/*
+ * See Zlib::GzipReader documentation for a description.
+ */
+static VALUE
+rb_gzreader_ungetc(VALUE obj, VALUE s)
+{
+ struct gzfile *gz;
+
+ if (FIXNUM_P(s))
+ return rb_gzreader_ungetbyte(obj, s);
+ gz = get_gzfile(obj);
+ StringValue(s);
+ if (gz->enc2 && gz->enc2 != rb_ascii8bit_encoding()) {
+ s = rb_str_conv_enc(s, rb_enc_get(s), gz->enc2);
+ }
+ gzfile_ungets(gz, (const Bytef*)RSTRING_PTR(s), RSTRING_LEN(s));
+ return Qnil;
+}
+
+/*
+ * See Zlib::GzipReader documentation for a description.
+ */
+static VALUE
+rb_gzreader_ungetbyte(VALUE obj, VALUE ch)
{
struct gzfile *gz = get_gzfile(obj);
- gzfile_ungetc(gz, NUM2CHR(ch));
+ gzfile_ungetbyte(gz, NUM2CHR(ch));
return Qnil;
}
@@ -3075,7 +3271,7 @@ gzreader_gets(int argc, VALUE *argv, VALUE obj)
gzreader_skip_linebreaks(gz);
}
- return dst;
+ return gzfile_newstr(gz, dst);
}
/*
@@ -3219,7 +3415,8 @@ rb_gzreader_readlines(int argc, VALUE *argv, VALUE obj)
* Zlib::OS_UNKNOWN
* The return values of Zlib::GzipFile#os_code method.
*/
-void Init_zlib()
+void
+Init_zlib()
{
VALUE mZlib, cZStream, cDeflate, cInflate;
#if GZIP_SUPPORT
@@ -3367,16 +3564,20 @@ void Init_zlib()
rb_define_singleton_method(cGzipReader, "open", rb_gzreader_s_open,-1);
rb_define_alloc_func(cGzipReader, rb_gzreader_s_allocate);
- rb_define_method(cGzipReader, "initialize", rb_gzreader_initialize, 1);
+ rb_define_method(cGzipReader, "initialize", rb_gzreader_initialize, -1);
rb_define_method(cGzipReader, "rewind", rb_gzreader_rewind, 0);
rb_define_method(cGzipReader, "unused", rb_gzreader_unused, 0);
rb_define_method(cGzipReader, "read", rb_gzreader_read, -1);
rb_define_method(cGzipReader, "readpartial", rb_gzreader_readpartial, -1);
rb_define_method(cGzipReader, "getc", rb_gzreader_getc, 0);
+ rb_define_method(cGzipReader, "getbyte", rb_gzreader_getbyte, 0);
rb_define_method(cGzipReader, "readchar", rb_gzreader_readchar, 0);
+ rb_define_method(cGzipReader, "readbyte", rb_gzreader_readbyte, 0);
rb_define_method(cGzipReader, "each_byte", rb_gzreader_each_byte, 0);
+ rb_define_method(cGzipReader, "each_char", rb_gzreader_each_char, 0);
rb_define_method(cGzipReader, "bytes", rb_gzreader_each_byte, 0);
rb_define_method(cGzipReader, "ungetc", rb_gzreader_ungetc, 1);
+ rb_define_method(cGzipReader, "ungetbyte", rb_gzreader_ungetbyte, 1);
rb_define_method(cGzipReader, "gets", rb_gzreader_gets, -1);
rb_define_method(cGzipReader, "readline", rb_gzreader_readline, -1);
rb_define_method(cGzipReader, "each", rb_gzreader_each, -1);
diff --git a/file.c b/file.c
index 564930dbb4..48808fd709 100644
--- a/file.c
+++ b/file.c
@@ -1988,7 +1988,7 @@ rb_file_chown(VALUE obj, VALUE owner, VALUE group)
o = NIL_P(owner) ? -1 : NUM2INT(owner);
g = NIL_P(group) ? -1 : NUM2INT(group);
GetOpenFile(obj, fptr);
-#if defined(DJGPP) || defined(__CYGWIN32__) || defined(_WIN32) || defined(__EMX__)
+#if defined(__CYGWIN32__) || defined(_WIN32) || defined(__EMX__)
if (NIL_P(fptr->pathv)) return Qnil;
if (chown(RSTRING_PTR(fptr->pathv), o, g) == -1)
rb_sys_fail_path(fptr->pathv);
@@ -2460,11 +2460,7 @@ rb_file_s_umask(int argc, VALUE *argv)
#endif
#ifndef CharNext /* defined as CharNext[AW] on Windows. */
-# if defined(DJGPP)
-# define CharNext(p) ((p) + mblen(p, RUBY_MBCHAR_MAXSIZE))
-# else
-# define CharNext(p) ((p) + 1)
-# endif
+# define CharNext(p) ((p) + 1)
#endif
#ifdef DOSISH_DRIVE_LETTER
@@ -3002,16 +2998,19 @@ rb_file_s_absolute_path(int argc, VALUE *argv)
static int
rmext(const char *p, int l1, const char *e)
{
- int l2;
+ int l0, l2;
if (!e) return 0;
+ for (l0 = 0; l0 < l1; ++l0) {
+ if (p[l0] != '.') break;
+ }
l2 = strlen(e);
if (l2 == 2 && e[1] == '*') {
unsigned char c = *e;
e = p + l1;
do {
- if (e <= p) return 0;
+ if (e <= p + l0) return 0;
} while (*--e != c);
return e - p;
}
@@ -3188,6 +3187,7 @@ rb_file_s_extname(VALUE klass, VALUE fname)
name = ++p;
e = 0;
+ while (*p && *p == '.') p++;
while (*p) {
if (*p == '.' || istrailinggabage(*p)) {
#if USE_NTFS
@@ -4513,15 +4513,6 @@ rb_path_check(const char *path)
return 1;
}
-#if defined(__MACOS__) || defined(riscos)
-static int
-is_macos_native_path(const char *path)
-{
- if (strchr(path, ':')) return 1;
- return 0;
-}
-#endif
-
static int
file_load_ok(const char *path)
{
@@ -4616,16 +4607,6 @@ rb_find_file(VALUE path)
f = StringValueCStr(path);
}
-#if defined(__MACOS__) || defined(riscos)
- if (is_macos_native_path(f)) {
- if (rb_safe_level() >= 1 && !fpath_check(f)) {
- rb_raise(rb_eSecurityError, "loading from unsafe file %s", f);
- }
- if (file_load_ok(f)) return path;
- return 0;
- }
-#endif
-
if (is_absolute_path(f) || is_explicit_relative(f)) {
if (rb_safe_level() >= 1 && !fpath_check(f)) {
rb_raise(rb_eSecurityError, "loading from unsafe file %s", f);
diff --git a/gc.c b/gc.c
index 9bce11d052..c69cc35334 100644
--- a/gc.c
+++ b/gc.c
@@ -13,7 +13,6 @@
#include "ruby/ruby.h"
#include "ruby/st.h"
-#include "ruby/node.h"
#include "ruby/re.h"
#include "ruby/io.h"
#include "ruby/util.h"
@@ -76,12 +75,8 @@ void *alloca ();
#endif /* __GNUC__ */
#ifndef GC_MALLOC_LIMIT
-#if defined(MSDOS) || defined(__human68k__)
-#define GC_MALLOC_LIMIT 200000
-#else
#define GC_MALLOC_LIMIT 8000000
#endif
-#endif
#define nomem_error rb_errNoMemError
@@ -729,7 +724,7 @@ rb_objspace_gc_disable(rb_objspace_t *objspace)
}
void
-rb_register_mark_object(VALUE obj)
+rb_gc_register_mark_object(VALUE obj)
{
VALUE ary = GET_THREAD()->vm->mark_object_ary;
rb_ary_push(ary, obj);
@@ -1475,7 +1470,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev)
case T_ARRAY:
if (FL_TEST(obj, ELTS_SHARED)) {
- ptr = obj->as.array.aux.shared;
+ ptr = obj->as.array.as.heap.aux.shared;
goto again;
}
else {
@@ -1518,9 +1513,10 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev)
if (obj->as.file.fptr) {
gc_mark(objspace, obj->as.file.fptr->pathv, lev);
gc_mark(objspace, obj->as.file.fptr->tied_io_for_writing, lev);
- gc_mark(objspace, obj->as.file.fptr->writeconv_stateless, lev);
+ gc_mark(objspace, obj->as.file.fptr->writeconv_asciicompat, lev);
gc_mark(objspace, obj->as.file.fptr->writeconv_pre_ecopts, lev);
gc_mark(objspace, obj->as.file.fptr->encs.ecopts, lev);
+ gc_mark(objspace, obj->as.file.fptr->write_lock, lev);
}
break;
@@ -1530,6 +1526,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev)
case T_FLOAT:
case T_BIGNUM:
+ case T_ZOMBIE:
break;
case T_MATCH:
@@ -1547,7 +1544,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev)
case T_COMPLEX:
gc_mark(objspace, obj->as.complex.real, lev);
- gc_mark(objspace, obj->as.complex.image, lev);
+ gc_mark(objspace, obj->as.complex.imag, lev);
break;
case T_STRUCT:
@@ -1737,6 +1734,15 @@ make_deferred(RVALUE *p)
p->as.basic.flags = (p->as.basic.flags & ~T_MASK) | T_ZOMBIE;
}
+static inline void
+make_io_deferred(RVALUE *p)
+{
+ rb_io_t *fptr = p->as.file.fptr;
+ make_deferred(p);
+ p->as.data.dfree = (void (*)(void*))rb_io_fptr_finalize;
+ p->as.data.data = fptr;
+}
+
static int
obj_free(rb_objspace_t *objspace, VALUE obj)
{
@@ -1811,10 +1817,7 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
break;
case T_FILE:
if (RANY(obj)->as.file.fptr) {
- rb_io_t *fptr = RANY(obj)->as.file.fptr;
- make_deferred(RANY(obj));
- RDATA(obj)->dfree = (void (*)(void*))rb_io_fptr_finalize;
- RDATA(obj)->data = fptr;
+ make_io_deferred(RANY(obj));
return 1;
}
break;
@@ -1861,41 +1864,6 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
return 0;
}
-#ifdef __GNUC__
-#if defined(__human68k__) || defined(DJGPP)
-#undef rb_setjmp
-#undef rb_jmp_buf
-#if defined(__human68k__)
-typedef unsigned long rb_jmp_buf[8];
-__asm__ (".even\n\
-_rb_setjmp:\n\
- move.l 4(sp),a0\n\
- movem.l d3-d7/a3-a5,(a0)\n\
- moveq.l #0,d0\n\
- rts");
-#else
-#if defined(DJGPP)
-typedef unsigned long rb_jmp_buf[6];
-__asm__ (".align 4\n\
-_rb_setjmp:\n\
- pushl %ebp\n\
- movl %esp,%ebp\n\
- movl 8(%ebp),%ebp\n\
- movl %eax,(%ebp)\n\
- movl %ebx,4(%ebp)\n\
- movl %ecx,8(%ebp)\n\
- movl %edx,12(%ebp)\n\
- movl %esi,16(%ebp)\n\
- movl %edi,20(%ebp)\n\
- popl %ebp\n\
- xorl %eax,%eax\n\
- ret");
-#endif
-#endif
-int rb_setjmp (rb_jmp_buf);
-#endif /* __human68k__ or DJGPP */
-#endif /* __GNUC__ */
-
#define GC_NOTIFY 0
void rb_vm_mark(void *ptr);
@@ -1935,7 +1903,7 @@ mark_current_machine_context(rb_objspace_t *objspace, rb_thread_t *th)
#ifdef __ia64
rb_gc_mark_locations(th->machine_register_stack_start, th->machine_register_stack_end);
#endif
-#if defined(__human68k__) || defined(__mc68000__)
+#if defined(__mc68000__)
mark_locations_array((VALUE*)((char*)STACK_END + 2),
(STACK_START - STACK_END));
#endif
@@ -2317,7 +2285,7 @@ run_final(rb_objspace_t *objspace, VALUE obj)
}
static void
-gc_finalize_deferred(rb_objspace_t *objspace)
+finalize_deferred(rb_objspace_t *objspace)
{
RVALUE *p = deferred_final_list;
deferred_final_list = 0;
@@ -2325,6 +2293,12 @@ gc_finalize_deferred(rb_objspace_t *objspace)
if (p) {
finalize_list(objspace, p);
}
+}
+
+static void
+gc_finalize_deferred(rb_objspace_t *objspace)
+{
+ finalize_deferred(objspace);
free_unused_heaps(objspace);
}
@@ -2357,15 +2331,13 @@ rb_gc_call_finalizer_at_exit(void)
{
rb_objspace_t *objspace = &rb_objspace;
RVALUE *p, *pend;
+ RVALUE *final_list = 0;
size_t i;
/* run finalizers */
if (finalizer_table) {
- p = deferred_final_list;
- deferred_final_list = 0;
- finalize_list(objspace, p);
+ finalize_deferred(objspace);
while (finalizer_table->num_entries > 0) {
- RVALUE *final_list = 0;
st_foreach(finalizer_table, chain_finalized_object,
(st_data_t)&final_list);
if (!(p = final_list)) break;
@@ -2385,26 +2357,31 @@ rb_gc_call_finalizer_at_exit(void)
while (p < pend) {
if (BUILTIN_TYPE(p) == T_DATA &&
DATA_PTR(p) && RANY(p)->as.data.dfree &&
- RANY(p)->as.basic.klass != rb_cThread) {
+ RANY(p)->as.basic.klass != rb_cThread && RANY(p)->as.basic.klass != rb_cMutex) {
p->as.free.flags = 0;
if ((long)RANY(p)->as.data.dfree == -1) {
xfree(DATA_PTR(p));
}
else if (RANY(p)->as.data.dfree) {
- (*RANY(p)->as.data.dfree)(DATA_PTR(p));
+ make_deferred(RANY(p));
+ RANY(p)->as.free.next = final_list;
+ final_list = p;
}
- VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
}
else if (BUILTIN_TYPE(p) == T_FILE) {
- if (rb_io_fptr_finalize(RANY(p)->as.file.fptr)) {
- p->as.free.flags = 0;
- VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
+ if (RANY(p)->as.file.fptr) {
+ make_io_deferred(RANY(p));
+ RANY(p)->as.free.next = final_list;
+ final_list = p;
}
}
p++;
}
}
during_gc = 0;
+ if (final_list) {
+ finalize_list(objspace, final_list);
+ }
}
void
@@ -2759,7 +2736,7 @@ gc_profile_result(void)
NUM2INT(rb_hash_aref(r, ID2SYM(rb_intern("HEAP_USE_SIZE")))),
NUM2INT(rb_hash_aref(r, ID2SYM(rb_intern("HEAP_TOTAL_SIZE")))),
NUM2INT(rb_hash_aref(r, ID2SYM(rb_intern("HEAP_TOTAL_OBJECTS")))),
- NUM2DBL(rb_hash_aref(r, ID2SYM(rb_intern("GC_TIME"))))*100);
+ NUM2DBL(rb_hash_aref(r, ID2SYM(rb_intern("GC_TIME"))))*1000);
}
#if GC_PROFILE_MORE_DETAIL
rb_str_cat2(result, "\n\n");
@@ -2772,8 +2749,8 @@ gc_profile_result(void)
NUM2INT(rb_hash_aref(r, ID2SYM(rb_intern("ALLOCATE_LIMIT")))),
NUM2INT(rb_hash_aref(r, ID2SYM(rb_intern("HEAP_USE_SLOTS")))),
rb_hash_aref(r, ID2SYM(rb_intern("HAVE_FINALIZE")))? "true" : "false",
- NUM2DBL(rb_hash_aref(r, ID2SYM(rb_intern("GC_MARK_TIME"))))*100,
- NUM2DBL(rb_hash_aref(r, ID2SYM(rb_intern("GC_SWEEP_TIME"))))*100);
+ NUM2DBL(rb_hash_aref(r, ID2SYM(rb_intern("GC_MARK_TIME"))))*1000,
+ NUM2DBL(rb_hash_aref(r, ID2SYM(rb_intern("GC_SWEEP_TIME"))))*1000);
}
#endif
}
diff --git a/gem_prelude.rb b/gem_prelude.rb
index 28bbd8372f..ddc56c87d1 100644
--- a/gem_prelude.rb
+++ b/gem_prelude.rb
@@ -1,4 +1,6 @@
# depends on: array.rb dir.rb env.rb file.rb hash.rb module.rb regexp.rb
+# vim: filetype=ruby
+# THIS FILE WAS AUTOGENERATED, DO NOT EDIT
if defined?(Gem) then
@@ -24,14 +26,6 @@ if defined?(Gem) then
:ruby_install_name => RbConfig::CONFIG["ruby_install_name"]
}
- def self.default_dir
- if defined? RUBY_FRAMEWORK_VERSION
- return File.join(File.dirname(ConfigMap[:sitedir]), "Gems")
- else
- File.join(ConfigMap[:libdir], 'ruby', 'gems', ConfigMap[:ruby_version])
- end
- end
-
def self.dir
@gem_home ||= nil
set_home(ENV['GEM_HOME'] || default_dir) unless @gem_home
@@ -48,7 +42,22 @@ if defined?(Gem) then
@gem_path
end
- # Set the Gem home directory (as reported by +dir+).
+ def self.post_install(&hook)
+ @post_install_hooks << hook
+ end
+
+ def self.post_uninstall(&hook)
+ @post_uninstall_hooks << hook
+ end
+
+ def self.pre_install(&hook)
+ @pre_install_hooks << hook
+ end
+
+ def self.pre_uninstall(&hook)
+ @pre_uninstall_hooks << hook
+ end
+
def self.set_home(home)
@gem_home = home
ensure_gem_subdirectories(@gem_home)
@@ -68,8 +77,121 @@ if defined?(Gem) then
def self.ensure_gem_subdirectories(path)
end
+
+ @post_install_hooks ||= []
+ @post_uninstall_hooks ||= []
+ @pre_uninstall_hooks ||= []
+ @pre_install_hooks ||= []
+
+ ##
+ # An Array of the default sources that come with RubyGems
+
+ def self.default_sources
+ %w[http://gems.rubyforge.org/]
+ end
+
+ ##
+ # Default home directory path to be used if an alternate value is not
+ # specified in the environment
+
+ def self.default_dir
+ if defined? RUBY_FRAMEWORK_VERSION then
+ File.join File.dirname(ConfigMap[:sitedir]), 'Gems',
+ ConfigMap[:ruby_version]
+ elsif RUBY_VERSION > '1.9' then
+ File.join(ConfigMap[:libdir], ConfigMap[:ruby_install_name], 'gems',
+ ConfigMap[:ruby_version])
+ else
+ File.join(ConfigMap[:libdir], ruby_engine, 'gems',
+ ConfigMap[:ruby_version])
+ end
+ end
+
+ ##
+ # Path for gems in the user's home directory
+
+ def self.user_dir
+ File.join(Gem.user_home, '.gem', ruby_engine,
+ ConfigMap[:ruby_version])
+ end
+
+ ##
+ # Default gem load path
+
+ def self.default_path
+ [user_dir, default_dir]
+ end
+
+ ##
+ # Deduce Ruby's --program-prefix and --program-suffix from its install name
+
+ def self.default_exec_format
+ baseruby = ConfigMap[:BASERUBY] || 'ruby'
+ ConfigMap[:RUBY_INSTALL_NAME].sub(baseruby, '%s') rescue '%s'
+ end
+
+ ##
+ # The default directory for binaries
+
+ def self.default_bindir
+ if defined? RUBY_FRAMEWORK_VERSION then # mac framework support
+ '/usr/bin'
+ else # generic install
+ ConfigMap[:bindir]
+ end
+ end
+
+ ##
+ # The default system-wide source info cache directory
+
+ def self.default_system_source_cache_dir
+ File.join Gem.dir, 'source_cache'
+ end
+
+ ##
+ # The default user-specific source info cache directory
+
+ def self.default_user_source_cache_dir
+ File.join Gem.user_home, '.gem', 'source_cache'
+ end
+
+ ##
+ # A wrapper around RUBY_ENGINE const that may not be defined
+
+ def self.ruby_engine
+ if defined? RUBY_ENGINE then
+ RUBY_ENGINE
+ else
+ 'ruby'
+ end
+ end
+
+
+
+ # Methods before this line will be removed when QuickLoader is replaced
+ # with the real RubyGems
+
GEM_PRELUDE_METHODS = Gem.methods(false)
+ begin
+ verbose, debug = $VERBOSE, $DEBUG
+ $DEBUG = $VERBOSE = nil
+
+ begin
+ require 'rubygems/defaults/operating_system'
+ rescue LoadError
+ end
+
+ if defined?(RUBY_ENGINE) then
+ begin
+ require "rubygems/defaults/#{RUBY_ENGINE}"
+ rescue LoadError
+ end
+ end
+ ensure
+ $VERBOSE, $DEBUG = verbose, debug
+ end
+
module QuickLoader
def self.load_full_rubygems_library
@@ -83,7 +205,8 @@ if defined?(Gem) then
undef_method :gem if method_defined? :gem
end
- $".delete File.join(Gem::ConfigMap[:libdir], 'ruby',
+ $".delete File.join(Gem::ConfigMap[:libdir],
+ Gem::ConfigMap[:ruby_install_name],
Gem::ConfigMap[:ruby_version], 'rubygems.rb')
require 'rubygems'
@@ -95,7 +218,7 @@ if defined?(Gem) then
def push_gem_version_on_load_path(gem_name, *version_requirements)
if version_requirements.empty?
unless GemPaths.has_key?(gem_name)
- raise LoadError.new("Could not find RubyGem #{gem_name} (>= 0)\n")
+ raise LoadError.new("Could not find RubyGem #{gem_name} (>= 0)\n")
end
# highest version gems already active
@@ -111,7 +234,7 @@ if defined?(Gem) then
if requirement == ">" || requirement == ">="
if (GemVersions[gem_name] <=> Gem.calculate_integers_for_gem_version(version)) >= 0
- return false
+ return false
end
elsif requirement == "~>"
loaded_version = GemVersions[gem_name]
@@ -159,12 +282,16 @@ if defined?(Gem) then
require_paths = []
- GemPaths.values.each do |path|
- if File.exist?(File.join(path, ".require_paths"))
- require_paths.concat(File.read(File.join(path, ".require_paths")).split.map {|require_path| File.join(path, require_path)})
+ GemPaths.each_value do |path|
+ if File.exist?(file = File.join(path, ".require_paths")) then
+ paths = File.read(file).split.map do |require_path|
+ File.join path, require_path
+ end
+
+ require_paths.concat paths
else
- require_paths << File.join(path, "bin") if File.exist?(File.join(path, "bin"))
- require_paths << File.join(path, "lib") if File.exist?(File.join(path, "lib"))
+ require_paths << file if File.exist?(file = File.join(path, "bin"))
+ require_paths << file if File.exist?(file = File.join(path, "lib"))
end
end
@@ -200,7 +327,7 @@ if defined?(Gem) then
begin
Gem.push_all_highest_version_gems_on_load_path
- $" << File.join(Gem::ConfigMap[:libdir], "ruby",
+ $" << File.join(Gem::ConfigMap[:libdir], Gem::ConfigMap[:ruby_install_name],
Gem::ConfigMap[:ruby_version], "rubygems.rb")
rescue Exception => e
puts "Error loading gem paths on load path in gem_prelude"
diff --git a/hash.c b/hash.c
index 08ecb00bff..e56c5bad3e 100644
--- a/hash.c
+++ b/hash.c
@@ -11,7 +11,6 @@
**********************************************************************/
-#include "eval_intern.h"
#include "ruby/ruby.h"
#include "ruby/st.h"
#include "ruby/util.h"
@@ -37,8 +36,6 @@ static ID id_hash, id_yield, id_default;
static int
rb_any_cmp(VALUE a, VALUE b)
{
- VALUE args[2];
-
if (a == b) return 0;
if (FIXNUM_P(a) && FIXNUM_P(b)) {
return a != b;
@@ -52,8 +49,6 @@ rb_any_cmp(VALUE a, VALUE b)
return a != b;
}
- args[0] = a;
- args[1] = b;
return !rb_eql(a, b);
}
@@ -506,7 +501,7 @@ rb_hash_lookup(VALUE hash, VALUE key)
*/
static VALUE
-rb_hash_fetch(int argc, VALUE *argv, VALUE hash)
+rb_hash_fetch_m(int argc, VALUE *argv, VALUE hash)
{
VALUE key, if_none;
VALUE val;
@@ -528,6 +523,12 @@ rb_hash_fetch(int argc, VALUE *argv, VALUE hash)
return val;
}
+VALUE
+rb_hash_fetch(VALUE hash, VALUE key)
+{
+ return rb_hash_fetch_m(1, &key, hash);
+}
+
/*
* call-seq:
* hsh.default(key=nil) => obj
@@ -615,6 +616,8 @@ rb_hash_default_proc(VALUE hash)
return Qnil;
}
+VALUE rb_obj_is_proc(VALUE proc);
+
/*
* call-seq:
* hsh.default_proc = proc_obj => proc_obj
@@ -1800,6 +1803,13 @@ extern char **environ;
#define GET_ENVIRON(e) (e)
#define FREE_ENVIRON(e)
#endif
+#ifdef ENV_IGNORECASE
+#define ENVMATCH(s1, s2) (STRCASECMP(s1, s2) == 0)
+#define ENVNMATCH(s1, s2, n) (STRNCASECMP(s1, s2, n) == 0)
+#else
+#define ENVMATCH(n1, n2) (strcmp(n1, n2) == 0)
+#define ENVNMATCH(s1, s2, n) (memcmp(s1, s2, n) == 0)
+#endif
static VALUE
env_str_new(const char *ptr, long len)
@@ -1833,12 +1843,7 @@ env_delete(VALUE obj, VALUE name)
VALUE value = env_str_new2(val);
ruby_setenv(nam, 0);
-#ifdef ENV_IGNORECASE
- if (STRCASECMP(nam, PATH_ENV) == 0)
-#else
- if (strcmp(nam, PATH_ENV) == 0)
-#endif
- {
+ if (ENVMATCH(nam, PATH_ENV)) {
path_tainted = 0;
}
return value;
@@ -1869,12 +1874,7 @@ rb_f_getenv(VALUE obj, VALUE name)
}
env = getenv(nam);
if (env) {
-#ifdef ENV_IGNORECASE
- if (STRCASECMP(nam, PATH_ENV) == 0 && !rb_env_path_tainted())
-#else
- if (strcmp(nam, PATH_ENV) == 0 && !rb_env_path_tainted())
-#endif
- {
+ if (ENVMATCH(nam, PATH_ENV) && !rb_env_path_tainted()) {
VALUE str = rb_str_new2(env);
rb_obj_freeze(str);
@@ -1911,11 +1911,7 @@ env_fetch(int argc, VALUE *argv)
}
return if_none;
}
-#ifdef ENV_IGNORECASE
- if (STRCASECMP(nam, PATH_ENV) == 0 && !rb_env_path_tainted())
-#else
- if (strcmp(nam, PATH_ENV) == 0 && !rb_env_path_tainted())
-#endif
+ if (ENVMATCH(nam, PATH_ENV) && !rb_env_path_tainted())
return rb_str_new2(env);
return env_str_new2(env);
}
@@ -1944,13 +1940,7 @@ envix(const char *nam)
env = GET_ENVIRON(environ);
for (i = 0; env[i]; i++) {
- if (
-#ifdef ENV_IGNORECASE
- STRNCASECMP(env[i],nam,len) == 0
-#else
- memcmp(env[i],nam,len) == 0
-#endif
- && env[i][len] == '=')
+ if (ENVNMATCH(env[i],nam,len) && env[i][len] == '=')
break; /* memcmp must come first to avoid */
} /* potential SEGV's */
FREE_ENVIRON(environ);
@@ -2023,18 +2013,7 @@ ruby_setenv(const char *name, const char *value)
}
len = strlen(name) + strlen(value) + 2;
environ[i] = ALLOC_N(char, len);
-#ifndef MSDOS
snprintf(environ[i],len,"%s=%s",name,value); /* all that work just for this */
-#else
- /* MS-DOS requires environment variable names to be in uppercase */
- /* [Tom Dinger, 27 August 1990: Well, it doesn't _require_ it, but
- * some utilities and applications may break because they only look
- * for upper case strings. (Fixed strupr() bug here.)]
- */
- strcpy(environ[i],name); strupr(environ[i]);
- sprintf(environ[i] + strlen(name),"=%s", value);
-#endif /* MSDOS */
-
#endif /* WIN32 */
}
@@ -2054,7 +2033,8 @@ env_aset(VALUE obj, VALUE nm, VALUE val)
}
if (NIL_P(val)) {
- rb_raise(rb_eTypeError, "cannot assign nil; use Hash#delete instead");
+ env_delete(obj, nm);
+ return Qnil;
}
StringValue(nm);
StringValue(val);
@@ -2066,11 +2046,7 @@ env_aset(VALUE obj, VALUE nm, VALUE val)
rb_raise(rb_eArgError, "bad environment variable value");
ruby_setenv(name, value);
-#ifdef ENV_IGNORECASE
- if (STRCASECMP(name, PATH_ENV) == 0) {
-#else
- if (strcmp(name, PATH_ENV) == 0) {
-#endif
+ if (ENVMATCH(name, PATH_ENV)) {
if (OBJ_TAINTED(val)) {
/* already tainted, no check */
path_tainted = 1;
@@ -2618,7 +2594,7 @@ InitVM_Hash(rb_vm_t *vm)
rb_define_method(rb_cHash,"[]", rb_hash_aref, 1);
rb_define_method(rb_cHash,"hash", rb_hash_hash, 0);
rb_define_method(rb_cHash,"eql?", rb_hash_eql, 1);
- rb_define_method(rb_cHash,"fetch", rb_hash_fetch, -1);
+ rb_define_method(rb_cHash,"fetch", rb_hash_fetch_m, -1);
rb_define_method(rb_cHash,"[]=", rb_hash_aset, 2);
rb_define_method(rb_cHash,"store", rb_hash_aset, 2);
rb_define_method(rb_cHash,"default", rb_hash_default, -1);
@@ -2666,7 +2642,6 @@ InitVM_Hash(rb_vm_t *vm)
rb_define_method(rb_cHash,"compare_by_identity", rb_hash_compare_by_id, 0);
rb_define_method(rb_cHash,"compare_by_identity?", rb_hash_compare_by_id_p, 0);
-#ifndef __MACOS__ /* environment variables nothing on MacOS. */
origenviron = environ;
envtbl = rb_obj_alloc(rb_cObject);
rb_extend_object(envtbl, rb_mEnumerable);
@@ -2712,8 +2687,4 @@ InitVM_Hash(rb_vm_t *vm)
rb_define_singleton_method(envtbl,"rassoc", env_rassoc, 1);
rb_define_global_const("ENV", envtbl);
-#else /* __MACOS__ */
- envtbl = rb_hash_s_new(0, NULL, rb_cHash);
- rb_define_global_const("ENV", envtbl);
-#endif /* ifndef __MACOS__ environment variables nothing on MacOS. */
}
diff --git a/id.h b/id.h
index 04cf72e976..40aaf2254c 100644
--- a/id.h
+++ b/id.h
@@ -1,3 +1,4 @@
+/* DO NOT EDIT THIS FILE DIRECTLY */
/**********************************************************************
id.h -
@@ -23,12 +24,112 @@
#define ID_JUNK 0x07
#define ID_INTERNAL ID_JUNK
+#ifdef USE_PARSE_H
#include "parse.h"
+#endif
#define symIFUNC ID2SYM(idIFUNC)
#define symCFUNC ID2SYM(idCFUNC)
enum ruby_method_ids {
+#ifndef tLAST_TOKEN
+ tUPLUS = 321,
+ tUMINUS = 322,
+ tPOW = 323,
+ tCMP = 324,
+ tEQ = 325,
+ tEQQ = 326,
+ tNEQ = 327,
+ tGEQ = 328,
+ tLEQ = 329,
+ tANDOP = 330,
+ tOROP = 331,
+ tMATCH = 332,
+ tNMATCH = 333,
+ tDOT2 = 334,
+ tDOT3 = 335,
+ tAREF = 336,
+ tASET = 337,
+ tLSHFT = 338,
+ tRSHFT = 339,
+ tLAMBDA = 352,
+ idNULL = 365,
+ idRespond_to = 366,
+ idIFUNC = 367,
+ idCFUNC = 368,
+ idThrowState = 369,
+ id_core_set_method_alias = 370,
+ id_core_set_variable_alias = 371,
+ id_core_undef_method = 372,
+ id_core_define_method = 373,
+ id_core_define_singleton_method = 374,
+ id_core_set_postexe = 375,
+ tLAST_TOKEN = 376,
+#elif tUPLUS != 321
+#error tUPLUS differs
+#elif tUMINUS != 322
+#error tUMINUS differs
+#elif tPOW != 323
+#error tPOW differs
+#elif tCMP != 324
+#error tCMP differs
+#elif tEQ != 325
+#error tEQ differs
+#elif tEQQ != 326
+#error tEQQ differs
+#elif tNEQ != 327
+#error tNEQ differs
+#elif tGEQ != 328
+#error tGEQ differs
+#elif tLEQ != 329
+#error tLEQ differs
+#elif tANDOP != 330
+#error tANDOP differs
+#elif tOROP != 331
+#error tOROP differs
+#elif tMATCH != 332
+#error tMATCH differs
+#elif tNMATCH != 333
+#error tNMATCH differs
+#elif tDOT2 != 334
+#error tDOT2 differs
+#elif tDOT3 != 335
+#error tDOT3 differs
+#elif tAREF != 336
+#error tAREF differs
+#elif tASET != 337
+#error tASET differs
+#elif tLSHFT != 338
+#error tLSHFT differs
+#elif tRSHFT != 339
+#error tRSHFT differs
+#elif tLAMBDA != 352
+#error tLAMBDA differs
+#elif idNULL != 365
+#error idNULL differs
+#elif idRespond_to != 366
+#error idRespond_to differs
+#elif idIFUNC != 367
+#error idIFUNC differs
+#elif idCFUNC != 368
+#error idCFUNC differs
+#elif idThrowState != 369
+#error idThrowState differs
+#elif id_core_set_method_alias != 370
+#error id_core_set_method_alias differs
+#elif id_core_set_variable_alias != 371
+#error id_core_set_variable_alias differs
+#elif id_core_undef_method != 372
+#error id_core_undef_method differs
+#elif id_core_define_method != 373
+#error id_core_define_method differs
+#elif id_core_define_singleton_method != 374
+#error id_core_define_singleton_method differs
+#elif id_core_set_postexe != 375
+#error id_core_set_postexe differs
+#elif tLAST_TOKEN != 376
+#error tLAST_TOKEN differs
+#endif
idPLUS = '+',
idMINUS = '-',
idMULT = '*',
@@ -62,22 +163,22 @@ enum ruby_method_ids {
tBitblt,
tAnswer,
#endif
- tLAST_ID
-};
-
-#define idIntern ((tIntern<<ID_SCOPE_SHIFT)|ID_LOCAL)
-#define idMethodMissing ((tMethodMissing<<ID_SCOPE_SHIFT)|ID_LOCAL)
-#define idLength ((tLength<<ID_SCOPE_SHIFT)|ID_LOCAL)
-#define idGets ((tGets<<ID_SCOPE_SHIFT)|ID_LOCAL)
-#define idSucc ((tSucc<<ID_SCOPE_SHIFT)|ID_LOCAL)
-#define idEach ((tEach<<ID_SCOPE_SHIFT)|ID_LOCAL)
-#define idLambda ((tLambda<<ID_SCOPE_SHIFT)|ID_LOCAL)
-#define idSend ((tSend<<ID_SCOPE_SHIFT)|ID_LOCAL)
-#define id__send__ ((t__send__<<ID_SCOPE_SHIFT)|ID_LOCAL)
-#define idInitialize ((tInitialize<<ID_SCOPE_SHIFT)|ID_LOCAL)
+ tLAST_ID,
+#define TOKEN2ID(n) id##n = ((t##n<<ID_SCOPE_SHIFT)|ID_LOCAL)
#if SUPPORT_JOKE
-#define idBitblt ((tBitblt<<ID_SCOPE_SHIFT)|ID_LOCAL)
-#define idAnswer ((tAnswer<<ID_SCOPE_SHIFT)|ID_LOCAL)
+ TOKEN2ID(Bitblt),
+ TOKEN2ID(Answer),
#endif
+ TOKEN2ID(Intern),
+ TOKEN2ID(MethodMissing),
+ TOKEN2ID(Length),
+ TOKEN2ID(Gets),
+ TOKEN2ID(Succ),
+ TOKEN2ID(Each),
+ TOKEN2ID(Lambda),
+ TOKEN2ID(Send),
+ TOKEN2ID(__send__),
+ TOKEN2ID(Initialize)
+};
#endif /* RUBY_ID_H */
diff --git a/include/ruby.h b/include/ruby.h
index 2cb3fbf9f7..dd7e2b8e59 100644
--- a/include/ruby.h
+++ b/include/ruby.h
@@ -1,6 +1,6 @@
/**********************************************************************
- ruby/mvm.h -
+ ruby.h -
$Author$
created at: Sun 10 12:06:15 Jun JST 2007
@@ -17,23 +17,18 @@
#define HAVE_RUBY_INTERN_H 1
#define HAVE_RUBY_IO_H 1
#define HAVE_RUBY_MISSING_H 1
-#define HAVE_RUBY_MVM_H 1
-#define HAVE_RUBY_NODE_H 1
+#define HAVE_RUBY_VM_H 1
#define HAVE_RUBY_ONIGURUMA_H 1
#define HAVE_RUBY_RE_H 1
#define HAVE_RUBY_REGEX_H 1
#define HAVE_RUBY_RUBY_H 1
-#define HAVE_RUBY_SIGNAL_H 1
#define HAVE_RUBY_ST_H 1
#define HAVE_RUBY_UTIL_H 1
+#define HAVE_RUBY_VM_H 1
#ifdef _WIN32
#define HAVE_RUBY_WIN32_H 1
#endif
#include "ruby/ruby.h"
-#if RUBY_VM
-#include "ruby/mvm.h"
-#endif
-extern void ruby_set_debug_option(const char *);
#endif /* RUBY_H */
diff --git a/include/ruby/backward/rubyio.h b/include/ruby/backward/rubyio.h
new file mode 100644
index 0000000000..d5246db546
--- /dev/null
+++ b/include/ruby/backward/rubyio.h
@@ -0,0 +1,6 @@
+#if defined __GNUC__
+#warning use "ruby/io.h" instead of "rubyio.h"
+#elif defined _MSC_VER || defined __BORLANDC__
+#pragma message("warning: use \"ruby/io.h\" instead of \"rubyio.h\"")
+#endif
+#include "ruby/io.h"
diff --git a/include/ruby/backward/rubysig.h b/include/ruby/backward/rubysig.h
new file mode 100644
index 0000000000..6a0cf0ef9c
--- /dev/null
+++ b/include/ruby/backward/rubysig.h
@@ -0,0 +1,33 @@
+/**********************************************************************
+
+ rubysig.h -
+
+ $Author$
+ $Date$
+ created at: Wed Aug 16 01:15:38 JST 1995
+
+ Copyright (C) 1993-2008 Yukihiro Matsumoto
+
+**********************************************************************/
+
+#if defined __GNUC__
+#warning rubysig.h is obsolete
+#elif defined _MSC_VER || defined __BORLANDC__
+#pragma message("warning: rubysig.h is obsolete")
+#endif
+
+#ifndef RUBYSIG_H
+#define RUBYSIG_H
+#include "ruby/ruby.h"
+
+struct rb_blocking_region_buffer;
+RUBY_EXTERN struct rb_blocking_region_buffer *rb_thread_blocking_region_begin(void);
+RUBY_EXTERN void rb_thread_blocking_region_end(struct rb_blocking_region_buffer *);
+#define TRAP_BEG do {void *__region = rb_thread_blocking_region_begin(void);
+#define TRAP_END rb_thread_blocking_region_end(__region);} while (0)
+#define RUBY_CRITICAL(statements) do {statements;} while (0)
+#define DEFER_INTS (0)
+#define ENABLE_INTS (1)
+#define ALLOW_INTS do {CHECK_INTS;} while (0)
+#define CHECK_INTS rb_thread_check_ints()
+#endif
diff --git a/include/ruby/defines.h b/include/ruby/defines.h
index 1a0274ec81..0b870db137 100644
--- a/include/ruby/defines.h
+++ b/include/ruby/defines.h
@@ -103,12 +103,10 @@ void xfree(void*);
#undef _WIN32
#endif
-#if defined(MSDOS) || defined(_WIN32) || defined(__human68k__) || defined(__EMX__)
+#if defined(_WIN32) || defined(__EMX__)
#define DOSISH 1
-#ifndef _WIN32_WCE
# define DOSISH_DRIVE_LETTER
#endif
-#endif
#if defined(__NeXT__) || defined(__APPLE__)
/* Do not trust WORDS_BIGENDIAN from configure since -arch compiler flag may
@@ -194,11 +192,7 @@ void xfree(void*);
#include "ruby/win32.h"
#endif
-#if defined(__VMS)
-#include "vms/vms.h"
-#endif
-
-#if defined(__BEOS__) && !defined(__HAIKU__)
+#if defined(__BEOS__) && !defined(__HAIKU__) && !defined(BONE)
#include <net/socket.h> /* intern.h needs fd_set definition */
#endif
@@ -245,25 +239,19 @@ void rb_ia64_flushrs(void);
#if defined(DOSISH)
#define PATH_SEP ";"
-#elif defined(riscos)
-#define PATH_SEP ","
#else
#define PATH_SEP ":"
#endif
#define PATH_SEP_CHAR PATH_SEP[0]
-#if defined(__human68k__)
-#define PATH_ENV "path"
-#else
#define PATH_ENV "PATH"
-#endif
-#if defined(DOSISH) && !defined(__human68k__) && !defined(__EMX__)
+#if defined(DOSISH) && !defined(__EMX__)
#define ENV_IGNORECASE
#endif
#ifndef CASEFOLD_FILESYSTEM
-# if defined DOSISH || defined __VMS
+# if defined DOSISH
# define CASEFOLD_FILESYSTEM 1
# else
# define CASEFOLD_FILESYSTEM 0
diff --git a/include/ruby/encoding.h b/include/ruby/encoding.h
index 1e48877291..10f85c9ad3 100644
--- a/include/ruby/encoding.h
+++ b/include/ruby/encoding.h
@@ -53,7 +53,7 @@
(RBASIC(obj)->flags & ~ENC_CODERANGE_MASK) | (cr))
#define ENC_CODERANGE_CLEAR(obj) ENC_CODERANGE_SET(obj,0)
-/* assumed ASCII compatiblity */
+/* assumed ASCII compatibility */
#define ENC_CODERANGE_AND(a, b) \
(a == ENC_CODERANGE_7BIT ? b : \
a == ENC_CODERANGE_VALID ? (b == ENC_CODERANGE_7BIT ? ENC_CODERANGE_VALID : b) : \
@@ -92,16 +92,20 @@ char* rb_enc_nth(const char*, const char*, int, rb_encoding*);
VALUE rb_obj_encoding(VALUE);
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);
+
/* index -> rb_encoding */
rb_encoding* rb_enc_from_index(int idx);
/* name -> rb_encoding */
rb_encoding * rb_enc_find(const char *name);
-/* encoding -> name */
+/* rb_encoding * -> name */
#define rb_enc_name(enc) (enc)->name
-/* encoding -> minlen/maxlen */
+/* rb_encoding * -> minlen/maxlen */
#define rb_enc_mbminlen(enc) (enc)->min_enc_len
#define rb_enc_mbmaxlen(enc) (enc)->max_enc_len
@@ -120,7 +124,7 @@ int rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc);
int rb_enc_ascget(const char *p, const char *e, int *len, rb_encoding *enc);
/* -> code or raise exception */
-int rb_enc_codepoint(const char *p, const char *e, rb_encoding *enc);
+unsigned int rb_enc_codepoint(const char *p, const char *e, rb_encoding *enc);
#define rb_enc_mbc_to_codepoint(p, e, enc) ONIGENC_MBC_TO_CODE(enc,(UChar*)(p),(UChar*)(e))
/* -> codelen>0 or raise exception */
@@ -129,11 +133,11 @@ int rb_enc_codelen(int code, rb_encoding *enc);
/* code,ptr,encoding -> write buf */
#define rb_enc_mbcput(c,buf,enc) ONIGENC_CODE_TO_MBC(enc,c,(UChar*)(buf))
-/* ptr, ptr, encoding -> prev_char */
-#define rb_enc_prev_char(s,p,enc) (char *)onigenc_get_prev_char_head(enc,(UChar*)(s),(UChar*)(p))
-/* ptr, ptr, encoding -> next_char */
-#define rb_enc_left_char_head(s,p,enc) (char *)onigenc_get_left_adjust_char_head(enc,(UChar*)(s),(UChar*)(p))
-#define rb_enc_right_char_head(s,p,enc) (char *)onigenc_get_right_adjust_char_head(enc,(UChar*)(s),(UChar*)(p))
+/* start, ptr, end, encoding -> prev_char */
+#define rb_enc_prev_char(s,p,e,enc) (char *)onigenc_get_prev_char_head(enc,(UChar*)(s),(UChar*)(p),(UChar*)(e))
+/* start, ptr, end, encoding -> next_char */
+#define rb_enc_left_char_head(s,p,e,enc) (char *)onigenc_get_left_adjust_char_head(enc,(UChar*)(s),(UChar*)(p),(UChar*)(e))
+#define rb_enc_right_char_head(s,p,e,enc) (char *)onigenc_get_right_adjust_char_head(enc,(UChar*)(s),(UChar*)(p),(UChar*)(e))
/* ptr, ptr, encoding -> newline_or_not */
#define rb_enc_is_newline(p,end,enc) ONIGENC_IS_MBC_NEWLINE(enc,(UChar*)(p),(UChar*)(end))
@@ -168,11 +172,14 @@ rb_encoding *rb_usascii_encoding(void);
rb_encoding *rb_locale_encoding(void);
rb_encoding *rb_filesystem_encoding(void);
rb_encoding *rb_default_external_encoding(void);
+rb_encoding *rb_default_internal_encoding(void);
int rb_ascii8bit_encindex(void);
int rb_utf8_encindex(void);
int rb_usascii_encindex(void);
VALUE rb_enc_default_external(void);
+VALUE rb_enc_default_internal(void);
void rb_enc_set_default_external(VALUE encoding);
+void rb_enc_set_default_internal(VALUE encoding);
VALUE rb_locale_charmap(VALUE klass);
long rb_memsearch(const void*,long,const void*,long,rb_encoding*);
@@ -201,13 +208,14 @@ typedef enum {
econv_destination_buffer_full,
econv_source_buffer_empty,
econv_finished,
- econv_output_followed_by_input,
- econv_incomplete_input,
+ econv_after_output,
+ econv_incomplete_input
} rb_econv_result_t;
typedef struct rb_econv_t rb_econv_t;
-VALUE rb_str_transcode(VALUE str, VALUE to, int ecflags, VALUE ecopts);
+VALUE rb_str_encode(VALUE str, VALUE to, int ecflags, VALUE ecopts);
+int rb_econv_has_convpath_p(const char* from_encoding, const char* to_encoding);
int rb_econv_prepare_opts(VALUE opthash, VALUE *ecopts);
@@ -223,6 +231,10 @@ void rb_econv_close(rb_econv_t *ec);
/* result: 0:success -1:failure */
int rb_econv_set_replacement(rb_econv_t *ec, const unsigned char *str, size_t len, const char *encname);
+/* result: 0:success -1:failure */
+int rb_econv_decorate_at_first(rb_econv_t *ec, const char *decorator_name);
+int rb_econv_decorate_at_last(rb_econv_t *ec, const char *decorator_name);
+
VALUE rb_econv_open_exc(const char *senc, const char *denc, int ecflags);
/* result: 0:success -1:failure */
@@ -260,25 +272,22 @@ void rb_econv_binmode(rb_econv_t *ec);
#define ECONV_UNDEF_REPLACE 0x00000020
#define ECONV_UNDEF_HEX_CHARREF 0x00000030
-/* usable only if destination encoding is ascii compatible */
-#define ECONV_DECODER_MASK 0x00000f00
-#define ECONV_UNIVERSAL_NEWLINE_DECODER 0x00000100
+#define ECONV_DECORATOR_MASK 0x0000ff00
-/* usable only if source encoding is ascii compatible */
-#define ECONV_ENCODER_MASK 0x0000f000
-#define ECONV_CRLF_NEWLINE_ENCODER 0x00001000
-#define ECONV_CR_NEWLINE_ENCODER 0x00002000
-#define ECONV_XML_TEXT_ENCODER 0x00004000
-#define ECONV_XML_ATTR_CONTENT_ENCODER 0x00008000
+#define ECONV_UNIVERSAL_NEWLINE_DECORATOR 0x00000100
+#define ECONV_CRLF_NEWLINE_DECORATOR 0x00001000
+#define ECONV_CR_NEWLINE_DECORATOR 0x00002000
+#define ECONV_XML_TEXT_DECORATOR 0x00004000
+#define ECONV_XML_ATTR_CONTENT_DECORATOR 0x00008000
-#define ECONV_STATEFUL_ENCODER_MASK 0x00f00000
-#define ECONV_XML_ATTR_QUOTE_ENCODER 0x00100000
+#define ECONV_STATEFUL_DECORATOR_MASK 0x00f00000
+#define ECONV_XML_ATTR_QUOTE_DECORATOR 0x00100000
/* end of flags for rb_econv_open */
/* flags for rb_econv_convert */
#define ECONV_PARTIAL_INPUT 0x00010000
-#define ECONV_OUTPUT_FOLLOWED_BY_INPUT 0x00020000
+#define ECONV_AFTER_OUTPUT 0x00020000
/* end of flags for rb_econv_convert */
#endif /* RUBY_ENCODING_H */
diff --git a/include/ruby/intern.h b/include/ruby/intern.h
index 020ae5ff78..642a4507dd 100644
--- a/include/ruby/intern.h
+++ b/include/ruby/intern.h
@@ -357,6 +357,7 @@ VALUE rb_hash_dup(VALUE);
VALUE rb_hash_freeze(VALUE);
VALUE rb_hash_aref(VALUE, VALUE);
VALUE rb_hash_lookup(VALUE, VALUE);
+VALUE rb_hash_fetch(VALUE, VALUE);
VALUE rb_hash_aset(VALUE, VALUE, VALUE);
VALUE rb_hash_delete_if(VALUE);
VALUE rb_hash_delete(VALUE,VALUE);
@@ -380,6 +381,7 @@ VALUE rb_io_close(VALUE);
VALUE rb_io_flush(VALUE);
VALUE rb_io_eof(VALUE);
VALUE rb_io_binmode(VALUE);
+VALUE rb_io_ascii8bit_binmode(VALUE);
VALUE rb_io_addstr(VALUE, VALUE);
VALUE rb_io_printf(int, VALUE*, VALUE);
VALUE rb_io_print(int, VALUE*, VALUE);
@@ -544,6 +546,10 @@ VALUE rb_str_new5(VALUE, const char*, long);
VALUE rb_tainted_str_new_cstr(const char*);
VALUE rb_tainted_str_new(const char*, long);
VALUE rb_tainted_str_new2(const char*);
+VALUE rb_external_str_new(const char*, long);
+VALUE rb_external_str_new_cstr(const char*);
+VALUE rb_locale_str_new(const char*, long);
+VALUE rb_locale_str_new_cstr(const char*);
VALUE rb_str_buf_new(long);
VALUE rb_str_buf_new_cstr(const char*);
VALUE rb_str_buf_new2(const char*);
@@ -614,6 +620,18 @@ size_t rb_str_capacity(VALUE);
rb_usascii_str_new(str, strlen(str)) : \
rb_usascii_str_new_cstr(str); \
})
+#define rb_external_str_new_cstr(str) __extension__ ( \
+{ \
+ (__builtin_constant_p(str)) ? \
+ rb_external_str_new(str, strlen(str)) : \
+ rb_external_str_new_cstr(str); \
+})
+#define rb_locale_str_new_cstr(str) __extension__ ( \
+{ \
+ (__builtin_constant_p(str)) ? \
+ rb_locale_str_new(str, strlen(str)) : \
+ rb_locale_str_new_cstr(str); \
+})
#define rb_str_buf_new_cstr(str) __extension__ ( \
{ \
(__builtin_constant_p(str)) ? \
@@ -658,6 +676,7 @@ VALUE rb_struct_define_without_accessor(const char *, VALUE, rb_alloc_func_t, ..
typedef void rb_unblock_function_t(void *);
typedef VALUE rb_blocking_function_t(void *);
void rb_thread_check_ints(void);
+int rb_thread_interrupted(VALUE thval);
VALUE rb_thread_blocking_region(rb_blocking_function_t *func, void *data1,
rb_unblock_function_t *ubf, void *data2);
#define RUBY_UBF_IO ((rb_unblock_function_t *)-1)
@@ -668,10 +687,11 @@ VALUE rb_mutex_try_lock(VALUE mutex);
VALUE rb_mutex_lock(VALUE mutex);
VALUE rb_mutex_unlock(VALUE mutex);
VALUE rb_mutex_sleep(VALUE self, VALUE timeout);
-VALUE rb_mutex_synchronize(VALUE self);
+VALUE rb_mutex_synchronize(VALUE mutex, VALUE (*func)(VALUE arg), VALUE arg);
VALUE rb_barrier_new(void);
VALUE rb_barrier_wait(VALUE self);
VALUE rb_barrier_release(VALUE self);
+VALUE rb_barrier_destroy(VALUE self);
char *rb_thread_cwd(void);
/* time.c */
VALUE rb_time_new(time_t, long);
diff --git a/include/ruby/io.h b/include/ruby/io.h
index 49f8f783c1..72ee8b32aa 100644
--- a/include/ruby/io.h
+++ b/include/ruby/io.h
@@ -30,10 +30,10 @@ extern "C" {
typedef struct rb_io_t {
int fd; /* file descriptor */
FILE *stdio_file; /* stdio ptr for read/write if available */
- int mode; /* mode flags */
+ int mode; /* mode flags: FMODE_XXXs */
rb_pid_t pid; /* child's pid (for pipes) */
int lineno; /* number of lines read */
- VALUE pathv; /* pathname for file */
+ VALUE pathv; /* pathname for file */
void (*finalize)(struct rb_io_t*,int); /* finalize proc */
char *wbuf; /* wbuf_off + wbuf_len <= wbuf_capa */
@@ -68,11 +68,12 @@ typedef struct rb_io_t {
int cbuf_capa;
rb_econv_t *writeconv;
- VALUE writeconv_stateless;
+ VALUE writeconv_asciicompat;
int writeconv_pre_ecflags;
VALUE writeconv_pre_ecopts;
int writeconv_initialized;
+ VALUE write_lock;
} rb_io_t;
#define HAVE_RB_IO_T 1
@@ -124,7 +125,7 @@ typedef struct rb_io_t {
fp->cbuf_len = 0;\
fp->cbuf_capa = 0;\
fp->writeconv = NULL;\
- fp->writeconv_stateless = Qnil;\
+ fp->writeconv_asciicompat = Qnil;\
fp->writeconv_pre_ecflags = 0;\
fp->writeconv_pre_ecopts = Qnil;\
fp->writeconv_initialized = 0;\
@@ -133,6 +134,7 @@ typedef struct rb_io_t {
fp->encs.enc2 = NULL;\
fp->encs.ecflags = 0;\
fp->encs.ecopts = Qnil;\
+ fp->write_lock = 0;\
} while (0)
FILE *rb_io_stdio_file(rb_io_t *fptr);
@@ -162,11 +164,6 @@ void rb_io_read_check(rb_io_t*);
int rb_io_read_pending(rb_io_t*);
void rb_read_check(FILE*);
-DEPRECATED(int rb_getc(FILE*));
-DEPRECATED(long rb_io_fread(char *, long, FILE *));
-DEPRECATED(long rb_io_fwrite(const char *, long, FILE *));
-DEPRECATED(int rb_read_pending(FILE*));
-
int ruby_absolute_path_p(const char*);
#if defined(__cplusplus)
diff --git a/include/ruby/missing.h b/include/ruby/missing.h
index 392998c841..16d5a6f02b 100644
--- a/include/ruby/missing.h
+++ b/include/ruby/missing.h
@@ -38,57 +38,61 @@ struct timespec {
};
#endif
+#ifndef RUBY_EXTERN
+#define RUBY_EXTERN extern
+#endif
+
#ifndef HAVE_ACOSH
-extern double acosh(double);
-extern double asinh(double);
-extern double atanh(double);
+RUBY_EXTERN double acosh(double);
+RUBY_EXTERN double asinh(double);
+RUBY_EXTERN double atanh(double);
#endif
#ifndef HAVE_CRYPT
-extern char *crypt(const char *, const char *);
+RUBY_EXTERN char *crypt(const char *, const char *);
#endif
#ifndef HAVE_DUP2
-extern int dup2(int, int);
+RUBY_EXTERN int dup2(int, int);
#endif
#ifndef HAVE_EACCESS
-extern int eaccess(const char*, int);
+RUBY_EXTERN int eaccess(const char*, int);
#endif
#ifndef HAVE_FINITE
-extern int finite(double);
+RUBY_EXTERN int finite(double);
#endif
#ifndef HAVE_FLOCK
-extern int flock(int, int);
+RUBY_EXTERN int flock(int, int);
#endif
/*
#ifndef HAVE_FREXP
-extern double frexp(double, int *);
+RUBY_EXTERN double frexp(double, int *);
#endif
*/
#ifndef HAVE_HYPOT
-extern double hypot(double, double);
+RUBY_EXTERN double hypot(double, double);
#endif
#ifndef HAVE_ERF
-extern double erf(double);
-extern double erfc(double);
+RUBY_EXTERN double erf(double);
+RUBY_EXTERN double erfc(double);
#endif
#ifndef HAVE_TGAMMA
-extern double tgamma(double);
+RUBY_EXTERN double tgamma(double);
#endif
#ifndef HAVE_LGAMMA_R
-extern double lgamma_r(double, int *);
+RUBY_EXTERN double lgamma_r(double, int *);
#endif
#ifndef HAVE_CBRT
-extern double cbrt(double);
+RUBY_EXTERN double cbrt(double);
#endif
#ifndef isinf
@@ -96,62 +100,62 @@ extern double cbrt(double);
# if defined(HAVE_FINITE) && defined(HAVE_ISNAN)
# define isinf(x) (!finite(x) && !isnan(x))
# else
-extern int isinf(double);
+RUBY_EXTERN int isinf(double);
# endif
# endif
#endif
#ifndef HAVE_ISNAN
-extern int isnan(double);
+RUBY_EXTERN int isnan(double);
#endif
/*
#ifndef HAVE_MEMCMP
-extern int memcmp(const void *, const void *, size_t);
+RUBY_EXTERN int memcmp(const void *, const void *, size_t);
#endif
*/
#ifndef HAVE_MEMMOVE
-extern void *memmove(void *, const void *, size_t);
+RUBY_EXTERN void *memmove(void *, const void *, size_t);
#endif
/*
#ifndef HAVE_MODF
-extern double modf(double, double *);
+RUBY_EXTERN double modf(double, double *);
#endif
*/
#ifndef HAVE_STRCHR
-extern char *strchr(const char *, int);
-extern char *strrchr(const char *, int);
+RUBY_EXTERN char *strchr(const char *, int);
+RUBY_EXTERN char *strrchr(const char *, int);
#endif
#ifndef HAVE_STRERROR
-extern char *strerror(int);
+RUBY_EXTERN char *strerror(int);
#endif
#ifndef HAVE_STRSTR
-extern char *strstr(const char *, const char *);
+RUBY_EXTERN char *strstr(const char *, const char *);
#endif
/*
#ifndef HAVE_STRTOL
-extern long strtol(const char *, char **, int);
+RUBY_EXTERN long strtol(const char *, char **, int);
#endif
*/
#ifndef HAVE_VSNPRINTF
# include <stdarg.h>
-extern int snprintf(char *, size_t n, char const *, ...);
-extern int vsnprintf(char *, size_t n, char const *, va_list);
+RUBY_EXTERN int snprintf(char *, size_t n, char const *, ...);
+RUBY_EXTERN int vsnprintf(char *, size_t n, char const *, va_list);
#endif
#ifndef HAVE_STRLCPY
-extern size_t strlcpy(char *, const char*, size_t);
+RUBY_EXTERN size_t strlcpy(char *, const char*, size_t);
#endif
#ifndef HAVE_STRLCAT
-extern size_t strlcat(char *, const char*, size_t);
+RUBY_EXTERN size_t strlcat(char *, const char*, size_t);
#endif
#if defined(__cplusplus)
diff --git a/include/ruby/node.h b/include/ruby/node.h
deleted file mode 100644
index d83f55098c..0000000000
--- a/include/ruby/node.h
+++ /dev/null
@@ -1,514 +0,0 @@
-/**********************************************************************
-
- node.h -
-
- $Author$
- created at: Fri May 28 15:14:02 JST 1993
-
- Copyright (C) 1993-2007 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#ifndef RUBY_NODE_H
-#define RUBY_NODE_H 1
-
-#if defined(__cplusplus)
-extern "C" {
-#if 0
-} /* satisfy cc-mode */
-#endif
-#endif
-
-enum node_type {
- NODE_METHOD,
-#define NODE_METHOD NODE_METHOD
- NODE_FBODY,
-#define NODE_FBODY NODE_FBODY
- NODE_CFUNC,
-#define NODE_CFUNC NODE_CFUNC
- NODE_SCOPE,
-#define NODE_SCOPE NODE_SCOPE
- NODE_BLOCK,
-#define NODE_BLOCK NODE_BLOCK
- NODE_IF,
-#define NODE_IF NODE_IF
- NODE_CASE,
-#define NODE_CASE NODE_CASE
- NODE_WHEN,
-#define NODE_WHEN NODE_WHEN
- NODE_OPT_N,
-#define NODE_OPT_N NODE_OPT_N
- NODE_WHILE,
-#define NODE_WHILE NODE_WHILE
- NODE_UNTIL,
-#define NODE_UNTIL NODE_UNTIL
- NODE_ITER,
-#define NODE_ITER NODE_ITER
- NODE_FOR,
-#define NODE_FOR NODE_FOR
- NODE_BREAK,
-#define NODE_BREAK NODE_BREAK
- NODE_NEXT,
-#define NODE_NEXT NODE_NEXT
- NODE_REDO,
-#define NODE_REDO NODE_REDO
- NODE_RETRY,
-#define NODE_RETRY NODE_RETRY
- NODE_BEGIN,
-#define NODE_BEGIN NODE_BEGIN
- NODE_RESCUE,
-#define NODE_RESCUE NODE_RESCUE
- NODE_RESBODY,
-#define NODE_RESBODY NODE_RESBODY
- NODE_ENSURE,
-#define NODE_ENSURE NODE_ENSURE
- NODE_AND,
-#define NODE_AND NODE_AND
- NODE_OR,
-#define NODE_OR NODE_OR
- NODE_MASGN,
-#define NODE_MASGN NODE_MASGN
- NODE_LASGN,
-#define NODE_LASGN NODE_LASGN
- NODE_DASGN,
-#define NODE_DASGN NODE_DASGN
- NODE_DASGN_CURR,
-#define NODE_DASGN_CURR NODE_DASGN_CURR
- NODE_GASGN,
-#define NODE_GASGN NODE_GASGN
- NODE_IASGN,
-#define NODE_IASGN NODE_IASGN
- NODE_IASGN2,
-#define NODE_IASGN2 NODE_IASGN2
- NODE_CDECL,
-#define NODE_CDECL NODE_CDECL
- NODE_CVASGN,
-#define NODE_CVASGN NODE_CVASGN
- NODE_CVDECL,
-#define NODE_CVDECL NODE_CVDECL
- NODE_OP_ASGN1,
-#define NODE_OP_ASGN1 NODE_OP_ASGN1
- NODE_OP_ASGN2,
-#define NODE_OP_ASGN2 NODE_OP_ASGN2
- NODE_OP_ASGN_AND,
-#define NODE_OP_ASGN_AND NODE_OP_ASGN_AND
- NODE_OP_ASGN_OR,
-#define NODE_OP_ASGN_OR NODE_OP_ASGN_OR
- NODE_CALL,
-#define NODE_CALL NODE_CALL
- NODE_FCALL,
-#define NODE_FCALL NODE_FCALL
- NODE_VCALL,
-#define NODE_VCALL NODE_VCALL
- NODE_SUPER,
-#define NODE_SUPER NODE_SUPER
- NODE_ZSUPER,
-#define NODE_ZSUPER NODE_ZSUPER
- NODE_ARRAY,
-#define NODE_ARRAY NODE_ARRAY
- NODE_ZARRAY,
-#define NODE_ZARRAY NODE_ZARRAY
- NODE_VALUES,
-#define NODE_VALUES NODE_VALUES
- NODE_HASH,
-#define NODE_HASH NODE_HASH
- NODE_RETURN,
-#define NODE_RETURN NODE_RETURN
- NODE_YIELD,
-#define NODE_YIELD NODE_YIELD
- NODE_LVAR,
-#define NODE_LVAR NODE_LVAR
- NODE_DVAR,
-#define NODE_DVAR NODE_DVAR
- NODE_GVAR,
-#define NODE_GVAR NODE_GVAR
- NODE_IVAR,
-#define NODE_IVAR NODE_IVAR
- NODE_CONST,
-#define NODE_CONST NODE_CONST
- NODE_CVAR,
-#define NODE_CVAR NODE_CVAR
- NODE_NTH_REF,
-#define NODE_NTH_REF NODE_NTH_REF
- NODE_BACK_REF,
-#define NODE_BACK_REF NODE_BACK_REF
- NODE_MATCH,
-#define NODE_MATCH NODE_MATCH
- NODE_MATCH2,
-#define NODE_MATCH2 NODE_MATCH2
- NODE_MATCH3,
-#define NODE_MATCH3 NODE_MATCH3
- NODE_LIT,
-#define NODE_LIT NODE_LIT
- NODE_STR,
-#define NODE_STR NODE_STR
- NODE_DSTR,
-#define NODE_DSTR NODE_DSTR
- NODE_XSTR,
-#define NODE_XSTR NODE_XSTR
- NODE_DXSTR,
-#define NODE_DXSTR NODE_DXSTR
- NODE_EVSTR,
-#define NODE_EVSTR NODE_EVSTR
- NODE_DREGX,
-#define NODE_DREGX NODE_DREGX
- NODE_DREGX_ONCE,
-#define NODE_DREGX_ONCE NODE_DREGX_ONCE
- NODE_ARGS,
-#define NODE_ARGS NODE_ARGS
- NODE_ARGS_AUX,
-#define NODE_ARGS_AUX NODE_ARGS_AUX
- NODE_OPT_ARG,
-#define NODE_OPT_ARG NODE_OPT_ARG
- NODE_POSTARG,
-#define NODE_POSTARG NODE_POSTARG
- NODE_ARGSCAT,
-#define NODE_ARGSCAT NODE_ARGSCAT
- NODE_ARGSPUSH,
-#define NODE_ARGSPUSH NODE_ARGSPUSH
- NODE_SPLAT,
-#define NODE_SPLAT NODE_SPLAT
- NODE_TO_ARY,
-#define NODE_TO_ARY NODE_TO_ARY
- NODE_BLOCK_ARG,
-#define NODE_BLOCK_ARG NODE_BLOCK_ARG
- NODE_BLOCK_PASS,
-#define NODE_BLOCK_PASS NODE_BLOCK_PASS
- NODE_DEFN,
-#define NODE_DEFN NODE_DEFN
- NODE_DEFS,
-#define NODE_DEFS NODE_DEFS
- NODE_ALIAS,
-#define NODE_ALIAS NODE_ALIAS
- NODE_VALIAS,
-#define NODE_VALIAS NODE_VALIAS
- NODE_UNDEF,
-#define NODE_UNDEF NODE_UNDEF
- NODE_CLASS,
-#define NODE_CLASS NODE_CLASS
- NODE_MODULE,
-#define NODE_MODULE NODE_MODULE
- NODE_SCLASS,
-#define NODE_SCLASS NODE_SCLASS
- NODE_COLON2,
-#define NODE_COLON2 NODE_COLON2
- NODE_COLON3,
-#define NODE_COLON3 NODE_COLON3
- NODE_DOT2,
-#define NODE_DOT2 NODE_DOT2
- NODE_DOT3,
-#define NODE_DOT3 NODE_DOT3
- NODE_FLIP2,
-#define NODE_FLIP2 NODE_FLIP2
- NODE_FLIP3,
-#define NODE_FLIP3 NODE_FLIP3
- NODE_ATTRSET,
-#define NODE_ATTRSET NODE_ATTRSET
- NODE_SELF,
-#define NODE_SELF NODE_SELF
- NODE_NIL,
-#define NODE_NIL NODE_NIL
- NODE_TRUE,
-#define NODE_TRUE NODE_TRUE
- NODE_FALSE,
-#define NODE_FALSE NODE_FALSE
- NODE_ERRINFO,
-#define NODE_ERRINFO NODE_ERRINFO
- NODE_DEFINED,
-#define NODE_DEFINED NODE_DEFINED
- NODE_POSTEXE,
-#define NODE_POSTEXE NODE_POSTEXE
- NODE_ALLOCA,
-#define NODE_ALLOCA NODE_ALLOCA
- NODE_BMETHOD,
-#define NODE_BMETHOD NODE_BMETHOD
- NODE_MEMO,
-#define NODE_MEMO NODE_MEMO
- NODE_IFUNC,
-#define NODE_IFUNC NODE_IFUNC
- NODE_DSYM,
-#define NODE_DSYM NODE_DSYM
- NODE_ATTRASGN,
-#define NODE_ATTRASGN NODE_ATTRASGN
- NODE_PRELUDE,
-#define NODE_PRELUDE NODE_PRELUDE
- NODE_LAMBDA,
-#define NODE_LAMBDA NODE_LAMBDA
- NODE_OPTBLOCK,
-#define NODE_OPTBLOCK NODE_OPTBLOCK
- NODE_LAST
-#define NODE_LAST NODE_LAST
-};
-
-typedef struct RNode {
- unsigned long flags;
- char *nd_file;
- union {
- struct RNode *node;
- ID id;
- VALUE value;
- VALUE (*cfunc)(ANYARGS);
- ID *tbl;
- } u1;
- union {
- struct RNode *node;
- ID id;
- long argc;
- VALUE value;
- } u2;
- union {
- struct RNode *node;
- ID id;
- long state;
- struct global_entry *entry;
- long cnt;
- VALUE value;
- } u3;
-} NODE;
-
-#define RNODE(obj) (R_CAST(RNode)(obj))
-
-/* 0..4:T_TYPES, 5:FL_MARK, 6:reserved, 7:NODE_FL_NEWLINE */
-#define NODE_FL_NEWLINE (((VALUE)1)<<7)
-
-#define NODE_TYPESHIFT 8
-#define NODE_TYPEMASK (((VALUE)0x7f)<<NODE_TYPESHIFT)
-
-#define nd_type(n) ((int) (((RNODE(n))->flags & NODE_TYPEMASK)>>NODE_TYPESHIFT))
-#define nd_set_type(n,t) \
- RNODE(n)->flags=((RNODE(n)->flags&~NODE_TYPEMASK)|(((t)<<NODE_TYPESHIFT)&NODE_TYPEMASK))
-
-#define NODE_LSHIFT (NODE_TYPESHIFT+7)
-#define NODE_LMASK (((SIGNED_VALUE)1<<(sizeof(VALUE)*CHAR_BIT-NODE_LSHIFT))-1)
-#define nd_line(n) ((VALUE)(((RNODE(n))->flags>>NODE_LSHIFT)&NODE_LMASK))
-#define nd_set_line(n,l) \
- RNODE(n)->flags=((RNODE(n)->flags&~(-1<<NODE_LSHIFT))|(((l)&NODE_LMASK)<<NODE_LSHIFT))
-
-#define nd_head u1.node
-#define nd_alen u2.argc
-#define nd_next u3.node
-
-#define nd_cond u1.node
-#define nd_body u2.node
-#define nd_else u3.node
-
-#define nd_orig u3.value
-
-#define nd_resq u2.node
-#define nd_ensr u3.node
-
-#define nd_1st u1.node
-#define nd_2nd u2.node
-
-#define nd_stts u1.node
-
-#define nd_entry u3.entry
-#define nd_vid u1.id
-#define nd_cflag u2.id
-#define nd_cval u3.value
-
-#define nd_oid u1.id
-#define nd_cnt u3.cnt
-#define nd_tbl u1.tbl
-
-#define nd_var u1.node
-#define nd_iter u3.node
-
-#define nd_value u2.node
-#define nd_aid u3.id
-
-#define nd_lit u1.value
-
-#define nd_frml u2.argc
-#define nd_rest u1.id
-#define nd_opt u1.node
-#define nd_pid u1.id
-#define nd_plen u2.argc
-
-#define nd_recv u1.node
-#define nd_mid u2.id
-#define nd_args u3.node
-
-#define nd_noex u3.id
-#define nd_defn u3.node
-
-#define nd_cfnc u1.cfunc
-#define nd_argc u2.argc
-
-#define nd_cpath u1.node
-#define nd_super u3.node
-
-#define nd_modl u1.id
-#define nd_clss u1.value
-
-#define nd_beg u1.node
-#define nd_end u2.node
-#define nd_state u3.state
-#define nd_rval u2.value
-
-#define nd_nth u2.argc
-
-#define nd_tag u1.id
-#define nd_tval u2.value
-
-#define nd_visi u2.argc
-
-#define NEW_NODE(t,a0,a1,a2) rb_node_newnode((t),(VALUE)(a0),(VALUE)(a1),(VALUE)(a2))
-
-#define NEW_METHOD(n,x,v) NEW_NODE(NODE_METHOD,x,n,v)
-#define NEW_FBODY(n,i) NEW_NODE(NODE_FBODY,i,n,0)
-#define NEW_DEFN(i,a,d,p) NEW_NODE(NODE_DEFN,0,i,NEW_SCOPE(a,d))
-#define NEW_DEFS(r,i,a,d) NEW_NODE(NODE_DEFS,r,i,NEW_SCOPE(a,d))
-#define NEW_CFUNC(f,c) NEW_NODE(NODE_CFUNC,f,c,0)
-#define NEW_IFUNC(f,c) NEW_NODE(NODE_IFUNC,f,c,0)
-#define NEW_SCOPE(a,b) NEW_NODE(NODE_SCOPE,local_tbl(),b,a)
-#define NEW_BLOCK(a) NEW_NODE(NODE_BLOCK,a,0,0)
-#define NEW_IF(c,t,e) NEW_NODE(NODE_IF,c,t,e)
-#define NEW_UNLESS(c,t,e) NEW_IF(c,e,t)
-#define NEW_CASE(h,b) NEW_NODE(NODE_CASE,h,b,0)
-#define NEW_WHEN(c,t,e) NEW_NODE(NODE_WHEN,c,t,e)
-#define NEW_OPT_N(b) NEW_NODE(NODE_OPT_N,0,b,0)
-#define NEW_WHILE(c,b,n) NEW_NODE(NODE_WHILE,c,b,n)
-#define NEW_UNTIL(c,b,n) NEW_NODE(NODE_UNTIL,c,b,n)
-#define NEW_FOR(v,i,b) NEW_NODE(NODE_FOR,v,b,i)
-#define NEW_ITER(a,b) NEW_NODE(NODE_ITER,0,NEW_SCOPE(a,b),0)
-#define NEW_LAMBDA(a) NEW_NODE(NODE_LAMBDA,a,0,0)
-#define NEW_BREAK(s) NEW_NODE(NODE_BREAK,s,0,0)
-#define NEW_NEXT(s) NEW_NODE(NODE_NEXT,s,0,0)
-#define NEW_REDO() NEW_NODE(NODE_REDO,0,0,0)
-#define NEW_RETRY() NEW_NODE(NODE_RETRY,0,0,0)
-#define NEW_BEGIN(b) NEW_NODE(NODE_BEGIN,0,b,0)
-#define NEW_RESCUE(b,res,e) NEW_NODE(NODE_RESCUE,b,res,e)
-#define NEW_RESBODY(a,ex,n) NEW_NODE(NODE_RESBODY,n,ex,a)
-#define NEW_ENSURE(b,en) NEW_NODE(NODE_ENSURE,b,0,en)
-#define NEW_RETURN(s) NEW_NODE(NODE_RETURN,s,0,0)
-#define NEW_YIELD(a,s) NEW_NODE(NODE_YIELD,a,0,s)
-#define NEW_LIST(a) NEW_ARRAY(a)
-#define NEW_ARRAY(a) NEW_NODE(NODE_ARRAY,a,1,0)
-#define NEW_ZARRAY() NEW_NODE(NODE_ZARRAY,0,0,0)
-#define NEW_HASH(a) NEW_NODE(NODE_HASH,a,0,0)
-#define NEW_MASGN(l,r) NEW_NODE(NODE_MASGN,l,0,r)
-#define NEW_GASGN(v,val) NEW_NODE(NODE_GASGN,v,val,rb_global_entry(v))
-#define NEW_LASGN(v,val) NEW_NODE(NODE_LASGN,v,val,0)
-#define NEW_DASGN(v,val) NEW_NODE(NODE_DASGN,v,val,0)
-#define NEW_DASGN_CURR(v,val) NEW_NODE(NODE_DASGN_CURR,v,val,0)
-#define NEW_IASGN(v,val) NEW_NODE(NODE_IASGN,v,val,0)
-#define NEW_IASGN2(v,val) NEW_NODE(NODE_IASGN2,v,val,0)
-#define NEW_CDECL(v,val,path) NEW_NODE(NODE_CDECL,v,val,path)
-#define NEW_CVASGN(v,val) NEW_NODE(NODE_CVASGN,v,val,0)
-#define NEW_CVDECL(v,val) NEW_NODE(NODE_CVDECL,v,val,0)
-#define NEW_OP_ASGN1(p,id,a) NEW_NODE(NODE_OP_ASGN1,p,id,a)
-#define NEW_OP_ASGN2(r,i,o,val) NEW_NODE(NODE_OP_ASGN2,r,val,NEW_OP_ASGN22(i,o))
-#define NEW_OP_ASGN22(i,o) NEW_NODE(NODE_OP_ASGN2,i,o,rb_id_attrset(i))
-#define NEW_OP_ASGN_OR(i,val) NEW_NODE(NODE_OP_ASGN_OR,i,val,0)
-#define NEW_OP_ASGN_AND(i,val) NEW_NODE(NODE_OP_ASGN_AND,i,val,0)
-#define NEW_GVAR(v) NEW_NODE(NODE_GVAR,v,0,rb_global_entry(v))
-#define NEW_LVAR(v) NEW_NODE(NODE_LVAR,v,0,0)
-#define NEW_DVAR(v) NEW_NODE(NODE_DVAR,v,0,0)
-#define NEW_IVAR(v) NEW_NODE(NODE_IVAR,v,0,0)
-#define NEW_CONST(v) NEW_NODE(NODE_CONST,v,0,0)
-#define NEW_CVAR(v) NEW_NODE(NODE_CVAR,v,0,0)
-#define NEW_NTH_REF(n) NEW_NODE(NODE_NTH_REF,0,n,0)
-#define NEW_BACK_REF(n) NEW_NODE(NODE_BACK_REF,0,n,0)
-#define NEW_MATCH(c) NEW_NODE(NODE_MATCH,c,0,0)
-#define NEW_MATCH2(n1,n2) NEW_NODE(NODE_MATCH2,n1,n2,0)
-#define NEW_MATCH3(r,n2) NEW_NODE(NODE_MATCH3,r,n2,0)
-#define NEW_LIT(l) NEW_NODE(NODE_LIT,l,0,0)
-#define NEW_STR(s) NEW_NODE(NODE_STR,s,0,0)
-#define NEW_DSTR(s) NEW_NODE(NODE_DSTR,s,1,0)
-#define NEW_XSTR(s) NEW_NODE(NODE_XSTR,s,0,0)
-#define NEW_DXSTR(s) NEW_NODE(NODE_DXSTR,s,0,0)
-#define NEW_DSYM(s) NEW_NODE(NODE_DSYM,s,0,0)
-#define NEW_EVSTR(n) NEW_NODE(NODE_EVSTR,0,(n),0)
-#define NEW_CALL(r,m,a) NEW_NODE(NODE_CALL,r,m,a)
-#define NEW_FCALL(m,a) NEW_NODE(NODE_FCALL,0,m,a)
-#define NEW_VCALL(m) NEW_NODE(NODE_VCALL,0,m,0)
-#define NEW_SUPER(a) NEW_NODE(NODE_SUPER,0,0,a)
-#define NEW_ZSUPER() NEW_NODE(NODE_ZSUPER,0,0,0)
-#define NEW_ARGS(m,o) NEW_NODE(NODE_ARGS,o,m,0)
-#define NEW_ARGS_AUX(r,b) NEW_NODE(NODE_ARGS_AUX,r,b,0)
-#define NEW_OPT_ARG(i,v) NEW_NODE(NODE_OPT_ARG,i,v,0)
-#define NEW_POSTARG(i,v) NEW_NODE(NODE_POSTARG,i,v,0)
-#define NEW_ARGSCAT(a,b) NEW_NODE(NODE_ARGSCAT,a,b,0)
-#define NEW_ARGSPUSH(a,b) NEW_NODE(NODE_ARGSPUSH,a,b,0)
-#define NEW_SPLAT(a) NEW_NODE(NODE_SPLAT,a,0,0)
-#define NEW_TO_ARY(a) NEW_NODE(NODE_TO_ARY,a,0,0)
-#define NEW_BLOCK_ARG(v) NEW_NODE(NODE_BLOCK_ARG,v,0,local_cnt(v))
-#define NEW_BLOCK_PASS(b) NEW_NODE(NODE_BLOCK_PASS,0,b,0)
-#define NEW_ALIAS(n,o) NEW_NODE(NODE_ALIAS,n,o,0)
-#define NEW_VALIAS(n,o) NEW_NODE(NODE_VALIAS,n,o,0)
-#define NEW_UNDEF(i) NEW_NODE(NODE_UNDEF,0,i,0)
-#define NEW_CLASS(n,b,s) NEW_NODE(NODE_CLASS,n,NEW_SCOPE(0,b),(s))
-#define NEW_SCLASS(r,b) NEW_NODE(NODE_SCLASS,r,NEW_SCOPE(0,b),0)
-#define NEW_MODULE(n,b) NEW_NODE(NODE_MODULE,n,NEW_SCOPE(0,b),0)
-#define NEW_COLON2(c,i) NEW_NODE(NODE_COLON2,c,i,0)
-#define NEW_COLON3(i) NEW_NODE(NODE_COLON3,0,i,0)
-#define NEW_DOT2(b,e) NEW_NODE(NODE_DOT2,b,e,0)
-#define NEW_DOT3(b,e) NEW_NODE(NODE_DOT3,b,e,0)
-#define NEW_ATTRSET(a) NEW_NODE(NODE_ATTRSET,a,0,0)
-#define NEW_SELF() NEW_NODE(NODE_SELF,0,0,0)
-#define NEW_NIL() NEW_NODE(NODE_NIL,0,0,0)
-#define NEW_TRUE() NEW_NODE(NODE_TRUE,0,0,0)
-#define NEW_FALSE() NEW_NODE(NODE_FALSE,0,0,0)
-#define NEW_ERRINFO() NEW_NODE(NODE_ERRINFO,0,0,0)
-#define NEW_DEFINED(e) NEW_NODE(NODE_DEFINED,e,0,0)
-#define NEW_PREEXE(b) NEW_SCOPE(b)
-#define NEW_POSTEXE(b) NEW_NODE(NODE_POSTEXE,0,b,0)
-#define NEW_BMETHOD(b) NEW_NODE(NODE_BMETHOD,0,0,b)
-#define NEW_ATTRASGN(r,m,a) NEW_NODE(NODE_ATTRASGN,r,m,a)
-#define NEW_PRELUDE(p,b) NEW_NODE(NODE_PRELUDE,p,b,0)
-#define NEW_OPTBLOCK(a) NEW_NODE(NODE_OPTBLOCK,a,0,0)
-
-#define NOEX_PUBLIC 0x00
-#define NOEX_NOSUPER 0x01
-#define NOEX_PRIVATE 0x02
-#define NOEX_PROTECTED 0x04
-#define NOEX_MASK 0x06 /* 0110 */
-#define NOEX_BASIC 0x08
-
-#define NOEX_UNDEF NOEX_NOSUPER
-
-#define NOEX_MODFUNC 0x10
-#define NOEX_SUPER 0x20
-#define NOEX_VCALL 0x40
-
-#define NOEX_SAFE(n) (((n) >> 8) & 0x0F)
-#define NOEX_WITH(n, s) ((s << 8) | (n) | (ruby_running ? 0 : NOEX_BASIC))
-#define NOEX_WITH_SAFE(n) NOEX_WITH(n, rb_safe_level())
-
-#define CALL_PUBLIC 0
-#define CALL_FCALL 1
-#define CALL_VCALL 2
-#define CALL_SUPER 3
-
-VALUE rb_parser_new(void);
-VALUE rb_parser_end_seen_p(VALUE);
-VALUE rb_parser_encoding(VALUE);
-
-NODE *rb_parser_compile_cstr(volatile VALUE, const char*, const char*, int, int);
-NODE *rb_parser_compile_string(volatile VALUE, const char*, VALUE, int);
-NODE *rb_parser_compile_file(volatile VALUE, const char*, VALUE, int);
-
-NODE *rb_compile_cstr(const char*, const char*, int, int);
-NODE *rb_compile_string(const char*, VALUE, int);
-NODE *rb_compile_file(const char*, VALUE, int);
-
-void rb_add_method(VALUE, ID, NODE *, int);
-NODE *rb_node_newnode(enum node_type,VALUE,VALUE,VALUE);
-
-NODE* rb_method_node(VALUE klass, ID id);
-int rb_node_arity(NODE* node);
-
-struct global_entry *rb_global_entry(ID);
-VALUE rb_gvar_get(struct global_entry *);
-VALUE rb_gvar_set(struct global_entry *, VALUE);
-VALUE rb_gvar_defined(struct global_entry *);
-
-#if defined(__cplusplus)
-#if 0
-{ /* satisfy cc-mode */
-#endif
-} /* extern "C" { */
-#endif
-
-#endif /* RUBY_NODE_H */
diff --git a/include/ruby/oniguruma.h b/include/ruby/oniguruma.h
index 1784348e16..bc6905edaa 100644
--- a/include/ruby/oniguruma.h
+++ b/include/ruby/oniguruma.h
@@ -104,7 +104,7 @@ extern "C" {
#endif
typedef unsigned char OnigUChar;
-typedef unsigned long OnigCodePoint;
+typedef unsigned int OnigCodePoint;
typedef unsigned int OnigCtype;
typedef unsigned int OnigDistance;
@@ -164,7 +164,7 @@ typedef struct OnigEncodingTypeST {
int (*property_name_to_ctype)(struct OnigEncodingTypeST* enc, OnigUChar* p, OnigUChar* end);
int (*is_code_ctype)(OnigCodePoint code, OnigCtype ctype, struct OnigEncodingTypeST* enc);
int (*get_ctype_code_range)(OnigCtype ctype, OnigCodePoint* sb_out, const OnigCodePoint* ranges[], struct OnigEncodingTypeST* enc);
- OnigUChar* (*left_adjust_char_head)(const OnigUChar* start, const OnigUChar* p, struct OnigEncodingTypeST* enc);
+ OnigUChar* (*left_adjust_char_head)(const OnigUChar* start, const OnigUChar* p, const OnigUChar* end, struct OnigEncodingTypeST* enc);
int (*is_allowed_reverse_match)(const OnigUChar* p, const OnigUChar* end, struct OnigEncodingTypeST* enc);
int ruby_encoding_index;
} OnigEncodingType;
@@ -219,14 +219,14 @@ ONIG_EXTERN OnigEncodingType OnigEncodingASCII;
(enc)->mbc_case_fold(flag,(const OnigUChar** )pp,end,buf,enc)
#define ONIGENC_IS_ALLOWED_REVERSE_MATCH(enc,s,end) \
(enc)->is_allowed_reverse_match(s,end,enc)
-#define ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc,start,s) \
- (enc)->left_adjust_char_head(start, s, enc)
+#define ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc,start,s,end) \
+ (enc)->left_adjust_char_head(start, s, end, enc)
#define ONIGENC_APPLY_ALL_CASE_FOLD(enc,case_fold_flag,f,arg) \
(enc)->apply_all_case_fold(case_fold_flag,f,arg,enc)
#define ONIGENC_GET_CASE_FOLD_CODES_BY_STR(enc,case_fold_flag,p,end,acs) \
(enc)->get_case_fold_codes_by_str(case_fold_flag,p,end,acs,enc)
-#define ONIGENC_STEP_BACK(enc,start,s,n) \
- onigenc_step_back((enc),(start),(s),(n))
+#define ONIGENC_STEP_BACK(enc,start,s,end,n) \
+ onigenc_step_back((enc),(start),(s),(end),(n))
#define ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(n) (n)
#define ONIGENC_MBCLEN_CHARFOUND_P(r) (0 < (r))
@@ -290,7 +290,7 @@ int onigenc_mbclen_approximate P_((const OnigUChar* p,const OnigUChar* e, struct
(enc)->get_ctype_code_range(ctype,sbout,ranges,enc)
ONIG_EXTERN
-OnigUChar* onigenc_step_back P_((OnigEncoding enc, const OnigUChar* start, const OnigUChar* s, int n));
+OnigUChar* onigenc_step_back P_((OnigEncoding enc, const OnigUChar* start, const OnigUChar* s, const OnigUChar* end, int n));
/* encoding API */
@@ -303,13 +303,13 @@ OnigEncoding onigenc_get_default_encoding P_((void));
ONIG_EXTERN
void onigenc_set_default_caseconv_table P_((const OnigUChar* table));
ONIG_EXTERN
-OnigUChar* onigenc_get_right_adjust_char_head_with_prev P_((OnigEncoding enc, const OnigUChar* start, const OnigUChar* s, const OnigUChar** prev));
+OnigUChar* onigenc_get_right_adjust_char_head_with_prev P_((OnigEncoding enc, const OnigUChar* start, const OnigUChar* s, const OnigUChar* end, const OnigUChar** prev));
ONIG_EXTERN
-OnigUChar* onigenc_get_prev_char_head P_((OnigEncoding enc, const OnigUChar* start, const OnigUChar* s));
+OnigUChar* onigenc_get_prev_char_head P_((OnigEncoding enc, const OnigUChar* start, const OnigUChar* s, const OnigUChar* end));
ONIG_EXTERN
-OnigUChar* onigenc_get_left_adjust_char_head P_((OnigEncoding enc, const OnigUChar* start, const OnigUChar* s));
+OnigUChar* onigenc_get_left_adjust_char_head P_((OnigEncoding enc, const OnigUChar* start, const OnigUChar* s, const OnigUChar* end));
ONIG_EXTERN
-OnigUChar* onigenc_get_right_adjust_char_head P_((OnigEncoding enc, const OnigUChar* start, const OnigUChar* s));
+OnigUChar* onigenc_get_right_adjust_char_head P_((OnigEncoding enc, const OnigUChar* start, const OnigUChar* s, const OnigUChar* end));
ONIG_EXTERN
int onigenc_strlen P_((OnigEncoding enc, const OnigUChar* p, const OnigUChar* end));
ONIG_EXTERN
diff --git a/include/ruby/public_object.h b/include/ruby/public_object.h
index 7e4ac4556a..ba6c34bd88 100644
--- a/include/ruby/public_object.h
+++ b/include/ruby/public_object.h
@@ -1,39 +1,9 @@
#ifndef RUBY_PUBLIC_OBJECT_H
#define RUBY_PUBLIC_OBJECT_H 1
-#include "ruby/mvm.h"
+#include "ruby/vm.h"
-/*
-public_vars = %w{
- mKernel mComparable mEnumerable mPrecision mErrno mFileTest mGC
- mMath mProcess cBasicObject cObject cArray cBignum cBinding
- cClass cCont cDir cData cFalseClass cEncoding cEnumerator cFile
- cFixnum cFloat cHash cInteger cIO cMatch cMethod cModule
- cNameErrorMesg cNilClass cNumeric cProc cRange cRational cComplex
- cRegexp cStat cString cStruct cSymbol cThread cTime cTrueClass
- cUnboundMethod cMutex cBarrier eException eStandardError
- eSystemExit eInterrupt eSignal eFatal eArgError eEOFError
- eIndexError eStopIteration eKeyError eRangeError eIOError
- eRuntimeError eSecurityError eSystemCallError eThreadError
- eTypeError eZeroDivError eNotImpError eNoMemError eNoMethodError
- eFloatDomainError eLocalJumpError eSysStackError eRegexpError
- eEncCompatError eScriptError eNameError eSyntaxError eLoadError
- stdin stdout stderr argf
-}
-public_vars2 = %w{
- verbose debug progname
-}
-
-public_vars.each{|var|
- puts " rb_vmkey_#{var},"
- puts "\#define rb_#{var} (*((VALUE *)rb_vm_specific_ptr(rb_vmkey_#{var})))"
-}
-public_vars2.each{|var|
- puts " rb_vmkey_#{var},"
-}
-
- */
VALUE *rb_vm_specific_ptr(int key);
@@ -44,8 +14,6 @@ enum ruby_public_object_vmkey {
#define rb_mComparable (*rb_vm_specific_ptr(rb_vmkey_mComparable))
rb_vmkey_mEnumerable,
#define rb_mEnumerable (*rb_vm_specific_ptr(rb_vmkey_mEnumerable))
- rb_vmkey_mPrecision,
-#define rb_mPrecision (*rb_vm_specific_ptr(rb_vmkey_mPrecision))
rb_vmkey_mErrno,
#define rb_mErrno (*rb_vm_specific_ptr(rb_vmkey_mErrno))
rb_vmkey_mFileTest,
@@ -68,8 +36,6 @@ enum ruby_public_object_vmkey {
#define rb_cBinding (*rb_vm_specific_ptr(rb_vmkey_cBinding))
rb_vmkey_cClass,
#define rb_cClass (*rb_vm_specific_ptr(rb_vmkey_cClass))
- rb_vmkey_cCont,
-#define rb_cCont (*rb_vm_specific_ptr(rb_vmkey_cCont))
rb_vmkey_cDir,
#define rb_cDir (*rb_vm_specific_ptr(rb_vmkey_cDir))
rb_vmkey_cData,
@@ -78,6 +44,8 @@ enum ruby_public_object_vmkey {
#define rb_cFalseClass (*rb_vm_specific_ptr(rb_vmkey_cFalseClass))
rb_vmkey_cEncoding,
#define rb_cEncoding (*rb_vm_specific_ptr(rb_vmkey_cEncoding))
+ rb_vmkey_cEncodingConverter,
+#define rb_cEncodingConverter (*rb_vm_specific_ptr(rb_vmkey_cEncodingConverter))
rb_vmkey_cEnumerator,
#define rb_cEnumerator (*rb_vm_specific_ptr(rb_vmkey_cEnumerator))
rb_vmkey_cFile,
@@ -186,6 +154,8 @@ enum ruby_public_object_vmkey {
#define rb_eSysStackError (*rb_vm_specific_ptr(rb_vmkey_eSysStackError))
rb_vmkey_eRegexpError,
#define rb_eRegexpError (*rb_vm_specific_ptr(rb_vmkey_eRegexpError))
+ rb_vmkey_eEncodingError,
+#define rb_eEncodingError (*rb_vm_specific_ptr(rb_vmkey_eEncodingError))
rb_vmkey_eEncCompatError,
#define rb_eEncCompatError (*rb_vm_specific_ptr(rb_vmkey_eEncCompatError))
rb_vmkey_eScriptError,
@@ -196,6 +166,12 @@ enum ruby_public_object_vmkey {
#define rb_eSyntaxError (*rb_vm_specific_ptr(rb_vmkey_eSyntaxError))
rb_vmkey_eLoadError,
#define rb_eLoadError (*rb_vm_specific_ptr(rb_vmkey_eLoadError))
+ rb_vmkey_eUndefinedConversionError,
+#define rb_eUndefinedConversionError (*rb_vm_specific_ptr(rb_vmkey_eUndefinedConversionError))
+ rb_vmkey_eInvalidByteSequenceError,
+#define rb_eInvalidByteSequenceError (*rb_vm_specific_ptr(rb_vmkey_eInvalidByteSequenceError))
+ rb_vmkey_eConverterNotFoundError,
+#define rb_eConverterNotFoundError (*rb_vm_specific_ptr(rb_vmkey_eConverterNotFoundError))
rb_vmkey_stdin,
#define rb_stdin (*rb_vm_specific_ptr(rb_vmkey_stdin))
rb_vmkey_stdout,
@@ -209,6 +185,7 @@ enum ruby_public_object_vmkey {
rb_vmkey_debug,
#define ruby_debug (*rb_vm_specific_ptr(rb_vmkey_debug))
rb_vmkey_progname,
+#define ruby_progname (*rb_vm_specific_ptr(rb_vmkey_progname))
ruby_public_object_count
};
diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h
index 9438a85e87..7114c045c2 100644
--- a/include/ruby/ruby.h
+++ b/include/ruby/ruby.h
@@ -77,11 +77,6 @@ extern "C" {
# endif
#endif
-#if defined(__VMS)
-# pragma builtins
-# define alloca __alloca
-#endif
-
#if SIZEOF_LONG == SIZEOF_VOIDP
typedef unsigned long VALUE;
typedef unsigned long ID;
@@ -265,7 +260,7 @@ VALUE rb_ull2inum(unsigned LONG_LONG);
#define ID2SYM(x) (((VALUE)(x)<<RUBY_SPECIAL_SHIFT)|SYMBOL_FLAG)
#define SYM2ID(x) RSHIFT((unsigned long)x,RUBY_SPECIAL_SHIFT)
-/* special contants - i.e. non-zero and non-fixnum constants */
+/* special constants - i.e. non-zero and non-fixnum constants */
enum ruby_special_consts {
RUBY_Qfalse = 0,
RUBY_Qtrue = 2,
@@ -378,6 +373,13 @@ void rb_check_safe_str(VALUE);
/* obsolete macro - use SafeStringValue(v) */
#define Check_SafeStr(v) rb_check_safe_str((VALUE)(v))
+VALUE rb_str_export(VALUE);
+#define ExportStringValue(v) do {\
+ SafeStringValue(v);\
+ (v) = rb_str_export(v);\
+} while (0)
+VALUE rb_str_export_locale(VALUE);
+
VALUE rb_get_path(VALUE);
#define FilePathValue(v) ((v) = rb_get_path(v))
@@ -509,7 +511,7 @@ VALUE rb_newobj(void);
if (FL_TEST(obj, FL_EXIVAR)) rb_copy_generic_ivar((VALUE)clone,(VALUE)obj);\
} while (0)
#define DUPSETUP(dup,obj) do {\
- OBJSETUP(dup,rb_obj_class(obj),(RBASIC(obj)->flags)&(T_MASK|FL_EXIVAR|FL_TAINT|FL_UNTRUSTED));\
+ OBJSETUP(dup,rb_obj_class(obj), (RBASIC(obj)->flags)&(T_MASK|FL_EXIVAR|FL_TAINT|FL_UNTRUSTED)); \
if (FL_TEST(obj, FL_EXIVAR)) rb_copy_generic_ivar((VALUE)dup,(VALUE)obj);\
} while (0)
@@ -601,17 +603,34 @@ struct RString {
RSTRING(str)->as.heap.ptr)
#define RSTRING_END(str) (RSTRING_PTR(str)+RSTRING_LEN(str))
+#define RARRAY_EMBED_LEN_MAX 3
struct RArray {
struct RBasic basic;
- long len;
union {
- long capa;
- VALUE shared;
- } aux;
- VALUE *ptr;
+ struct {
+ long len;
+ union {
+ long capa;
+ VALUE shared;
+ } aux;
+ VALUE *ptr;
+ } heap;
+ VALUE ary[RARRAY_EMBED_LEN_MAX];
+ } as;
};
-#define RARRAY_LEN(a) RARRAY(a)->len
-#define RARRAY_PTR(a) RARRAY(a)->ptr
+#define RARRAY_EMBED_FLAG FL_USER1
+/* FL_USER2 is for ELTS_SHARED */
+#define RARRAY_EMBED_LEN_MASK (FL_USER4|FL_USER3)
+#define RARRAY_EMBED_LEN_SHIFT (FL_USHIFT+3)
+#define RARRAY_LEN(a) \
+ ((RBASIC(a)->flags & RARRAY_EMBED_FLAG) ? \
+ (long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \
+ (RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT)) : \
+ RARRAY(a)->as.heap.len)
+#define RARRAY_PTR(a) \
+ ((RBASIC(a)->flags & RARRAY_EMBED_FLAG) ? \
+ RARRAY(a)->as.ary : \
+ RARRAY(a)->as.heap.ptr)
struct RRegexp {
struct RBasic basic;
@@ -650,7 +669,7 @@ struct RRational {
struct RComplex {
struct RBasic basic;
VALUE real;
- VALUE image;
+ VALUE imag;
};
struct RData {
@@ -834,6 +853,26 @@ VALUE rb_define_module_under(VALUE, const char*);
void rb_include_module(VALUE,VALUE);
void rb_extend_object(VALUE,VALUE);
+struct rb_global_variable;
+
+typedef VALUE rb_gvar_getter_t(ID id, void *data, struct rb_global_variable *gvar);
+typedef void rb_gvar_setter_t(VALUE val, ID id, void *data, struct rb_global_variable *gvar);
+typedef void rb_gvar_marker_t(VALUE *var);
+
+VALUE rb_gvar_undef_getter(ID id, void *data, struct rb_global_variable *gvar);
+void rb_gvar_undef_setter(VALUE val, ID id, void *data, struct rb_global_variable *gvar);
+void rb_gvar_undef_marker(VALUE *var);
+
+VALUE rb_gvar_val_getter(ID id, void *data, struct rb_global_variable *gvar);
+void rb_gvar_val_setter(VALUE val, ID id, void *data, struct rb_global_variable *gvar);
+void rb_gvar_val_marker(VALUE *var);
+
+VALUE rb_gvar_var_getter(ID id, void *data, struct rb_global_variable *gvar);
+void rb_gvar_var_setter(VALUE val, ID id, void *data, struct rb_global_variable *gvar);
+void rb_gvar_var_marker(VALUE *var);
+
+void rb_gvar_readonly_setter(VALUE val, ID id, void *data, struct rb_global_variable *gvar);
+
void rb_define_variable(const char*,VALUE*);
void rb_define_virtual_variable(const char*,VALUE(*)(ANYARGS),void(*)(ANYARGS));
void rb_define_hooked_variable(const char*,VALUE*,VALUE(*)(ANYARGS),void(*)(ANYARGS));
@@ -852,7 +891,7 @@ void rb_define_alias(VALUE,const char*,const char*);
void rb_define_attr(VALUE,const char*,int,int);
void rb_global_variable(VALUE*);
-void rb_register_mark_object(VALUE);
+void rb_gc_register_mark_object(VALUE);
void rb_gc_register_address(VALUE*);
void rb_gc_unregister_address(VALUE*);
@@ -951,6 +990,90 @@ void *ruby_options(int, char**);
int ruby_run_node(void *);
#include "ruby/public_object.h"
+#if 0
+RUBY_EXTERN VALUE rb_mKernel;
+RUBY_EXTERN VALUE rb_mComparable;
+RUBY_EXTERN VALUE rb_mEnumerable;
+RUBY_EXTERN VALUE rb_mErrno;
+RUBY_EXTERN VALUE rb_mFileTest;
+RUBY_EXTERN VALUE rb_mGC;
+RUBY_EXTERN VALUE rb_mMath;
+RUBY_EXTERN VALUE rb_mProcess;
+
+RUBY_EXTERN VALUE rb_cBasicObject;
+RUBY_EXTERN VALUE rb_cObject;
+RUBY_EXTERN VALUE rb_cArray;
+RUBY_EXTERN VALUE rb_cBignum;
+RUBY_EXTERN VALUE rb_cBinding;
+RUBY_EXTERN VALUE rb_cClass;
+RUBY_EXTERN VALUE rb_cCont;
+RUBY_EXTERN VALUE rb_cDir;
+RUBY_EXTERN VALUE rb_cData;
+RUBY_EXTERN VALUE rb_cFalseClass;
+RUBY_EXTERN VALUE rb_cEncoding;
+RUBY_EXTERN VALUE rb_cEnumerator;
+RUBY_EXTERN VALUE rb_cFile;
+RUBY_EXTERN VALUE rb_cFixnum;
+RUBY_EXTERN VALUE rb_cFloat;
+RUBY_EXTERN VALUE rb_cHash;
+RUBY_EXTERN VALUE rb_cInteger;
+RUBY_EXTERN VALUE rb_cIO;
+RUBY_EXTERN VALUE rb_cMatch;
+RUBY_EXTERN VALUE rb_cMethod;
+RUBY_EXTERN VALUE rb_cModule;
+RUBY_EXTERN VALUE rb_cNameErrorMesg;
+RUBY_EXTERN VALUE rb_cNilClass;
+RUBY_EXTERN VALUE rb_cNumeric;
+RUBY_EXTERN VALUE rb_cProc;
+RUBY_EXTERN VALUE rb_cRange;
+RUBY_EXTERN VALUE rb_cRational;
+RUBY_EXTERN VALUE rb_cComplex;
+RUBY_EXTERN VALUE rb_cRegexp;
+RUBY_EXTERN VALUE rb_cStat;
+RUBY_EXTERN VALUE rb_cString;
+RUBY_EXTERN VALUE rb_cStruct;
+RUBY_EXTERN VALUE rb_cSymbol;
+RUBY_EXTERN VALUE rb_cThread;
+RUBY_EXTERN VALUE rb_cTime;
+RUBY_EXTERN VALUE rb_cTrueClass;
+RUBY_EXTERN VALUE rb_cUnboundMethod;
+
+RUBY_EXTERN VALUE rb_eException;
+RUBY_EXTERN VALUE rb_eStandardError;
+RUBY_EXTERN VALUE rb_eSystemExit;
+RUBY_EXTERN VALUE rb_eInterrupt;
+RUBY_EXTERN VALUE rb_eSignal;
+RUBY_EXTERN VALUE rb_eFatal;
+RUBY_EXTERN VALUE rb_eArgError;
+RUBY_EXTERN VALUE rb_eEOFError;
+RUBY_EXTERN VALUE rb_eIndexError;
+RUBY_EXTERN VALUE rb_eStopIteration;
+RUBY_EXTERN VALUE rb_eKeyError;
+RUBY_EXTERN VALUE rb_eRangeError;
+RUBY_EXTERN VALUE rb_eIOError;
+RUBY_EXTERN VALUE rb_eRuntimeError;
+RUBY_EXTERN VALUE rb_eSecurityError;
+RUBY_EXTERN VALUE rb_eSystemCallError;
+RUBY_EXTERN VALUE rb_eThreadError;
+RUBY_EXTERN VALUE rb_eTypeError;
+RUBY_EXTERN VALUE rb_eZeroDivError;
+RUBY_EXTERN VALUE rb_eNotImpError;
+RUBY_EXTERN VALUE rb_eNoMemError;
+RUBY_EXTERN VALUE rb_eNoMethodError;
+RUBY_EXTERN VALUE rb_eFloatDomainError;
+RUBY_EXTERN VALUE rb_eLocalJumpError;
+RUBY_EXTERN VALUE rb_eSysStackError;
+RUBY_EXTERN VALUE rb_eRegexpError;
+RUBY_EXTERN VALUE rb_eEncodingError;
+RUBY_EXTERN VALUE rb_eEncCompatError;
+
+RUBY_EXTERN VALUE rb_eScriptError;
+RUBY_EXTERN VALUE rb_eNameError;
+RUBY_EXTERN VALUE rb_eSyntaxError;
+RUBY_EXTERN VALUE rb_eLoadError;
+
+RUBY_EXTERN VALUE rb_stdin, rb_stdout, rb_stderr;
+#endif
static inline VALUE
rb_class_of(VALUE obj)
@@ -998,6 +1121,15 @@ rb_special_const_p(VALUE obj)
static char *dln_libs_to_be_linked[] = { EXTLIB, 0 };
#endif
+#if (defined(__APPLE__) || defined(__NeXT__)) && defined(__MACH__)
+/* to link startup code with ObjC support */
+#define RUBY_GLOBAL_SETUP static void objcdummyfunction(void) {objc_msgSend();}
+#else
+#define RUBY_GLOBAL_SETUP
+#endif
+
+void ruby_sysinit(int *, char ***);
+
#define RUBY_VM 1 /* YARV */
#define HAVE_NATIVETHREAD
int ruby_native_thread_p(void);
diff --git a/include/ruby/util.h b/include/ruby/util.h
index c7bb9636a3..a66ace9417 100644
--- a/include/ruby/util.h
+++ b/include/ruby/util.h
@@ -45,7 +45,7 @@ unsigned long ruby_scan_oct(const char *, int, int *);
#define scan_hex ruby_scan_hex
unsigned long ruby_scan_hex(const char *, int, int *);
-#if defined(MSDOS) || defined(__CYGWIN32__) || defined(_WIN32)
+#if defined(__CYGWIN32__) || defined(_WIN32)
void ruby_add_suffix(VALUE str, const char *suffix);
#endif
@@ -56,8 +56,8 @@ void ruby_setenv(const char *, const char *);
void ruby_unsetenv(const char *);
#undef setenv
#undef unsetenv
-#define setenv(name,val) ruby_setenv(name,val)
-#define unsetenv(name,val) ruby_unsetenv(name);
+#define setenv(name,val,replace) ruby_setenv(name,val)
+#define unsetenv(name) ruby_unsetenv(name)
char *ruby_strdup(const char *);
#undef strdup
diff --git a/include/ruby/mvm.h b/include/ruby/vm.h
index 7090262289..02f9a80e78 100644
--- a/include/ruby/mvm.h
+++ b/include/ruby/vm.h
@@ -1,6 +1,6 @@
/**********************************************************************
- ruby/mvm.h -
+ ruby/vm.h -
$Author$
created at: Sat May 31 15:17:36 2008
@@ -9,9 +9,8 @@
**********************************************************************/
-#ifndef RUBY_MVM_H
-#define RUBY_MVM_H 1
-
+#ifndef RUBY_VM_H
+#define RUBY_VM_H 1
#define HAVE_MVM 1
/* VM type declaration */
@@ -63,4 +62,4 @@ void ruby_init_stack(void *);
void *variable_in_this_stack_frame; \
ruby_init_stack(&variable_in_this_stack_frame);
-#endif /* RUBY_MVM_H */
+#endif /* RUBY_VM_H */
diff --git a/include/ruby/win32.h b/include/ruby/win32.h
index 19e5030d92..bd4d66493b 100644
--- a/include/ruby/win32.h
+++ b/include/ruby/win32.h
@@ -33,11 +33,6 @@ extern "C" {
#define NT 1 /* deprecated */
-#ifdef _WIN32_WCE
-#undef CharNext
-#define CharNext CharNextA
-#endif
-
//
// We're not using Microsoft's "extensions" to C for
// Structured Exception Handling (SEH) so we can nuke these
@@ -164,7 +159,7 @@ extern DWORD rb_w32_osid(void);
#undef execv
#define execv(path,argv) rb_w32_aspawn(P_OVERLAY,path,argv)
-#if !defined(__BORLANDC__) && !defined(_WIN32_WCE)
+#if !defined(__BORLANDC__)
#undef isatty
#define isatty(h) rb_w32_isatty(h)
#endif
@@ -265,7 +260,7 @@ extern int kill(int, int);
extern int fcntl(int, int, ...);
extern rb_pid_t rb_w32_getpid(void);
extern rb_pid_t rb_w32_getppid(void);
-#if !defined(__BORLANDC__) && !defined(_WIN32_WCE)
+#if !defined(__BORLANDC__)
extern int rb_w32_isatty(int);
#endif
extern int rb_w32_mkdir(const char *, int);
diff --git a/include/rubyio.h b/include/rubyio.h
deleted file mode 100644
index 59ecedca96..0000000000
--- a/include/rubyio.h
+++ /dev/null
@@ -1 +0,0 @@
-#include "ruby/io.h"
diff --git a/include/rubysig.h b/include/rubysig.h
deleted file mode 100644
index 9546127938..0000000000
--- a/include/rubysig.h
+++ /dev/null
@@ -1 +0,0 @@
-#include "ruby/signal.h"
diff --git a/inits.c b/inits.c
index 60bd0f1d5a..ad9885b087 100644
--- a/inits.c
+++ b/inits.c
@@ -15,14 +15,13 @@
#define INIT_FOR_VM 1
#include "inits.c"
#define CALL(n) {void Init_##n(void); Init_##n();}
-#define rb_call_inits() rb_call_inits(void)
#else
#define CALL(n) {void InitVM_##n(rb_vm_t *); InitVM_##n(vm);}
-#define rb_call_inits() rb_vm_call_inits(rb_vm_t *vm)
+#define rb_call_inits(void) rb_vm_call_inits(rb_vm_t *vm)
#endif
void
-rb_call_inits()
+rb_call_inits(void)
{
CALL(RandomSeed);
CALL(sym);
@@ -32,10 +31,10 @@ rb_call_inits()
CALL(Encoding);
CALL(Comparable);
CALL(Enumerable);
- CALL(Precision);
CALL(String);
CALL(Exception);
CALL(eval);
+ CALL(safe);
CALL(jump);
CALL(Numeric);
CALL(Bignum);
diff --git a/insns.def b/insns.def
index c91147ed16..0ea72c13db 100644
--- a/insns.def
+++ b/insns.def
@@ -761,7 +761,7 @@ defined
klass = vm_get_cbase(GET_ISEQ(), GET_LFP(), GET_DFP());
break;
case DEFINED_GVAR:
- if (rb_gvar_defined((struct global_entry *)(obj & ~1))) {
+ if (rb_gvar_defined((struct rb_global_entry *)(obj & ~1))) {
expr_type = "global-variable";
}
break;
diff --git a/instruby.rb b/instruby.rb
index 85fea0ec0f..3c83dc3dc1 100755
--- a/instruby.rb
+++ b/instruby.rb
@@ -2,6 +2,7 @@
load "./rbconfig.rb"
include RbConfig
+$".unshift File.expand_path("./rbconfig.rb")
srcdir = File.dirname(__FILE__)
$:.unshift File.expand_path("lib", srcdir)
@@ -10,6 +11,7 @@ require 'shellwords'
require 'optparse'
require 'optparse/shellwords'
require 'tempfile'
+require 'rdoc/ri/paths'
STDOUT.sync = true
File.umask(0)
@@ -280,7 +282,7 @@ install?(:rdoc) do
if $rdocdir
puts "installing rdoc"
- ridatadir = File.join(CONFIG['datadir'], 'ri/$(MAJOR).$(MINOR).$(TEENY)/system')
+ ridatadir = RDoc::RI::Paths::SYSDIR
Config.expand(ridatadir)
makedirs [ridatadir]
install_recursive($rdocdir, ridatadir, :mode => $data_mode)
@@ -345,14 +347,9 @@ end
install?(:local, :comm, :lib) do
puts "installing library scripts"
- Dir.chdir srcdir
makedirs [rubylibdir]
-
- for f in Dir["lib/**/*{.rb,help-message}"]
- dir = File.dirname(f).sub!(/\Alib/, rubylibdir) || rubylibdir
- makedirs dir
- install f, dir, :mode => $data_mode
- end
+ noinst = %w[README* *.txt *.rdoc]
+ install_recursive(File.join(srcdir, "lib"), rubylibdir, :no_install => noinst, :mode => $data_mode)
end
install?(:local, :arch, :lib) do
@@ -371,19 +368,25 @@ end
install?(:local, :comm, :man) do
puts "installing manpages"
- Dir.chdir(srcdir)
+ has_goruby = File.exist?(goruby_install_name+exeext)
+ Dir.chdir("#{srcdir}/man")
for mdoc in Dir["*.[1-9]"]
next unless File.file?(mdoc) and open(mdoc){|fh| fh.read(1) == '.'}
+ if mdoc == "goruby.1"
+ next unless has_goruby
+ end
destdir = mandir + mdoc[/(\d+)$/]
- destfile = File.join(destdir, mdoc.sub(/ruby/, ruby_install_name))
+ section = $1
+ destname = ruby_install_name.sub(/ruby/, File.basename(mdoc, ".#{section}"))
+ destfile = File.join(destdir, "#{destname}.#{section}")
makedirs destdir
if $mantype == "doc"
install mdoc, destfile, :mode => $data_mode
else
- require 'mdoc2man.rb'
+ require "../tool/mdoc2man.rb"
w = Tempfile.open(mdoc)
diff --git a/io.c b/io.c
index ba0749c106..db20692647 100644
--- a/io.c
+++ b/io.c
@@ -13,7 +13,6 @@
#include "ruby/ruby.h"
#include "ruby/io.h"
-#include "vm_core.h"
#include "eval_intern.h"
#include <ctype.h>
#include <errno.h>
@@ -31,11 +30,11 @@
# include <sys/socket.h>
#endif
-#if defined(MSDOS) || defined(__BOW__) || defined(__CYGWIN__) || defined(_WIN32) || defined(__human68k__) || defined(__EMX__) || defined(__BEOS__)
+#if defined(__BOW__) || defined(__CYGWIN__) || defined(_WIN32) || defined(__EMX__) || defined(__BEOS__)
# define NO_SAFE_RENAME
#endif
-#if defined(MSDOS) || defined(__CYGWIN__) || defined(_WIN32)
+#if defined(__CYGWIN__) || defined(_WIN32)
# define NO_LONG_FNAME
#endif
@@ -48,7 +47,7 @@
#endif
#include <sys/types.h>
-#if defined(HAVE_SYS_IOCTL_H) && !defined(DJGPP) && !defined(_WIN32) && !defined(__human68k__)
+#if defined(HAVE_SYS_IOCTL_H) && !defined(_WIN32)
#include <sys/ioctl.h>
#endif
#if defined(HAVE_FCNTL_H) || defined(_WIN32)
@@ -162,16 +161,10 @@ static rb_thread_lock_t max_file_descriptor_lock;
# define STDIO_READ_DATA_PENDING(fp) ((fp)->FILE_READPTR < (fp)->FILE_READEND)
#elif defined(__BEOS__)
# define STDIO_READ_DATA_PENDING(fp) (fp->_state._eof == 0)
-#elif defined(__VMS)
-# define STDIO_READ_DATA_PENDING(fp) (((unsigned int)(*(fp))->_cnt) > 0)
#else
# define STDIO_READ_DATA_PENDING(fp) (!feof(fp))
#endif
-#if defined(__VMS)
-#define open(file_spec, flags, mode) open(file_spec, flags, mode, "rfm=stmlf")
-#endif
-
#define GetWriteIO(io) rb_io_get_write_io(io)
#define READ_DATA_PENDING(fptr) ((fptr)->rbuf_len)
@@ -413,12 +406,6 @@ rb_io_check_writable(rb_io_t *fptr)
}
int
-rb_read_pending(FILE *fp)
-{
- return STDIO_READ_DATA_PENDING(fp);
-}
-
-int
rb_io_read_pending(rb_io_t *fptr)
{
return READ_DATA_PENDING(fptr);
@@ -539,11 +526,29 @@ rb_write_internal(int fd, void *buf, size_t count)
return rb_thread_blocking_region(internal_write_func, &iis, RUBY_UBF_IO, 0);
}
+static long
+io_writable_length(rb_io_t *fptr, long l)
+{
+ if (PIPE_BUF < l &&
+ !rb_thread_alone() &&
+ wsplit_p(fptr)) {
+ l = PIPE_BUF;
+ }
+ return l;
+}
+
+static VALUE
+io_flush_buffer(VALUE arg)
+{
+ rb_io_t *fptr = (rb_io_t *)arg;
+ long l = io_writable_length(fptr, fptr->wbuf_len);
+ return rb_write_internal(fptr->fd, fptr->wbuf+fptr->wbuf_off, l);
+}
+
static int
io_fflush(rb_io_t *fptr)
{
- int r, l;
- int wbuf_off, wbuf_len;
+ long r;
rb_io_check_closed(fptr);
if (fptr->wbuf_len == 0)
@@ -554,15 +559,7 @@ io_fflush(rb_io_t *fptr)
retry:
if (fptr->wbuf_len == 0)
return 0;
- wbuf_off = fptr->wbuf_off;
- wbuf_len = fptr->wbuf_len;
- l = wbuf_len;
- if (PIPE_BUF < l &&
- !rb_thread_alone() &&
- wsplit_p(fptr)) {
- l = PIPE_BUF;
- }
- r = rb_write_internal(fptr->fd, fptr->wbuf+wbuf_off, l);
+ r = rb_mutex_synchronize(fptr->write_lock, io_flush_buffer, (VALUE)fptr);
/* xxx: Other threads may modify wbuf.
* A lock is required, definitely. */
rb_io_check_closed(fptr);
@@ -675,16 +672,16 @@ rb_io_wait_writable(int f)
#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
/* Windows */
-# define NEED_NEWLINE_DECODER(fptr) (!(fptr->mode & FMODE_BINMODE))
-# define NEED_NEWLINE_ENCODER(fptr) (!(fptr->mode & FMODE_BINMODE))
-# define TEXTMODE_NEWLINE_ENCODER ECONV_CRLF_NEWLINE_ENCODER
+# define NEED_NEWLINE_DECORATOR_ON_READ(fptr) (!(fptr->mode & FMODE_BINMODE))
+# define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) (!(fptr->mode & FMODE_BINMODE))
+# define TEXTMODE_NEWLINE_DECORATOR_ON_WRITE ECONV_CRLF_NEWLINE_DECORATOR
#else
/* Unix */
-# define NEED_NEWLINE_DECODER(fptr) (fptr->mode & FMODE_TEXTMODE)
-# define NEED_NEWLINE_ENCODER(fptr) 0
+# define NEED_NEWLINE_DECORATOR_ON_READ(fptr) (fptr->mode & FMODE_TEXTMODE)
+# define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) 0
#endif
-#define NEED_READCONV(fptr) (fptr->encs.enc2 != NULL || NEED_NEWLINE_DECODER(fptr))
-#define NEED_WRITECONV(fptr) (fptr->encs.enc != NULL || NEED_NEWLINE_ENCODER(fptr) || (fptr->encs.ecflags & (ECONV_DECODER_MASK|ECONV_ENCODER_MASK|ECONV_STATEFUL_ENCODER_MASK)))
+#define NEED_READCONV(fptr) (fptr->encs.enc2 != NULL || NEED_NEWLINE_DECORATOR_ON_READ(fptr))
+#define NEED_WRITECONV(fptr) ((fptr->encs.enc != NULL && fptr->encs.enc != rb_ascii8bit_encoding()) || NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) || (fptr->encs.ecflags & (ECONV_DECORATOR_MASK|ECONV_STATEFUL_DECORATOR_MASK)))
static void
make_writeconv(rb_io_t *fptr)
@@ -699,51 +696,43 @@ make_writeconv(rb_io_t *fptr)
ecflags = fptr->encs.ecflags;
ecopts = fptr->encs.ecopts;
-#ifdef TEXTMODE_NEWLINE_ENCODER
- if (NEED_NEWLINE_ENCODER(fptr))
- ecflags |= TEXTMODE_NEWLINE_ENCODER;
+#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
+ if (NEED_NEWLINE_DECORATOR_ON_WRITE(fptr))
+ ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
#endif
- if (!fptr->encs.enc) {
+ if (!fptr->encs.enc || (fptr->encs.enc == rb_ascii8bit_encoding() && !fptr->encs.enc2)) {
/* no encoding conversion */
fptr->writeconv_pre_ecflags = 0;
fptr->writeconv_pre_ecopts = Qnil;
fptr->writeconv = rb_econv_open_opts("", "", ecflags, ecopts);
if (!fptr->writeconv)
rb_exc_raise(rb_econv_open_exc("", "", ecflags));
- fptr->writeconv_stateless = Qnil;
+ fptr->writeconv_asciicompat = Qnil;
}
else {
enc = fptr->encs.enc2 ? fptr->encs.enc2 : fptr->encs.enc;
- senc = rb_econv_asciicompat_encoding(enc->name);
- if (!senc && !(fptr->encs.ecflags & ECONV_STATEFUL_ENCODER_MASK)) {
+ senc = rb_econv_asciicompat_encoding(rb_enc_name(enc));
+ if (!senc && !(fptr->encs.ecflags & ECONV_STATEFUL_DECORATOR_MASK)) {
/* single conversion */
fptr->writeconv_pre_ecflags = ecflags;
fptr->writeconv_pre_ecopts = ecopts;
fptr->writeconv = NULL;
- fptr->writeconv_stateless = Qnil;
+ fptr->writeconv_asciicompat = Qnil;
}
else {
/* double conversion */
- fptr->writeconv_pre_ecflags = ecflags & ~ECONV_STATEFUL_ENCODER_MASK;
+ fptr->writeconv_pre_ecflags = ecflags & ~ECONV_STATEFUL_DECORATOR_MASK;
fptr->writeconv_pre_ecopts = ecopts;
if (senc) {
- denc = enc->name;
- fptr->writeconv_stateless = rb_str_new2(senc);
- }
- else if ((fptr->encs.ecflags & ECONV_STATEFUL_ENCODER_MASK) && !rb_enc_asciicompat(enc)) {
- /* xxx: stateful encoder works for ASCII compatible encoding.
- * So we need to choose an encoding which is ASCII compatible and superset of enc.
- * For encodings which is superset of UTF-8, UTF-8 is not appropriate choice. */
- senc = "UTF-8";
- denc = enc->name;
- fptr->writeconv_stateless = rb_str_new2("UTF-8");
+ denc = rb_enc_name(enc);
+ fptr->writeconv_asciicompat = rb_str_new2(senc);
}
else {
senc = denc = "";
- fptr->writeconv_stateless = rb_str_new2(enc->name);
+ fptr->writeconv_asciicompat = rb_str_new2(rb_enc_name(enc));
}
- ecflags = fptr->encs.ecflags & (ECONV_ERROR_HANDLER_MASK|ECONV_STATEFUL_ENCODER_MASK);
+ ecflags = fptr->encs.ecflags & (ECONV_ERROR_HANDLER_MASK|ECONV_STATEFUL_DECORATOR_MASK);
ecopts = fptr->encs.ecopts;
fptr->writeconv = rb_econv_open_opts(senc, denc, ecflags, ecopts);
if (!fptr->writeconv)
@@ -754,46 +743,39 @@ make_writeconv(rb_io_t *fptr)
}
/* writing functions */
-static long
-io_fwrite(VALUE str, rb_io_t *fptr)
-{
- long len, n, r, l, offset = 0;
-
- if (NEED_WRITECONV(fptr)) {
- VALUE common_encoding = Qnil;
- make_writeconv(fptr);
-
- if (fptr->writeconv) {
- if (!NIL_P(fptr->writeconv_stateless))
- common_encoding = fptr->writeconv_stateless;
- }
- else {
- if (fptr->encs.enc2)
- common_encoding = rb_enc_from_encoding(fptr->encs.enc2);
- else
- common_encoding = rb_enc_from_encoding(fptr->encs.enc);
- }
+struct binwrite_arg {
+ rb_io_t *fptr;
+ VALUE str;
+ long offset;
+ long length;
+};
- if (!NIL_P(common_encoding)) {
- str = rb_str_transcode(str, common_encoding,
- fptr->writeconv_pre_ecflags, fptr->writeconv_pre_ecopts);
- }
+static VALUE
+io_binwrite_string(VALUE arg)
+{
+ struct binwrite_arg *p = (struct binwrite_arg *)arg;
+ long l = io_writable_length(p->fptr, p->length);
+ return rb_write_internal(p->fptr->fd, RSTRING_PTR(p->str)+p->offset, l);
+}
- if (fptr->writeconv) {
- str = rb_econv_str_convert(fptr->writeconv, str, ECONV_PARTIAL_INPUT);
- }
- }
+static long
+io_binwrite(VALUE str, rb_io_t *fptr, int nosync)
+{
+ long len, n, r, offset = 0;
len = RSTRING_LEN(str);
if ((n = len) <= 0) return n;
- if (fptr->wbuf == NULL && !(fptr->mode & FMODE_SYNC)) {
+ if (fptr->wbuf == NULL && !(!nosync && (fptr->mode & FMODE_SYNC))) {
fptr->wbuf_off = 0;
fptr->wbuf_len = 0;
fptr->wbuf_capa = 8192;
fptr->wbuf = ALLOC_N(char, fptr->wbuf_capa);
+ fptr->write_lock = rb_mutex_new();
}
- if ((fptr->mode & (FMODE_SYNC|FMODE_TTY)) ||
+ if ((!nosync && (fptr->mode & (FMODE_SYNC|FMODE_TTY))) ||
(fptr->wbuf && fptr->wbuf_capa <= fptr->wbuf_len + len)) {
+ struct binwrite_arg arg;
+
/* xxx: use writev to avoid double write if available */
if (fptr->wbuf_len && fptr->wbuf_len+len <= fptr->wbuf_capa) {
if (fptr->wbuf_capa < fptr->wbuf_off+fptr->wbuf_len+len) {
@@ -813,14 +795,18 @@ io_fwrite(VALUE str, rb_io_t *fptr)
if (fptr->stdio_file != stderr && !rb_thread_fd_writable(fptr->fd)) {
rb_io_check_closed(fptr);
}
+ arg.fptr = fptr;
+ arg.str = str;
+ arg.offset = offset;
retry:
- l = n;
- if (PIPE_BUF < l &&
- !rb_thread_alone() &&
- wsplit_p(fptr)) {
- l = PIPE_BUF;
- }
- r = rb_write_internal(fptr->fd, RSTRING_PTR(str)+offset, l);
+ arg.length = n;
+ if (fptr->write_lock) {
+ r = rb_mutex_synchronize(fptr->write_lock, io_binwrite_string, (VALUE)&arg);
+ }
+ else {
+ long l = io_writable_length(fptr, n);
+ r = rb_write_internal(fptr->fd, RSTRING_PTR(str)+offset, l);
+ }
/* xxx: other threads may modify given string. */
if (r == n) return len;
if (0 <= r) {
@@ -846,38 +832,50 @@ io_fwrite(VALUE str, rb_io_t *fptr)
return len;
}
-long
-rb_io_fwrite(const char *ptr, long len, FILE *f)
+static VALUE
+do_writeconv(VALUE str, rb_io_t *fptr)
{
- rb_io_t of;
+ if (NEED_WRITECONV(fptr)) {
+ VALUE common_encoding = Qnil;
+
+ make_writeconv(fptr);
- of.fd = fileno(f);
- of.stdio_file = f;
- of.mode = FMODE_WRITABLE;
- of.pathv = Qnil;
- return io_fwrite(rb_str_new(ptr, len), &of);
+ if (fptr->writeconv) {
+ if (!NIL_P(fptr->writeconv_asciicompat))
+ common_encoding = fptr->writeconv_asciicompat;
+ else if (!rb_enc_asciicompat(rb_enc_get(str))) {
+ rb_raise(rb_eArgError, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
+ rb_enc_name(rb_enc_get(str)));
+ }
+ }
+ else {
+ if (fptr->encs.enc2)
+ common_encoding = rb_enc_from_encoding(fptr->encs.enc2);
+ else if (fptr->encs.enc != rb_ascii8bit_encoding())
+ common_encoding = rb_enc_from_encoding(fptr->encs.enc);
+ }
+
+ if (!NIL_P(common_encoding)) {
+ str = rb_str_encode(str, common_encoding,
+ fptr->writeconv_pre_ecflags, fptr->writeconv_pre_ecopts);
+ }
+
+ if (fptr->writeconv) {
+ str = rb_econv_str_convert(fptr->writeconv, str, ECONV_PARTIAL_INPUT);
+ }
+ }
+ return str;
}
-/*
- * call-seq:
- * ios.write(string) => integer
- *
- * Writes the given string to <em>ios</em>. The stream must be opened
- * for writing. If the argument is not a string, it will be converted
- * to a string using <code>to_s</code>. Returns the number of bytes
- * written.
- *
- * count = $stdout.write( "This is a test\n" )
- * puts "That was #{count} bytes of data"
- *
- * <em>produces:</em>
- *
- * This is a test
- * That was 15 bytes of data
- */
+static long
+io_fwrite(VALUE str, rb_io_t *fptr, int nosync)
+{
+ str = do_writeconv(str, fptr);
+ return io_binwrite(str, fptr, nosync);
+}
static VALUE
-io_write(VALUE io, VALUE str)
+io_write(VALUE io, VALUE str, int nosync)
{
rb_io_t *fptr;
long n;
@@ -897,12 +895,36 @@ io_write(VALUE io, VALUE str)
GetOpenFile(io, fptr);
rb_io_check_writable(fptr);
- n = io_fwrite(str, fptr);
+ n = io_fwrite(str, fptr, nosync);
if (n == -1L) rb_sys_fail_path(fptr->pathv);
return LONG2FIX(n);
}
+/*
+ * call-seq:
+ * ios.write(string) => integer
+ *
+ * Writes the given string to <em>ios</em>. The stream must be opened
+ * for writing. If the argument is not a string, it will be converted
+ * to a string using <code>to_s</code>. Returns the number of bytes
+ * written.
+ *
+ * count = $stdout.write( "This is a test\n" )
+ * puts "That was #{count} bytes of data"
+ *
+ * <em>produces:</em>
+ *
+ * This is a test
+ * That was 15 bytes of data
+ */
+
+static VALUE
+io_write_m(VALUE io, VALUE str)
+{
+ return io_write(io, str, 0);
+}
+
VALUE
rb_io_write(VALUE io, VALUE str)
{
@@ -1068,6 +1090,8 @@ rb_io_set_pos(VALUE io, VALUE offset)
return OFFT2NUM(pos);
}
+static void clear_readconv(rb_io_t *fptr);
+
/*
* call-seq:
* ios.rewind => 0
@@ -1094,6 +1118,9 @@ rb_io_rewind(VALUE io)
ARGF.gets_lineno -= fptr->lineno;
}
fptr->lineno = 0;
+ if (fptr->readconv) {
+ clear_readconv(fptr);
+ }
return INT2FIX(0);
}
@@ -1403,22 +1430,6 @@ io_fread(VALUE str, long offset, rb_io_t *fptr)
return len - n;
}
-long
-rb_io_fread(char *ptr, long len, FILE *f)
-{
- rb_io_t of;
- VALUE str;
- long n;
-
- of.fd = fileno(f);
- of.stdio_file = f;
- of.mode = FMODE_READABLE;
- str = rb_str_new(ptr, len);
- n = io_fread(str, 0, &of);
- MEMCPY(ptr, RSTRING_PTR(str), char, n);
- return n;
-}
-
#define SMALLBUF 100
static long
@@ -1458,7 +1469,7 @@ io_enc_str(VALUE str, rb_io_t *fptr)
}
static void
-make_readconv(rb_io_t *fptr)
+make_readconv(rb_io_t *fptr, int size)
{
if (!fptr->readconv) {
int ecflags;
@@ -1466,11 +1477,11 @@ make_readconv(rb_io_t *fptr)
const char *sname, *dname;
ecflags = fptr->encs.ecflags;
ecopts = fptr->encs.ecopts;
- if (NEED_NEWLINE_DECODER(fptr))
- ecflags |= ECONV_UNIVERSAL_NEWLINE_DECODER;
+ if (NEED_NEWLINE_DECORATOR_ON_READ(fptr))
+ ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
if (fptr->encs.enc2) {
- sname = fptr->encs.enc2->name;
- dname = fptr->encs.enc->name;
+ sname = rb_enc_name(fptr->encs.enc2);
+ dname = rb_enc_name(fptr->encs.enc);
}
else {
sname = dname = "";
@@ -1480,7 +1491,7 @@ make_readconv(rb_io_t *fptr)
rb_exc_raise(rb_econv_open_exc(sname, dname, ecflags));
fptr->cbuf_off = 0;
fptr->cbuf_len = 0;
- fptr->cbuf_capa = 1024;
+ fptr->cbuf_capa = size < 1024 ? 1024 : size;
fptr->cbuf = ALLOC_N(char, fptr->cbuf_capa);
}
}
@@ -1510,7 +1521,7 @@ more_char(rb_io_t *fptr)
se = sp + fptr->rbuf_len;
ds = dp = (unsigned char *)fptr->cbuf + fptr->cbuf_off + fptr->cbuf_len;
de = (unsigned char *)fptr->cbuf + fptr->cbuf_capa;
- res = rb_econv_convert(fptr->readconv, &sp, se, &dp, de, ECONV_PARTIAL_INPUT|ECONV_OUTPUT_FOLLOWED_BY_INPUT);
+ res = rb_econv_convert(fptr->readconv, &sp, se, &dp, de, ECONV_PARTIAL_INPUT|ECONV_AFTER_OUTPUT);
fptr->rbuf_off += sp - ss;
fptr->rbuf_len -= sp - ss;
fptr->cbuf_len += dp - ds;
@@ -1527,8 +1538,10 @@ more_char(rb_io_t *fptr)
if (cbuf_len0 != fptr->cbuf_len)
return 0;
- if (res == econv_finished)
+ if (res == econv_finished) {
+ clear_readconv(fptr);
return -1;
+ }
if (res == econv_source_buffer_empty) {
if (fptr->rbuf_len == 0) {
@@ -1584,8 +1597,9 @@ read_all(rb_io_t *fptr, long siz, VALUE str)
int cr;
if (NEED_READCONV(fptr)) {
- VALUE str = rb_str_new(NULL, 0);
- make_readconv(fptr);
+ if (NIL_P(str)) str = rb_str_new(NULL, 0);
+ else rb_str_set_len(str, 0);
+ make_readconv(fptr, 0);
while (1) {
if (fptr->cbuf_len) {
io_shift_cbuf(fptr, fptr->cbuf_len, &str);
@@ -1755,10 +1769,10 @@ io_getpartial(int argc, VALUE *argv, VALUE io, int nonblock)
* Note that readpartial behaves similar to sysread.
* The differences are:
* * If the buffer is not empty, read from the buffer instead of "sysread for buffered IO (IOError)".
- * * It doesn't cause Errno::EAGAIN and Errno::EINTR. When readpartial meets EAGAIN and EINTR by read system call, readpartial retry the system call.
+ * * It doesn't cause Errno::EWOULDBLOCK and Errno::EINTR. When readpartial meets EWOULDBLOCK and EINTR by read system call, readpartial retry the system call.
*
* The later means that readpartial is nonblocking-flag insensitive.
- * It blocks on the situation IO#sysread causes Errno::EAGAIN as if the fd is blocking mode.
+ * It blocks on the situation IO#sysread causes Errno::EWOULDBLOCK as if the fd is blocking mode.
*
*/
@@ -1780,22 +1794,36 @@ io_readpartial(int argc, VALUE *argv, VALUE io)
* ios.read_nonblock(maxlen, outbuf) => outbuf
*
* Reads at most <i>maxlen</i> bytes from <em>ios</em> using
- * read(2) system call after O_NONBLOCK is set for
+ * the read(2) system call after O_NONBLOCK is set for
* the underlying file descriptor.
*
* If the optional <i>outbuf</i> argument is present,
* it must reference a String, which will receive the data.
*
- * read_nonblock just calls read(2).
- * It causes all errors read(2) causes: EAGAIN, EINTR, etc.
+ * read_nonblock just calls the read(2) system call.
+ * It causes all errors the read(2) system call causes: Errno::EWOULDBLOCK, Errno::EINTR, etc.
* The caller should care such errors.
*
* read_nonblock causes EOFError on EOF.
*
* If the read buffer is not empty,
* read_nonblock reads from the buffer like readpartial.
- * In this case, read(2) is not called.
- *
+ * In this case, the read(2) system call is not called.
+ *
+ * When read_nonblock raises EWOULDBLOCK,
+ * read_nonblock should not be called
+ * until io is readable for avoiding busy loop.
+ * This can be done as follows.
+ *
+ * begin
+ * result = io.read_nonblock(maxlen)
+ * rescue Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::EINTR
+ * IO.select([io])
+ * retry
+ * end
+ *
+ * Note that this is identical to readpartial
+ * except the non-blocking flag is set.
*/
static VALUE
@@ -1815,18 +1843,33 @@ io_read_nonblock(int argc, VALUE *argv, VALUE io)
* ios.write_nonblock(string) => integer
*
* Writes the given string to <em>ios</em> using
- * write(2) system call after O_NONBLOCK is set for
+ * the write(2) system call after O_NONBLOCK is set for
* the underlying file descriptor.
*
* It returns the number of bytes written.
*
- * write_nonblock just calls write(2).
- * It causes all errors write(2) causes: EAGAIN, EINTR, etc.
+ * write_nonblock just calls the write(2) system call.
+ * It causes all errors the write(2) system call causes: Errno::EWOULDBLOCK, Errno::EINTR, etc.
* The result may also be smaller than string.length (partial write).
* The caller should care such errors and partial write.
*
* If the write buffer is not empty, it is flushed at first.
*
+ * When write_nonblock raises EWOULDBLOCK,
+ * write_nonblock should not be called
+ * until io is writable for avoiding busy loop.
+ * This can be done as follows.
+ *
+ * begin
+ * result = io.write_nonblock(string)
+ * rescue Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::EINTR
+ * IO.select(nil, [io])
+ * retry
+ * end
+ *
+ * Note that this doesn't guarantee to write all data in string.
+ * The length written is reported as result and it should be checked later.
+ *
*/
static VALUE
@@ -1938,7 +1981,7 @@ appendline(rb_io_t *fptr, int delim, VALUE *strp, long *lp)
long limit = *lp;
if (NEED_READCONV(fptr)) {
- make_readconv(fptr);
+ make_readconv(fptr, 0);
while (1) {
const char *p, *e;
int searchlen;
@@ -2174,18 +2217,17 @@ rb_io_getline_1(VALUE rs, long limit, VALUE io)
}
newline = (unsigned char)rsptr[rslen - 1];
- if (fptr->encs.enc2)
- enc = fptr->encs.enc;
- else
- enc = io_input_encoding(fptr);
+ /* MS - Optimisation */
+ enc = io_read_encoding(fptr);
while ((c = appendline(fptr, newline, &str, &limit)) != EOF) {
- const char *s, *p, *pp;
+ const char *s, *p, *pp, *e;
if (c == newline) {
if (RSTRING_LEN(str) < rslen) continue;
s = RSTRING_PTR(str);
- p = s + RSTRING_LEN(str) - rslen;
- pp = rb_enc_left_char_head(s, p, enc);
+ e = s + RSTRING_LEN(str);
+ p = e - rslen;
+ pp = rb_enc_left_char_head(s, p, e, enc);
if (pp != p) continue;
if (!rspara) rscheck(rsptr, rslen, rs);
if (memcmp(p, rsptr, rslen) == 0) break;
@@ -2193,7 +2235,7 @@ rb_io_getline_1(VALUE rs, long limit, VALUE io)
if (limit == 0) {
s = RSTRING_PTR(str);
p = s + RSTRING_LEN(str);
- pp = rb_enc_left_char_head(s, p-1, enc);
+ pp = rb_enc_left_char_head(s, p-1, p, enc);
if (extra_limit &&
MBCLEN_NEEDMORE_P(rb_enc_precise_mbclen(pp, p, enc))) {
/* relax the limit while incomplete character.
@@ -2258,7 +2300,7 @@ rb_io_gets(VALUE io)
* to <code>$_</code>. Returns <code>nil</code> if called at end of
* file. If the first argument is an integer, or optional second
* argument is given, the returning string would not be longer than the
- * given value.
+ * given value in bytes.
*
* File.new("testfile").gets #=> "This is line one\n"
* $_ #=> "This is line one\n"
@@ -2364,8 +2406,8 @@ rb_io_readline(int argc, VALUE *argv, VALUE io)
* <i>sep</i> is <code>nil</code>, the rest of the stream is returned
* as a single record. If the first argument is an integer, or
* optional second argument is given, the returning string would not be
- * longer than the given value. The stream must be opened for reading
- * or an <code>IOError</code> will be raised.
+ * longer than the given value in bytes. The stream must be opened for
+ * reading or an <code>IOError</code> will be raised.
*
* f = File.new("testfile")
* f.readlines[0] #=> "This is line one\n"
@@ -2474,7 +2516,7 @@ io_getc(rb_io_t *fptr, rb_encoding *enc)
if (NEED_READCONV(fptr)) {
VALUE str = Qnil;
- make_readconv(fptr);
+ make_readconv(fptr, 0);
while (1) {
if (fptr->cbuf_len) {
@@ -2674,16 +2716,6 @@ rb_io_getc(VALUE io)
READ_CHECK(fptr);
return io_getc(fptr, enc);
}
-int
-rb_getc(FILE *f)
-{
- int c;
-
- rb_read_check(f);
- c = getc(f);
-
- return c;
-}
/*
* call-seq:
@@ -2749,7 +2781,7 @@ rb_io_getbyte(VALUE io)
* call-seq:
* ios.readbyte => fixnum
*
- * Reads a character as with <code>IO#getc</code>, but raises an
+ * Reads a byte as with <code>IO#getbyte</code>, but raises an
* <code>EOFError</code> on end of file.
*/
@@ -2836,8 +2868,8 @@ rb_io_ungetc(VALUE io, VALUE c)
SafeStringValue(c);
}
if (NEED_READCONV(fptr)) {
- make_readconv(fptr);
len = RSTRING_LEN(c);
+ make_readconv(fptr, len);
if (fptr->cbuf_capa - fptr->cbuf_len < len)
rb_raise(rb_eIOError, "ungetc failed");
if (fptr->cbuf_off < len) {
@@ -3043,12 +3075,33 @@ finish_writeconv(rb_io_t *fptr, int noraise)
}
+struct finish_writeconv_arg {
+ rb_io_t *fptr;
+ int noraise;
+};
+
+static VALUE
+finish_writeconv_sync(VALUE arg)
+{
+ struct finish_writeconv_arg *p = (struct finish_writeconv_arg *)arg;
+ finish_writeconv(p->fptr, p->noraise);
+ return Qnil;
+}
+
static void
fptr_finalize(rb_io_t *fptr, int noraise)
{
int ebadf = 0;
if (fptr->writeconv) {
- finish_writeconv(fptr, noraise);
+ if (fptr->write_lock) {
+ struct finish_writeconv_arg arg;
+ arg.fptr = fptr;
+ arg.noraise = noraise;
+ rb_mutex_synchronize(fptr->write_lock, finish_writeconv_sync, (VALUE)&arg);
+ }
+ else {
+ finish_writeconv(fptr, noraise);
+ }
}
if (fptr->wbuf_len) {
io_fflush(fptr);
@@ -3532,7 +3585,33 @@ rb_io_binmode(VALUE io)
rb_econv_binmode(fptr->writeconv);
fptr->mode |= FMODE_BINMODE;
fptr->mode &= ~FMODE_TEXTMODE;
- fptr->writeconv_pre_ecflags &= ~(ECONV_UNIVERSAL_NEWLINE_DECODER|ECONV_CRLF_NEWLINE_ENCODER|ECONV_CR_NEWLINE_ENCODER);
+ fptr->writeconv_pre_ecflags &= ~(ECONV_UNIVERSAL_NEWLINE_DECORATOR|ECONV_CRLF_NEWLINE_DECORATOR|ECONV_CR_NEWLINE_DECORATOR);
+ return io;
+}
+
+VALUE
+rb_io_ascii8bit_binmode(VALUE io)
+{
+ rb_io_t *fptr;
+
+ GetOpenFile(io, fptr);
+ if (fptr->readconv) {
+ rb_econv_close(fptr->readconv);
+ fptr->readconv = NULL;
+ }
+ if (fptr->writeconv) {
+ rb_econv_close(fptr->writeconv);
+ fptr->writeconv = NULL;
+ }
+ fptr->mode |= FMODE_BINMODE;
+ fptr->mode &= ~FMODE_TEXTMODE;
+
+ fptr->encs.enc = rb_ascii8bit_encoding();
+ fptr->encs.enc2 = NULL;
+ fptr->encs.ecflags = 0;
+ fptr->encs.ecopts = Qnil;
+ clear_codeconv(fptr);
+
return io;
}
@@ -3540,9 +3619,13 @@ rb_io_binmode(VALUE io)
* call-seq:
* ios.binmode => ios
*
- * Puts <em>ios</em> into binary mode. This is useful only in
- * MS-DOS/Windows environments. Once a stream is in binary mode, it
- * cannot be reset to nonbinary mode.
+ * Puts <em>ios</em> into binary mode.
+ * Once a stream is in binary mode, it cannot be reset to nonbinary mode.
+ *
+ * - newline conversion disabled
+ * - encoding conversion disabled
+ * - content is treated as ASCII-8BIT
+ *
*/
static VALUE
@@ -3550,11 +3633,11 @@ rb_io_binmode_m(VALUE io)
{
VALUE write_io;
- rb_io_binmode(io);
+ rb_io_ascii8bit_binmode(io);
write_io = GetWriteIO(io);
if (write_io != io)
- rb_io_binmode(write_io);
+ rb_io_ascii8bit_binmode(write_io);
return io;
}
@@ -3746,52 +3829,87 @@ rb_io_oflags_modestr(int oflags)
return NULL; /* not reached */
}
+/*
+ * Convert external/internal encodings to enc/enc2
+ * NULL => use default encoding
+ * Qnil => no encoding specified (internal only)
+ */
+static void
+rb_io_ext_int_to_encs(rb_encoding *ext, rb_encoding *intern, rb_encoding **enc, rb_encoding **enc2)
+{
+ int default_ext = 0;
+
+ if (ext == NULL) {
+ ext = rb_default_external_encoding();
+ default_ext = 1;
+ }
+ if (intern == NULL && ext != rb_ascii8bit_encoding())
+ /* If external is ASCII-8BIT, no default transcoding */
+ intern = rb_default_internal_encoding();
+ if (intern == NULL || intern == (rb_encoding *)Qnil || intern == ext) {
+ /* No internal encoding => use external + no transcoding */
+ *enc = default_ext ? NULL : ext;
+ *enc2 = NULL;
+ }
+ else {
+ *enc = intern;
+ *enc2 = ext;
+ }
+}
+
static void
parse_mode_enc(const char *estr, rb_encoding **enc_p, rb_encoding **enc2_p)
{
- const char *p0, *p1;
- char *enc2name;
+ const char *p;
+ char encname[ENCODING_MAXNAMELEN+1];
int idx, idx2;
+ rb_encoding *ext_enc, *int_enc;
- /* parse estr as "enc" or "enc2:enc" */
+ /* parse estr as "enc" or "enc2:enc" or "enc:-" */
- *enc_p = 0;
- *enc2_p = 0;
-
- p0 = strrchr(estr, ':');
- if (!p0) p1 = estr;
- else p1 = p0 + 1;
- idx = rb_enc_find_index(p1);
- if (idx >= 0) {
- *enc_p = rb_enc_from_index(idx);
+ p = strrchr(estr, ':');
+ if (p) {
+ int len = (p++) - estr;
+ if (len == 0 || len > ENCODING_MAXNAMELEN)
+ idx = -1;
+ else {
+ memcpy(encname, estr, len);
+ encname[len] = '\0';
+ estr = encname;
+ idx = rb_enc_find_index(encname);
+ }
}
+ else
+ idx = rb_enc_find_index(estr);
+
+ if (idx >= 0)
+ ext_enc = rb_enc_from_index(idx);
else {
- rb_warn("Unsupported encoding %s ignored", p1);
+ if (idx != -2)
+ rb_warn("Unsupported encoding %s ignored", estr);
+ ext_enc = NULL;
}
- if (*enc_p && p0) {
- int n = p0 - estr;
- if (n > ENCODING_MAXNAMELEN) {
- idx2 = -1;
- }
- else {
- enc2name = ALLOCA_N(char, n+1);
- memcpy(enc2name, estr, n);
- enc2name[n] = '\0';
- estr = enc2name;
- idx2 = rb_enc_find_index(enc2name);
- }
- if (idx2 < 0) {
- rb_warn("Unsupported encoding %.*s ignored", n, estr);
- }
- else if (idx2 == idx) {
- rb_warn("Ignoring internal encoding %.*s: it is identical to external encoding %s",
- n, estr, p1);
+ int_enc = NULL;
+ if (p) {
+ if (*p == '-' && *(p+1) == '\0') {
+ /* Special case - "-" => no transcoding */
+ int_enc = (rb_encoding *)Qnil;
}
else {
- *enc2_p = rb_enc_from_index(idx2);
+ idx2 = rb_enc_find_index(p);
+ if (idx2 < 0)
+ rb_warn("Unsupported encoding %s ignored", p);
+ else if (idx2 == idx) {
+ rb_warn("Ignoring internal encoding %s: it is identical to external encoding %s", p, estr);
+ int_enc = (rb_encoding *)Qnil;
+ }
+ else
+ int_enc = rb_enc_from_index(idx2);
}
}
+
+ rb_io_ext_int_to_encs(ext_enc, int_enc, enc_p, enc2_p);
}
static void
@@ -3802,7 +3920,7 @@ mode_enc(rb_io_t *fptr, const char *estr)
parse_mode_enc(estr, &fptr->encs.enc, &fptr->encs.enc2);
}
-void
+static void
rb_io_mode_enc(rb_io_t *fptr, const char *modestr)
{
const char *p = strchr(modestr, ':');
@@ -3811,8 +3929,8 @@ rb_io_mode_enc(rb_io_t *fptr, const char *modestr)
}
}
-static int
-io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p)
+int
+rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p)
{
VALUE encoding=Qnil, extenc=Qnil, intenc=Qnil;
int extracted = 0;
@@ -3827,28 +3945,32 @@ io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p)
}
if (!NIL_P(extenc)) {
rb_encoding *extencoding = rb_to_encoding(extenc);
+ rb_encoding *intencoding = NULL;
extracted = 1;
- *enc_p = 0;
- *enc2_p = 0;
if (!NIL_P(encoding)) {
rb_warn("Ignoring encoding parameter '%s': external_encoding is used",
RSTRING_PTR(encoding));
}
if (!NIL_P(intenc)) {
- rb_encoding *intencoding = rb_to_encoding(intenc);
+ if (!NIL_P(encoding = rb_check_string_type(intenc))) {
+ char *p = StringValueCStr(encoding);
+ if (*p == '-' && *(p+1) == '\0') {
+ /* Special case - "-" => no transcoding */
+ intencoding = (rb_encoding *)Qnil;
+ }
+ else
+ intencoding = rb_to_encoding(intenc);
+ }
+ else
+ intencoding = rb_to_encoding(intenc);
if (extencoding == intencoding) {
rb_warn("Ignoring internal encoding '%s': it is identical to external encoding '%s'",
RSTRING_PTR(rb_inspect(intenc)),
RSTRING_PTR(rb_inspect(extenc)));
- }
- else {
- *enc_p = intencoding;
- *enc2_p = extencoding;
+ intencoding = (rb_encoding *)Qnil;
}
}
- else {
- *enc_p = extencoding;
- }
+ rb_io_ext_int_to_encs(extencoding, intencoding, enc_p, enc2_p);
}
else {
if (!NIL_P(intenc)) {
@@ -3865,7 +3987,34 @@ io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p)
typedef struct rb_io_enc_t convconfig_t;
static void
-rb_io_extract_modeenc(VALUE *vmode_p, VALUE opthash,
+validate_enc_binmode(int fmode, rb_encoding *enc, rb_encoding *enc2)
+{
+ if ((fmode & FMODE_READABLE) &&
+ !enc2 &&
+ !(fmode & FMODE_BINMODE) &&
+ !rb_enc_asciicompat(enc ? enc : rb_default_external_encoding()))
+ rb_raise(rb_eArgError, "ASCII incompatible encoding needs binmode");
+}
+
+static void
+extract_binmode(VALUE opthash, int *fmode)
+{
+ if (!NIL_P(opthash)) {
+ VALUE v;
+ v = rb_hash_aref(opthash, sym_textmode);
+ if (!NIL_P(v) && RTEST(v))
+ *fmode |= FMODE_TEXTMODE;
+ v = rb_hash_aref(opthash, sym_binmode);
+ if (!NIL_P(v) && RTEST(v))
+ *fmode |= FMODE_BINMODE;
+
+ if ((*fmode & FMODE_BINMODE) && (*fmode & FMODE_TEXTMODE))
+ rb_raise(rb_eArgError, "both textmode and binmode specified");
+ }
+}
+
+static void
+rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash,
int *oflags_p, int *fmode_p, convconfig_t *convconfig_p)
{
VALUE vmode;
@@ -3873,13 +4022,13 @@ rb_io_extract_modeenc(VALUE *vmode_p, VALUE opthash,
rb_encoding *enc, *enc2;
int ecflags;
VALUE ecopts;
- int has_enc = 0;
+ int has_enc = 0, has_vmode = 0;
VALUE intmode;
vmode = *vmode_p;
- enc = NULL;
- enc2 = NULL;
+ /* Set to defaults */
+ rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2);
if (NIL_P(vmode)) {
fmode = FMODE_READABLE;
@@ -3892,6 +4041,8 @@ rb_io_extract_modeenc(VALUE *vmode_p, VALUE opthash,
}
else {
const char *p;
+
+ vmode_handle:
SafeStringValue(vmode);
p = StringValueCStr(vmode);
fmode = rb_io_modestr_fmode(p);
@@ -3901,6 +4052,12 @@ rb_io_extract_modeenc(VALUE *vmode_p, VALUE opthash,
has_enc = 1;
parse_mode_enc(p+1, &enc, &enc2);
}
+ else {
+ rb_encoding *e;
+
+ e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
+ rb_io_ext_int_to_encs(e, NULL, &enc, &enc2);
+ }
}
if (NIL_P(opthash)) {
@@ -3909,30 +4066,44 @@ rb_io_extract_modeenc(VALUE *vmode_p, VALUE opthash,
}
else {
VALUE v;
- v = rb_hash_aref(opthash, sym_textmode);
- if (RTEST(v))
- fmode |= FMODE_TEXTMODE;
- v = rb_hash_aref(opthash, sym_binmode);
- if (RTEST(v)) {
- fmode |= FMODE_BINMODE;
+ extract_binmode(opthash, &fmode);
#ifdef O_BINARY
+ if (fmode & FMODE_BINMODE)
oflags |= O_BINARY;
#endif
- }
+ if (!has_vmode) {
+ v = rb_hash_aref(opthash, sym_mode);
+ if (!NIL_P(v)) {
+ if (!NIL_P(vmode)) {
+ rb_raise(rb_eArgError, "mode specified twice");
+ }
+ has_vmode = 1;
+ vmode = v;
+ goto vmode_handle;
+ }
+ }
+ v = rb_hash_aref(opthash, sym_perm);
+ if (!NIL_P(v)) {
+ if (vperm_p) {
+ if (!NIL_P(*vperm_p)) {
+ rb_raise(rb_eArgError, "perm specified twice");
+ }
+ *vperm_p = v;
+ }
+ else {
+ /* perm no use, just ignore */
+ }
+ }
ecflags = rb_econv_prepare_opts(opthash, &ecopts);
- if (io_extract_encoding_option(opthash, &enc, &enc2)) {
+ if (rb_io_extract_encoding_option(opthash, &enc, &enc2)) {
if (has_enc) {
rb_raise(rb_eArgError, "encoding specified twice");
}
}
}
- if ((fmode & FMODE_BINMODE) && (fmode & FMODE_TEXTMODE))
- rb_raise(rb_eArgError, "both textmode and binmode specified");
-
- if (enc && !rb_enc_asciicompat(enc) && !(fmode & FMODE_BINMODE))
- rb_raise(rb_eArgError, "ASCII incompatible encoding needs binmode");
+ validate_enc_binmode(fmode, enc, enc2);
*vmode_p = vmode;
@@ -4093,18 +4264,19 @@ rb_file_open_generic(VALUE io, VALUE filename, const struct openat_args *base,
int oflags, int fmode, convconfig_t *convconfig, mode_t perm)
{
rb_io_t *fptr;
+ convconfig_t cc;
+ if (!convconfig) {
+ /* Set to default encodings */
+ rb_io_ext_int_to_encs(NULL, NULL, &cc.enc, &cc.enc2);
+ cc.ecflags = 0;
+ cc.ecopts = Qnil;
+ convconfig = &cc;
+ }
+ validate_enc_binmode(fmode, convconfig->enc, convconfig->enc2);
MakeOpenFile(io, fptr);
fptr->mode = fmode;
- if (convconfig) {
- fptr->encs = *convconfig;
- }
- else {
- fptr->encs.enc = NULL;
- fptr->encs.enc2 = NULL;
- fptr->encs.ecflags = 0;
- fptr->encs.ecopts = Qnil;
- }
+ fptr->encs = *convconfig;
fptr->pathv = rb_str_new_frozen(filename);
fptr->fd = rb_sysopenat(RSTRING_PTR(fptr->pathv), base, oflags, perm);
io_check_tty(fptr);
@@ -4115,21 +4287,23 @@ rb_file_open_generic(VALUE io, VALUE filename, const struct openat_args *base,
static VALUE
rb_file_openat_internal(VALUE io, VALUE filename, struct openat_args *oargs, const char *modestr)
{
- int fmode;
-
+ int fmode = rb_io_modestr_fmode(modestr);
const char *p = strchr(modestr, ':');
convconfig_t convconfig;
+
if (p) {
parse_mode_enc(p+1, &convconfig.enc, &convconfig.enc2);
}
else {
- convconfig.enc = NULL;
- convconfig.enc2 = NULL;
+ rb_encoding *e;
+ /* Set to default encodings */
+
+ e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
+ rb_io_ext_int_to_encs(e, NULL, &convconfig.enc, &convconfig.enc2);
convconfig.ecflags = 0;
convconfig.ecopts = Qnil;
}
- fmode = rb_io_modestr_fmode(modestr);
return rb_file_open_generic(io, filename, oargs,
rb_io_fmode_oflags(fmode),
fmode,
@@ -4146,6 +4320,7 @@ rb_file_open_internal(VALUE io, VALUE filename, const char *modestr)
VALUE
rb_file_open_str(VALUE fname, const char *modestr)
{
+ FilePathValue(fname);
return rb_file_open_internal(io_alloc(rb_cFile), fname, modestr);
}
@@ -4233,9 +4408,6 @@ pipe_finalize(rb_io_t *fptr, int noraise)
}
fptr->fd = -1;
fptr->stdio_file = 0;
-#if defined DJGPP
- status <<= 8;
-#endif
rb_last_status_set(status, fptr->pid);
#else
fptr_finalize(fptr, noraise);
@@ -4432,8 +4604,6 @@ pipe_open(struct rb_exec_arg *eargp, VALUE prog, const char *modestr, int fmode,
}
else {
fflush(stdin); /* is it really needed? */
- rb_io_flush(rb_stdout);
- rb_io_flush(rb_stderr);
pid = rb_fork(&status, 0, 0, Qnil);
if (pid == 0) { /* child */
popen_redirect(&arg);
@@ -4584,12 +4754,12 @@ pipe_open_s(VALUE prog, const char *modestr, int fmode, convconfig_t *convconfig
}
static VALUE
-pop_last_hash(int *argc_p, VALUE **argv_p)
+pop_last_hash(int *argc_p, VALUE *argv)
{
VALUE last, tmp;
if (*argc_p == 0)
return Qnil;
- last = (*argv_p)[*argc_p-1];
+ last = argv[*argc_p-1];
tmp = rb_check_convert_type(last, T_HASH, "Hash", "to_hash");
if (NIL_P(tmp))
return Qnil;
@@ -4660,10 +4830,10 @@ rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
int oflags, fmode;
convconfig_t convconfig;
- opt = pop_last_hash(&argc, &argv);
+ opt = pop_last_hash(&argc, argv);
rb_scan_args(argc, argv, "11", &pname, &pmode);
- rb_io_extract_modeenc(&pmode, opt, &oflags, &fmode, &convconfig);
+ rb_io_extract_modeenc(&pmode, 0, opt, &oflags, &fmode, &convconfig);
modestr = rb_io_oflags_modestr(oflags);
tmp = rb_check_array_type(pname);
@@ -4700,9 +4870,9 @@ rb_scan_open_args(int argc, VALUE *argv,
int oflags, fmode;
mode_t perm;
- opt = pop_last_hash(&argc, &argv);
-
+ opt = pop_last_hash(&argc, argv);
rb_scan_args(argc, argv, "12", &fname, &vmode, &vperm);
+ FilePathValue(fname);
#if defined _WIN32 || defined __APPLE__
{
static rb_encoding *fs_encoding;
@@ -4718,13 +4888,12 @@ rb_scan_open_args(int argc, VALUE *argv,
static VALUE fs_enc;
if (!fs_enc)
fs_enc = rb_enc_from_encoding(fs_encoding);
- fname = rb_str_transcode(fname, fs_enc, 0, Qnil);
+ fname = rb_str_encode(fname, fs_enc, 0, Qnil);
}
}
#endif
- FilePathValue(fname);
- rb_io_extract_modeenc(&vmode, opt, &oflags, &fmode, convconfig_p);
+ rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, convconfig_p);
perm = NIL_P(vperm) ? 0666 : NUM2UINT(vperm);
@@ -4989,7 +5158,7 @@ rb_io_open(VALUE filename, VALUE vmode, VALUE vperm, VALUE opt)
convconfig_t convconfig;
mode_t perm;
- rb_io_extract_modeenc(&vmode, opt, &oflags, &fmode, &convconfig);
+ rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, &convconfig);
perm = NIL_P(vperm) ? 0666 : NUM2UINT(vperm);
if (!NIL_P(cmd = check_pipe_command(filename))) {
@@ -5473,8 +5642,15 @@ void
rb_p(VALUE obj) /* for debug print within C code */
{
VALUE str = rb_obj_as_string(rb_inspect(obj));
- rb_str_buf_append(str, rb_default_rs);
- rb_io_write(rb_stdout, str);
+ if (TYPE(rb_stdout) == T_FILE &&
+ rb_method_basic_definition_p(CLASS_OF(rb_stdout), id_write)) {
+ io_write(rb_stdout, str, 1);
+ io_write(rb_stdout, rb_default_rs, 0);
+ }
+ else {
+ rb_io_write(rb_stdout, str);
+ rb_io_write(rb_stdout, rb_default_rs);
+ }
}
/*
@@ -5674,9 +5850,9 @@ rb_io_initialize(int argc, VALUE *argv, VALUE io)
rb_secure(4);
- opt = pop_last_hash(&argc, &argv);
+ opt = pop_last_hash(&argc, argv);
rb_scan_args(argc, argv, "11", &fnum, &vmode);
- rb_io_extract_modeenc(&vmode, opt, &oflags, &fmode, &convconfig);
+ rb_io_extract_modeenc(&vmode, 0, opt, &oflags, &fmode, &convconfig);
fd = NUM2INT(fnum);
UPDATE_MAXFD(fd);
@@ -5810,7 +5986,7 @@ argf_init(struct argf *p, VALUE v)
{
p->filename = Qnil;
p->current_file = Qnil;
- p->lineno = Qnil;
+ p->lineno = INT2FIX(0);
p->argv = v;
p->defin = rb_stdin;
p->defout = rb_stdout;
@@ -6078,9 +6254,9 @@ static VALUE argf_gets(int, VALUE *, VALUE);
* reads the input one paragraph at a time, where paragraphs are
* divided by two consecutive newlines. If the first argument is an
* integer, or optional second argument is given, the returning string
- * would not be longer than the given value. If multiple filenames are
- * present in +ARGV+, +gets(nil)+ will read the contents one file at a
- * time.
+ * would not be longer than the given value in bytes. If multiple
+ * filenames are present in +ARGV+, +gets(nil)+ will read the contents
+ * one file at a time.
*
* ARGV << "testfile"
* print while gets
@@ -6485,7 +6661,6 @@ rb_f_select(int argc, VALUE *argv, VALUE obj)
}
-#if !defined(MSDOS) && !defined(__human68k__)
static int
io_cntl(int fd, int cmd, long narg, int io_p)
{
@@ -6505,12 +6680,10 @@ io_cntl(int fd, int cmd, long narg, int io_p)
#endif
return retval;
}
-#endif
static VALUE
rb_io_ctl(VALUE io, VALUE req, VALUE arg, int io_p)
{
-#if !defined(MSDOS) && !defined(__human68k__)
int cmd = NUM2ULONG(req);
rb_io_t *fptr;
long len = 0;
@@ -6576,10 +6749,6 @@ rb_io_ctl(VALUE io, VALUE req, VALUE arg, int io_p)
}
return INT2NUM(retval);
-#else
- rb_notimplement();
- return Qnil; /* not reached */
-#endif
}
@@ -6758,38 +6927,56 @@ io_new_instance(VALUE args)
}
static void
-io_encoding_set(rb_io_t *fptr, int argc, VALUE v1, VALUE v2, VALUE opt)
+io_encoding_set(rb_io_t *fptr, VALUE v1, VALUE v2, VALUE opt)
{
- if (NIL_P(v2)) argc = 1;
- if (argc == 2) {
- fptr->encs.enc2 = rb_to_encoding(v1);
- fptr->encs.enc = rb_to_encoding(v2);
- fptr->encs.ecflags = rb_econv_prepare_opts(opt, &fptr->encs.ecopts);
- clear_codeconv(fptr);
+ rb_encoding *enc, *enc2;
+ int ecflags;
+ VALUE ecopts, tmp;
+
+ if (!NIL_P(v2)) {
+ enc2 = rb_to_encoding(v1);
+ tmp = rb_check_string_type(v2);
+ if (!NIL_P(tmp)) {
+ char *p = StringValueCStr(tmp);
+ if (*p == '-' && *(p+1) == '\0') {
+ /* Special case - "-" => no transcoding */
+ enc = enc2;
+ enc2 = NULL;
+ }
+ else
+ enc = rb_to_encoding(v2);
+ }
+ else
+ enc = rb_to_encoding(v2);
+ ecflags = rb_econv_prepare_opts(opt, &ecopts);
}
- else if (argc == 1) {
+ else {
if (NIL_P(v1)) {
- fptr->encs.enc = NULL;
- fptr->encs.enc2 = NULL;
- fptr->encs.ecflags = 0;
- fptr->encs.ecopts = Qnil;
- clear_codeconv(fptr);
+ /* Set to default encodings */
+ rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2);
+ ecflags = 0;
+ ecopts = Qnil;
}
else {
- VALUE tmp = rb_check_string_type(v1);
+ tmp = rb_check_string_type(v1);
if (!NIL_P(tmp)) {
- mode_enc(fptr, StringValueCStr(tmp));
- fptr->encs.ecflags = rb_econv_prepare_opts(opt, &fptr->encs.ecopts);
+ parse_mode_enc(StringValueCStr(tmp), &enc, &enc2);
+ ecflags = rb_econv_prepare_opts(opt, &ecopts);
}
else {
- fptr->encs.enc = rb_to_encoding(v1);
- fptr->encs.enc2 = NULL;
- fptr->encs.ecflags = 0;
- fptr->encs.ecopts = Qnil;
- clear_codeconv(fptr);
+ rb_io_ext_int_to_encs(rb_to_encoding(v1), NULL, &enc, &enc2);
+ ecflags = 0;
+ ecopts = Qnil;
}
}
}
+ validate_enc_binmode(fptr->mode, enc, enc2);
+ fptr->encs.enc = enc;
+ fptr->encs.enc2 = enc2;
+ fptr->encs.ecflags = ecflags;
+ fptr->encs.ecopts = ecopts;
+ clear_codeconv(fptr);
+
}
/*
@@ -6846,16 +7033,13 @@ io_encoding_set(rb_io_t *fptr, int argc, VALUE v1, VALUE v2, VALUE opt)
static VALUE
rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
{
-#ifdef __human68k__
- rb_notimplement();
- return Qnil; /* not reached */
-#else
int pipes[2], state;
VALUE r, w, args[3], v1, v2;
VALUE opt;
- rb_io_t *fptr;
+ rb_io_t *fptr, *fptr2;
+ int fmode = 0;
- opt = pop_last_hash(&argc, &argv);
+ opt = pop_last_hash(&argc, argv);
rb_scan_args(argc, argv, "02", &v1, &v2);
if (rb_pipe(pipes) == -1)
rb_sys_fail(0);
@@ -6870,7 +7054,7 @@ rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
rb_jump_tag(state);
}
GetOpenFile(r, fptr);
- io_encoding_set(fptr, argc, v1, v2, opt);
+ io_encoding_set(fptr, v1, v2, opt);
args[1] = INT2NUM(pipes[1]);
args[2] = INT2FIX(O_WRONLY);
w = rb_protect(io_new_instance, (VALUE)args, &state);
@@ -6879,10 +7063,14 @@ rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
if (!NIL_P(r)) rb_io_close(r);
rb_jump_tag(state);
}
- rb_io_synchronized(RFILE(w)->fptr);
+ GetOpenFile(w, fptr2);
+ rb_io_synchronized(fptr2);
+
+ extract_binmode(opt, &fmode);
+ fptr->mode |= fmode;
+ fptr2->mode |= fmode;
return rb_assoc_new(r, w);
-#endif
}
struct foreach_arg {
@@ -6895,7 +7083,6 @@ static void
open_key_args(int argc, VALUE *argv, struct foreach_arg *arg)
{
VALUE opt, v;
- VALUE vmode, vperm;
FilePathValue(argv[0]);
arg->io = 0;
@@ -6906,9 +7093,8 @@ open_key_args(int argc, VALUE *argv, struct foreach_arg *arg)
arg->io = rb_io_open(argv[0], INT2NUM(O_RDONLY), INT2FIX(0666), Qnil);
return;
}
- opt = rb_check_convert_type(argv[argc-1], T_HASH, "Hash", "to_hash");
+ opt = pop_last_hash(&arg->argc, arg->argv);
if (NIL_P(opt)) goto no_key;
- arg->argc--;
v = rb_hash_aref(opt, sym_open_args);
if (!NIL_P(v)) {
@@ -6922,15 +7108,7 @@ open_key_args(int argc, VALUE *argv, struct foreach_arg *arg)
arg->io = rb_io_open_with_args(RARRAY_LEN(args), RARRAY_PTR(args));
return;
}
- vmode = Qnil;
- vperm = INT2NUM(O_RDONLY);
- v = rb_hash_aref(opt, sym_mode);
- if (!NIL_P(v))
- vmode = v;
- v = rb_hash_aref(opt, sym_perm);
- if (!NIL_P(v))
- vperm = v;
- arg->io = rb_io_open(argv[0], vmode, vperm, opt);
+ arg->io = rb_io_open(argv[0], Qnil, Qnil, opt);
}
static VALUE
@@ -7069,6 +7247,37 @@ rb_io_s_read(int argc, VALUE *argv, VALUE io)
return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
}
+/*
+ * call-seq:
+ * IO.binread(name, [length [, offset]] ) => string
+ *
+ * Opens the file, optionally seeks to the given offset, then returns
+ * <i>length</i> bytes (defaulting to the rest of the file).
+ * <code>read</code> ensures the file is closed before returning.
+ * The open mode would be "rb:ASCII-8BIT".
+ *
+ * IO.binread("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
+ * IO.binread("testfile", 20) #=> "This is line one\nThi"
+ * IO.binread("testfile", 20, 10) #=> "ne one\nThis is line "
+ */
+
+static VALUE
+rb_io_s_binread(int argc, VALUE *argv, VALUE io)
+{
+ VALUE offset;
+ struct foreach_arg arg;
+
+ rb_scan_args(argc, argv, "12", NULL, NULL, &offset);
+ arg.io = rb_io_open(argv[0], rb_str_new_cstr("rb:ASCII-8BIT"), Qnil, Qnil);
+ if (NIL_P(arg.io)) return Qnil;
+ arg.argv = argv+1;
+ arg.argc = (argc > 1) ? 1 : 0;
+ if (!NIL_P(offset)) {
+ rb_io_seek(arg.io, offset, SEEK_SET);
+ }
+ return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
+}
+
struct copy_stream_struct {
VALUE src;
VALUE dst;
@@ -7084,7 +7293,7 @@ struct copy_stream_struct {
int error_no;
const char *notimp;
rb_fdset_t fds;
- rb_thread_t *th;
+ VALUE th;
};
static int
@@ -7212,7 +7421,7 @@ copy_stream_sendfile(struct copy_stream_struct *stp)
#endif
if (copy_stream_wait_write(stp) == -1)
return -1;
- if (RUBY_VM_INTERRUPTED(stp->th))
+ if (rb_thread_interrupted(stp->th))
return -1;
goto retry_sendfile;
}
@@ -7342,7 +7551,7 @@ copy_stream_read_write(struct copy_stream_struct *stp)
if (!use_eof)
copy_length -= ss;
- if (RUBY_VM_INTERRUPTED(stp->th))
+ if (rb_thread_interrupted(stp->th))
return;
}
}
@@ -7446,7 +7655,7 @@ copy_stream_body(VALUE arg)
int src_fd, dst_fd;
VALUE argf = rb_vm_argf();
- stp->th = GET_THREAD();
+ stp->th = rb_thread_current();
stp->total = 0;
@@ -7521,7 +7730,7 @@ copy_stream_body(VALUE arg)
rb_str_resize(str,len);
read_buffered_data(RSTRING_PTR(str), len, src_fptr);
if (dst_fptr) /* IO or filename */
- io_fwrite(str, dst_fptr);
+ io_binwrite(str, dst_fptr, 0);
else /* others such as StringIO */
rb_io_write(stp->dst, str);
stp->total += len;
@@ -7692,10 +7901,10 @@ rb_io_set_encoding(int argc, VALUE *argv, VALUE io)
rb_io_t *fptr;
VALUE v1, v2, opt;
- opt = pop_last_hash(&argc, &argv);
+ opt = pop_last_hash(&argc, argv);
rb_scan_args(argc, argv, "11", &v1, &v2);
GetOpenFile(io, fptr);
- io_encoding_set(fptr, argc, v1, v2, opt);
+ io_encoding_set(fptr, v1, v2, opt);
return io;
}
@@ -8339,6 +8548,7 @@ InitVM_IO(rb_vm_t *vm)
rb_define_singleton_method(rb_cIO, "foreach", rb_io_s_foreach, -1);
rb_define_singleton_method(rb_cIO, "readlines", rb_io_s_readlines, -1);
rb_define_singleton_method(rb_cIO, "read", rb_io_s_read, -1);
+ rb_define_singleton_method(rb_cIO, "binread", rb_io_s_binread, -1);
rb_define_singleton_method(rb_cIO, "select", rb_f_select, -1);
rb_define_singleton_method(rb_cIO, "pipe", rb_io_s_pipe, -1);
rb_define_singleton_method(rb_cIO, "try_convert", rb_io_s_try_convert, 1);
@@ -8349,8 +8559,8 @@ InitVM_IO(rb_vm_t *vm)
rb_output_fs = Qnil;
rb_define_hooked_variable("$,", &rb_output_fs, 0, rb_str_setter);
- rb_global_variable(&rb_default_rs);
rb_rs = rb_default_rs = rb_str_new2("\n");
+ rb_gc_register_mark_object(rb_default_rs);
rb_output_rs = Qnil;
OBJ_FREEZE(rb_default_rs); /* avoid modifying RS_default */
rb_define_hooked_variable("$/", &rb_rs, 0, rb_str_setter);
@@ -8395,7 +8605,7 @@ InitVM_IO(rb_vm_t *vm)
rb_define_method(rb_cIO, "write_nonblock", rb_io_write_nonblock, 1);
rb_define_method(rb_cIO, "readpartial", io_readpartial, -1);
rb_define_method(rb_cIO, "read", io_read, -1);
- rb_define_method(rb_cIO, "write", io_write, 1);
+ rb_define_method(rb_cIO, "write", io_write_m, 1);
rb_define_method(rb_cIO, "gets", rb_io_gets_m, -1);
rb_define_method(rb_cIO, "readline", rb_io_readline, -1);
rb_define_method(rb_cIO, "getc", rb_io_getc, 0);
@@ -8533,13 +8743,13 @@ InitVM_IO(rb_vm_t *vm)
rb_define_global_const("ARGF", argf);
rb_define_hooked_variable("$.", argfp, argf_lineno_getter, argf_lineno_setter);
- rb_define_hooked_variable("$FILENAME", argfp, argf_filename_getter, 0);
+ rb_define_hooked_variable("$FILENAME", argfp, argf_filename_getter, rb_gvar_readonly_setter);
ARGF.filename = rb_str_new2("-");
rb_define_hooked_variable("$-i", argfp, opt_i_get, opt_i_set);
- rb_define_hooked_variable("$*", argfp, argf_argv_getter, 0);
+ rb_define_hooked_variable("$*", argfp, argf_argv_getter, rb_gvar_readonly_setter);
-#if defined (_WIN32) || defined(DJGPP) || defined(__CYGWIN__) || defined(__human68k__)
+#if defined (_WIN32) || defined(__CYGWIN__)
atexit(pipe_atexit);
#endif
diff --git a/iseq.c b/iseq.c
index bf19507d1b..085e346476 100644
--- a/iseq.c
+++ b/iseq.c
@@ -10,11 +10,11 @@
**********************************************************************/
#include "ruby/ruby.h"
-#include "ruby/node.h"
/* #define MARK_FREE_DEBUG 1 */
#include "gc.h"
#include "vm_core.h"
+#include "iseq.h"
#include "insns.inc"
#include "insns_info.inc"
@@ -305,6 +305,13 @@ rb_iseq_new(NODE *node, VALUE name, VALUE filename,
&COMPILE_OPTION_DEFAULT);
}
+VALUE
+rb_iseq_new_top(NODE *node, VALUE name, VALUE filename, VALUE parent)
+{
+ return rb_iseq_new_with_opt(node, name, filename, parent, ISEQ_TYPE_TOP,
+ &COMPILE_OPTION_DEFAULT);
+}
+
static VALUE
rb_iseq_new_with_bopt_and_opt(NODE *node, VALUE name, VALUE filename,
VALUE parent, VALUE type, VALUE bopt,
@@ -498,9 +505,10 @@ iseq_s_compile_file(int argc, VALUE *argv, VALUE self)
rb_secure(1);
rb_scan_args(argc, argv, "11", &file, &opt);
+ FilePathValue(file);
fname = StringValueCStr(file);
- f = rb_file_open(fname, "r");
+ f = rb_file_open_str(file, "r");
parser = rb_parser_new();
node = rb_parser_compile_file(parser, fname, f, NUM2INT(line));
@@ -568,6 +576,12 @@ iseq_to_a(VALUE self)
return iseq_data_to_ary(iseq);
}
+int
+rb_iseq_first_lineno(rb_iseq_t *iseq)
+{
+ return iseq->insn_info_table[0].line_no;
+}
+
/* TODO: search algorithm is brute force.
this should be binary search or so. */
@@ -696,7 +710,7 @@ insn_operand_intern(rb_iseq_t *iseq,
}
case TS_GENTRY:
{
- struct global_entry *entry = (struct global_entry *)op;
+ struct rb_global_entry *entry = (struct rb_global_entry *)op;
ret = rb_str_dup(rb_id2str(entry->id));
}
break;
@@ -1117,7 +1131,7 @@ iseq_data_to_ary(rb_iseq_t *iseq)
break;
case TS_GENTRY:
{
- struct global_entry *entry = (struct global_entry *)*seq;
+ struct rb_global_entry *entry = (struct rb_global_entry *)*seq;
rb_ary_push(ary, ID2SYM(entry->id));
}
break;
diff --git a/iseq.h b/iseq.h
new file mode 100644
index 0000000000..631ef30e9d
--- /dev/null
+++ b/iseq.h
@@ -0,0 +1,94 @@
+/**********************************************************************
+
+ iseq.h -
+
+ $Author$
+ created at: 04/01/01 23:36:57 JST
+
+ Copyright (C) 2004-2008 Koichi Sasada
+
+**********************************************************************/
+
+#ifndef RUBY_COMPILE_H
+#define RUBY_COMPILE_H
+
+VALUE iseq_load(VALUE self, VALUE data, VALUE parent, VALUE opt);
+
+#define ISEQ_TYPE_TOP INT2FIX(1)
+#define ISEQ_TYPE_METHOD INT2FIX(2)
+#define ISEQ_TYPE_BLOCK INT2FIX(3)
+#define ISEQ_TYPE_CLASS INT2FIX(4)
+#define ISEQ_TYPE_RESCUE INT2FIX(5)
+#define ISEQ_TYPE_ENSURE INT2FIX(6)
+#define ISEQ_TYPE_EVAL INT2FIX(7)
+#define ISEQ_TYPE_DEFINED_GUARD INT2FIX(8)
+
+#define CATCH_TYPE_RESCUE INT2FIX(1)
+#define CATCH_TYPE_ENSURE INT2FIX(2)
+#define CATCH_TYPE_RETRY INT2FIX(3)
+#define CATCH_TYPE_BREAK INT2FIX(4)
+#define CATCH_TYPE_REDO INT2FIX(5)
+#define CATCH_TYPE_NEXT INT2FIX(6)
+
+struct iseq_insn_info_entry {
+ unsigned short position;
+ unsigned short line_no;
+ unsigned short sp;
+};
+
+struct iseq_catch_table_entry {
+ VALUE type;
+ VALUE iseq;
+ unsigned long start;
+ unsigned long end;
+ unsigned long cont;
+ unsigned long sp;
+};
+
+#define INITIAL_ISEQ_COMPILE_DATA_STORAGE_BUFF_SIZE (512)
+
+struct iseq_compile_data_storage {
+ struct iseq_compile_data_storage *next;
+ unsigned long pos;
+ unsigned long size;
+ char *buff;
+};
+
+struct iseq_compile_data {
+ /* GC is needed */
+ VALUE err_info;
+ VALUE mark_ary;
+ VALUE catch_table_ary; /* Array */
+
+ /* GC is not needed */
+ struct iseq_label_data *start_label;
+ struct iseq_label_data *end_label;
+ struct iseq_label_data *redo_label;
+ VALUE current_block;
+ VALUE loopval_popped; /* used by NODE_BREAK */
+ VALUE ensure_node;
+ VALUE for_iseq;
+ struct iseq_compile_data_ensure_node_stack *ensure_node_stack;
+ int cached_const;
+ struct iseq_compile_data_storage *storage_head;
+ struct iseq_compile_data_storage *storage_current;
+ int last_line;
+ int flip_cnt;
+ int label_no;
+ int node_level;
+ const rb_compile_option_t *option;
+};
+
+/* defined? */
+#define DEFINED_IVAR INT2FIX(1)
+#define DEFINED_IVAR2 INT2FIX(2)
+#define DEFINED_GVAR INT2FIX(3)
+#define DEFINED_CVAR INT2FIX(4)
+#define DEFINED_CONST INT2FIX(5)
+#define DEFINED_METHOD INT2FIX(6)
+#define DEFINED_YIELD INT2FIX(7)
+#define DEFINED_REF INT2FIX(8)
+#define DEFINED_ZSUPER INT2FIX(9)
+#define DEFINED_FUNC INT2FIX(10)
+
+#endif /* RUBY_COMPILE_H */
diff --git a/lib/base64.rb b/lib/base64.rb
new file mode 100644
index 0000000000..ebd796eccd
--- /dev/null
+++ b/lib/base64.rb
@@ -0,0 +1,91 @@
+#
+# = base64.rb: methods for base64-encoding and -decoding stings
+#
+
+# The Base64 module provides for the encoding (#encode64, #strict_encode64,
+# #urlsafe_encode64) and decoding (#decode64, #strict_decode64,
+# #urlsafe_decode64) of binary data using a Base64 representation.
+#
+# == Example
+#
+# A simple encoding and decoding.
+#
+# require "base64"
+#
+# enc = Base64.encode64('Send reinforcements')
+# # -> "U2VuZCByZWluZm9yY2VtZW50cw==\n"
+# plain = Base64.decode64(enc)
+# # -> "Send reinforcements"
+#
+# The purpose of using base64 to encode data is that it translates any
+# binary data into purely printable characters.
+
+module Base64
+ module_function
+
+ # Returns the Base64-encoded version of +bin+.
+ # This method complies with RFC 2045.
+ # Line feeds are added to every 60 encoded charactors.
+ #
+ # require 'base64'
+ # Base64.encode64("Now is the time for all good coders\nto learn Ruby")
+ #
+ # <i>Generates:</i>
+ #
+ # Tm93IGlzIHRoZSB0aW1lIGZvciBhbGwgZ29vZCBjb2RlcnMKdG8gbGVhcm4g
+ # UnVieQ==
+ def encode64(bin)
+ [bin].pack("m")
+ end
+
+ # Returns the Base64-decoded version of +str+.
+ # This method complies with RFC 2045.
+ # Characters outside the base alphabet are ignored.
+ #
+ # require 'base64'
+ # str = 'VGhpcyBpcyBsaW5lIG9uZQpUaGlzIG' +
+ # 'lzIGxpbmUgdHdvClRoaXMgaXMgbGlu' +
+ # 'ZSB0aHJlZQpBbmQgc28gb24uLi4K'
+ # puts Base64.decode64(str)
+ #
+ # <i>Generates:</i>
+ #
+ # This is line one
+ # This is line two
+ # This is line three
+ # And so on...
+ def decode64(str)
+ str.unpack("m").first
+ end
+
+ # Returns the Base64-encoded version of +bin+.
+ # This method complies with RFC 4648.
+ # No line feeds are added.
+ def strict_encode64(bin)
+ [bin].pack("m0")
+ end
+
+ # Returns the Base64-decoded version of +str+.
+ # This method complies with RFC 4648.
+ # ArgumentError is raised if +str+ is incorrectly padded or contains
+ # non-alphabet characters. Note that CR or LF are also rejected.
+ def strict_decode64(str)
+ str.unpack("m0").first
+ end
+
+ # Returns the Base64-encoded version of +bin+.
+ # This method complies with ``Base 64 Encoding with URL and Filename Safe
+ # Alphabet'' in RFC 4648.
+ # The alphabet uses '-' instead of '+' and '_' instead of '/'.
+ def urlsafe_encode64(bin)
+ strict_encode64(bin).tr("+/", "-_")
+ end
+
+ # Returns the Base64-decoded version of +str+.
+ # This method complies with ``Base 64 Encoding with URL and Filename Safe
+ # Alphabet'' in RFC 4648.
+ # The alphabet uses '-' instead of '+' and '_' instead of '/'.
+ def urlsafe_decode64(str)
+ strict_decode64(str.tr("-_", "+/"))
+ end
+end
diff --git a/lib/cgi.rb b/lib/cgi.rb
index 4ae060d5ce..6acf05b382 100644
--- a/lib/cgi.rb
+++ b/lib/cgi.rb
@@ -30,9 +30,7 @@
# See http://www.w3.org/CGI/ for more information on the CGI
# protocol.
-raise "Please, use ruby 1.5.4 or later." if RUBY_VERSION < "1.5.4"
-
-require 'English'
+raise "Please, use ruby 1.9.0 or later." if RUBY_VERSION < "1.9.0"
# CGI class. See documentation for the file cgi.rb for an overview
# of the CGI protocol.
@@ -271,2060 +269,6 @@ require 'English'
# CGI.new("html4Tr") # html4.01 Transitional
# CGI.new("html4Fr") # html4.01 Frameset
#
-class CGI
-
- # :stopdoc:
-
- # String for carriage return
- CR = "\015"
-
- # String for linefeed
- LF = "\012"
-
- # Standard internet newline sequence
- EOL = CR + LF
-
- REVISION = '$Id$' #:nodoc:
-
- NEEDS_BINMODE = true if /WIN/i.match(RUBY_PLATFORM)
-
- # Path separators in different environments.
- PATH_SEPARATOR = {'UNIX'=>'/', 'WINDOWS'=>'\\', 'MACINTOSH'=>':'}
-
- # HTTP status codes.
- HTTP_STATUS = {
- "OK" => "200 OK",
- "PARTIAL_CONTENT" => "206 Partial Content",
- "MULTIPLE_CHOICES" => "300 Multiple Choices",
- "MOVED" => "301 Moved Permanently",
- "REDIRECT" => "302 Found",
- "NOT_MODIFIED" => "304 Not Modified",
- "BAD_REQUEST" => "400 Bad Request",
- "AUTH_REQUIRED" => "401 Authorization Required",
- "FORBIDDEN" => "403 Forbidden",
- "NOT_FOUND" => "404 Not Found",
- "METHOD_NOT_ALLOWED" => "405 Method Not Allowed",
- "NOT_ACCEPTABLE" => "406 Not Acceptable",
- "LENGTH_REQUIRED" => "411 Length Required",
- "PRECONDITION_FAILED" => "412 Rrecondition Failed",
- "SERVER_ERROR" => "500 Internal Server Error",
- "NOT_IMPLEMENTED" => "501 Method Not Implemented",
- "BAD_GATEWAY" => "502 Bad Gateway",
- "VARIANT_ALSO_VARIES" => "506 Variant Also Negotiates"
- }
-
- # Abbreviated day-of-week names specified by RFC 822
- RFC822_DAYS = %w[ Sun Mon Tue Wed Thu Fri Sat ]
-
- # Abbreviated month names specified by RFC 822
- RFC822_MONTHS = %w[ Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ]
-
- # :startdoc:
-
- def env_table
- ENV
- end
-
- def stdinput
- $stdin
- end
-
- def stdoutput
- $DEFAULT_OUTPUT
- end
-
- private :env_table, :stdinput, :stdoutput
-
- # URL-encode a string.
- # url_encoded_string = CGI::escape("'Stop!' said Fred")
- # # => "%27Stop%21%27+said+Fred"
- def CGI::escape(string)
- string.gsub(/([^ a-zA-Z0-9_.-]+)/) do
- '%' + $1.unpack('H2' * $1.bytesize).join('%').upcase
- end.tr(' ', '+')
- end
-
-
- # URL-decode a string.
- # string = CGI::unescape("%27Stop%21%27+said+Fred")
- # # => "'Stop!' said Fred"
- def CGI::unescape(string)
- enc = string.encoding
- string.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/) do
- [$1.delete('%')].pack('H*').force_encoding(enc)
- end
- end
-
- TABLE_FOR_ESCAPE_HTML__ = {
- '&' => '&amp;',
- '"' => '&quot;',
- '<' => '&lt;',
- '>' => '&gt;',
- }
-
- # Escape special characters in HTML, namely &\"<>
- # CGI::escapeHTML('Usage: foo "bar" <baz>')
- # # => "Usage: foo &quot;bar&quot; &lt;baz&gt;"
- def CGI::escapeHTML(string)
- string.gsub(/[&\"<>]/, TABLE_FOR_ESCAPE_HTML__)
- end
-
-
- # Unescape a string that has been HTML-escaped
- # CGI::unescapeHTML("Usage: foo &quot;bar&quot; &lt;baz&gt;")
- # # => "Usage: foo \"bar\" <baz>"
- def CGI::unescapeHTML(string)
- enc = string.encoding
- if [Encoding::UTF_16BE, Encoding::UTF_16LE, Encoding::UTF_32BE, Encoding::UTF_32LE].include?(enc)
- return string.gsub(Regexp.new('&(amp|quot|gt|lt|#[0-9]+|#x[0-9A-Fa-f]+);'.encode(enc))) do
- case $1.encode("US-ASCII")
- when 'amp' then '&'.encode(enc)
- when 'quot' then '"'.encode(enc)
- when 'gt' then '>'.encode(enc)
- when 'lt' then '<'.encode(enc)
- when /\A#0*(\d+)\z/ then $1.to_i.chr(enc)
- when /\A#x([0-9a-f]+)\z/i then $1.hex.chr(enc)
- end
- end
- end
- asciicompat = Encoding.compatible?(string, "a")
- string.gsub(/&(amp|quot|gt|lt|\#[0-9]+|\#x[0-9A-Fa-f]+);/) do
- match = $1.dup
- case match
- when 'amp' then '&'
- when 'quot' then '"'
- when 'gt' then '>'
- when 'lt' then '<'
- when /\A#0*(\d+)\z/
- n = $1.to_i
- if enc == Encoding::UTF_8 or
- enc == Encoding::ISO_8859_1 && n < 256 or
- asciicompat && n < 128
- n.chr(enc)
- else
- "&##{$1};"
- end
- when /\A#x([0-9a-f]+)\z/i
- n = $1.hex
- if enc == Encoding::UTF_8 or
- enc == Encoding::ISO_8859_1 && n < 256 or
- asciicompat && n < 128
- n.chr(enc)
- else
- "&#x#{$1};"
- end
- else
- "&#{match};"
- end
- end
- end
- def CGI::escape_html(str)
- escapeHTML(str)
- end
- def CGI::unescape_html(str)
- unescapeHTML(str)
- end
-
- # Escape only the tags of certain HTML elements in +string+.
- #
- # Takes an element or elements or array of elements. Each element
- # is specified by the name of the element, without angle brackets.
- # This matches both the start and the end tag of that element.
- # The attribute list of the open tag will also be escaped (for
- # instance, the double-quotes surrounding attribute values).
- #
- # print CGI::escapeElement('<BR><A HREF="url"></A>', "A", "IMG")
- # # "<BR>&lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt"
- #
- # print CGI::escapeElement('<BR><A HREF="url"></A>', ["A", "IMG"])
- # # "<BR>&lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt"
- def CGI::escapeElement(string, *elements)
- elements = elements[0] if elements[0].kind_of?(Array)
- unless elements.empty?
- string.gsub(/<\/?(?:#{elements.join("|")})(?!\w)(?:.|\n)*?>/i) do
- CGI::escapeHTML($&)
- end
- else
- string
- end
- end
-
-
- # Undo escaping such as that done by CGI::escapeElement()
- #
- # print CGI::unescapeElement(
- # CGI::escapeHTML('<BR><A HREF="url"></A>'), "A", "IMG")
- # # "&lt;BR&gt;<A HREF="url"></A>"
- #
- # print CGI::unescapeElement(
- # CGI::escapeHTML('<BR><A HREF="url"></A>'), ["A", "IMG"])
- # # "&lt;BR&gt;<A HREF="url"></A>"
- def CGI::unescapeElement(string, *elements)
- elements = elements[0] if elements[0].kind_of?(Array)
- unless elements.empty?
- string.gsub(/&lt;\/?(?:#{elements.join("|")})(?!\w)(?:.|\n)*?&gt;/i) do
- CGI::unescapeHTML($&)
- end
- else
- string
- end
- end
- def CGI::escape_element(str)
- escapeElement(str)
- end
- def CGI::unescape_element(str)
- unescapeElement(str)
- end
-
- # Format a +Time+ object as a String using the format specified by RFC 1123.
- #
- # CGI::rfc1123_date(Time.now)
- # # Sat, 01 Jan 2000 00:00:00 GMT
- def CGI::rfc1123_date(time)
- t = time.clone.gmtime
- return format("%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT",
- RFC822_DAYS[t.wday], t.day, RFC822_MONTHS[t.month-1], t.year,
- t.hour, t.min, t.sec)
- end
-
-
- # Create an HTTP header block as a string.
- #
- # Includes the empty line that ends the header block.
- #
- # +options+ can be a string specifying the Content-Type (defaults
- # to text/html), or a hash of header key/value pairs. The following
- # header keys are recognized:
- #
- # type:: the Content-Type header. Defaults to "text/html"
- # charset:: the charset of the body, appended to the Content-Type header.
- # nph:: a boolean value. If true, prepend protocol string and status code, and
- # date; and sets default values for "server" and "connection" if not
- # explicitly set.
- # status:: the HTTP status code, returned as the Status header. See the
- # list of available status codes below.
- # server:: the server software, returned as the Server header.
- # connection:: the connection type, returned as the Connection header (for
- # instance, "close".
- # length:: the length of the content that will be sent, returned as the
- # Content-Length header.
- # language:: the language of the content, returned as the Content-Language
- # header.
- # expires:: the time on which the current content expires, as a +Time+
- # object, returned as the Expires header.
- # cookie:: a cookie or cookies, returned as one or more Set-Cookie headers.
- # The value can be the literal string of the cookie; a CGI::Cookie
- # object; an Array of literal cookie strings or Cookie objects; or a
- # hash all of whose values are literal cookie strings or Cookie objects.
- # These cookies are in addition to the cookies held in the
- # @output_cookies field.
- #
- # Other header lines can also be set; they are appended as key: value.
- #
- # header
- # # Content-Type: text/html
- #
- # header("text/plain")
- # # Content-Type: text/plain
- #
- # header("nph" => true,
- # "status" => "OK", # == "200 OK"
- # # "status" => "200 GOOD",
- # "server" => ENV['SERVER_SOFTWARE'],
- # "connection" => "close",
- # "type" => "text/html",
- # "charset" => "iso-2022-jp",
- # # Content-Type: text/html; charset=iso-2022-jp
- # "length" => 103,
- # "language" => "ja",
- # "expires" => Time.now + 30,
- # "cookie" => [cookie1, cookie2],
- # "my_header1" => "my_value"
- # "my_header2" => "my_value")
- #
- # The status codes are:
- #
- # "OK" --> "200 OK"
- # "PARTIAL_CONTENT" --> "206 Partial Content"
- # "MULTIPLE_CHOICES" --> "300 Multiple Choices"
- # "MOVED" --> "301 Moved Permanently"
- # "REDIRECT" --> "302 Found"
- # "NOT_MODIFIED" --> "304 Not Modified"
- # "BAD_REQUEST" --> "400 Bad Request"
- # "AUTH_REQUIRED" --> "401 Authorization Required"
- # "FORBIDDEN" --> "403 Forbidden"
- # "NOT_FOUND" --> "404 Not Found"
- # "METHOD_NOT_ALLOWED" --> "405 Method Not Allowed"
- # "NOT_ACCEPTABLE" --> "406 Not Acceptable"
- # "LENGTH_REQUIRED" --> "411 Length Required"
- # "PRECONDITION_FAILED" --> "412 Precondition Failed"
- # "SERVER_ERROR" --> "500 Internal Server Error"
- # "NOT_IMPLEMENTED" --> "501 Method Not Implemented"
- # "BAD_GATEWAY" --> "502 Bad Gateway"
- # "VARIANT_ALSO_VARIES" --> "506 Variant Also Negotiates"
- #
- # This method does not perform charset conversion.
- #
- def header(options = "text/html")
-
- buf = ""
-
- case options
- when String
- options = { "type" => options }
- when Hash
- options = options.dup
- end
-
- unless options.has_key?("type")
- options["type"] = "text/html"
- end
-
- if options.has_key?("charset")
- options["type"] += "; charset=" + options.delete("charset")
- end
-
- options.delete("nph") if defined?(MOD_RUBY)
- if options.delete("nph") or
- (/IIS\/(\d+)/.match(env_table['SERVER_SOFTWARE']) and $1.to_i < 5)
- buf += (env_table["SERVER_PROTOCOL"] or "HTTP/1.0") + " " +
- (HTTP_STATUS[options["status"]] or options["status"] or "200 OK") +
- EOL +
- "Date: " + CGI::rfc1123_date(Time.now) + EOL
-
- unless options.has_key?("server")
- options["server"] = (env_table['SERVER_SOFTWARE'] or "")
- end
-
- unless options.has_key?("connection")
- options["connection"] = "close"
- end
-
- options.delete("status")
- end
-
- if options.has_key?("status")
- buf += "Status: " +
- (HTTP_STATUS[options["status"]] or options["status"]) + EOL
- options.delete("status")
- end
-
- if options.has_key?("server")
- buf += "Server: " + options.delete("server") + EOL
- end
-
- if options.has_key?("connection")
- buf += "Connection: " + options.delete("connection") + EOL
- end
-
- buf += "Content-Type: " + options.delete("type") + EOL
-
- if options.has_key?("length")
- buf += "Content-Length: " + options.delete("length").to_s + EOL
- end
-
- if options.has_key?("language")
- buf += "Content-Language: " + options.delete("language") + EOL
- end
-
- if options.has_key?("expires")
- buf += "Expires: " + CGI::rfc1123_date( options.delete("expires") ) + EOL
- end
-
- if options.has_key?("cookie")
- if options["cookie"].kind_of?(String) or
- options["cookie"].kind_of?(Cookie)
- buf += "Set-Cookie: " + options.delete("cookie").to_s + EOL
- elsif options["cookie"].kind_of?(Array)
- options.delete("cookie").each{|cookie|
- buf += "Set-Cookie: " + cookie.to_s + EOL
- }
- elsif options["cookie"].kind_of?(Hash)
- options.delete("cookie").each_value{|cookie|
- buf += "Set-Cookie: " + cookie.to_s + EOL
- }
- end
- end
- if @output_cookies
- for cookie in @output_cookies
- buf += "Set-Cookie: " + cookie.to_s + EOL
- end
- end
-
- options.each{|key, value|
- buf += key + ": " + value.to_s + EOL
- }
-
- if defined?(MOD_RUBY)
- table = Apache::request.headers_out
- buf.scan(/([^:]+): (.+)#{EOL}/){ |name, value|
- warn sprintf("name:%s value:%s\n", name, value) if $DEBUG
- case name
- when 'Set-Cookie'
- table.add(name, value)
- when /^status$/i
- Apache::request.status_line = value
- Apache::request.status = value.to_i
- when /^content-type$/i
- Apache::request.content_type = value
- when /^content-encoding$/i
- Apache::request.content_encoding = value
- when /^location$/i
- if Apache::request.status == 200
- Apache::request.status = 302
- end
- Apache::request.headers_out[name] = value
- else
- Apache::request.headers_out[name] = value
- end
- }
- Apache::request.send_http_header
- ''
- else
- buf + EOL
- end
-
- end # header()
-
-
- # Print an HTTP header and body to $DEFAULT_OUTPUT ($>)
- #
- # The header is provided by +options+, as for #header().
- # The body of the document is that returned by the passed-
- # in block. This block takes no arguments. It is required.
- #
- # cgi = CGI.new
- # cgi.out{ "string" }
- # # Content-Type: text/html
- # # Content-Length: 6
- # #
- # # string
- #
- # cgi.out("text/plain") { "string" }
- # # Content-Type: text/plain
- # # Content-Length: 6
- # #
- # # string
- #
- # cgi.out("nph" => true,
- # "status" => "OK", # == "200 OK"
- # "server" => ENV['SERVER_SOFTWARE'],
- # "connection" => "close",
- # "type" => "text/html",
- # "charset" => "iso-2022-jp",
- # # Content-Type: text/html; charset=iso-2022-jp
- # "language" => "ja",
- # "expires" => Time.now + (3600 * 24 * 30),
- # "cookie" => [cookie1, cookie2],
- # "my_header1" => "my_value",
- # "my_header2" => "my_value") { "string" }
- #
- # Content-Length is automatically calculated from the size of
- # the String returned by the content block.
- #
- # If ENV['REQUEST_METHOD'] == "HEAD", then only the header
- # is outputted (the content block is still required, but it
- # is ignored).
- #
- # If the charset is "iso-2022-jp" or "euc-jp" or "shift_jis" then
- # the content is converted to this charset, and the language is set
- # to "ja".
- def out(options = "text/html") # :yield:
-
- options = { "type" => options } if options.kind_of?(String)
- content = yield
- options["length"] = content.bytesize.to_s
- output = stdoutput
- output.binmode if defined? output.binmode
- output.print header(options)
- output.print content unless "HEAD" == env_table['REQUEST_METHOD']
- end
-
-
- # Print an argument or list of arguments to the default output stream
- #
- # cgi = CGI.new
- # cgi.print # default: cgi.print == $DEFAULT_OUTPUT.print
- def print(*options)
- stdoutput.print(*options)
- end
-
- # Class representing an HTTP cookie.
- #
- # In addition to its specific fields and methods, a Cookie instance
- # is a delegator to the array of its values.
- #
- # See RFC 2965.
- #
- # == Examples of use
- # cookie1 = CGI::Cookie::new("name", "value1", "value2", ...)
- # cookie1 = CGI::Cookie::new("name" => "name", "value" => "value")
- # cookie1 = CGI::Cookie::new('name' => 'name',
- # 'value' => ['value1', 'value2', ...],
- # 'path' => 'path', # optional
- # 'domain' => 'domain', # optional
- # 'expires' => Time.now, # optional
- # 'secure' => true # optional
- # )
- #
- # cgi.out("cookie" => [cookie1, cookie2]) { "string" }
- #
- # name = cookie1.name
- # values = cookie1.value
- # path = cookie1.path
- # domain = cookie1.domain
- # expires = cookie1.expires
- # secure = cookie1.secure
- #
- # cookie1.name = 'name'
- # cookie1.value = ['value1', 'value2', ...]
- # cookie1.path = 'path'
- # cookie1.domain = 'domain'
- # cookie1.expires = Time.now + 30
- # cookie1.secure = true
- class Cookie < Array
-
- # Create a new CGI::Cookie object.
- #
- # The contents of the cookie can be specified as a +name+ and one
- # or more +value+ arguments. Alternatively, the contents can
- # be specified as a single hash argument. The possible keywords of
- # this hash are as follows:
- #
- # name:: the name of the cookie. Required.
- # value:: the cookie's value or list of values.
- # path:: the path for which this cookie applies. Defaults to the
- # base directory of the CGI script.
- # domain:: the domain for which this cookie applies.
- # expires:: the time at which this cookie expires, as a +Time+ object.
- # secure:: whether this cookie is a secure cookie or not (default to
- # false). Secure cookies are only transmitted to HTTPS
- # servers.
- #
- # These keywords correspond to attributes of the cookie object.
- def initialize(name = "", *value)
- if name.kind_of?(String)
- @name = name
- @value = value
- %r|^(.*/)|.match(ENV["SCRIPT_NAME"])
- @path = ($1 or "")
- @secure = false
- return super(@value)
- end
-
- options = name
- unless options.has_key?("name")
- raise ArgumentError, "`name' required"
- end
-
- @name = options["name"]
- @value = Array(options["value"])
- # simple support for IE
- if options["path"]
- @path = options["path"]
- else
- %r|^(.*/)|.match(ENV["SCRIPT_NAME"])
- @path = ($1 or "")
- end
- @domain = options["domain"]
- @expires = options["expires"]
- @secure = options["secure"] == true ? true : false
-
- super(@value)
- end
-
- attr_accessor("name", "value", "path", "domain", "expires")
- attr_reader("secure")
-
- # Set whether the Cookie is a secure cookie or not.
- #
- # +val+ must be a boolean.
- def secure=(val)
- @secure = val if val == true or val == false
- @secure
- end
-
- # Convert the Cookie to its string representation.
- def to_s
- buf = ""
- buf += @name + '='
-
- if @value.kind_of?(String)
- buf += CGI::escape(@value)
- else
- buf += @value.collect{|v| CGI::escape(v) }.join("&")
- end
-
- if @domain
- buf += '; domain=' + @domain
- end
-
- if @path
- buf += '; path=' + @path
- end
-
- if @expires
- buf += '; expires=' + CGI::rfc1123_date(@expires)
- end
-
- if @secure == true
- buf += '; secure'
- end
-
- buf
- end
-
- end # class Cookie
-
-
- # Parse a raw cookie string into a hash of cookie-name=>Cookie
- # pairs.
- #
- # cookies = CGI::Cookie::parse("raw_cookie_string")
- # # { "name1" => cookie1, "name2" => cookie2, ... }
- #
- def Cookie::parse(raw_cookie)
- cookies = Hash.new([])
- return cookies unless raw_cookie
-
- raw_cookie.split(/[;,]\s?/).each do |pairs|
- name, values = pairs.split('=',2)
- next unless name and values
- name = CGI::unescape(name)
- values ||= ""
- values = values.split('&').collect{|v| CGI::unescape(v) }
- if cookies.has_key?(name)
- values = cookies[name].value + values
- end
- cookies[name] = Cookie::new(name, *values)
- end
-
- cookies
- end
-
- # Parse an HTTP query string into a hash of key=>value pairs.
- #
- # params = CGI::parse("query_string")
- # # {"name1" => ["value1", "value2", ...],
- # # "name2" => ["value1", "value2", ...], ... }
- #
- def CGI::parse(query)
- params = Hash.new([].freeze)
-
- query.split(/[&;]/).each do |pairs|
- key, value = pairs.split('=',2).collect{|v| CGI::unescape(v) }
- if params.has_key?(key)
- params[key].push(value)
- else
- params[key] = [value]
- end
- end
-
- params
- end
-
- # Mixin module. It provides the follow functionality groups:
- #
- # 1. Access to CGI environment variables as methods. See
- # documentation to the CGI class for a list of these variables.
- #
- # 2. Access to cookies, including the cookies attribute.
- #
- # 3. Access to parameters, including the params attribute, and overloading
- # [] to perform parameter value lookup by key.
- #
- # 4. The initialize_query method, for initialising the above
- # mechanisms, handling multipart forms, and allowing the
- # class to be used in "offline" mode.
- #
- module QueryExtension
-
- %w[ CONTENT_LENGTH SERVER_PORT ].each do |env|
- define_method(env.sub(/^HTTP_/, '').downcase) do
- (val = env_table[env]) && Integer(val)
- end
- end
-
- %w[ AUTH_TYPE CONTENT_TYPE GATEWAY_INTERFACE PATH_INFO
- PATH_TRANSLATED QUERY_STRING REMOTE_ADDR REMOTE_HOST
- REMOTE_IDENT REMOTE_USER REQUEST_METHOD SCRIPT_NAME
- SERVER_NAME SERVER_PROTOCOL SERVER_SOFTWARE
-
- HTTP_ACCEPT HTTP_ACCEPT_CHARSET HTTP_ACCEPT_ENCODING
- HTTP_ACCEPT_LANGUAGE HTTP_CACHE_CONTROL HTTP_FROM HTTP_HOST
- HTTP_NEGOTIATE HTTP_PRAGMA HTTP_REFERER HTTP_USER_AGENT ].each do |env|
- define_method(env.sub(/^HTTP_/, '').downcase) do
- env_table[env]
- end
- end
-
- # Get the raw cookies as a string.
- def raw_cookie
- env_table["HTTP_COOKIE"]
- end
-
- # Get the raw RFC2965 cookies as a string.
- def raw_cookie2
- env_table["HTTP_COOKIE2"]
- end
-
- # Get the cookies as a hash of cookie-name=>Cookie pairs.
- attr_accessor :cookies
-
- # Get the parameters as a hash of name=>values pairs, where
- # values is an Array.
- attr_reader :params
-
- # Set all the parameters.
- def params=(hash)
- @params.clear
- @params.update(hash)
- end
-
- def read_multipart(boundary, content_length)
- params = Hash.new([])
- boundary = "--" + boundary
- quoted_boundary = Regexp.quote(boundary)
- buf = ""
- bufsize = 10 * 1024
- boundary_end=""
-
- # start multipart/form-data
- stdinput.binmode if defined? stdinput.binmode
- boundary_size = boundary.bytesize + EOL.bytesize
- content_length -= boundary_size
- status = stdinput.read(boundary_size)
- if nil == status
- raise EOFError, "no content body"
- elsif boundary + EOL != status
- raise EOFError, "bad content body"
- end
-
- loop do
- head = nil
- body = MorphingBody.new
-
- until head and /#{quoted_boundary}(?:#{EOL}|--)/.match(buf)
- if (not head) and /#{EOL}#{EOL}/.match(buf)
- buf = buf.sub(/\A((?:.|\n)*?#{EOL})#{EOL}/) do
- head = $1.dup
- ""
- end
- next
- end
-
- if head and ( (EOL + boundary + EOL).bytesize < buf.bytesize )
- body.print buf[0 ... (buf.bytesize - (EOL + boundary + EOL).bytesize)]
- buf[0 ... (buf.bytesize - (EOL + boundary + EOL).bytesize)] = ""
- end
-
- c = if bufsize < content_length
- stdinput.read(bufsize)
- else
- stdinput.read(content_length)
- end
- if c.nil? || c.empty?
- raise EOFError, "bad content body"
- end
- buf.concat(c)
- content_length -= c.bytesize
- end
-
- buf = buf.sub(/\A((?:.|\n)*?)(?:[\r\n]{1,2})?#{quoted_boundary}([\r\n]{1,2}|--)/) do
- body.print $1
- if "--" == $2
- content_length = -1
- end
- boundary_end = $2.dup
- ""
- end
-
- body.rewind
-
- /Content-Disposition:.* filename=(?:"((?:\\.|[^\"])*)"|([^;\s]*))/i.match(head)
- filename = ($1 or $2 or "")
- if /Mac/i.match(env_table['HTTP_USER_AGENT']) and
- /Mozilla/i.match(env_table['HTTP_USER_AGENT']) and
- (not /MSIE/i.match(env_table['HTTP_USER_AGENT']))
- filename = CGI::unescape(filename)
- end
-
- /Content-Type: ([^\s]*)/i.match(head)
- content_type = ($1 or "")
-
- (class << body; self; end).class_eval do
- alias local_path path
- define_method(:original_filename) {filename.dup.taint}
- define_method(:content_type) {content_type.dup.taint}
- end
-
- /Content-Disposition:.* name="?([^\";\s]*)"?/i.match(head)
- name = ($1 || "").dup
-
- if params.has_key?(name)
- params[name].push(body)
- else
- params[name] = [body]
- end
- break if buf.bytesize == 0
- break if content_length == -1
- end
- raise EOFError, "bad boundary end of body part" unless boundary_end=~/--/
-
- params
- end # read_multipart
- private :read_multipart
-
- # offline mode. read name=value pairs on standard input.
- def read_from_cmdline
- require "shellwords"
-
- string = unless ARGV.empty?
- ARGV.join(' ')
- else
- if STDIN.tty?
- STDERR.print(
- %|(offline mode: enter name=value pairs on standard input)\n|
- )
- end
- readlines.join(' ').gsub(/\n/, '')
- end.gsub(/\\=/, '%3D').gsub(/\\&/, '%26')
-
- words = Shellwords.shellwords(string)
-
- if words.find{|x| /=/.match(x) }
- words.join('&')
- else
- words.join('+')
- end
- end
- private :read_from_cmdline
-
- # A wrapper class to use a StringIO object as the body and switch
- # to a TempFile when the passed threshold is passed.
- class MorphingBody
- begin
- require "stringio"
- @@small_buffer = lambda{StringIO.new}
- rescue LoadError
- require "tempfile"
- @@small_buffer = lambda{
- n = Tempfile.new("CGI")
- n.binmode
- n
- }
- end
-
- def initialize(morph_threshold = 10240)
- @threshold = morph_threshold
- @body = @@small_buffer.call
- @cur_size = 0
- @morph_check = true
- end
-
- def print(data)
- if @morph_check && (@cur_size + data.bytesize > @threshold)
- convert_body
- end
- @body.print data
- end
- def rewind
- @body.rewind
- end
- def path
- @body.path
- end
-
- # returns the true body object.
- def extract
- @body
- end
-
- private
- def convert_body
- new_body = TempFile.new("CGI")
- new_body.binmode if defined? @body.binmode
- new_body.binmode if defined? new_body.binmode
-
- @body.rewind
- new_body.print @body.read
- @body = new_body
- @morph_check = false
- end
- end
-
- # Initialize the data from the query.
- #
- # Handles multipart forms (in particular, forms that involve file uploads).
- # Reads query parameters in the @params field, and cookies into @cookies.
- def initialize_query()
- if ("POST" == env_table['REQUEST_METHOD']) and
- %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|.match(env_table['CONTENT_TYPE'])
- boundary = $1.dup
- @multipart = true
- @params = read_multipart(boundary, Integer(env_table['CONTENT_LENGTH']))
- else
- @multipart = false
- @params = CGI::parse(
- case env_table['REQUEST_METHOD']
- when "GET", "HEAD"
- if defined?(MOD_RUBY)
- Apache::request.args or ""
- else
- env_table['QUERY_STRING'] or ""
- end
- when "POST"
- stdinput.binmode if defined? stdinput.binmode
- stdinput.read(Integer(env_table['CONTENT_LENGTH'])) or ''
- else
- read_from_cmdline
- end
- )
- end
-
- @cookies = CGI::Cookie::parse((env_table['HTTP_COOKIE'] or env_table['COOKIE']))
- end
- private :initialize_query
-
- def multipart?
- @multipart
- end
-
- # Get the value for the parameter with a given key.
- #
- # If the parameter has multiple values, only the first will be
- # retrieved; use #params() to get the array of values.
- def [](key)
- params = @params[key]
- return '' unless params
- value = params[0]
- if @multipart
- if value
- return value
- elsif defined? StringIO
- StringIO.new("")
- else
- Tempfile.new("CGI")
- end
- else
- str = if value then value.dup else "" end
- str
- end
- end
-
- # Return all parameter keys as an array.
- def keys(*args)
- @params.keys(*args)
- end
-
- # Returns true if a given parameter key exists in the query.
- def has_key?(*args)
- @params.has_key?(*args)
- end
- alias key? has_key?
- alias include? has_key?
-
- end # QueryExtension
-
-
- # Prettify (indent) an HTML string.
- #
- # +string+ is the HTML string to indent. +shift+ is the indentation
- # unit to use; it defaults to two spaces.
- #
- # print CGI::pretty("<HTML><BODY></BODY></HTML>")
- # # <HTML>
- # # <BODY>
- # # </BODY>
- # # </HTML>
- #
- # print CGI::pretty("<HTML><BODY></BODY></HTML>", "\t")
- # # <HTML>
- # # <BODY>
- # # </BODY>
- # # </HTML>
- #
- def CGI::pretty(string, shift = " ")
- lines = string.gsub(/(?!\A)<(?:.|\n)*?>/, "\n\\0").gsub(/<(?:.|\n)*?>(?!\n)/, "\\0\n")
- end_pos = 0
- while end_pos = lines.index(/^<\/(\w+)/, end_pos)
- element = $1.dup
- start_pos = lines.rindex(/^\s*<#{element}/i, end_pos)
- lines[start_pos ... end_pos] = "__" + lines[start_pos ... end_pos].gsub(/\n(?!\z)/, "\n" + shift) + "__"
- end
- lines.gsub(/^((?:#{Regexp::quote(shift)})*)__(?=<\/?\w)/, '\1')
- end
-
-
- # Base module for HTML-generation mixins.
- #
- # Provides methods for code generation for tags following
- # the various DTD element types.
- module TagMaker # :nodoc:
-
- # Generate code for an element with required start and end tags.
- #
- # - -
- def nn_element_def(element)
- nOE_element_def(element, <<-END)
- if block_given?
- yield.to_s
- else
- ""
- end +
- "</#{element.upcase}>"
- END
- end
-
- # Generate code for an empty element.
- #
- # - O EMPTY
- def nOE_element_def(element, append = nil)
- s = <<-END
- attributes={attributes=>nil} if attributes.kind_of?(String)
- "<#{element.upcase}" + attributes.collect{|name, value|
- next unless value
- " " + CGI::escapeHTML(name) +
- if true == value
- ""
- else
- '="' + CGI::escapeHTML(value) + '"'
- end
- }.join + ">"
- END
- s.sub!(/\Z/, " +") << append if append
- s
- end
-
- # Generate code for an element for which the end (and possibly the
- # start) tag is optional.
- #
- # O O or - O
- def nO_element_def(element)
- nOE_element_def(element, <<-END)
- if block_given?
- yield.to_s + "</#{element.upcase}>"
- else
- ""
- end
- END
- end
-
- end # TagMaker
-
-
- #
- # Mixin module providing HTML generation methods.
- #
- # For example,
- # cgi.a("http://www.example.com") { "Example" }
- # # => "<A HREF=\"http://www.example.com\">Example</A>"
- #
- # Modules Http3, Http4, etc., contain more basic HTML-generation methods
- # (:title, :center, etc.).
- #
- # See class CGI for a detailed example.
- #
- module HtmlExtension
-
-
- # Generate an Anchor element as a string.
- #
- # +href+ can either be a string, giving the URL
- # for the HREF attribute, or it can be a hash of
- # the element's attributes.
- #
- # The body of the element is the string returned by the no-argument
- # block passed in.
- #
- # a("http://www.example.com") { "Example" }
- # # => "<A HREF=\"http://www.example.com\">Example</A>"
- #
- # a("HREF" => "http://www.example.com", "TARGET" => "_top") { "Example" }
- # # => "<A HREF=\"http://www.example.com\" TARGET=\"_top\">Example</A>"
- #
- def a(href = "") # :yield:
- attributes = if href.kind_of?(String)
- { "HREF" => href }
- else
- href
- end
- if block_given?
- super(attributes){ yield }
- else
- super(attributes)
- end
- end
-
- # Generate a Document Base URI element as a String.
- #
- # +href+ can either by a string, giving the base URL for the HREF
- # attribute, or it can be a has of the element's attributes.
- #
- # The passed-in no-argument block is ignored.
- #
- # base("http://www.example.com/cgi")
- # # => "<BASE HREF=\"http://www.example.com/cgi\">"
- def base(href = "") # :yield:
- attributes = if href.kind_of?(String)
- { "HREF" => href }
- else
- href
- end
- if block_given?
- super(attributes){ yield }
- else
- super(attributes)
- end
- end
-
- # Generate a BlockQuote element as a string.
- #
- # +cite+ can either be a string, give the URI for the source of
- # the quoted text, or a hash, giving all attributes of the element,
- # or it can be omitted, in which case the element has no attributes.
- #
- # The body is provided by the passed-in no-argument block
- #
- # blockquote("http://www.example.com/quotes/foo.html") { "Foo!" }
- # #=> "<BLOCKQUOTE CITE=\"http://www.example.com/quotes/foo.html\">Foo!</BLOCKQUOTE>
- def blockquote(cite = {}) # :yield:
- attributes = if cite.kind_of?(String)
- { "CITE" => cite }
- else
- cite
- end
- if block_given?
- super(attributes){ yield }
- else
- super(attributes)
- end
- end
-
-
- # Generate a Table Caption element as a string.
- #
- # +align+ can be a string, giving the alignment of the caption
- # (one of top, bottom, left, or right). It can be a hash of
- # all the attributes of the element. Or it can be omitted.
- #
- # The body of the element is provided by the passed-in no-argument block.
- #
- # caption("left") { "Capital Cities" }
- # # => <CAPTION ALIGN=\"left\">Capital Cities</CAPTION>
- def caption(align = {}) # :yield:
- attributes = if align.kind_of?(String)
- { "ALIGN" => align }
- else
- align
- end
- if block_given?
- super(attributes){ yield }
- else
- super(attributes)
- end
- end
-
-
- # Generate a Checkbox Input element as a string.
- #
- # The attributes of the element can be specified as three arguments,
- # +name+, +value+, and +checked+. +checked+ is a boolean value;
- # if true, the CHECKED attribute will be included in the element.
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # checkbox("name")
- # # = checkbox("NAME" => "name")
- #
- # checkbox("name", "value")
- # # = checkbox("NAME" => "name", "VALUE" => "value")
- #
- # checkbox("name", "value", true)
- # # = checkbox("NAME" => "name", "VALUE" => "value", "CHECKED" => true)
- def checkbox(name = "", value = nil, checked = nil)
- attributes = if name.kind_of?(String)
- { "TYPE" => "checkbox", "NAME" => name,
- "VALUE" => value, "CHECKED" => checked }
- else
- name["TYPE"] = "checkbox"
- name
- end
- input(attributes)
- end
-
- # Generate a sequence of checkbox elements, as a String.
- #
- # The checkboxes will all have the same +name+ attribute.
- # Each checkbox is followed by a label.
- # There will be one checkbox for each value. Each value
- # can be specified as a String, which will be used both
- # as the value of the VALUE attribute and as the label
- # for that checkbox. A single-element array has the
- # same effect.
- #
- # Each value can also be specified as a three-element array.
- # The first element is the VALUE attribute; the second is the
- # label; and the third is a boolean specifying whether this
- # checkbox is CHECKED.
- #
- # Each value can also be specified as a two-element
- # array, by omitting either the value element (defaults
- # to the same as the label), or the boolean checked element
- # (defaults to false).
- #
- # checkbox_group("name", "foo", "bar", "baz")
- # # <INPUT TYPE="checkbox" NAME="name" VALUE="foo">foo
- # # <INPUT TYPE="checkbox" NAME="name" VALUE="bar">bar
- # # <INPUT TYPE="checkbox" NAME="name" VALUE="baz">baz
- #
- # checkbox_group("name", ["foo"], ["bar", true], "baz")
- # # <INPUT TYPE="checkbox" NAME="name" VALUE="foo">foo
- # # <INPUT TYPE="checkbox" CHECKED NAME="name" VALUE="bar">bar
- # # <INPUT TYPE="checkbox" NAME="name" VALUE="baz">baz
- #
- # checkbox_group("name", ["1", "Foo"], ["2", "Bar", true], "Baz")
- # # <INPUT TYPE="checkbox" NAME="name" VALUE="1">Foo
- # # <INPUT TYPE="checkbox" CHECKED NAME="name" VALUE="2">Bar
- # # <INPUT TYPE="checkbox" NAME="name" VALUE="Baz">Baz
- #
- # checkbox_group("NAME" => "name",
- # "VALUES" => ["foo", "bar", "baz"])
- #
- # checkbox_group("NAME" => "name",
- # "VALUES" => [["foo"], ["bar", true], "baz"])
- #
- # checkbox_group("NAME" => "name",
- # "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"])
- def checkbox_group(name = "", *values)
- if name.kind_of?(Hash)
- values = name["VALUES"]
- name = name["NAME"]
- end
- values.collect{|value|
- if value.kind_of?(String)
- checkbox(name, value) + value
- else
- if value[value.bytesize - 1] == true
- checkbox(name, value[0], true) +
- value[value.bytesize - 2]
- else
- checkbox(name, value[0]) +
- value[value.bytesize - 1]
- end
- end
- }.join
- end
-
-
- # Generate an File Upload Input element as a string.
- #
- # The attributes of the element can be specified as three arguments,
- # +name+, +size+, and +maxlength+. +maxlength+ is the maximum length
- # of the file's _name_, not of the file's _contents_.
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # See #multipart_form() for forms that include file uploads.
- #
- # file_field("name")
- # # <INPUT TYPE="file" NAME="name" SIZE="20">
- #
- # file_field("name", 40)
- # # <INPUT TYPE="file" NAME="name" SIZE="40">
- #
- # file_field("name", 40, 100)
- # # <INPUT TYPE="file" NAME="name" SIZE="40" MAXLENGTH="100">
- #
- # file_field("NAME" => "name", "SIZE" => 40)
- # # <INPUT TYPE="file" NAME="name" SIZE="40">
- def file_field(name = "", size = 20, maxlength = nil)
- attributes = if name.kind_of?(String)
- { "TYPE" => "file", "NAME" => name,
- "SIZE" => size.to_s }
- else
- name["TYPE"] = "file"
- name
- end
- attributes["MAXLENGTH"] = maxlength.to_s if maxlength
- input(attributes)
- end
-
-
- # Generate a Form element as a string.
- #
- # +method+ should be either "get" or "post", and defaults to the latter.
- # +action+ defaults to the current CGI script name. +enctype+
- # defaults to "application/x-www-form-urlencoded".
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # See also #multipart_form() for forms that include file uploads.
- #
- # form{ "string" }
- # # <FORM METHOD="post" ENCTYPE="application/x-www-form-urlencoded">string</FORM>
- #
- # form("get") { "string" }
- # # <FORM METHOD="get" ENCTYPE="application/x-www-form-urlencoded">string</FORM>
- #
- # form("get", "url") { "string" }
- # # <FORM METHOD="get" ACTION="url" ENCTYPE="application/x-www-form-urlencoded">string</FORM>
- #
- # form("METHOD" => "post", "ENCTYPE" => "enctype") { "string" }
- # # <FORM METHOD="post" ENCTYPE="enctype">string</FORM>
- def form(method = "post", action = script_name, enctype = "application/x-www-form-urlencoded")
- attributes = if method.kind_of?(String)
- { "METHOD" => method, "ACTION" => action,
- "ENCTYPE" => enctype }
- else
- unless method.has_key?("METHOD")
- method["METHOD"] = "post"
- end
- unless method.has_key?("ENCTYPE")
- method["ENCTYPE"] = enctype
- end
- method
- end
- if block_given?
- body = yield
- else
- body = ""
- end
- if @output_hidden
- body += @output_hidden.collect{|k,v|
- "<INPUT TYPE=\"HIDDEN\" NAME=\"#{k}\" VALUE=\"#{v}\">"
- }.join
- end
- super(attributes){body}
- end
-
- # Generate a Hidden Input element as a string.
- #
- # The attributes of the element can be specified as two arguments,
- # +name+ and +value+.
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # hidden("name")
- # # <INPUT TYPE="hidden" NAME="name">
- #
- # hidden("name", "value")
- # # <INPUT TYPE="hidden" NAME="name" VALUE="value">
- #
- # hidden("NAME" => "name", "VALUE" => "reset", "ID" => "foo")
- # # <INPUT TYPE="hidden" NAME="name" VALUE="value" ID="foo">
- def hidden(name = "", value = nil)
- attributes = if name.kind_of?(String)
- { "TYPE" => "hidden", "NAME" => name, "VALUE" => value }
- else
- name["TYPE"] = "hidden"
- name
- end
- input(attributes)
- end
-
- # Generate a top-level HTML element as a string.
- #
- # The attributes of the element are specified as a hash. The
- # pseudo-attribute "PRETTY" can be used to specify that the generated
- # HTML string should be indented. "PRETTY" can also be specified as
- # a string as the sole argument to this method. The pseudo-attribute
- # "DOCTYPE", if given, is used as the leading DOCTYPE SGML tag; it
- # should include the entire text of this tag, including angle brackets.
- #
- # The body of the html element is supplied as a block.
- #
- # html{ "string" }
- # # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><HTML>string</HTML>
- #
- # html("LANG" => "ja") { "string" }
- # # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><HTML LANG="ja">string</HTML>
- #
- # html("DOCTYPE" => false) { "string" }
- # # <HTML>string</HTML>
- #
- # html("DOCTYPE" => '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">') { "string" }
- # # <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"><HTML>string</HTML>
- #
- # html("PRETTY" => " ") { "<BODY></BODY>" }
- # # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
- # # <HTML>
- # # <BODY>
- # # </BODY>
- # # </HTML>
- #
- # html("PRETTY" => "\t") { "<BODY></BODY>" }
- # # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
- # # <HTML>
- # # <BODY>
- # # </BODY>
- # # </HTML>
- #
- # html("PRETTY") { "<BODY></BODY>" }
- # # = html("PRETTY" => " ") { "<BODY></BODY>" }
- #
- # html(if $VERBOSE then "PRETTY" end) { "HTML string" }
- #
- def html(attributes = {}) # :yield:
- if nil == attributes
- attributes = {}
- elsif "PRETTY" == attributes
- attributes = { "PRETTY" => true }
- end
- pretty = attributes.delete("PRETTY")
- pretty = " " if true == pretty
- buf = ""
-
- if attributes.has_key?("DOCTYPE")
- if attributes["DOCTYPE"]
- buf += attributes.delete("DOCTYPE")
- else
- attributes.delete("DOCTYPE")
- end
- else
- buf += doctype
- end
-
- if block_given?
- buf += super(attributes){ yield }
- else
- buf += super(attributes)
- end
-
- if pretty
- CGI::pretty(buf, pretty)
- else
- buf
- end
-
- end
-
- # Generate an Image Button Input element as a string.
- #
- # +src+ is the URL of the image to use for the button. +name+
- # is the input name. +alt+ is the alternative text for the image.
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # image_button("url")
- # # <INPUT TYPE="image" SRC="url">
- #
- # image_button("url", "name", "string")
- # # <INPUT TYPE="image" SRC="url" NAME="name" ALT="string">
- #
- # image_button("SRC" => "url", "ATL" => "strng")
- # # <INPUT TYPE="image" SRC="url" ALT="string">
- def image_button(src = "", name = nil, alt = nil)
- attributes = if src.kind_of?(String)
- { "TYPE" => "image", "SRC" => src, "NAME" => name,
- "ALT" => alt }
- else
- src["TYPE"] = "image"
- src["SRC"] ||= ""
- src
- end
- input(attributes)
- end
-
-
- # Generate an Image element as a string.
- #
- # +src+ is the URL of the image. +alt+ is the alternative text for
- # the image. +width+ is the width of the image, and +height+ is
- # its height.
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # img("src", "alt", 100, 50)
- # # <IMG SRC="src" ALT="alt" WIDTH="100" HEIGHT="50">
- #
- # img("SRC" => "src", "ALT" => "alt", "WIDTH" => 100, "HEIGHT" => 50)
- # # <IMG SRC="src" ALT="alt" WIDTH="100" HEIGHT="50">
- def img(src = "", alt = "", width = nil, height = nil)
- attributes = if src.kind_of?(String)
- { "SRC" => src, "ALT" => alt }
- else
- src
- end
- attributes["WIDTH"] = width.to_s if width
- attributes["HEIGHT"] = height.to_s if height
- super(attributes)
- end
-
-
- # Generate a Form element with multipart encoding as a String.
- #
- # Multipart encoding is used for forms that include file uploads.
- #
- # +action+ is the action to perform. +enctype+ is the encoding
- # type, which defaults to "multipart/form-data".
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # multipart_form{ "string" }
- # # <FORM METHOD="post" ENCTYPE="multipart/form-data">string</FORM>
- #
- # multipart_form("url") { "string" }
- # # <FORM METHOD="post" ACTION="url" ENCTYPE="multipart/form-data">string</FORM>
- def multipart_form(action = nil, enctype = "multipart/form-data")
- attributes = if action == nil
- { "METHOD" => "post", "ENCTYPE" => enctype }
- elsif action.kind_of?(String)
- { "METHOD" => "post", "ACTION" => action,
- "ENCTYPE" => enctype }
- else
- unless action.has_key?("METHOD")
- action["METHOD"] = "post"
- end
- unless action.has_key?("ENCTYPE")
- action["ENCTYPE"] = enctype
- end
- action
- end
- if block_given?
- form(attributes){ yield }
- else
- form(attributes)
- end
- end
-
-
- # Generate a Password Input element as a string.
- #
- # +name+ is the name of the input field. +value+ is its default
- # value. +size+ is the size of the input field display. +maxlength+
- # is the maximum length of the inputted password.
- #
- # Alternatively, attributes can be specified as a hash.
- #
- # password_field("name")
- # # <INPUT TYPE="password" NAME="name" SIZE="40">
- #
- # password_field("name", "value")
- # # <INPUT TYPE="password" NAME="name" VALUE="value" SIZE="40">
- #
- # password_field("password", "value", 80, 200)
- # # <INPUT TYPE="password" NAME="name" VALUE="value" SIZE="80" MAXLENGTH="200">
- #
- # password_field("NAME" => "name", "VALUE" => "value")
- # # <INPUT TYPE="password" NAME="name" VALUE="value">
- def password_field(name = "", value = nil, size = 40, maxlength = nil)
- attributes = if name.kind_of?(String)
- { "TYPE" => "password", "NAME" => name,
- "VALUE" => value, "SIZE" => size.to_s }
- else
- name["TYPE"] = "password"
- name
- end
- attributes["MAXLENGTH"] = maxlength.to_s if maxlength
- input(attributes)
- end
-
- # Generate a Select element as a string.
- #
- # +name+ is the name of the element. The +values+ are the options that
- # can be selected from the Select menu. Each value can be a String or
- # a one, two, or three-element Array. If a String or a one-element
- # Array, this is both the value of that option and the text displayed for
- # it. If a three-element Array, the elements are the option value, displayed
- # text, and a boolean value specifying whether this option starts as selected.
- # The two-element version omits either the option value (defaults to the same
- # as the display text) or the boolean selected specifier (defaults to false).
- #
- # The attributes and options can also be specified as a hash. In this
- # case, options are specified as an array of values as described above,
- # with the hash key of "VALUES".
- #
- # popup_menu("name", "foo", "bar", "baz")
- # # <SELECT NAME="name">
- # # <OPTION VALUE="foo">foo</OPTION>
- # # <OPTION VALUE="bar">bar</OPTION>
- # # <OPTION VALUE="baz">baz</OPTION>
- # # </SELECT>
- #
- # popup_menu("name", ["foo"], ["bar", true], "baz")
- # # <SELECT NAME="name">
- # # <OPTION VALUE="foo">foo</OPTION>
- # # <OPTION VALUE="bar" SELECTED>bar</OPTION>
- # # <OPTION VALUE="baz">baz</OPTION>
- # # </SELECT>
- #
- # popup_menu("name", ["1", "Foo"], ["2", "Bar", true], "Baz")
- # # <SELECT NAME="name">
- # # <OPTION VALUE="1">Foo</OPTION>
- # # <OPTION SELECTED VALUE="2">Bar</OPTION>
- # # <OPTION VALUE="Baz">Baz</OPTION>
- # # </SELECT>
- #
- # popup_menu("NAME" => "name", "SIZE" => 2, "MULTIPLE" => true,
- # "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"])
- # # <SELECT NAME="name" MULTIPLE SIZE="2">
- # # <OPTION VALUE="1">Foo</OPTION>
- # # <OPTION SELECTED VALUE="2">Bar</OPTION>
- # # <OPTION VALUE="Baz">Baz</OPTION>
- # # </SELECT>
- def popup_menu(name = "", *values)
-
- if name.kind_of?(Hash)
- values = name["VALUES"]
- size = name["SIZE"].to_s if name["SIZE"]
- multiple = name["MULTIPLE"]
- name = name["NAME"]
- else
- size = nil
- multiple = nil
- end
-
- select({ "NAME" => name, "SIZE" => size,
- "MULTIPLE" => multiple }){
- values.collect{|value|
- if value.kind_of?(String)
- option({ "VALUE" => value }){ value }
- else
- if value[value.bytesize - 1] == true
- option({ "VALUE" => value[0], "SELECTED" => true }){
- value[value.bytesize - 2]
- }
- else
- option({ "VALUE" => value[0] }){
- value[value.bytesize - 1]
- }
- end
- end
- }.join
- }
-
- end
-
- # Generates a radio-button Input element.
- #
- # +name+ is the name of the input field. +value+ is the value of
- # the field if checked. +checked+ specifies whether the field
- # starts off checked.
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # radio_button("name", "value")
- # # <INPUT TYPE="radio" NAME="name" VALUE="value">
- #
- # radio_button("name", "value", true)
- # # <INPUT TYPE="radio" NAME="name" VALUE="value" CHECKED>
- #
- # radio_button("NAME" => "name", "VALUE" => "value", "ID" => "foo")
- # # <INPUT TYPE="radio" NAME="name" VALUE="value" ID="foo">
- def radio_button(name = "", value = nil, checked = nil)
- attributes = if name.kind_of?(String)
- { "TYPE" => "radio", "NAME" => name,
- "VALUE" => value, "CHECKED" => checked }
- else
- name["TYPE"] = "radio"
- name
- end
- input(attributes)
- end
-
- # Generate a sequence of radio button Input elements, as a String.
- #
- # This works the same as #checkbox_group(). However, it is not valid
- # to have more than one radiobutton in a group checked.
- #
- # radio_group("name", "foo", "bar", "baz")
- # # <INPUT TYPE="radio" NAME="name" VALUE="foo">foo
- # # <INPUT TYPE="radio" NAME="name" VALUE="bar">bar
- # # <INPUT TYPE="radio" NAME="name" VALUE="baz">baz
- #
- # radio_group("name", ["foo"], ["bar", true], "baz")
- # # <INPUT TYPE="radio" NAME="name" VALUE="foo">foo
- # # <INPUT TYPE="radio" CHECKED NAME="name" VALUE="bar">bar
- # # <INPUT TYPE="radio" NAME="name" VALUE="baz">baz
- #
- # radio_group("name", ["1", "Foo"], ["2", "Bar", true], "Baz")
- # # <INPUT TYPE="radio" NAME="name" VALUE="1">Foo
- # # <INPUT TYPE="radio" CHECKED NAME="name" VALUE="2">Bar
- # # <INPUT TYPE="radio" NAME="name" VALUE="Baz">Baz
- #
- # radio_group("NAME" => "name",
- # "VALUES" => ["foo", "bar", "baz"])
- #
- # radio_group("NAME" => "name",
- # "VALUES" => [["foo"], ["bar", true], "baz"])
- #
- # radio_group("NAME" => "name",
- # "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"])
- def radio_group(name = "", *values)
- if name.kind_of?(Hash)
- values = name["VALUES"]
- name = name["NAME"]
- end
- values.collect{|value|
- if value.kind_of?(String)
- radio_button(name, value) + value
- else
- if value[value.bytesize - 1] == true
- radio_button(name, value[0], true) +
- value[value.bytesize - 2]
- else
- radio_button(name, value[0]) +
- value[value.bytesize - 1]
- end
- end
- }.join
- end
-
- # Generate a reset button Input element, as a String.
- #
- # This resets the values on a form to their initial values. +value+
- # is the text displayed on the button. +name+ is the name of this button.
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # reset
- # # <INPUT TYPE="reset">
- #
- # reset("reset")
- # # <INPUT TYPE="reset" VALUE="reset">
- #
- # reset("VALUE" => "reset", "ID" => "foo")
- # # <INPUT TYPE="reset" VALUE="reset" ID="foo">
- def reset(value = nil, name = nil)
- attributes = if (not value) or value.kind_of?(String)
- { "TYPE" => "reset", "VALUE" => value, "NAME" => name }
- else
- value["TYPE"] = "reset"
- value
- end
- input(attributes)
- end
-
- alias scrolling_list popup_menu
-
- # Generate a submit button Input element, as a String.
- #
- # +value+ is the text to display on the button. +name+ is the name
- # of the input.
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # submit
- # # <INPUT TYPE="submit">
- #
- # submit("ok")
- # # <INPUT TYPE="submit" VALUE="ok">
- #
- # submit("ok", "button1")
- # # <INPUT TYPE="submit" VALUE="ok" NAME="button1">
- #
- # submit("VALUE" => "ok", "NAME" => "button1", "ID" => "foo")
- # # <INPUT TYPE="submit" VALUE="ok" NAME="button1" ID="foo">
- def submit(value = nil, name = nil)
- attributes = if (not value) or value.kind_of?(String)
- { "TYPE" => "submit", "VALUE" => value, "NAME" => name }
- else
- value["TYPE"] = "submit"
- value
- end
- input(attributes)
- end
-
- # Generate a text field Input element, as a String.
- #
- # +name+ is the name of the input field. +value+ is its initial
- # value. +size+ is the size of the input area. +maxlength+
- # is the maximum length of input accepted.
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # text_field("name")
- # # <INPUT TYPE="text" NAME="name" SIZE="40">
- #
- # text_field("name", "value")
- # # <INPUT TYPE="text" NAME="name" VALUE="value" SIZE="40">
- #
- # text_field("name", "value", 80)
- # # <INPUT TYPE="text" NAME="name" VALUE="value" SIZE="80">
- #
- # text_field("name", "value", 80, 200)
- # # <INPUT TYPE="text" NAME="name" VALUE="value" SIZE="80" MAXLENGTH="200">
- #
- # text_field("NAME" => "name", "VALUE" => "value")
- # # <INPUT TYPE="text" NAME="name" VALUE="value">
- def text_field(name = "", value = nil, size = 40, maxlength = nil)
- attributes = if name.kind_of?(String)
- { "TYPE" => "text", "NAME" => name, "VALUE" => value,
- "SIZE" => size.to_s }
- else
- name["TYPE"] = "text"
- name
- end
- attributes["MAXLENGTH"] = maxlength.to_s if maxlength
- input(attributes)
- end
-
- # Generate a TextArea element, as a String.
- #
- # +name+ is the name of the textarea. +cols+ is the number of
- # columns and +rows+ is the number of rows in the display.
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # The body is provided by the passed-in no-argument block
- #
- # textarea("name")
- # # = textarea("NAME" => "name", "COLS" => 70, "ROWS" => 10)
- #
- # textarea("name", 40, 5)
- # # = textarea("NAME" => "name", "COLS" => 40, "ROWS" => 5)
- def textarea(name = "", cols = 70, rows = 10) # :yield:
- attributes = if name.kind_of?(String)
- { "NAME" => name, "COLS" => cols.to_s,
- "ROWS" => rows.to_s }
- else
- name
- end
- if block_given?
- super(attributes){ yield }
- else
- super(attributes)
- end
- end
-
- end # HtmlExtension
-
-
- # Mixin module for HTML version 3 generation methods.
- module Html3 # :nodoc:
-
- # The DOCTYPE declaration for this version of HTML
- def doctype
- %|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">|
- end
-
- # Initialise the HTML generation methods for this version.
- def element_init
- extend TagMaker
- methods = ""
- # - -
- for element in %w[ A TT I B U STRIKE BIG SMALL SUB SUP EM STRONG
- DFN CODE SAMP KBD VAR CITE FONT ADDRESS DIV center MAP
- APPLET PRE XMP LISTING DL OL UL DIR MENU SELECT table TITLE
- STYLE SCRIPT H1 H2 H3 H4 H5 H6 TEXTAREA FORM BLOCKQUOTE
- CAPTION ]
- methods += <<-BEGIN + nn_element_def(element) + <<-END
- def #{element.downcase}(attributes = {})
- BEGIN
- end
- END
- end
-
- # - O EMPTY
- for element in %w[ IMG BASE BASEFONT BR AREA LINK PARAM HR INPUT
- ISINDEX META ]
- methods += <<-BEGIN + nOE_element_def(element) + <<-END
- def #{element.downcase}(attributes = {})
- BEGIN
- end
- END
- end
-
- # O O or - O
- for element in %w[ HTML HEAD BODY P PLAINTEXT DT DD LI OPTION tr
- th td ]
- methods += <<-BEGIN + nO_element_def(element) + <<-END
- def #{element.downcase}(attributes = {})
- BEGIN
- end
- END
- end
- eval(methods)
- end
-
- end # Html3
-
-
- # Mixin module for HTML version 4 generation methods.
- module Html4 # :nodoc:
-
- # The DOCTYPE declaration for this version of HTML
- def doctype
- %|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">|
- end
-
- # Initialise the HTML generation methods for this version.
- def element_init
- extend TagMaker
- methods = ""
- # - -
- for element in %w[ TT I B BIG SMALL EM STRONG DFN CODE SAMP KBD
- VAR CITE ABBR ACRONYM SUB SUP SPAN BDO ADDRESS DIV MAP OBJECT
- H1 H2 H3 H4 H5 H6 PRE Q INS DEL DL OL UL LABEL SELECT OPTGROUP
- FIELDSET LEGEND BUTTON TABLE TITLE STYLE SCRIPT NOSCRIPT
- TEXTAREA FORM A BLOCKQUOTE CAPTION ]
- methods += <<-BEGIN + nn_element_def(element) + <<-END
- def #{element.downcase}(attributes = {})
- BEGIN
- end
- END
- end
-
- # - O EMPTY
- for element in %w[ IMG BASE BR AREA LINK PARAM HR INPUT COL META ]
- methods += <<-BEGIN + nOE_element_def(element) + <<-END
- def #{element.downcase}(attributes = {})
- BEGIN
- end
- END
- end
-
- # O O or - O
- for element in %w[ HTML BODY P DT DD LI OPTION THEAD TFOOT TBODY
- COLGROUP TR TH TD HEAD]
- methods += <<-BEGIN + nO_element_def(element) + <<-END
- def #{element.downcase}(attributes = {})
- BEGIN
- end
- END
- end
- eval(methods)
- end
-
- end # Html4
-
-
- # Mixin module for HTML version 4 transitional generation methods.
- module Html4Tr # :nodoc:
-
- # The DOCTYPE declaration for this version of HTML
- def doctype
- %|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">|
- end
-
- # Initialise the HTML generation methods for this version.
- def element_init
- extend TagMaker
- methods = ""
- # - -
- for element in %w[ TT I B U S STRIKE BIG SMALL EM STRONG DFN
- CODE SAMP KBD VAR CITE ABBR ACRONYM FONT SUB SUP SPAN BDO
- ADDRESS DIV CENTER MAP OBJECT APPLET H1 H2 H3 H4 H5 H6 PRE Q
- INS DEL DL OL UL DIR MENU LABEL SELECT OPTGROUP FIELDSET
- LEGEND BUTTON TABLE IFRAME NOFRAMES TITLE STYLE SCRIPT
- NOSCRIPT TEXTAREA FORM A BLOCKQUOTE CAPTION ]
- methods += <<-BEGIN + nn_element_def(element) + <<-END
- def #{element.downcase}(attributes = {})
- BEGIN
- end
- END
- end
-
- # - O EMPTY
- for element in %w[ IMG BASE BASEFONT BR AREA LINK PARAM HR INPUT
- COL ISINDEX META ]
- methods += <<-BEGIN + nOE_element_def(element) + <<-END
- def #{element.downcase}(attributes = {})
- BEGIN
- end
- END
- end
-
- # O O or - O
- for element in %w[ HTML BODY P DT DD LI OPTION THEAD TFOOT TBODY
- COLGROUP TR TH TD HEAD ]
- methods += <<-BEGIN + nO_element_def(element) + <<-END
- def #{element.downcase}(attributes = {})
- BEGIN
- end
- END
- end
- eval(methods)
- end
-
- end # Html4Tr
-
-
- # Mixin module for generating HTML version 4 with framesets.
- module Html4Fr # :nodoc:
-
- # The DOCTYPE declaration for this version of HTML
- def doctype
- %|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">|
- end
-
- # Initialise the HTML generation methods for this version.
- def element_init
- methods = ""
- # - -
- for element in %w[ FRAMESET ]
- methods += <<-BEGIN + nn_element_def(element) + <<-END
- def #{element.downcase}(attributes = {})
- BEGIN
- end
- END
- end
-
- # - O EMPTY
- for element in %w[ FRAME ]
- methods += <<-BEGIN + nOE_element_def(element) + <<-END
- def #{element.downcase}(attributes = {})
- BEGIN
- end
- END
- end
- eval(methods)
- end
-
- end # Html4Fr
-
-
- # Creates a new CGI instance.
- #
- # +type+ specifies which version of HTML to load the HTML generation
- # methods for. The following versions of HTML are supported:
- #
- # html3:: HTML 3.x
- # html4:: HTML 4.0
- # html4Tr:: HTML 4.0 Transitional
- # html4Fr:: HTML 4.0 with Framesets
- #
- # If not specified, no HTML generation methods will be loaded.
- #
- # If the CGI object is not created in a standard CGI call environment
- # (that is, it can't locate REQUEST_METHOD in its environment), then
- # it will run in "offline" mode. In this mode, it reads its parameters
- # from the command line or (failing that) from standard input. Otherwise,
- # cookies and other parameters are parsed automatically from the standard
- # CGI locations, which varies according to the REQUEST_METHOD.
- def initialize(type = "query")
- if defined?(MOD_RUBY) && !ENV.key?("GATEWAY_INTERFACE")
- Apache.request.setup_cgi_env
- end
-
- extend QueryExtension
- @multipart = false
-
- initialize_query() # set @params, @cookies
- @output_cookies = nil
- @output_hidden = nil
-
- case type
- when "html3"
- extend Html3
- element_init()
- extend HtmlExtension
- when "html4"
- extend Html4
- element_init()
- extend HtmlExtension
- when "html4Tr"
- extend Html4Tr
- element_init()
- extend HtmlExtension
- when "html4Fr"
- extend Html4Tr
- element_init()
- extend Html4Fr
- element_init()
- extend HtmlExtension
- end
- end
-
-end # class CGI
+require 'cgi/core'
+require 'cgi/cookie'
+require 'cgi/util'
diff --git a/lib/cgi/cookie.rb b/lib/cgi/cookie.rb
new file mode 100644
index 0000000000..befe1402e6
--- /dev/null
+++ b/lib/cgi/cookie.rb
@@ -0,0 +1,137 @@
+ # Class representing an HTTP cookie.
+ #
+ # In addition to its specific fields and methods, a Cookie instance
+ # is a delegator to the array of its values.
+ #
+ # See RFC 2965.
+ #
+ # == Examples of use
+ # cookie1 = CGI::Cookie::new("name", "value1", "value2", ...)
+ # cookie1 = CGI::Cookie::new("name" => "name", "value" => "value")
+ # cookie1 = CGI::Cookie::new('name' => 'name',
+ # 'value' => ['value1', 'value2', ...],
+ # 'path' => 'path', # optional
+ # 'domain' => 'domain', # optional
+ # 'expires' => Time.now, # optional
+ # 'secure' => true # optional
+ # )
+ #
+ # cgi.out("cookie" => [cookie1, cookie2]) { "string" }
+ #
+ # name = cookie1.name
+ # values = cookie1.value
+ # path = cookie1.path
+ # domain = cookie1.domain
+ # expires = cookie1.expires
+ # secure = cookie1.secure
+ #
+ # cookie1.name = 'name'
+ # cookie1.value = ['value1', 'value2', ...]
+ # cookie1.path = 'path'
+ # cookie1.domain = 'domain'
+ # cookie1.expires = Time.now + 30
+ # cookie1.secure = true
+class CGI
+ class Cookie < Array
+
+ # Create a new CGI::Cookie object.
+ #
+ # The contents of the cookie can be specified as a +name+ and one
+ # or more +value+ arguments. Alternatively, the contents can
+ # be specified as a single hash argument. The possible keywords of
+ # this hash are as follows:
+ #
+ # name:: the name of the cookie. Required.
+ # value:: the cookie's value or list of values.
+ # path:: the path for which this cookie applies. Defaults to the
+ # base directory of the CGI script.
+ # domain:: the domain for which this cookie applies.
+ # expires:: the time at which this cookie expires, as a +Time+ object.
+ # secure:: whether this cookie is a secure cookie or not (default to
+ # false). Secure cookies are only transmitted to HTTPS
+ # servers.
+ #
+ # These keywords correspond to attributes of the cookie object.
+ def initialize(name = "", *value)
+ if name.kind_of?(String)
+ @name = name
+ @value = value
+ %r|^(.*/)|.match(ENV["SCRIPT_NAME"])
+ @path = ($1 or "")
+ @secure = false
+ return super(@value)
+ end
+
+ options = name
+ unless options.has_key?("name")
+ raise ArgumentError, "`name' required"
+ end
+
+ @name = options["name"]
+ @value = Array(options["value"])
+ # simple support for IE
+ if options["path"]
+ @path = options["path"]
+ else
+ %r|^(.*/)|.match(ENV["SCRIPT_NAME"])
+ @path = ($1 or "")
+ end
+ @domain = options["domain"]
+ @expires = options["expires"]
+ @secure = options["secure"] == true ? true : false
+
+ super(@value)
+ end
+
+ attr_accessor("name", "value", "path", "domain", "expires")
+ attr_reader("secure")
+
+ # Set whether the Cookie is a secure cookie or not.
+ #
+ # +val+ must be a boolean.
+ def secure=(val)
+ @secure = val if val == true or val == false
+ @secure
+ end
+
+ # Convert the Cookie to its string representation.
+ def to_s
+ val = @value.kind_of?(String) ? CGI::escape(@value) : @value.collect{|v| CGI::escape(v) }.join("&")
+ buf = "#{@name}=#{val}"
+ buf << "; domain=#{@domain}" if @domain
+ buf << "; path=#{@path}" if @path
+ buf << "; expires=#{CGI::rfc1123_date(@expires)}" if @expires
+ buf << "; secure" if @secure == true
+ buf
+ end
+
+ end # class Cookie
+
+
+ # Parse a raw cookie string into a hash of cookie-name=>Cookie
+ # pairs.
+ #
+ # cookies = CGI::Cookie::parse("raw_cookie_string")
+ # # { "name1" => cookie1, "name2" => cookie2, ... }
+ #
+ def Cookie::parse(raw_cookie)
+ cookies = Hash.new([])
+ return cookies unless raw_cookie
+
+ raw_cookie.split(/[;,]\s?/).each do |pairs|
+ name, values = pairs.split('=',2)
+ next unless name and values
+ name = CGI::unescape(name)
+ values ||= ""
+ values = values.split('&').collect{|v| CGI::unescape(v) }
+ if cookies.has_key?(name)
+ values = cookies[name].value + values
+ end
+ cookies[name] = Cookie::new(name, *values)
+ end
+
+ cookies
+ end
+end
+
+
diff --git a/lib/cgi/core.rb b/lib/cgi/core.rb
new file mode 100644
index 0000000000..87c4f68540
--- /dev/null
+++ b/lib/cgi/core.rb
@@ -0,0 +1,784 @@
+class CGI
+
+ $CGI_ENV = ENV # for FCGI support
+
+ # String for carriage return
+ CR = "\015"
+
+ # String for linefeed
+ LF = "\012"
+
+ # Standard internet newline sequence
+ EOL = CR + LF
+
+ REVISION = '$Id$' #:nodoc:
+
+ NEEDS_BINMODE = true if /WIN/i.match(RUBY_PLATFORM)
+
+ # Path separators in different environments.
+ PATH_SEPARATOR = {'UNIX'=>'/', 'WINDOWS'=>'\\', 'MACINTOSH'=>':'}
+
+ # HTTP status codes.
+ HTTP_STATUS = {
+ "OK" => "200 OK",
+ "PARTIAL_CONTENT" => "206 Partial Content",
+ "MULTIPLE_CHOICES" => "300 Multiple Choices",
+ "MOVED" => "301 Moved Permanently",
+ "REDIRECT" => "302 Found",
+ "NOT_MODIFIED" => "304 Not Modified",
+ "BAD_REQUEST" => "400 Bad Request",
+ "AUTH_REQUIRED" => "401 Authorization Required",
+ "FORBIDDEN" => "403 Forbidden",
+ "NOT_FOUND" => "404 Not Found",
+ "METHOD_NOT_ALLOWED" => "405 Method Not Allowed",
+ "NOT_ACCEPTABLE" => "406 Not Acceptable",
+ "LENGTH_REQUIRED" => "411 Length Required",
+ "PRECONDITION_FAILED" => "412 Rrecondition Failed",
+ "SERVER_ERROR" => "500 Internal Server Error",
+ "NOT_IMPLEMENTED" => "501 Method Not Implemented",
+ "BAD_GATEWAY" => "502 Bad Gateway",
+ "VARIANT_ALSO_VARIES" => "506 Variant Also Negotiates"
+ }
+
+ # Abbreviated day-of-week names specified by RFC 822
+ RFC822_DAYS = %w[ Sun Mon Tue Wed Thu Fri Sat ]
+
+ # Abbreviated month names specified by RFC 822
+ RFC822_MONTHS = %w[ Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ]
+
+ # :startdoc:
+
+ def env_table
+ ENV
+ end
+
+ def stdinput
+ $stdin
+ end
+
+ def stdoutput
+ $stdout
+ end
+
+ private :env_table, :stdinput, :stdoutput
+
+
+ # Create an HTTP header block as a string.
+ #
+ # Includes the empty line that ends the header block.
+ #
+ # +options+ can be a string specifying the Content-Type (defaults
+ # to text/html), or a hash of header key/value pairs. The following
+ # header keys are recognized:
+ #
+ # type:: the Content-Type header. Defaults to "text/html"
+ # charset:: the charset of the body, appended to the Content-Type header.
+ # nph:: a boolean value. If true, prepend protocol string and status code, and
+ # date; and sets default values for "server" and "connection" if not
+ # explicitly set.
+ # status:: the HTTP status code, returned as the Status header. See the
+ # list of available status codes below.
+ # server:: the server software, returned as the Server header.
+ # connection:: the connection type, returned as the Connection header (for
+ # instance, "close".
+ # length:: the length of the content that will be sent, returned as the
+ # Content-Length header.
+ # language:: the language of the content, returned as the Content-Language
+ # header.
+ # expires:: the time on which the current content expires, as a +Time+
+ # object, returned as the Expires header.
+ # cookie:: a cookie or cookies, returned as one or more Set-Cookie headers.
+ # The value can be the literal string of the cookie; a CGI::Cookie
+ # object; an Array of literal cookie strings or Cookie objects; or a
+ # hash all of whose values are literal cookie strings or Cookie objects.
+ # These cookies are in addition to the cookies held in the
+ # @output_cookies field.
+ #
+ # Other header lines can also be set; they are appended as key: value.
+ #
+ # header
+ # # Content-Type: text/html
+ #
+ # header("text/plain")
+ # # Content-Type: text/plain
+ #
+ # header("nph" => true,
+ # "status" => "OK", # == "200 OK"
+ # # "status" => "200 GOOD",
+ # "server" => ENV['SERVER_SOFTWARE'],
+ # "connection" => "close",
+ # "type" => "text/html",
+ # "charset" => "iso-2022-jp",
+ # # Content-Type: text/html; charset=iso-2022-jp
+ # "length" => 103,
+ # "language" => "ja",
+ # "expires" => Time.now + 30,
+ # "cookie" => [cookie1, cookie2],
+ # "my_header1" => "my_value"
+ # "my_header2" => "my_value")
+ #
+ # The status codes are:
+ #
+ # "OK" --> "200 OK"
+ # "PARTIAL_CONTENT" --> "206 Partial Content"
+ # "MULTIPLE_CHOICES" --> "300 Multiple Choices"
+ # "MOVED" --> "301 Moved Permanently"
+ # "REDIRECT" --> "302 Found"
+ # "NOT_MODIFIED" --> "304 Not Modified"
+ # "BAD_REQUEST" --> "400 Bad Request"
+ # "AUTH_REQUIRED" --> "401 Authorization Required"
+ # "FORBIDDEN" --> "403 Forbidden"
+ # "NOT_FOUND" --> "404 Not Found"
+ # "METHOD_NOT_ALLOWED" --> "405 Method Not Allowed"
+ # "NOT_ACCEPTABLE" --> "406 Not Acceptable"
+ # "LENGTH_REQUIRED" --> "411 Length Required"
+ # "PRECONDITION_FAILED" --> "412 Precondition Failed"
+ # "SERVER_ERROR" --> "500 Internal Server Error"
+ # "NOT_IMPLEMENTED" --> "501 Method Not Implemented"
+ # "BAD_GATEWAY" --> "502 Bad Gateway"
+ # "VARIANT_ALSO_VARIES" --> "506 Variant Also Negotiates"
+ #
+ # This method does not perform charset conversion.
+ def header(options='text/html')
+ if options.is_a?(String)
+ content_type = options
+ buf = _header_for_string(content_type)
+ elsif options.is_a?(Hash)
+ if options.size == 1 && options.has_key?('type')
+ content_type = options['type']
+ buf = _header_for_string(content_type)
+ else
+ buf = _header_for_hash(options.dup)
+ end
+ else
+ raise ArgumentError.new("expected String or Hash but got #{options.class}")
+ end
+ if defined?(MOD_RUBY)
+ _header_for_modruby(buf)
+ return ''
+ else
+ buf << EOL # empty line of separator
+ return buf
+ end
+ end # header()
+
+ def _header_for_string(content_type) #:nodoc:
+ buf = ''
+ if nph?()
+ buf << "#{$CGI_ENV['SERVER_PROTOCOL'] || 'HTTP/1.0'} 200 OK#{EOL}"
+ buf << "Date: #{CGI.rfc1123_date(Time.now)}#{EOL}"
+ buf << "Server: #{$CGI_ENV['SERVER_SOFTWARE']}#{EOL}"
+ buf << "Connection: close#{EOL}"
+ end
+ buf << "Content-Type: #{content_type}#{EOL}"
+ if @output_cookies
+ @output_cookies.each {|cookie| buf << "Set-Cookie: #{cookie}#{EOL}" }
+ end
+ return buf
+ end # _header_for_string
+ private :_header_for_string
+
+ def _header_for_hash(options) #:nodoc:
+ buf = ''
+ ## add charset to option['type']
+ options['type'] ||= 'text/html'
+ charset = options.delete('charset')
+ options['type'] += "; charset=#{charset}" if charset
+ ## NPH
+ options.delete('nph') if defined?(MOD_RUBY)
+ if options.delete('nph') || nph?()
+ protocol = $CGI_ENV['SERVER_PROTOCOL'] || 'HTTP/1.0'
+ status = options.delete('status')
+ status = HTTP_STATUS[status] || status || '200 OK'
+ buf << "#{protocol} #{status}#{EOL}"
+ buf << "Date: #{CGI.rfc1123_date(Time.now)}#{EOL}"
+ options['server'] ||= $CGI_ENV['SERVER_SOFTWARE'] || ''
+ options['connection'] ||= 'close'
+ end
+ ## common headers
+ status = options.delete('status')
+ buf << "Status: #{HTTP_STATUS[status] || status}#{EOL}" if status
+ server = options.delete('server')
+ buf << "Server: #{server}#{EOL}" if server
+ connection = options.delete('connection')
+ buf << "Connection: #{connection}#{EOL}" if connection
+ type = options.delete('type')
+ buf << "Content-Type: #{type}#{EOL}" #if type
+ length = options.delete('length')
+ buf << "Content-Length: #{length}#{EOL}" if length
+ language = options.delete('language')
+ buf << "Content-Language: #{language}#{EOL}" if language
+ expires = options.delete('expires')
+ buf << "Expires: #{CGI.rfc1123_date(expires)}#{EOL}" if expires
+ ## cookie
+ if cookie = options.delete('cookie')
+ case cookie
+ when String, Cookie
+ buf << "Set-Cookie: #{cookie}#{EOL}"
+ when Array
+ arr = cookie
+ arr.each {|c| buf << "Set-Cookie: #{c}#{EOL}" }
+ when Hash
+ hash = cookie
+ hash.each {|name, c| buf << "Set-Cookie: #{c}#{EOL}" }
+ end
+ end
+ if @output_cookies
+ @output_cookies.each {|c| buf << "Set-Cookie: #{c}#{EOL}" }
+ end
+ ## other headers
+ options.each do |key, value|
+ buf << "#{key}: #{value}#{EOL}"
+ end
+ return buf
+ end # _header_for_hash
+ private :_header_for_hash
+
+ def nph? #:nodoc:
+ return /IIS\/(\d+)/.match($CGI_ENV['SERVER_SOFTWARE']) && $1.to_i < 5
+ end
+
+ def _header_for_modruby(buf) #:nodoc:
+ request = Apache::request
+ buf.scan(/([^:]+): (.+)#{EOL}/o) do |name, value|
+ warn sprintf("name:%s value:%s\n", name, value) if $DEBUG
+ case name
+ when 'Set-Cookie'
+ request.headers_out.add(name, value)
+ when /^status$/i
+ request.status_line = value
+ request.status = value.to_i
+ when /^content-type$/i
+ request.content_type = value
+ when /^content-encoding$/i
+ request.content_encoding = value
+ when /^location$/i
+ request.status = 302 if request.status == 200
+ request.headers_out[name] = value
+ else
+ request.headers_out[name] = value
+ end
+ end
+ request.send_http_header
+ return ''
+ end
+ private :_header_for_modruby
+ #
+
+ # Print an HTTP header and body to $DEFAULT_OUTPUT ($>)
+ #
+ # The header is provided by +options+, as for #header().
+ # The body of the document is that returned by the passed-
+ # in block. This block takes no arguments. It is required.
+ #
+ # cgi = CGI.new
+ # cgi.out{ "string" }
+ # # Content-Type: text/html
+ # # Content-Length: 6
+ # #
+ # # string
+ #
+ # cgi.out("text/plain") { "string" }
+ # # Content-Type: text/plain
+ # # Content-Length: 6
+ # #
+ # # string
+ #
+ # cgi.out("nph" => true,
+ # "status" => "OK", # == "200 OK"
+ # "server" => ENV['SERVER_SOFTWARE'],
+ # "connection" => "close",
+ # "type" => "text/html",
+ # "charset" => "iso-2022-jp",
+ # # Content-Type: text/html; charset=iso-2022-jp
+ # "language" => "ja",
+ # "expires" => Time.now + (3600 * 24 * 30),
+ # "cookie" => [cookie1, cookie2],
+ # "my_header1" => "my_value",
+ # "my_header2" => "my_value") { "string" }
+ #
+ # Content-Length is automatically calculated from the size of
+ # the String returned by the content block.
+ #
+ # If ENV['REQUEST_METHOD'] == "HEAD", then only the header
+ # is outputted (the content block is still required, but it
+ # is ignored).
+ #
+ # If the charset is "iso-2022-jp" or "euc-jp" or "shift_jis" then
+ # the content is converted to this charset, and the language is set
+ # to "ja".
+ def out(options = "text/html") # :yield:
+
+ options = { "type" => options } if options.kind_of?(String)
+ content = yield
+ options["length"] = content.bytesize.to_s
+ output = stdoutput
+ output.binmode if defined? output.binmode
+ output.print header(options)
+ output.print content unless "HEAD" == env_table['REQUEST_METHOD']
+ end
+
+
+ # Print an argument or list of arguments to the default output stream
+ #
+ # cgi = CGI.new
+ # cgi.print # default: cgi.print == $DEFAULT_OUTPUT.print
+ def print(*options)
+ stdoutput.print(*options)
+ end
+
+ # Parse an HTTP query string into a hash of key=>value pairs.
+ #
+ # params = CGI::parse("query_string")
+ # # {"name1" => ["value1", "value2", ...],
+ # # "name2" => ["value1", "value2", ...], ... }
+ #
+ def CGI::parse(query)
+ params = {}
+ query.split(/[&;]/).each do |pairs|
+ key, value = pairs.split('=',2).collect{|v| CGI::unescape(v) }
+ if key && value
+ params.has_key?(key) ? params[key].push(value) : params[key] = [value]
+ end
+ end
+ params.default=[].freeze
+ params
+ end
+
+ # Maximum content length of post data
+ ##MAX_CONTENT_LENGTH = 2 * 1024 * 1024
+
+ # Maximum content length of multipart data
+ MAX_MULTIPART_LENGTH = 128 * 1024 * 1024
+
+ # Maximum number of request parameters when multipart
+ MAX_MULTIPART_COUNT = 128
+
+ # Mixin module. It provides the follow functionality groups:
+ #
+ # 1. Access to CGI environment variables as methods. See
+ # documentation to the CGI class for a list of these variables.
+ #
+ # 2. Access to cookies, including the cookies attribute.
+ #
+ # 3. Access to parameters, including the params attribute, and overloading
+ # [] to perform parameter value lookup by key.
+ #
+ # 4. The initialize_query method, for initialising the above
+ # mechanisms, handling multipart forms, and allowing the
+ # class to be used in "offline" mode.
+ #
+ module QueryExtension
+
+ %w[ CONTENT_LENGTH SERVER_PORT ].each do |env|
+ define_method(env.sub(/^HTTP_/, '').downcase) do
+ (val = env_table[env]) && Integer(val)
+ end
+ end
+
+ %w[ AUTH_TYPE CONTENT_TYPE GATEWAY_INTERFACE PATH_INFO
+ PATH_TRANSLATED QUERY_STRING REMOTE_ADDR REMOTE_HOST
+ REMOTE_IDENT REMOTE_USER REQUEST_METHOD SCRIPT_NAME
+ SERVER_NAME SERVER_PROTOCOL SERVER_SOFTWARE
+
+ HTTP_ACCEPT HTTP_ACCEPT_CHARSET HTTP_ACCEPT_ENCODING
+ HTTP_ACCEPT_LANGUAGE HTTP_CACHE_CONTROL HTTP_FROM HTTP_HOST
+ HTTP_NEGOTIATE HTTP_PRAGMA HTTP_REFERER HTTP_USER_AGENT ].each do |env|
+ define_method(env.sub(/^HTTP_/, '').downcase) do
+ env_table[env]
+ end
+ end
+
+ # Get the raw cookies as a string.
+ def raw_cookie
+ env_table["HTTP_COOKIE"]
+ end
+
+ # Get the raw RFC2965 cookies as a string.
+ def raw_cookie2
+ env_table["HTTP_COOKIE2"]
+ end
+
+ # Get the cookies as a hash of cookie-name=>Cookie pairs.
+ attr_accessor :cookies
+
+ # Get the parameters as a hash of name=>values pairs, where
+ # values is an Array.
+ attr_reader :params
+
+ # Get the uploaed files as a hash of name=>values pairs
+ attr_reader :files
+
+ # Set all the parameters.
+ def params=(hash)
+ @params.clear
+ @params.update(hash)
+ end
+
+ def read_multipart(boundary, content_length)
+ ## read first boundary
+ stdin = $stdin
+ first_line = "--#{boundary}#{EOL}"
+ content_length -= first_line.bytesize
+ status = stdin.read(first_line.bytesize)
+ raise EOFError.new("no content body") unless status
+ raise EOFError.new("bad content body") unless first_line == status
+ ## parse and set params
+ params = {}
+ @files = {}
+ boundary_rexp = /--#{Regexp.quote(boundary)}(#{EOL}|--)/
+ boundary_size = "#{EOL}--#{boundary}#{EOL}".bytesize
+ boundary_end = nil
+ buf = ''
+ bufsize = 10 * 1024
+ max_count = MAX_MULTIPART_COUNT
+ n = 0
+ while true
+ (n += 1) < max_count or raise StandardError.new("too many parameters.")
+ ## create body (StringIO or Tempfile)
+ body = create_body(bufsize < content_length)
+ class << body
+ alias local_path path
+ attr_reader :original_filename, :content_type
+ end
+ ## find head and boundary
+ head = nil
+ separator = EOL * 2
+ until head && matched = boundary_rexp.match(buf)
+ if !head && pos = buf.index(separator)
+ len = pos + EOL.bytesize
+ head = buf[0, len]
+ buf = buf[(pos+separator.bytesize)..-1]
+ else
+ if head && buf.size > boundary_size
+ len = buf.size - boundary_size
+ body.print(buf[0, len])
+ buf[0, len] = ''
+ end
+ c = stdin.read(bufsize < content_length ? bufsize : content_length)
+ raise EOFError.new("bad content body") if c.nil? || c.empty?
+ buf << c
+ content_length -= c.bytesize
+ end
+ end
+ ## read to end of boundary
+ m = matched
+ len = m.begin(0)
+ s = buf[0, len]
+ if s =~ /(\r?\n)\z/
+ s = buf[0, len - $1.bytesize]
+ end
+ body.print(s)
+ buf = buf[m.end(0)..-1]
+ boundary_end = m[1]
+ content_length = -1 if boundary_end == '--'
+ ## reset file cursor position
+ body.rewind
+ ## original filename
+ /Content-Disposition:.* filename=(?:"(.*?)"|([^;\r\n]*))/i.match(head)
+ filename = $1 || $2 || ''
+ filename = CGI.unescape(filename) if unescape_filename?()
+ body.instance_variable_set('@original_filename', filename.taint)
+ ## content type
+ /Content-Type: (.*)/i.match(head)
+ (content_type = $1 || '').chomp!
+ body.instance_variable_set('@content_type', content_type.taint)
+ ## query parameter name
+ /Content-Disposition:.* name=(?:"(.*?)"|([^;\r\n]*))/i.match(head)
+ name = $1 || $2 || ''
+ if body.original_filename.empty?
+ value=body.read.dup.force_encoding(@accept_charset)
+ (params[name] ||= []) << value
+ unless value.valid_encoding?
+ if @accept_charset_error_block
+ @accept_charset_error_block.call(name,value)
+ else
+ raise InvalidEncoding,"Accept-Charset encoding error"
+ end
+ end
+ class << params[name].last;self;end.class_eval do
+ define_method(:read){self}
+ define_method(:original_filename){""}
+ define_method(:content_type){""}
+ end
+ else
+ (params[name] ||= []) << body
+ @files[name]=body
+ end
+ ## break loop
+ break if buf.size == 0
+ break if content_length == -1
+ end
+ raise EOFError, "bad boundary end of body part" unless boundary_end =~ /--/
+ params.default = []
+ params
+ end # read_multipart
+ private :read_multipart
+ def create_body(is_large) #:nodoc:
+ if is_large
+ require 'tempfile'
+ body = Tempfile.new('CGI', encoding: "ascii-8bit")
+ else
+ begin
+ require 'stringio'
+ body = StringIO.new("".force_encoding("ascii-8bit"))
+ rescue LoadError
+ require 'tempfile'
+ body = Tempfile.new('CGI', encoding: "ascii-8bit")
+ end
+ end
+ body.binmode if defined? body.binmode
+ return body
+ end
+ def unescape_filename? #:nodoc:
+ user_agent = $CGI_ENV['HTTP_USER_AGENT']
+ return /Mac/i.match(user_agent) && /Mozilla/i.match(user_agent) && !/MSIE/i.match(user_agent)
+ end
+
+ # offline mode. read name=value pairs on standard input.
+ def read_from_cmdline
+ require "shellwords"
+
+ string = unless ARGV.empty?
+ ARGV.join(' ')
+ else
+ if STDIN.tty?
+ STDERR.print(
+ %|(offline mode: enter name=value pairs on standard input)\n|
+ )
+ end
+ readlines.join(' ').gsub(/\n/, '')
+ end.gsub(/\\=/, '%3D').gsub(/\\&/, '%26')
+
+ words = Shellwords.shellwords(string)
+
+ if words.find{|x| /=/.match(x) }
+ words.join('&')
+ else
+ words.join('+')
+ end
+ end
+ private :read_from_cmdline
+
+ # A wrapper class to use a StringIO object as the body and switch
+ # to a TempFile when the passed threshold is passed.
+ # Initialize the data from the query.
+ #
+ # Handles multipart forms (in particular, forms that involve file uploads).
+ # Reads query parameters in the @params field, and cookies into @cookies.
+ def initialize_query()
+ if ("POST" == env_table['REQUEST_METHOD']) and
+ %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|.match(env_table['CONTENT_TYPE'])
+ raise StandardError.new("too large multipart data.") if env_table['CONTENT_LENGTH'].to_i > MAX_MULTIPART_LENGTH
+ boundary = $1.dup
+ @multipart = true
+ @params = read_multipart(boundary, Integer(env_table['CONTENT_LENGTH']))
+ else
+ @multipart = false
+ @params = CGI::parse(
+ case env_table['REQUEST_METHOD']
+ when "GET", "HEAD"
+ if defined?(MOD_RUBY)
+ Apache::request.args or ""
+ else
+ env_table['QUERY_STRING'] or ""
+ end
+ when "POST"
+ stdinput.binmode if defined? stdinput.binmode
+ stdinput.read(Integer(env_table['CONTENT_LENGTH'])) or ''
+ else
+ read_from_cmdline
+ end.dup.force_encoding(@accept_charset)
+ )
+ unless @accept_charset=~/ASCII-8BIT/i || @accept_charset==Encoding::ASCII_8BIT
+ @params.each do |key,values|
+ values.each do |value|
+ unless value.valid_encoding?
+ if @accept_charset_error_block
+ @accept_charset_error_block.call(key,value)
+ else
+ raise InvalidEncoding,"Accept-Charset encoding error"
+ end
+ end
+ end
+ end
+ end
+ end
+
+ @cookies = CGI::Cookie::parse((env_table['HTTP_COOKIE'] or env_table['COOKIE']))
+ end
+ private :initialize_query
+
+ def multipart?
+ @multipart
+ end
+
+ # Get the value for the parameter with a given key.
+ #
+ # If the parameter has multiple values, only the first will be
+ # retrieved; use #params() to get the array of values.
+ def [](key)
+ params = @params[key]
+ return '' unless params
+ value = params[0]
+ if @multipart
+ if value
+ return value
+ elsif defined? StringIO
+ StringIO.new("".force_encoding("ascii-8bit"))
+ else
+ Tempfile.new("CGI",encoding:"ascii-8bit")
+ end
+ else
+ str = if value then value.dup else "" end
+ str
+ end
+ end
+
+ # Return all parameter keys as an array.
+ def keys(*args)
+ @params.keys(*args)
+ end
+
+ # Returns true if a given parameter key exists in the query.
+ def has_key?(*args)
+ @params.has_key?(*args)
+ end
+ alias key? has_key?
+ alias include? has_key?
+
+ end # QueryExtension
+
+ # InvalidEncoding Exception class
+ class InvalidEncoding < Exception; end
+
+ # @@accept_charset is default accept character set.
+ # This default value default is "UTF-8"
+ # If you want to change the default accept character set
+ # when create a new CGI instance, set this:
+ #
+ # CGI.accept_charset = "EUC-JP"
+ #
+
+ @@accept_charset="UTF-8"
+
+ def self.accept_charset
+ @@accept_charset
+ end
+
+ def self.accept_charset=(accept_charset)
+ @@accept_charset=accept_charset
+ end
+
+ # Create a new CGI instance.
+ #
+ # CGI accept constructor parameters either in a hash, string as a block.
+ # But string is as same as using :tag_maker of hash.
+ #
+ # CGI.new("html3") #=> CGI.new(:tag_maker=>"html3")
+ #
+ # And, if you specify string, @accept_charset cannot be changed.
+ # Instead, please use hash parameter.
+ #
+ # == accept_charset
+ #
+ # :accept_charset specifies encoding of received query string.
+ # ( Default value is @@accept_charset. )
+ # If not valid, raise CGI::InvalidEncoding
+ #
+ # Example. Suppose @@accept_charset # => "UTF-8"
+ #
+ # when not specified:
+ #
+ # cgi=CGI.new # @accept_charset # => "UTF-8"
+ #
+ # when specified "EUC-JP":
+ #
+ # cgi=CGI.new(:accept_charset => "EUC-JP") # => "EUC-JP"
+ #
+ # == block
+ #
+ # When you use a block, you can write a process
+ # that query encoding is invalid. Example:
+ #
+ # encoding_error={}
+ # cgi=CGI.new(:accept_charset=>"EUC-JP") do |name,value|
+ # encoding_error[key] = value
+ # end
+ #
+ # == tag_maker
+ #
+ # :tag_maker specifies which version of HTML to load the HTML generation
+ # methods for. The following versions of HTML are supported:
+ #
+ # html3:: HTML 3.x
+ # html4:: HTML 4.0
+ # html4Tr:: HTML 4.0 Transitional
+ # html4Fr:: HTML 4.0 with Framesets
+ #
+ # If not specified, no HTML generation methods will be loaded.
+ #
+ # If the CGI object is not created in a standard CGI call environment
+ # (that is, it can't locate REQUEST_METHOD in its environment), then
+ # it will run in "offline" mode. In this mode, it reads its parameters
+ # from the command line or (failing that) from standard input. Otherwise,
+ # cookies and other parameters are parsed automatically from the standard
+ # CGI locations, which varies according to the REQUEST_METHOD. It works this:
+ #
+ # CGI.new(:tag_maker=>"html3")
+ #
+ # This will be obsolete:
+ #
+ # CGI.new("html3")
+ #
+ attr_reader :accept_charset
+ def initialize(options = {},&block)
+ @accept_charset_error_block=block if block_given?
+ @options={:accept_charset=>@@accept_charset}
+ case options
+ when Hash
+ @options.merge!(options)
+ when String
+ @options[:tag_maker]=options
+ end
+ @accept_charset=@options[:accept_charset]
+ if defined?(MOD_RUBY) && !ENV.key?("GATEWAY_INTERFACE")
+ Apache.request.setup_cgi_env
+ end
+
+ extend QueryExtension
+ @multipart = false
+
+ initialize_query() # set @params, @cookies
+ @output_cookies = nil
+ @output_hidden = nil
+
+ case @options[:tag_maker]
+ when "html3"
+ require 'cgi/html'
+ extend Html3
+ element_init()
+ extend HtmlExtension
+ when "html4"
+ require 'cgi/html'
+ extend Html4
+ element_init()
+ extend HtmlExtension
+ when "html4Tr"
+ require 'cgi/html'
+ extend Html4Tr
+ element_init()
+ extend HtmlExtension
+ when "html4Fr"
+ require 'cgi/html'
+ extend Html4Tr
+ element_init()
+ extend Html4Fr
+ element_init()
+ extend HtmlExtension
+ end
+ end
+
+end # class CGI
+
+
diff --git a/lib/cgi/html.rb b/lib/cgi/html.rb
new file mode 100644
index 0000000000..62f1fc1898
--- /dev/null
+++ b/lib/cgi/html.rb
@@ -0,0 +1,1021 @@
+ # Base module for HTML-generation mixins.
+ #
+ # Provides methods for code generation for tags following
+ # the various DTD element types.
+class CGI
+ module TagMaker # :nodoc:
+
+ # Generate code for an element with required start and end tags.
+ #
+ # - -
+ def nn_element_def(element)
+ nOE_element_def(element, <<-END)
+ if block_given?
+ yield.to_s
+ else
+ ""
+ end +
+ "</#{element.upcase}>"
+ END
+ end
+
+ # Generate code for an empty element.
+ #
+ # - O EMPTY
+ def nOE_element_def(element, append = nil)
+ s = <<-END
+ attributes={attributes=>nil} if attributes.kind_of?(String)
+ "<#{element.upcase}" + attributes.collect{|name, value|
+ next unless value
+ " " + CGI::escapeHTML(name.to_s) +
+ if true == value
+ ""
+ else
+ '="' + CGI::escapeHTML(value.to_s) + '"'
+ end
+ }.join + ">"
+ END
+ s.sub!(/\Z/, " +") << append if append
+ s
+ end
+
+ # Generate code for an element for which the end (and possibly the
+ # start) tag is optional.
+ #
+ # O O or - O
+ def nO_element_def(element)
+ nOE_element_def(element, <<-END)
+ if block_given?
+ yield.to_s + "</#{element.upcase}>"
+ else
+ ""
+ end
+ END
+ end
+
+ end # TagMaker
+
+
+ #
+ # Mixin module providing HTML generation methods.
+ #
+ # For example,
+ # cgi.a("http://www.example.com") { "Example" }
+ # # => "<A HREF=\"http://www.example.com\">Example</A>"
+ #
+ # Modules Http3, Http4, etc., contain more basic HTML-generation methods
+ # (:title, :center, etc.).
+ #
+ # See class CGI for a detailed example.
+ #
+ module HtmlExtension
+
+
+ # Generate an Anchor element as a string.
+ #
+ # +href+ can either be a string, giving the URL
+ # for the HREF attribute, or it can be a hash of
+ # the element's attributes.
+ #
+ # The body of the element is the string returned by the no-argument
+ # block passed in.
+ #
+ # a("http://www.example.com") { "Example" }
+ # # => "<A HREF=\"http://www.example.com\">Example</A>"
+ #
+ # a("HREF" => "http://www.example.com", "TARGET" => "_top") { "Example" }
+ # # => "<A HREF=\"http://www.example.com\" TARGET=\"_top\">Example</A>"
+ #
+ def a(href = "") # :yield:
+ attributes = if href.kind_of?(String)
+ { "HREF" => href }
+ else
+ href
+ end
+ if block_given?
+ super(attributes){ yield }
+ else
+ super(attributes)
+ end
+ end
+
+ # Generate a Document Base URI element as a String.
+ #
+ # +href+ can either by a string, giving the base URL for the HREF
+ # attribute, or it can be a has of the element's attributes.
+ #
+ # The passed-in no-argument block is ignored.
+ #
+ # base("http://www.example.com/cgi")
+ # # => "<BASE HREF=\"http://www.example.com/cgi\">"
+ def base(href = "") # :yield:
+ attributes = if href.kind_of?(String)
+ { "HREF" => href }
+ else
+ href
+ end
+ if block_given?
+ super(attributes){ yield }
+ else
+ super(attributes)
+ end
+ end
+
+ # Generate a BlockQuote element as a string.
+ #
+ # +cite+ can either be a string, give the URI for the source of
+ # the quoted text, or a hash, giving all attributes of the element,
+ # or it can be omitted, in which case the element has no attributes.
+ #
+ # The body is provided by the passed-in no-argument block
+ #
+ # blockquote("http://www.example.com/quotes/foo.html") { "Foo!" }
+ # #=> "<BLOCKQUOTE CITE=\"http://www.example.com/quotes/foo.html\">Foo!</BLOCKQUOTE>
+ def blockquote(cite = {}) # :yield:
+ attributes = if cite.kind_of?(String)
+ { "CITE" => cite }
+ else
+ cite
+ end
+ if block_given?
+ super(attributes){ yield }
+ else
+ super(attributes)
+ end
+ end
+
+
+ # Generate a Table Caption element as a string.
+ #
+ # +align+ can be a string, giving the alignment of the caption
+ # (one of top, bottom, left, or right). It can be a hash of
+ # all the attributes of the element. Or it can be omitted.
+ #
+ # The body of the element is provided by the passed-in no-argument block.
+ #
+ # caption("left") { "Capital Cities" }
+ # # => <CAPTION ALIGN=\"left\">Capital Cities</CAPTION>
+ def caption(align = {}) # :yield:
+ attributes = if align.kind_of?(String)
+ { "ALIGN" => align }
+ else
+ align
+ end
+ if block_given?
+ super(attributes){ yield }
+ else
+ super(attributes)
+ end
+ end
+
+
+ # Generate a Checkbox Input element as a string.
+ #
+ # The attributes of the element can be specified as three arguments,
+ # +name+, +value+, and +checked+. +checked+ is a boolean value;
+ # if true, the CHECKED attribute will be included in the element.
+ #
+ # Alternatively, the attributes can be specified as a hash.
+ #
+ # checkbox("name")
+ # # = checkbox("NAME" => "name")
+ #
+ # checkbox("name", "value")
+ # # = checkbox("NAME" => "name", "VALUE" => "value")
+ #
+ # checkbox("name", "value", true)
+ # # = checkbox("NAME" => "name", "VALUE" => "value", "CHECKED" => true)
+ def checkbox(name = "", value = nil, checked = nil)
+ attributes = if name.kind_of?(String)
+ { "TYPE" => "checkbox", "NAME" => name,
+ "VALUE" => value, "CHECKED" => checked }
+ else
+ name["TYPE"] = "checkbox"
+ name
+ end
+ input(attributes)
+ end
+
+ # Generate a sequence of checkbox elements, as a String.
+ #
+ # The checkboxes will all have the same +name+ attribute.
+ # Each checkbox is followed by a label.
+ # There will be one checkbox for each value. Each value
+ # can be specified as a String, which will be used both
+ # as the value of the VALUE attribute and as the label
+ # for that checkbox. A single-element array has the
+ # same effect.
+ #
+ # Each value can also be specified as a three-element array.
+ # The first element is the VALUE attribute; the second is the
+ # label; and the third is a boolean specifying whether this
+ # checkbox is CHECKED.
+ #
+ # Each value can also be specified as a two-element
+ # array, by omitting either the value element (defaults
+ # to the same as the label), or the boolean checked element
+ # (defaults to false).
+ #
+ # checkbox_group("name", "foo", "bar", "baz")
+ # # <INPUT TYPE="checkbox" NAME="name" VALUE="foo">foo
+ # # <INPUT TYPE="checkbox" NAME="name" VALUE="bar">bar
+ # # <INPUT TYPE="checkbox" NAME="name" VALUE="baz">baz
+ #
+ # checkbox_group("name", ["foo"], ["bar", true], "baz")
+ # # <INPUT TYPE="checkbox" NAME="name" VALUE="foo">foo
+ # # <INPUT TYPE="checkbox" CHECKED NAME="name" VALUE="bar">bar
+ # # <INPUT TYPE="checkbox" NAME="name" VALUE="baz">baz
+ #
+ # checkbox_group("name", ["1", "Foo"], ["2", "Bar", true], "Baz")
+ # # <INPUT TYPE="checkbox" NAME="name" VALUE="1">Foo
+ # # <INPUT TYPE="checkbox" CHECKED NAME="name" VALUE="2">Bar
+ # # <INPUT TYPE="checkbox" NAME="name" VALUE="Baz">Baz
+ #
+ # checkbox_group("NAME" => "name",
+ # "VALUES" => ["foo", "bar", "baz"])
+ #
+ # checkbox_group("NAME" => "name",
+ # "VALUES" => [["foo"], ["bar", true], "baz"])
+ #
+ # checkbox_group("NAME" => "name",
+ # "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"])
+ def checkbox_group(name = "", *values)
+ if name.kind_of?(Hash)
+ values = name["VALUES"]
+ name = name["NAME"]
+ end
+ values.collect{|value|
+ if value.kind_of?(String)
+ checkbox(name, value) + value
+ else
+ if value[-1] == true || value[-1] == false
+ checkbox(name, value[0], value[-1]) +
+ value[-2]
+ else
+ checkbox(name, value[0]) +
+ value[-1]
+ end
+ end
+ }.join
+ end
+
+
+ # Generate an File Upload Input element as a string.
+ #
+ # The attributes of the element can be specified as three arguments,
+ # +name+, +size+, and +maxlength+. +maxlength+ is the maximum length
+ # of the file's _name_, not of the file's _contents_.
+ #
+ # Alternatively, the attributes can be specified as a hash.
+ #
+ # See #multipart_form() for forms that include file uploads.
+ #
+ # file_field("name")
+ # # <INPUT TYPE="file" NAME="name" SIZE="20">
+ #
+ # file_field("name", 40)
+ # # <INPUT TYPE="file" NAME="name" SIZE="40">
+ #
+ # file_field("name", 40, 100)
+ # # <INPUT TYPE="file" NAME="name" SIZE="40" MAXLENGTH="100">
+ #
+ # file_field("NAME" => "name", "SIZE" => 40)
+ # # <INPUT TYPE="file" NAME="name" SIZE="40">
+ def file_field(name = "", size = 20, maxlength = nil)
+ attributes = if name.kind_of?(String)
+ { "TYPE" => "file", "NAME" => name,
+ "SIZE" => size.to_s }
+ else
+ name["TYPE"] = "file"
+ name
+ end
+ attributes["MAXLENGTH"] = maxlength.to_s if maxlength
+ input(attributes)
+ end
+
+
+ # Generate a Form element as a string.
+ #
+ # +method+ should be either "get" or "post", and defaults to the latter.
+ # +action+ defaults to the current CGI script name. +enctype+
+ # defaults to "application/x-www-form-urlencoded".
+ #
+ # Alternatively, the attributes can be specified as a hash.
+ #
+ # See also #multipart_form() for forms that include file uploads.
+ #
+ # form{ "string" }
+ # # <FORM METHOD="post" ENCTYPE="application/x-www-form-urlencoded">string</FORM>
+ #
+ # form("get") { "string" }
+ # # <FORM METHOD="get" ENCTYPE="application/x-www-form-urlencoded">string</FORM>
+ #
+ # form("get", "url") { "string" }
+ # # <FORM METHOD="get" ACTION="url" ENCTYPE="application/x-www-form-urlencoded">string</FORM>
+ #
+ # form("METHOD" => "post", "ENCTYPE" => "enctype") { "string" }
+ # # <FORM METHOD="post" ENCTYPE="enctype">string</FORM>
+ def form(method = "post", action = script_name, enctype = "application/x-www-form-urlencoded")
+ attributes = if method.kind_of?(String)
+ { "METHOD" => method, "ACTION" => action,
+ "ENCTYPE" => enctype }
+ else
+ unless method.has_key?("METHOD")
+ method["METHOD"] = "post"
+ end
+ unless method.has_key?("ENCTYPE")
+ method["ENCTYPE"] = enctype
+ end
+ method
+ end
+ if block_given?
+ body = yield
+ else
+ body = ""
+ end
+ if @output_hidden
+ body += @output_hidden.collect{|k,v|
+ "<INPUT TYPE=\"HIDDEN\" NAME=\"#{k}\" VALUE=\"#{v}\">"
+ }.join
+ end
+ super(attributes){body}
+ end
+
+ # Generate a Hidden Input element as a string.
+ #
+ # The attributes of the element can be specified as two arguments,
+ # +name+ and +value+.
+ #
+ # Alternatively, the attributes can be specified as a hash.
+ #
+ # hidden("name")
+ # # <INPUT TYPE="hidden" NAME="name">
+ #
+ # hidden("name", "value")
+ # # <INPUT TYPE="hidden" NAME="name" VALUE="value">
+ #
+ # hidden("NAME" => "name", "VALUE" => "reset", "ID" => "foo")
+ # # <INPUT TYPE="hidden" NAME="name" VALUE="value" ID="foo">
+ def hidden(name = "", value = nil)
+ attributes = if name.kind_of?(String)
+ { "TYPE" => "hidden", "NAME" => name, "VALUE" => value }
+ else
+ name["TYPE"] = "hidden"
+ name
+ end
+ input(attributes)
+ end
+
+ # Generate a top-level HTML element as a string.
+ #
+ # The attributes of the element are specified as a hash. The
+ # pseudo-attribute "PRETTY" can be used to specify that the generated
+ # HTML string should be indented. "PRETTY" can also be specified as
+ # a string as the sole argument to this method. The pseudo-attribute
+ # "DOCTYPE", if given, is used as the leading DOCTYPE SGML tag; it
+ # should include the entire text of this tag, including angle brackets.
+ #
+ # The body of the html element is supplied as a block.
+ #
+ # html{ "string" }
+ # # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><HTML>string</HTML>
+ #
+ # html("LANG" => "ja") { "string" }
+ # # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><HTML LANG="ja">string</HTML>
+ #
+ # html("DOCTYPE" => false) { "string" }
+ # # <HTML>string</HTML>
+ #
+ # html("DOCTYPE" => '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">') { "string" }
+ # # <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"><HTML>string</HTML>
+ #
+ # html("PRETTY" => " ") { "<BODY></BODY>" }
+ # # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+ # # <HTML>
+ # # <BODY>
+ # # </BODY>
+ # # </HTML>
+ #
+ # html("PRETTY" => "\t") { "<BODY></BODY>" }
+ # # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+ # # <HTML>
+ # # <BODY>
+ # # </BODY>
+ # # </HTML>
+ #
+ # html("PRETTY") { "<BODY></BODY>" }
+ # # = html("PRETTY" => " ") { "<BODY></BODY>" }
+ #
+ # html(if $VERBOSE then "PRETTY" end) { "HTML string" }
+ #
+ def html(attributes = {}) # :yield:
+ if nil == attributes
+ attributes = {}
+ elsif "PRETTY" == attributes
+ attributes = { "PRETTY" => true }
+ end
+ pretty = attributes.delete("PRETTY")
+ pretty = " " if true == pretty
+ buf = ""
+
+ if attributes.has_key?("DOCTYPE")
+ if attributes["DOCTYPE"]
+ buf += attributes.delete("DOCTYPE")
+ else
+ attributes.delete("DOCTYPE")
+ end
+ else
+ buf += doctype
+ end
+
+ if block_given?
+ buf += super(attributes){ yield }
+ else
+ buf += super(attributes)
+ end
+
+ if pretty
+ CGI::pretty(buf, pretty)
+ else
+ buf
+ end
+
+ end
+
+ # Generate an Image Button Input element as a string.
+ #
+ # +src+ is the URL of the image to use for the button. +name+
+ # is the input name. +alt+ is the alternative text for the image.
+ #
+ # Alternatively, the attributes can be specified as a hash.
+ #
+ # image_button("url")
+ # # <INPUT TYPE="image" SRC="url">
+ #
+ # image_button("url", "name", "string")
+ # # <INPUT TYPE="image" SRC="url" NAME="name" ALT="string">
+ #
+ # image_button("SRC" => "url", "ATL" => "strng")
+ # # <INPUT TYPE="image" SRC="url" ALT="string">
+ def image_button(src = "", name = nil, alt = nil)
+ attributes = if src.kind_of?(String)
+ { "TYPE" => "image", "SRC" => src, "NAME" => name,
+ "ALT" => alt }
+ else
+ src["TYPE"] = "image"
+ src["SRC"] ||= ""
+ src
+ end
+ input(attributes)
+ end
+
+
+ # Generate an Image element as a string.
+ #
+ # +src+ is the URL of the image. +alt+ is the alternative text for
+ # the image. +width+ is the width of the image, and +height+ is
+ # its height.
+ #
+ # Alternatively, the attributes can be specified as a hash.
+ #
+ # img("src", "alt", 100, 50)
+ # # <IMG SRC="src" ALT="alt" WIDTH="100" HEIGHT="50">
+ #
+ # img("SRC" => "src", "ALT" => "alt", "WIDTH" => 100, "HEIGHT" => 50)
+ # # <IMG SRC="src" ALT="alt" WIDTH="100" HEIGHT="50">
+ def img(src = "", alt = "", width = nil, height = nil)
+ attributes = if src.kind_of?(String)
+ { "SRC" => src, "ALT" => alt }
+ else
+ src
+ end
+ attributes["WIDTH"] = width.to_s if width
+ attributes["HEIGHT"] = height.to_s if height
+ super(attributes)
+ end
+
+
+ # Generate a Form element with multipart encoding as a String.
+ #
+ # Multipart encoding is used for forms that include file uploads.
+ #
+ # +action+ is the action to perform. +enctype+ is the encoding
+ # type, which defaults to "multipart/form-data".
+ #
+ # Alternatively, the attributes can be specified as a hash.
+ #
+ # multipart_form{ "string" }
+ # # <FORM METHOD="post" ENCTYPE="multipart/form-data">string</FORM>
+ #
+ # multipart_form("url") { "string" }
+ # # <FORM METHOD="post" ACTION="url" ENCTYPE="multipart/form-data">string</FORM>
+ def multipart_form(action = nil, enctype = "multipart/form-data")
+ attributes = if action == nil
+ { "METHOD" => "post", "ENCTYPE" => enctype }
+ elsif action.kind_of?(String)
+ { "METHOD" => "post", "ACTION" => action,
+ "ENCTYPE" => enctype }
+ else
+ unless action.has_key?("METHOD")
+ action["METHOD"] = "post"
+ end
+ unless action.has_key?("ENCTYPE")
+ action["ENCTYPE"] = enctype
+ end
+ action
+ end
+ if block_given?
+ form(attributes){ yield }
+ else
+ form(attributes)
+ end
+ end
+
+
+ # Generate a Password Input element as a string.
+ #
+ # +name+ is the name of the input field. +value+ is its default
+ # value. +size+ is the size of the input field display. +maxlength+
+ # is the maximum length of the inputted password.
+ #
+ # Alternatively, attributes can be specified as a hash.
+ #
+ # password_field("name")
+ # # <INPUT TYPE="password" NAME="name" SIZE="40">
+ #
+ # password_field("name", "value")
+ # # <INPUT TYPE="password" NAME="name" VALUE="value" SIZE="40">
+ #
+ # password_field("password", "value", 80, 200)
+ # # <INPUT TYPE="password" NAME="name" VALUE="value" SIZE="80" MAXLENGTH="200">
+ #
+ # password_field("NAME" => "name", "VALUE" => "value")
+ # # <INPUT TYPE="password" NAME="name" VALUE="value">
+ def password_field(name = "", value = nil, size = 40, maxlength = nil)
+ attributes = if name.kind_of?(String)
+ { "TYPE" => "password", "NAME" => name,
+ "VALUE" => value, "SIZE" => size.to_s }
+ else
+ name["TYPE"] = "password"
+ name
+ end
+ attributes["MAXLENGTH"] = maxlength.to_s if maxlength
+ input(attributes)
+ end
+
+ # Generate a Select element as a string.
+ #
+ # +name+ is the name of the element. The +values+ are the options that
+ # can be selected from the Select menu. Each value can be a String or
+ # a one, two, or three-element Array. If a String or a one-element
+ # Array, this is both the value of that option and the text displayed for
+ # it. If a three-element Array, the elements are the option value, displayed
+ # text, and a boolean value specifying whether this option starts as selected.
+ # The two-element version omits either the option value (defaults to the same
+ # as the display text) or the boolean selected specifier (defaults to false).
+ #
+ # The attributes and options can also be specified as a hash. In this
+ # case, options are specified as an array of values as described above,
+ # with the hash key of "VALUES".
+ #
+ # popup_menu("name", "foo", "bar", "baz")
+ # # <SELECT NAME="name">
+ # # <OPTION VALUE="foo">foo</OPTION>
+ # # <OPTION VALUE="bar">bar</OPTION>
+ # # <OPTION VALUE="baz">baz</OPTION>
+ # # </SELECT>
+ #
+ # popup_menu("name", ["foo"], ["bar", true], "baz")
+ # # <SELECT NAME="name">
+ # # <OPTION VALUE="foo">foo</OPTION>
+ # # <OPTION VALUE="bar" SELECTED>bar</OPTION>
+ # # <OPTION VALUE="baz">baz</OPTION>
+ # # </SELECT>
+ #
+ # popup_menu("name", ["1", "Foo"], ["2", "Bar", true], "Baz")
+ # # <SELECT NAME="name">
+ # # <OPTION VALUE="1">Foo</OPTION>
+ # # <OPTION SELECTED VALUE="2">Bar</OPTION>
+ # # <OPTION VALUE="Baz">Baz</OPTION>
+ # # </SELECT>
+ #
+ # popup_menu("NAME" => "name", "SIZE" => 2, "MULTIPLE" => true,
+ # "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"])
+ # # <SELECT NAME="name" MULTIPLE SIZE="2">
+ # # <OPTION VALUE="1">Foo</OPTION>
+ # # <OPTION SELECTED VALUE="2">Bar</OPTION>
+ # # <OPTION VALUE="Baz">Baz</OPTION>
+ # # </SELECT>
+ def popup_menu(name = "", *values)
+
+ if name.kind_of?(Hash)
+ values = name["VALUES"]
+ size = name["SIZE"].to_s if name["SIZE"]
+ multiple = name["MULTIPLE"]
+ name = name["NAME"]
+ else
+ size = nil
+ multiple = nil
+ end
+
+ select({ "NAME" => name, "SIZE" => size,
+ "MULTIPLE" => multiple }){
+ values.collect{|value|
+ if value.kind_of?(String)
+ option({ "VALUE" => value }){ value }
+ else
+ if value[value.size - 1] == true
+ option({ "VALUE" => value[0], "SELECTED" => true }){
+ value[value.size - 2]
+ }
+ else
+ option({ "VALUE" => value[0] }){
+ value[value.size - 1]
+ }
+ end
+ end
+ }.join
+ }
+
+ end
+
+ # Generates a radio-button Input element.
+ #
+ # +name+ is the name of the input field. +value+ is the value of
+ # the field if checked. +checked+ specifies whether the field
+ # starts off checked.
+ #
+ # Alternatively, the attributes can be specified as a hash.
+ #
+ # radio_button("name", "value")
+ # # <INPUT TYPE="radio" NAME="name" VALUE="value">
+ #
+ # radio_button("name", "value", true)
+ # # <INPUT TYPE="radio" NAME="name" VALUE="value" CHECKED>
+ #
+ # radio_button("NAME" => "name", "VALUE" => "value", "ID" => "foo")
+ # # <INPUT TYPE="radio" NAME="name" VALUE="value" ID="foo">
+ def radio_button(name = "", value = nil, checked = nil)
+ attributes = if name.kind_of?(String)
+ { "TYPE" => "radio", "NAME" => name,
+ "VALUE" => value, "CHECKED" => checked }
+ else
+ name["TYPE"] = "radio"
+ name
+ end
+ input(attributes)
+ end
+
+ # Generate a sequence of radio button Input elements, as a String.
+ #
+ # This works the same as #checkbox_group(). However, it is not valid
+ # to have more than one radiobutton in a group checked.
+ #
+ # radio_group("name", "foo", "bar", "baz")
+ # # <INPUT TYPE="radio" NAME="name" VALUE="foo">foo
+ # # <INPUT TYPE="radio" NAME="name" VALUE="bar">bar
+ # # <INPUT TYPE="radio" NAME="name" VALUE="baz">baz
+ #
+ # radio_group("name", ["foo"], ["bar", true], "baz")
+ # # <INPUT TYPE="radio" NAME="name" VALUE="foo">foo
+ # # <INPUT TYPE="radio" CHECKED NAME="name" VALUE="bar">bar
+ # # <INPUT TYPE="radio" NAME="name" VALUE="baz">baz
+ #
+ # radio_group("name", ["1", "Foo"], ["2", "Bar", true], "Baz")
+ # # <INPUT TYPE="radio" NAME="name" VALUE="1">Foo
+ # # <INPUT TYPE="radio" CHECKED NAME="name" VALUE="2">Bar
+ # # <INPUT TYPE="radio" NAME="name" VALUE="Baz">Baz
+ #
+ # radio_group("NAME" => "name",
+ # "VALUES" => ["foo", "bar", "baz"])
+ #
+ # radio_group("NAME" => "name",
+ # "VALUES" => [["foo"], ["bar", true], "baz"])
+ #
+ # radio_group("NAME" => "name",
+ # "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"])
+ def radio_group(name = "", *values)
+ if name.kind_of?(Hash)
+ values = name["VALUES"]
+ name = name["NAME"]
+ end
+ values.collect{|value|
+ if value.kind_of?(String)
+ radio_button(name, value) + value
+ else
+ if value[-1] == true || value[-1] == false
+ radio_button(name, value[0], value[-1]) +
+ value[-2]
+ else
+ radio_button(name, value[0]) +
+ value[-1]
+ end
+ end
+ }.join
+ end
+
+ # Generate a reset button Input element, as a String.
+ #
+ # This resets the values on a form to their initial values. +value+
+ # is the text displayed on the button. +name+ is the name of this button.
+ #
+ # Alternatively, the attributes can be specified as a hash.
+ #
+ # reset
+ # # <INPUT TYPE="reset">
+ #
+ # reset("reset")
+ # # <INPUT TYPE="reset" VALUE="reset">
+ #
+ # reset("VALUE" => "reset", "ID" => "foo")
+ # # <INPUT TYPE="reset" VALUE="reset" ID="foo">
+ def reset(value = nil, name = nil)
+ attributes = if (not value) or value.kind_of?(String)
+ { "TYPE" => "reset", "VALUE" => value, "NAME" => name }
+ else
+ value["TYPE"] = "reset"
+ value
+ end
+ input(attributes)
+ end
+
+ alias scrolling_list popup_menu
+
+ # Generate a submit button Input element, as a String.
+ #
+ # +value+ is the text to display on the button. +name+ is the name
+ # of the input.
+ #
+ # Alternatively, the attributes can be specified as a hash.
+ #
+ # submit
+ # # <INPUT TYPE="submit">
+ #
+ # submit("ok")
+ # # <INPUT TYPE="submit" VALUE="ok">
+ #
+ # submit("ok", "button1")
+ # # <INPUT TYPE="submit" VALUE="ok" NAME="button1">
+ #
+ # submit("VALUE" => "ok", "NAME" => "button1", "ID" => "foo")
+ # # <INPUT TYPE="submit" VALUE="ok" NAME="button1" ID="foo">
+ def submit(value = nil, name = nil)
+ attributes = if (not value) or value.kind_of?(String)
+ { "TYPE" => "submit", "VALUE" => value, "NAME" => name }
+ else
+ value["TYPE"] = "submit"
+ value
+ end
+ input(attributes)
+ end
+
+ # Generate a text field Input element, as a String.
+ #
+ # +name+ is the name of the input field. +value+ is its initial
+ # value. +size+ is the size of the input area. +maxlength+
+ # is the maximum length of input accepted.
+ #
+ # Alternatively, the attributes can be specified as a hash.
+ #
+ # text_field("name")
+ # # <INPUT TYPE="text" NAME="name" SIZE="40">
+ #
+ # text_field("name", "value")
+ # # <INPUT TYPE="text" NAME="name" VALUE="value" SIZE="40">
+ #
+ # text_field("name", "value", 80)
+ # # <INPUT TYPE="text" NAME="name" VALUE="value" SIZE="80">
+ #
+ # text_field("name", "value", 80, 200)
+ # # <INPUT TYPE="text" NAME="name" VALUE="value" SIZE="80" MAXLENGTH="200">
+ #
+ # text_field("NAME" => "name", "VALUE" => "value")
+ # # <INPUT TYPE="text" NAME="name" VALUE="value">
+ def text_field(name = "", value = nil, size = 40, maxlength = nil)
+ attributes = if name.kind_of?(String)
+ { "TYPE" => "text", "NAME" => name, "VALUE" => value,
+ "SIZE" => size.to_s }
+ else
+ name["TYPE"] = "text"
+ name
+ end
+ attributes["MAXLENGTH"] = maxlength.to_s if maxlength
+ input(attributes)
+ end
+
+ # Generate a TextArea element, as a String.
+ #
+ # +name+ is the name of the textarea. +cols+ is the number of
+ # columns and +rows+ is the number of rows in the display.
+ #
+ # Alternatively, the attributes can be specified as a hash.
+ #
+ # The body is provided by the passed-in no-argument block
+ #
+ # textarea("name")
+ # # = textarea("NAME" => "name", "COLS" => 70, "ROWS" => 10)
+ #
+ # textarea("name", 40, 5)
+ # # = textarea("NAME" => "name", "COLS" => 40, "ROWS" => 5)
+ def textarea(name = "", cols = 70, rows = 10) # :yield:
+ attributes = if name.kind_of?(String)
+ { "NAME" => name, "COLS" => cols.to_s,
+ "ROWS" => rows.to_s }
+ else
+ name
+ end
+ if block_given?
+ super(attributes){ yield }
+ else
+ super(attributes)
+ end
+ end
+
+ end # HtmlExtension
+
+
+ # Mixin module for HTML version 3 generation methods.
+ module Html3 # :nodoc:
+
+ # The DOCTYPE declaration for this version of HTML
+ def doctype
+ %|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">|
+ end
+
+ # Initialise the HTML generation methods for this version.
+ def element_init
+ extend TagMaker
+ methods = ""
+ # - -
+ for element in %w[ A TT I B U STRIKE BIG SMALL SUB SUP EM STRONG
+ DFN CODE SAMP KBD VAR CITE FONT ADDRESS DIV center MAP
+ APPLET PRE XMP LISTING DL OL UL DIR MENU SELECT table TITLE
+ STYLE SCRIPT H1 H2 H3 H4 H5 H6 TEXTAREA FORM BLOCKQUOTE
+ CAPTION ]
+ methods += <<-BEGIN + nn_element_def(element) + <<-END
+ def #{element.downcase}(attributes = {})
+ BEGIN
+ end
+ END
+ end
+
+ # - O EMPTY
+ for element in %w[ IMG BASE BASEFONT BR AREA LINK PARAM HR INPUT
+ ISINDEX META ]
+ methods += <<-BEGIN + nOE_element_def(element) + <<-END
+ def #{element.downcase}(attributes = {})
+ BEGIN
+ end
+ END
+ end
+
+ # O O or - O
+ for element in %w[ HTML HEAD BODY P PLAINTEXT DT DD LI OPTION tr
+ th td ]
+ methods += <<-BEGIN + nO_element_def(element) + <<-END
+ def #{element.downcase}(attributes = {})
+ BEGIN
+ end
+ END
+ end
+ eval(methods)
+ end
+
+ end # Html3
+
+
+ # Mixin module for HTML version 4 generation methods.
+ module Html4 # :nodoc:
+
+ # The DOCTYPE declaration for this version of HTML
+ def doctype
+ %|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">|
+ end
+
+ # Initialise the HTML generation methods for this version.
+ def element_init
+ extend TagMaker
+ methods = ""
+ # - -
+ for element in %w[ TT I B BIG SMALL EM STRONG DFN CODE SAMP KBD
+ VAR CITE ABBR ACRONYM SUB SUP SPAN BDO ADDRESS DIV MAP OBJECT
+ H1 H2 H3 H4 H5 H6 PRE Q INS DEL DL OL UL LABEL SELECT OPTGROUP
+ FIELDSET LEGEND BUTTON TABLE TITLE STYLE SCRIPT NOSCRIPT
+ TEXTAREA FORM A BLOCKQUOTE CAPTION ]
+ methods += <<-BEGIN + nn_element_def(element) + <<-END
+ def #{element.downcase}(attributes = {})
+ BEGIN
+ end
+ END
+ end
+
+ # - O EMPTY
+ for element in %w[ IMG BASE BR AREA LINK PARAM HR INPUT COL META ]
+ methods += <<-BEGIN + nOE_element_def(element) + <<-END
+ def #{element.downcase}(attributes = {})
+ BEGIN
+ end
+ END
+ end
+
+ # O O or - O
+ for element in %w[ HTML BODY P DT DD LI OPTION THEAD TFOOT TBODY
+ COLGROUP TR TH TD HEAD]
+ methods += <<-BEGIN + nO_element_def(element) + <<-END
+ def #{element.downcase}(attributes = {})
+ BEGIN
+ end
+ END
+ end
+ eval(methods)
+ end
+
+ end # Html4
+
+
+ # Mixin module for HTML version 4 transitional generation methods.
+ module Html4Tr # :nodoc:
+
+ # The DOCTYPE declaration for this version of HTML
+ def doctype
+ %|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">|
+ end
+
+ # Initialise the HTML generation methods for this version.
+ def element_init
+ extend TagMaker
+ methods = ""
+ # - -
+ for element in %w[ TT I B U S STRIKE BIG SMALL EM STRONG DFN
+ CODE SAMP KBD VAR CITE ABBR ACRONYM FONT SUB SUP SPAN BDO
+ ADDRESS DIV CENTER MAP OBJECT APPLET H1 H2 H3 H4 H5 H6 PRE Q
+ INS DEL DL OL UL DIR MENU LABEL SELECT OPTGROUP FIELDSET
+ LEGEND BUTTON TABLE IFRAME NOFRAMES TITLE STYLE SCRIPT
+ NOSCRIPT TEXTAREA FORM A BLOCKQUOTE CAPTION ]
+ methods += <<-BEGIN + nn_element_def(element) + <<-END
+ def #{element.downcase}(attributes = {})
+ BEGIN
+ end
+ END
+ end
+
+ # - O EMPTY
+ for element in %w[ IMG BASE BASEFONT BR AREA LINK PARAM HR INPUT
+ COL ISINDEX META ]
+ methods += <<-BEGIN + nOE_element_def(element) + <<-END
+ def #{element.downcase}(attributes = {})
+ BEGIN
+ end
+ END
+ end
+
+ # O O or - O
+ for element in %w[ HTML BODY P DT DD LI OPTION THEAD TFOOT TBODY
+ COLGROUP TR TH TD HEAD ]
+ methods += <<-BEGIN + nO_element_def(element) + <<-END
+ def #{element.downcase}(attributes = {})
+ BEGIN
+ end
+ END
+ end
+ eval(methods)
+ end
+
+ end # Html4Tr
+
+
+ # Mixin module for generating HTML version 4 with framesets.
+ module Html4Fr # :nodoc:
+
+ # The DOCTYPE declaration for this version of HTML
+ def doctype
+ %|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">|
+ end
+
+ # Initialise the HTML generation methods for this version.
+ def element_init
+ methods = ""
+ # - -
+ for element in %w[ FRAMESET ]
+ methods += <<-BEGIN + nn_element_def(element) + <<-END
+ def #{element.downcase}(attributes = {})
+ BEGIN
+ end
+ END
+ end
+
+ # - O EMPTY
+ for element in %w[ FRAME ]
+ methods += <<-BEGIN + nOE_element_def(element) + <<-END
+ def #{element.downcase}(attributes = {})
+ BEGIN
+ end
+ END
+ end
+ eval(methods)
+ end
+
+ end # Html4Fr
+end
+
+
diff --git a/lib/cgi/session.rb b/lib/cgi/session.rb
index a9cfedd56b..063d910856 100644
--- a/lib/cgi/session.rb
+++ b/lib/cgi/session.rb
@@ -163,7 +163,7 @@ class CGI
def Session::callback(dbman) #:nodoc:
Proc.new{
- dbman[0].close unless dbman.empty?
+ dbman[0].close unless dbman.empty?
}
end
@@ -254,24 +254,24 @@ class CGI
session_key = option['session_key'] || '_session_id'
session_id = option['session_id']
unless session_id
- if option['new_session']
- session_id = create_new_id
- end
+ if option['new_session']
+ session_id = create_new_id
+ end
end
unless session_id
- if request.key?(session_key)
- session_id = request[session_key]
- session_id = session_id.read if session_id.respond_to?(:read)
- end
- unless session_id
- session_id, = request.cookies[session_key]
- end
- unless session_id
- unless option.fetch('new_session', true)
- raise ArgumentError, "session_key `%s' should be supplied"%session_key
- end
- session_id = create_new_id
- end
+ if request.key?(session_key)
+ session_id = request[session_key]
+ session_id = session_id.read if session_id.respond_to?(:read)
+ end
+ unless session_id
+ session_id, = request.cookies[session_key]
+ end
+ unless session_id
+ unless option.fetch('new_session', true)
+ raise ArgumentError, "session_key `%s' should be supplied"%session_key
+ end
+ session_id = create_new_id
+ end
end
@session_id = session_id
dbman = option['database_manager'] || FileStore
@@ -285,20 +285,21 @@ class CGI
retry
end
request.instance_eval do
- @output_hidden = {session_key => session_id} unless option['no_hidden']
- @output_cookies = [
+ @output_hidden = {session_key => session_id} unless option['no_hidden']
+ @output_cookies = [
Cookie::new("name" => session_key,
- "value" => session_id,
- "expires" => option['session_expires'],
- "domain" => option['session_domain'],
- "secure" => option['session_secure'],
- "path" => if option['session_path'] then
- option['session_path']
- elsif ENV["SCRIPT_NAME"] then
- File::dirname(ENV["SCRIPT_NAME"])
- else
- ""
- end)
+ "value" => session_id,
+ "expires" => option['session_expires'],
+ "domain" => option['session_domain'],
+ "secure" => option['session_secure'],
+ "path" =>
+ if option['session_path']
+ option['session_path']
+ elsif ENV["SCRIPT_NAME"]
+ File::dirname(ENV["SCRIPT_NAME"])
+ else
+ ""
+ end)
] unless option['no_cookies']
end
@dbprot = [@dbman]
@@ -373,56 +374,56 @@ class CGI
# This session's FileStore file will be created if it does
# not exist, or opened if it does.
def initialize(session, option={})
- dir = option['tmpdir'] || Dir::tmpdir
- prefix = option['prefix'] || 'cgi_sid_'
- suffix = option['suffix'] || ''
- id = session.session_id
+ dir = option['tmpdir'] || Dir::tmpdir
+ prefix = option['prefix'] || 'cgi_sid_'
+ suffix = option['suffix'] || ''
+ id = session.session_id
require 'digest/md5'
md5 = Digest::MD5.hexdigest(id)[0,16]
- @path = dir+"/"+prefix+md5+suffix
- if File::exist? @path
- @hash = nil
- else
+ @path = dir+"/"+prefix+md5+suffix
+ if File::exist? @path
+ @hash = nil
+ else
unless session.new_session
raise CGI::Session::NoSession, "uninitialized session"
end
- @hash = {}
- end
+ @hash = {}
+ end
end
# Restore session state from the session's FileStore file.
#
# Returns the session state as a hash.
def restore
- unless @hash
- @hash = {}
+ unless @hash
+ @hash = {}
begin
lockf = File.open(@path+".lock", "r")
lockf.flock File::LOCK_SH
- f = File.open(@path, 'r')
- for line in f
- line.chomp!
- k, v = line.split('=',2)
- @hash[CGI::unescape(k)] = CGI::unescape(v)
- end
+ f = File.open(@path, 'r')
+ for line in f
+ line.chomp!
+ k, v = line.split('=',2)
+ @hash[CGI::unescape(k)] = Marshal.restore(CGI::unescape(v))
+ end
ensure
- f.close unless f.nil?
+ f.close unless f.nil?
lockf.close if lockf
end
- end
- @hash
+ end
+ @hash
end
# Save session state to the session's FileStore file.
def update
- return unless @hash
+ return unless @hash
begin
lockf = File.open(@path+".lock", File::CREAT|File::RDWR, 0600)
- lockf.flock File::LOCK_EX
+ lockf.flock File::LOCK_EX
f = File.open(@path+".new", File::CREAT|File::TRUNC|File::WRONLY, 0600)
- for k,v in @hash
- f.printf "%s=%s\n", CGI::escape(k), CGI::escape(String(v))
- end
+ for k,v in @hash
+ f.printf "%s=%s\n", CGI::escape(k), CGI::escape(String(Marshal.dump(v)))
+ end
f.close
File.rename @path+".new", @path
ensure
@@ -433,15 +434,14 @@ class CGI
# Update and close the session's FileStore file.
def close
- update
+ update
end
# Close and delete the session's FileStore file.
def delete
File::unlink @path+".lock" rescue nil
File::unlink @path+".new" rescue nil
- File::unlink @path
- rescue Errno::ENOENT
+ File::unlink @path rescue Errno::ENOENT
end
end
@@ -459,7 +459,7 @@ class CGI
# +option+ is a list of initialisation options. None are
# currently recognised.
def initialize(session, option=nil)
- @session_id = session.session_id
+ @session_id = session.session_id
unless GLOBAL_HASH_TABLE.key?(@session_id)
unless session.new_session
raise CGI::Session::NoSession, "uninitialized session"
@@ -472,26 +472,26 @@ class CGI
#
# Returns session data as a hash.
def restore
- GLOBAL_HASH_TABLE[@session_id]
+ GLOBAL_HASH_TABLE[@session_id]
end
# Update session state.
#
# A no-op.
def update
- # don't need to update; hash is shared
+ # don't need to update; hash is shared
end
# Close session storage.
#
# A no-op.
def close
- # don't need to close
+ # don't need to close
end
# Delete the session state.
def delete
- GLOBAL_HASH_TABLE.delete(@session_id)
+ GLOBAL_HASH_TABLE.delete(@session_id)
end
end
diff --git a/lib/cgi/session/pstore.rb b/lib/cgi/session/pstore.rb
index 6039183363..3cd3e46000 100644
--- a/lib/cgi/session/pstore.rb
+++ b/lib/cgi/session/pstore.rb
@@ -43,55 +43,55 @@ class CGI
# This session's PStore file will be created if it does
# not exist, or opened if it does.
def initialize(session, option={})
- dir = option['tmpdir'] || Dir::tmpdir
- prefix = option['prefix'] || ''
- id = session.session_id
+ dir = option['tmpdir'] || Dir::tmpdir
+ prefix = option['prefix'] || ''
+ id = session.session_id
require 'digest/md5'
md5 = Digest::MD5.hexdigest(id)[0,16]
- path = dir+"/"+prefix+md5
- path.untaint
- if File::exist?(path)
- @hash = nil
- else
+ path = dir+"/"+prefix+md5
+ path.untaint
+ if File::exist?(path)
+ @hash = nil
+ else
unless session.new_session
raise CGI::Session::NoSession, "uninitialized session"
end
- @hash = {}
- end
- @p = ::PStore.new(path)
- @p.transaction do |p|
- File.chmod(0600, p.path)
- end
+ @hash = {}
+ end
+ @p = ::PStore.new(path)
+ @p.transaction do |p|
+ File.chmod(0600, p.path)
+ end
end
# Restore session state from the session's PStore file.
#
# Returns the session state as a hash.
def restore
- unless @hash
- @p.transaction do
+ unless @hash
+ @p.transaction do
@hash = @p['hash'] || {}
- end
- end
- @hash
+ end
+ end
+ @hash
end
# Save session state to the session's PStore file.
def update
- @p.transaction do
- @p['hash'] = @hash
- end
+ @p.transaction do
+ @p['hash'] = @hash
+ end
end
# Update and close the session's PStore file.
def close
- update
+ update
end
# Close and delete the session's PStore file.
def delete
- path = @p.path
- File::unlink path
+ path = @p.path
+ File::unlink path
end
end
diff --git a/lib/cgi/util.rb b/lib/cgi/util.rb
new file mode 100644
index 0000000000..991b68ce73
--- /dev/null
+++ b/lib/cgi/util.rb
@@ -0,0 +1,181 @@
+class CGI
+ # URL-encode a string.
+ # url_encoded_string = CGI::escape("'Stop!' said Fred")
+ # # => "%27Stop%21%27+said+Fred"
+ def CGI::escape(string)
+ string.gsub(/([^ a-zA-Z0-9_.-]+)/) do
+ '%' + $1.unpack('H2' * $1.bytesize).join('%').upcase
+ end.tr(' ', '+')
+ end
+
+
+ # URL-decode a string.
+ # string = CGI::unescape("%27Stop%21%27+said+Fred")
+ # # => "'Stop!' said Fred"
+ def CGI::unescape(string)
+ enc = string.encoding
+ string.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/) do
+ [$1.delete('%')].pack('H*').force_encoding(enc)
+ end
+ end
+
+ TABLE_FOR_ESCAPE_HTML__ = {
+ '&' => '&amp;',
+ '"' => '&quot;',
+ '<' => '&lt;',
+ '>' => '&gt;',
+ }
+
+ # Escape special characters in HTML, namely &\"<>
+ # CGI::escapeHTML('Usage: foo "bar" <baz>')
+ # # => "Usage: foo &quot;bar&quot; &lt;baz&gt;"
+ def CGI::escapeHTML(string)
+ string.gsub(/[&\"<>]/, TABLE_FOR_ESCAPE_HTML__)
+ end
+
+
+ # Unescape a string that has been HTML-escaped
+ # CGI::unescapeHTML("Usage: foo &quot;bar&quot; &lt;baz&gt;")
+ # # => "Usage: foo \"bar\" <baz>"
+ def CGI::unescapeHTML(string)
+ enc = string.encoding
+ if [Encoding::UTF_16BE, Encoding::UTF_16LE, Encoding::UTF_32BE, Encoding::UTF_32LE].include?(enc)
+ return string.gsub(Regexp.new('&(amp|quot|gt|lt|#[0-9]+|#x[0-9A-Fa-f]+);'.encode(enc))) do
+ case $1.encode("US-ASCII")
+ when 'amp' then '&'.encode(enc)
+ when 'quot' then '"'.encode(enc)
+ when 'gt' then '>'.encode(enc)
+ when 'lt' then '<'.encode(enc)
+ when /\A#0*(\d+)\z/ then $1.to_i.chr(enc)
+ when /\A#x([0-9a-f]+)\z/i then $1.hex.chr(enc)
+ end
+ end
+ end
+ asciicompat = Encoding.compatible?(string, "a")
+ string.gsub(/&(amp|quot|gt|lt|\#[0-9]+|\#x[0-9A-Fa-f]+);/) do
+ match = $1.dup
+ case match
+ when 'amp' then '&'
+ when 'quot' then '"'
+ when 'gt' then '>'
+ when 'lt' then '<'
+ when /\A#0*(\d+)\z/
+ n = $1.to_i
+ if enc == Encoding::UTF_8 or
+ enc == Encoding::ISO_8859_1 && n < 256 or
+ asciicompat && n < 128
+ n.chr(enc)
+ else
+ "&##{$1};"
+ end
+ when /\A#x([0-9a-f]+)\z/i
+ n = $1.hex
+ if enc == Encoding::UTF_8 or
+ enc == Encoding::ISO_8859_1 && n < 256 or
+ asciicompat && n < 128
+ n.chr(enc)
+ else
+ "&#x#{$1};"
+ end
+ else
+ "&#{match};"
+ end
+ end
+ end
+ def CGI::escape_html(str)
+ escapeHTML(str)
+ end
+ def CGI::unescape_html(str)
+ unescapeHTML(str)
+ end
+
+ # Escape only the tags of certain HTML elements in +string+.
+ #
+ # Takes an element or elements or array of elements. Each element
+ # is specified by the name of the element, without angle brackets.
+ # This matches both the start and the end tag of that element.
+ # The attribute list of the open tag will also be escaped (for
+ # instance, the double-quotes surrounding attribute values).
+ #
+ # print CGI::escapeElement('<BR><A HREF="url"></A>', "A", "IMG")
+ # # "<BR>&lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt"
+ #
+ # print CGI::escapeElement('<BR><A HREF="url"></A>', ["A", "IMG"])
+ # # "<BR>&lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt"
+ def CGI::escapeElement(string, *elements)
+ elements = elements[0] if elements[0].kind_of?(Array)
+ unless elements.empty?
+ string.gsub(/<\/?(?:#{elements.join("|")})(?!\w)(?:.|\n)*?>/i) do
+ CGI::escapeHTML($&)
+ end
+ else
+ string
+ end
+ end
+
+
+ # Undo escaping such as that done by CGI::escapeElement()
+ #
+ # print CGI::unescapeElement(
+ # CGI::escapeHTML('<BR><A HREF="url"></A>'), "A", "IMG")
+ # # "&lt;BR&gt;<A HREF="url"></A>"
+ #
+ # print CGI::unescapeElement(
+ # CGI::escapeHTML('<BR><A HREF="url"></A>'), ["A", "IMG"])
+ # # "&lt;BR&gt;<A HREF="url"></A>"
+ def CGI::unescapeElement(string, *elements)
+ elements = elements[0] if elements[0].kind_of?(Array)
+ unless elements.empty?
+ string.gsub(/&lt;\/?(?:#{elements.join("|")})(?!\w)(?:.|\n)*?&gt;/i) do
+ CGI::unescapeHTML($&)
+ end
+ else
+ string
+ end
+ end
+ def CGI::escape_element(str)
+ escapeElement(str)
+ end
+ def CGI::unescape_element(str)
+ unescapeElement(str)
+ end
+
+ # Format a +Time+ object as a String using the format specified by RFC 1123.
+ #
+ # CGI::rfc1123_date(Time.now)
+ # # Sat, 01 Jan 2000 00:00:00 GMT
+ def CGI::rfc1123_date(time)
+ t = time.clone.gmtime
+ return format("%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT",
+ RFC822_DAYS[t.wday], t.day, RFC822_MONTHS[t.month-1], t.year,
+ t.hour, t.min, t.sec)
+ end
+
+ # Prettify (indent) an HTML string.
+ #
+ # +string+ is the HTML string to indent. +shift+ is the indentation
+ # unit to use; it defaults to two spaces.
+ #
+ # print CGI::pretty("<HTML><BODY></BODY></HTML>")
+ # # <HTML>
+ # # <BODY>
+ # # </BODY>
+ # # </HTML>
+ #
+ # print CGI::pretty("<HTML><BODY></BODY></HTML>", "\t")
+ # # <HTML>
+ # # <BODY>
+ # # </BODY>
+ # # </HTML>
+ #
+ def CGI::pretty(string, shift = " ")
+ lines = string.gsub(/(?!\A)<(?:.|\n)*?>/, "\n\\0").gsub(/<(?:.|\n)*?>(?!\n)/, "\\0\n")
+ end_pos = 0
+ while end_pos = lines.index(/^<\/(\w+)/, end_pos)
+ element = $1.dup
+ start_pos = lines.rindex(/^\s*<#{element}/i, end_pos)
+ lines[start_pos ... end_pos] = "__" + lines[start_pos ... end_pos].gsub(/\n(?!\z)/, "\n" + shift) + "__"
+ end
+ lines.gsub(/^((?:#{Regexp::quote(shift)})*)__(?=<\/?\w)/, '\1')
+ end
+end
diff --git a/lib/cmath.rb b/lib/cmath.rb
index 55995879e6..00bcc9087f 100644
--- a/lib/cmath.rb
+++ b/lib/cmath.rb
@@ -25,17 +25,17 @@ module CMath
alias atanh! atanh
def exp(z)
- if z.scalar?
+ if z.real?
exp!(z)
else
- Complex(exp!(z.real) * cos!(z.image),
- exp!(z.real) * sin!(z.image))
+ Complex(exp!(z.real) * cos!(z.imag),
+ exp!(z.real) * sin!(z.imag))
end
end
def log(*args)
z, b = args
- if z.scalar? and z >= 0 and (b.nil? or b >= 0)
+ if z.real? and z >= 0 and (b.nil? or b >= 0)
log!(*args)
else
r, theta = z.polar
@@ -48,7 +48,7 @@ module CMath
end
def log10(z)
- if z.scalar?
+ if z.real?
log10!(z)
else
log(z) / log!(10)
@@ -56,14 +56,14 @@ module CMath
end
def sqrt(z)
- if z.scalar?
+ if z.real?
if z >= 0
sqrt!(z)
else
- Complex(0,sqrt!(-z))
+ Complex(0, sqrt!(-z))
end
else
- if z.image < 0
+ if z.imag < 0
sqrt(z.conjugate).conjugate
else
r = z.abs
@@ -74,25 +74,25 @@ module CMath
end
def sin(z)
- if z.scalar?
+ if z.real?
sin!(z)
else
- Complex(sin!(z.real) * cosh!(z.image),
- cos!(z.real) * sinh!(z.image))
+ Complex(sin!(z.real) * cosh!(z.imag),
+ cos!(z.real) * sinh!(z.imag))
end
end
def cos(z)
- if z.scalar?
+ if z.real?
cos!(z)
else
- Complex(cos!(z.real) * cosh!(z.image),
- -sin!(z.real) * sinh!(z.image))
+ Complex(cos!(z.real) * cosh!(z.imag),
+ -sin!(z.real) * sinh!(z.imag))
end
end
def tan(z)
- if z.scalar?
+ if z.real?
tan!(z)
else
sin(z)/cos(z)
@@ -100,25 +100,25 @@ module CMath
end
def sinh(z)
- if z.scalar?
+ if z.real?
sinh!(z)
else
- Complex(sinh!(z.real) * cos!(z.image),
- cosh!(z.real) * sin!(z.image))
+ Complex(sinh!(z.real) * cos!(z.imag),
+ cosh!(z.real) * sin!(z.imag))
end
end
def cosh(z)
- if z.scalar?
+ if z.real?
cosh!(z)
else
- Complex(cosh!(z.real) * cos!(z.image),
- sinh!(z.real) * sin!(z.image))
+ Complex(cosh!(z.real) * cos!(z.imag),
+ sinh!(z.real) * sin!(z.imag))
end
end
def tanh(z)
- if z.scalar?
+ if z.real?
tanh!(z)
else
sinh(z) / cosh(z)
@@ -126,39 +126,39 @@ module CMath
end
def asin(z)
- if z.scalar? and z >= -1 and z <= 1
+ if z.real? and z >= -1 and z <= 1
asin!(z)
else
- -1.0.im * log(1.0.im * z + sqrt(1.0 - z * z))
+ Complex(0, -1.0) * log(Complex(0, 1.0) * z + sqrt(1.0 - z * z))
end
end
def acos(z)
- if z.scalar? and z >= -1 and z <= 1
+ if z.real? and z >= -1 and z <= 1
acos!(z)
else
- -1.0.im * log(z + 1.0.im * sqrt(1.0 - z * z))
+ Complex(0, -1.0) * log(z + Complex(0, 1.0) * sqrt(1.0 - z * z))
end
end
def atan(z)
- if z.scalar?
+ if z.real?
atan!(z)
else
- 1.0.im * log((1.0.im + z) / (1.0.im - z)) / 2.0
+ Complex(0, 1.0) * log((Complex(0, 1.0) + z) / (Complex(0, 1.0) - z)) / 2.0
end
end
def atan2(y,x)
- if y.scalar? and x.scalar?
+ if y.real? and x.real?
atan2!(y,x)
else
- -1.0.im * log((x + 1.0.im * y) / sqrt(x * x + y * y))
+ Complex(0, -1.0) * log((x + Complex(0, 1.0) * y) / sqrt(x * x + y * y))
end
end
def acosh(z)
- if z.scalar? and z >= 1
+ if z.real? and z >= 1
acosh!(z)
else
log(z + sqrt(z * z - 1.0))
@@ -166,7 +166,7 @@ module CMath
end
def asinh(z)
- if z.scalar?
+ if z.real?
asinh!(z)
else
log(z + sqrt(1.0 + z * z))
@@ -174,7 +174,7 @@ module CMath
end
def atanh(z)
- if z.scalar? and z >= -1 and z <= 1
+ if z.real? and z >= -1 and z <= 1
atanh!(z)
else
log((1.0 + z) / (1.0 - z)) / 2.0
@@ -220,4 +220,14 @@ module CMath
module_function :atanh!
module_function :atanh
+ module_function :log2
+ module_function :cbrt
+ module_function :frexp
+ module_function :ldexp
+ module_function :hypot
+ module_function :erf
+ module_function :erfc
+ module_function :gamma
+ module_function :lgamma
+
end
diff --git a/lib/complex.rb b/lib/complex.rb
index 1845f30b1f..301879143f 100644
--- a/lib/complex.rb
+++ b/lib/complex.rb
@@ -1,10 +1,24 @@
require 'cmath'
-Object.instance_eval{remove_const :Math}
-Math = CMath
+unless defined?(Math.exp!)
+ Object.instance_eval{remove_const :Math}
+ Math = CMath
+end
def Complex.generic? (other)
other.kind_of?(Integer) ||
other.kind_of?(Float) ||
other.kind_of?(Rational)
end
+
+class Complex
+
+ alias image imag
+
+end
+
+class Numeric
+
+ def im() Complex(0, self) end
+
+end
diff --git a/lib/csv.rb b/lib/csv.rb
index f60d5b1cb0..6fb5da4d79 100644
--- a/lib/csv.rb
+++ b/lib/csv.rb
@@ -1,5 +1,5 @@
-#!/usr/local/bin/ruby -w
-
+#!/usr/bin/env ruby -w
+# encoding: UTF-8
# = csv.rb -- CSV Reading and Writing
#
# Created by James Edward Gray II on 2005-10-31.
@@ -37,6 +37,7 @@
#
# === CSV Parsing
#
+# * This parser is m17n aware. See CSV for full details.
# * This library has a stricter parser and will throw MalformedCSVErrors on
# problematic data.
# * This library has a less liberal idea of a line ending than CSV. What you
@@ -91,7 +92,6 @@
require "forwardable"
require "English"
-require "enumerator"
require "date"
require "stringio"
@@ -130,7 +130,7 @@ require "stringio"
#
# === To a File
#
-# CSV.open("path/to/file.csv", "w") do |csv|
+# CSV.open("path/to/file.csv", "wb") do |csv|
# csv << ["row", "of", "CSV", "data"]
# csv << ["another", "row"]
# # ...
@@ -155,9 +155,51 @@ require "stringio"
# CSV(csv = "") { |csv_str| csv_str << %w{my data here} } # to a String
# CSV($stderr) { |csv_err| csv_err << %w{my data here} } # to $stderr
#
+# == CSV and Character Encodings (M17n or Multilingualization)
+#
+# This new CSV parser is m17n savvy. The parser works in the Encoding of the IO
+# or String object being read from or written to. Your data is never transcoded
+# (unless you ask Ruby to transcode it for you) and will literally be parsed in
+# the Encoding it is in. Thus CSV will return Arrays or Rows of Strings in the
+# Encoding of your data. This is accomplished by transcoding the parser itself
+# into your Encoding.
+#
+# Some transcoding must take place, of course, to accomplish this multiencoding
+# support. For example, <tt>:col_sep</tt>, <tt>:row_sep</tt>, and
+# <tt>:quote_char</tt> must be transcoded to match your data. Hopefully this
+# makes the entire process feel transparent, since CSV's defaults should just
+# magically work for you data. However, you can set these values manually in
+# the target Encoding to avoid the translation.
+#
+# It's also important to note that while all of CSV's core parser is now
+# Encoding agnostic, some features are not. For example, the built-in
+# converters will try to transcode data to UTF-8 before making conversions.
+# Again, you can provide custom converters that are aware of your Encodings to
+# avoid this translation. It's just too hard for me to support native
+# conversions in all of Ruby's Encodings.
+#
+# Anyway, the practical side of this is simple: make sure IO and String objects
+# passed into CSV have the proper Encoding set and everything should just work.
+# CSV methods that allow you to open IO objects (CSV::foreach(), CSV::open(),
+# CSV::read(), and CSV::readlines()) do allow you to specify the Encoding.
+#
+# One minor exception comes when generating CSV into a String with an Encoding
+# that is not ASCII compatible. There's no existing data for CSV to use to
+# prepare itself and thus you will probably need to manually specify the desired
+# Encoding for most of those cases. It will try to guess using the fields in a
+# row of output though, when using CSV::generate_line() or Array#to_csv().
+#
+# I try to point out any other Encoding issues in the documentation of methods
+# as they come up.
+#
+# This has been tested to the best of my ability with all non-"dummy" Encodings
+# Ruby ships with. However, it is brave new code and may have some bugs.
+# Please feel free to {report}[mailto:james@grayproductions.net] any issues you
+# find with it.
+#
class CSV
# The version of the installed library.
- VERSION = "2.0.0".freeze
+ VERSION = "2.4.4".freeze
#
# A CSV::Row is part Array and part Hash. It retains an order for the fields
@@ -188,9 +230,9 @@ class CSV
# handle extra headers or fields
@row = if headers.size > fields.size
- headers.each_with_index.map { |header, i| [header, fields[i]] }
+ headers.zip(fields)
else
- fields.each_with_index.map { |field, i| [headers[i], field] }
+ fields.zip(headers).map { |pair| pair.reverse }
end
end
@@ -444,6 +486,17 @@ class CSV
fields.to_csv(options)
end
alias_method :to_s, :to_csv
+
+ # A summary of fields, by header, in an ASCII-8BIT String.
+ def inspect
+ str = ["#<", self.class.to_s]
+ each do |header, field|
+ str << " " << (header.is_a?(Symbol) ? header.to_s : header.inspect) <<
+ ":" << field.inspect
+ end
+ str << ">"
+ str.map { |s| s.encode("ASCII-8BIT") }.join
+ end
end
#
@@ -775,6 +828,11 @@ class CSV
end.join
end
alias_method :to_s, :to_csv
+
+ # Shows the mode and size of this table in a US-ASCII String.
+ def inspect
+ "#<#{self.class} mode:#{@mode} row_count:#{to_a.size}>".encode("US-ASCII")
+ end
end
# The error thrown when the parser encounters illegal CSV formatting.
@@ -799,6 +857,10 @@ class CSV
DateTimeMatcher =
/ \A(?: (\w+,?\s+)?\w+\s+\d{1,2}\s+\d{1,2}:\d{1,2}:\d{1,2},?\s+\d{2,4} |
\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2} )\z /x
+
+ # The encoding used by all converters.
+ ConverterEncoding = Encoding.find("UTF-8")
+
#
# This Hash holds the built-in converters of CSV that can be accessed by name.
# You can select Converters with CSV.convert() or through the +options+ Hash
@@ -813,22 +875,40 @@ class CSV
# <b><tt>:all</tt></b>:: All built-in converters. A combination of
# <tt>:date_time</tt> and <tt>:numeric</tt>.
#
+ # All built-in converters transcode field data to UTF-8 before attempting a
+ # conversion. If your data cannot be transcoded to UTF-8 the conversion will
+ # fail and the field will remain unchanged.
+ #
# This Hash is intentionally left unfrozen and users should feel free to add
# values to it that can be accessed by all CSV objects.
#
# To add a combo field, the value should be an Array of names. Combo fields
# can be nested with other combo fields.
#
- Converters = { :integer => lambda { |f| Integer(f) rescue f },
- :float => lambda { |f| Float(f) rescue f },
- :numeric => [:integer, :float],
- :date => lambda { |f|
- f =~ DateMatcher ? (Date.parse(f) rescue f) : f
+ Converters = { integer: lambda { |f|
+ Integer(f.encode(ConverterEncoding)) rescue f
+ },
+ float: lambda { |f|
+ Float(f.encode(ConverterEncoding)) rescue f
+ },
+ numeric: [:integer, :float],
+ date: lambda { |f|
+ begin
+ e = f.encode(ConverterEncoding)
+ e =~ DateMatcher ? Date.parse(e) : f
+ rescue # encoding conversion or date parse errors
+ f
+ end
},
- :date_time => lambda { |f|
- f =~ DateTimeMatcher ? (DateTime.parse(f) rescue f) : f
+ date_time: lambda { |f|
+ begin
+ e = f.encode(ConverterEncoding)
+ e =~ DateTimeMatcher ? DateTime.parse(e) : f
+ rescue # encoding conversion or date parse errors
+ f
+ end
},
- :all => [:date_time, :numeric] }
+ all: [:date_time, :numeric] }
#
# This Hash holds the built-in header converters of CSV that can be accessed
@@ -840,6 +920,10 @@ class CSV
# replaced with underscores, non-word characters
# are dropped, and finally to_sym() is called.
#
+ # All built-in header converters transcode header data to UTF-8 before
+ # attempting a conversion. If your data cannot be transcoded to UTF-8 the
+ # conversion will fail and the header will remain unchanged.
+ #
# This Hash is intetionally left unfrozen and users should feel free to add
# values to it that can be accessed by all CSV objects.
#
@@ -847,9 +931,10 @@ class CSV
# can be nested with other combo fields.
#
HeaderConverters = {
- :downcase => lambda { |h| h.downcase },
- :symbol => lambda { |h|
- h.downcase.tr(" ", "_").delete("^a-z0-9_").to_sym
+ downcase: lambda { |h| h.encode(ConverterEncoding).downcase },
+ symbol: lambda { |h|
+ h.encode(ConverterEncoding).downcase.gsub(/\s+/, "_").
+ gsub(/\W+/, "").to_sym
}
}
@@ -859,6 +944,7 @@ class CSV
# <b><tt>:col_sep</tt></b>:: <tt>","</tt>
# <b><tt>:row_sep</tt></b>:: <tt>:auto</tt>
# <b><tt>:quote_char</tt></b>:: <tt>'"'</tt>
+ # <b><tt>:field_size_limit</tt></b>:: +nil+
# <b><tt>:converters</tt></b>:: +nil+
# <b><tt>:unconverted_fields</tt></b>:: +nil+
# <b><tt>:headers</tt></b>:: +false+
@@ -867,18 +953,44 @@ class CSV
# <b><tt>:skip_blanks</tt></b>:: +false+
# <b><tt>:force_quotes</tt></b>:: +false+
#
- DEFAULT_OPTIONS = { :col_sep => ",",
- :row_sep => :auto,
- :quote_char => '"',
- :converters => nil,
- :unconverted_fields => nil,
- :headers => false,
- :return_headers => false,
- :header_converters => nil,
- :skip_blanks => false,
- :force_quotes => false }.freeze
+ DEFAULT_OPTIONS = { col_sep: ",",
+ row_sep: :auto,
+ quote_char: '"',
+ field_size_limit: nil,
+ converters: nil,
+ unconverted_fields: nil,
+ headers: false,
+ return_headers: false,
+ header_converters: nil,
+ skip_blanks: false,
+ force_quotes: false }.freeze
#
+ # This method will return a CSV instance, just like CSV::new(), but the
+ # instance will be cached and returned for all future calls to this method for
+ # the same +data+ object (tested by Object#object_id()) with the same
+ # +options+.
+ #
+ # If a block is given, the instance is passed to the block and the return
+ # value becomes the return value of the block.
+ #
+ def self.instance(data = $stdout, options = Hash.new)
+ # create a _signature_ for this method call, data object and options
+ sig = [data.object_id] +
+ options.values_at(*DEFAULT_OPTIONS.keys.sort_by { |sym| sym.to_s })
+
+ # fetch or create the instance for this signature
+ @@instances ||= Hash.new
+ instance = (@@instances[sig] ||= new(data, options))
+
+ if block_given?
+ yield instance # run block, if given, returning result
+ else
+ instance # or return the instance
+ end
+ end
+
+ #
# This method allows you to serialize an Array of Ruby objects to a String or
# File of CSV data. This is not as powerful as Marshal or YAML, but perhaps
# useful for spreadsheet and database interaction.
@@ -959,6 +1071,53 @@ class CSV
end
#
+ # This method is the reading counterpart to CSV::dump(). See that method for
+ # a detailed description of the process.
+ #
+ # You can customize loading by adding a class method called csv_load() which
+ # will be passed a Hash of meta information, an Array of headers, and an Array
+ # of fields for the object the method is expected to return.
+ #
+ # Remember that all fields will be Strings after this load. If you need
+ # something else, use +options+ to setup converters or provide a custom
+ # csv_load() implementation.
+ #
+ def self.load(io_or_str, options = Hash.new)
+ csv = new(io_or_str, options)
+
+ # load meta information
+ meta = Hash[*csv.shift]
+ cls = meta["class".encode(csv.encoding)].split("::".encode(csv.encoding)).
+ inject(Object) do |c, const|
+ c.const_get(const)
+ end
+
+ # load headers
+ headers = csv.shift
+
+ # unserialize each object stored in the file
+ results = csv.inject(Array.new) do |all, row|
+ begin
+ obj = cls.csv_load(meta, headers, row)
+ rescue NoMethodError
+ obj = cls.allocate
+ headers.zip(row) do |name, value|
+ if name[0] == ?@
+ obj.instance_variable_set(name, value)
+ else
+ obj.send(name, value)
+ end
+ end
+ end
+ all << obj
+ end
+
+ csv.close unless io_or_str.is_a? String
+
+ results
+ end
+
+ #
# :call-seq:
# filter( options = Hash.new ) { |row| ... }
# filter( input, options = Hash.new ) { |row| ... }
@@ -984,7 +1143,7 @@ class CSV
#
def self.filter(*args)
# parse options for input, output, or both
- in_options, out_options = Hash.new, {:row_sep => $INPUT_RECORD_SEPARATOR}
+ in_options, out_options = Hash.new, {row_sep: $INPUT_RECORD_SEPARATOR}
if args.last.is_a? Hash
args.pop.each do |key, value|
case key.to_s
@@ -1014,10 +1173,20 @@ class CSV
# pass a +path+ and any +options+ you wish to set for the read. Each row of
# file will be passed to the provided +block+ in turn.
#
- # The +options+ parameter can be anything CSV::new() understands.
+ # The +options+ parameter can be anything CSV::new() understands. This method
+ # also understands an additional <tt>:encoding</tt> parameter that you can use
+ # to specify the Encoding of the data in the file to be read. You must provide
+ # this unless your data is in Encoding::default_external(). CSV will use this
+ # to deterime how to parse the data. You may provide a second Encoding to
+ # have the data transcoded as it is read. For example,
+ # <tt>encoding: "UTF-32BE:UTF-8"</tt> would read UTF-32BE data from the file
+ # but transcode it to UTF-8 before CSV parses it.
#
def self.foreach(path, options = Hash.new, &block)
- open(path, options) do |csv|
+ encoding = options.delete(:encoding)
+ mode = "rb"
+ mode << ":#{encoding}" if encoding
+ open(path, mode, options) do |csv|
csv.each(&block)
end
end
@@ -1035,7 +1204,10 @@ class CSV
# Note that a passed String *is* modfied by this method. Call dup() before
# passing if you need a new String.
#
- # The +options+ parameter can be anthing CSV::new() understands.
+ # The +options+ parameter can be anthing CSV::new() understands. This method
+ # understands an additional <tt>:encoding</tt> parameter when not passed a
+ # String to set the base Encoding for the output. CSV needs this hint if you
+ # plan to output non-ASCII compatible data.
#
def self.generate(*args)
# add a default empty String, if none was given
@@ -1044,7 +1216,10 @@ class CSV
io.seek(0, IO::SEEK_END)
args.unshift(io)
else
- args.unshift("")
+ encoding = args.last.is_a?(Hash) ? args.last.delete(:encoding) : nil
+ str = ""
+ str.encode!(encoding) if encoding
+ args.unshift(str)
end
csv = new(*args) # wrap
yield csv # yield for appending
@@ -1055,97 +1230,40 @@ class CSV
# This method is a shortcut for converting a single row (Array) into a CSV
# String.
#
- # The +options+ parameter can be anthing CSV::new() understands.
+ # The +options+ parameter can be anthing CSV::new() understands. This method
+ # understands an additional <tt>:encoding</tt> parameter to set the base
+ # Encoding for the output. This method will try to guess your Encoding from
+ # the first non-+nil+ field in +row+, if possible, but you may need to use
+ # this parameter as a backup plan.
#
# The <tt>:row_sep</tt> +option+ defaults to <tt>$INPUT_RECORD_SEPARATOR</tt>
# (<tt>$/</tt>) when calling this method.
#
def self.generate_line(row, options = Hash.new)
- options = {:row_sep => $INPUT_RECORD_SEPARATOR}.merge(options)
- (new("", options) << row).string
- end
-
- #
- # This method will return a CSV instance, just like CSV::new(), but the
- # instance will be cached and returned for all future calls to this method for
- # the same +data+ object (tested by Object#object_id()) with the same
- # +options+.
- #
- # If a block is given, the instance is passed to the block and the return
- # value becomes the return value of the block.
- #
- def self.instance(data = $stdout, options = Hash.new)
- # create a _signature_ for this method call, data object and options
- sig = [data.object_id] +
- options.values_at(*DEFAULT_OPTIONS.keys.sort_by { |sym| sym.to_s })
-
- # fetch or create the instance for this signature
- @@instances ||= Hash.new
- instance = (@@instances[sig] ||= new(data, options))
-
- if block_given?
- yield instance # run block, if given, returning result
- else
- instance # or return the instance
- end
- end
-
- #
- # This method is the reading counterpart to CSV::dump(). See that method for
- # a detailed description of the process.
- #
- # You can customize loading by adding a class method called csv_load() which
- # will be passed a Hash of meta information, an Array of headers, and an Array
- # of fields for the object the method is expected to return.
- #
- # Remember that all fields will be Strings after this load. If you need
- # something else, use +options+ to setup converters or provide a custom
- # csv_load() implementation.
- #
- def self.load(io_or_str, options = Hash.new)
- csv = new(io_or_str, options)
-
- # load meta information
- meta = Hash[*csv.shift]
- cls = meta["class"].split("::").inject(Object) do |c, const|
- c.const_get(const)
- end
-
- # load headers
- headers = csv.shift
-
- # unserialize each object stored in the file
- results = csv.inject(Array.new) do |all, row|
- begin
- obj = cls.csv_load(meta, headers, row)
- rescue NoMethodError
- obj = cls.allocate
- headers.zip(row) do |name, value|
- if name[0] == ?@
- obj.instance_variable_set(name, value)
- else
- obj.send(name, value)
- end
- end
- end
- all << obj
- end
-
- csv.close unless io_or_str.is_a? String
-
- results
+ options = {row_sep: $INPUT_RECORD_SEPARATOR}.merge(options)
+ encoding = options.delete(:encoding)
+ str = ""
+ if encoding
+ str.force_encoding(encoding)
+ elsif field = row.find { |f| not f.nil? }
+ str.force_encoding(String(field).encoding)
+ end
+ (new(str, options) << row).string
end
#
# :call-seq:
- # open( filename, mode="r", options = Hash.new ) { |csv| ... }
- # open( filename, mode="r", options = Hash.new )
+ # open( filename, mode = "rb", options = Hash.new ) { |faster_csv| ... }
+ # open( filename, options = Hash.new ) { |faster_csv| ... }
+ # open( filename, mode = "rb", options = Hash.new )
+ # open( filename, options = Hash.new )
#
# This method opens an IO object, and wraps that with CSV. This is intended
# as the primary interface for writing a CSV file.
#
- # You may pass any +args+ Ruby's open() understands followed by an optional
- # Hash containing any +options+ CSV::new() understands.
+ # You must pass a +filename+ and may optionally add a +mode+ for Ruby's
+ # open(). You may also pass an optional Hash containing any +options+
+ # CSV::new() understands as the final argument.
#
# This method works like Ruby's open() call, in that it will pass a CSV object
# to a provided block and close it when the block terminates, or it will
@@ -1153,24 +1271,38 @@ class CSV
# from the Ruby 1.8 CSV library which passed rows to the block. Use
# CSV::foreach() for that behavior.)
#
- # An opened CSV object will delegate to many IO methods, for convenience. You
+ # You must provide a +mode+ with an embedded Encoding designator unless your
+ # data is in Encoding::default_external(). CSV will check the Encoding of the
+ # underlying IO object (set by the +mode+ you pass) to deterime how to parse
+ # the data. You may provide a second Encoding to have the data transcoded as
+ # it is read just as you can with a normal call to IO::open(). For example,
+ # <tt>"rb:UTF-32BE:UTF-8"</tt> would read UTF-32BE data from the file but
+ # transcode it to UTF-8 before CSV parses it.
+ #
+ # An opened CSV object will delegate to many IO methods for convenience. You
# may call:
#
# * binmode()
+ # * binmode?()
# * close()
# * close_read()
# * close_write()
# * closed?()
# * eof()
# * eof?()
+ # * external_encoding()
# * fcntl()
# * fileno()
+ # * flock()
# * flush()
# * fsync()
+ # * internal_encoding()
# * ioctl()
# * isatty()
+ # * path()
# * pid()
# * pos()
+ # * pos=()
# * reopen()
# * seek()
# * stat()
@@ -1179,11 +1311,14 @@ class CSV
# * tell()
# * to_i()
# * to_io()
+ # * truncate()
# * tty?()
#
def self.open(*args)
# find the +options+ Hash
options = if args.last.is_a? Hash then args.pop else Hash.new end
+ # default to a binary open mode
+ args << "rb" if args.size == 1
# wrap a File opened with the remaining +args+
csv = new(File.open(*args), options)
@@ -1237,10 +1372,20 @@ class CSV
#
# Use to slurp a CSV file into an Array of Arrays. Pass the +path+ to the
- # file and any +options+ CSV::new() understands.
+ # file and any +options+ CSV::new() understands. This method also understands
+ # an additional <tt>:encoding</tt> parameter that you can use to specify the
+ # Encoding of the data in the file to be read. You must provide this unless
+ # your data is in Encoding::default_external(). CSV will use this to deterime
+ # how to parse the data. You may provide a second Encoding to have the data
+ # transcoded as it is read. For example,
+ # <tt>encoding: "UTF-32BE:UTF-8"</tt> would read UTF-32BE data from the file
+ # but transcode it to UTF-8 before CSV parses it.
#
def self.read(path, options = Hash.new)
- open(path, options) { |csv| csv.read }
+ encoding = options.delete(:encoding)
+ mode = "rb"
+ mode << ":#{encoding}" if encoding
+ open(path, mode, options) { |csv| csv.read }
end
# Alias for CSV::read().
@@ -1251,14 +1396,14 @@ class CSV
#
# A shortcut for:
#
- # CSV.read( path, { :headers => true,
- # :converters => :numeric,
- # :header_converters => :symbol }.merge(options) )
+ # CSV.read( path, { headers: true,
+ # converters: :numeric,
+ # header_converters: :symbol }.merge(options) )
#
def self.table(path, options = Hash.new)
- read( path, { :headers => true,
- :converters => :numeric,
- :header_converters => :symbol }.merge(options) )
+ read( path, { headers: true,
+ converters: :numeric,
+ header_converters: :symbol }.merge(options) )
end
#
@@ -1276,6 +1421,8 @@ class CSV
# Available options are:
#
# <b><tt>:col_sep</tt></b>:: The String placed between each field.
+ # This String will be transcoded into
+ # the data's Encoding before parsing.
# <b><tt>:row_sep</tt></b>:: The String appended to the end of each
# row. This can be set to the special
# <tt>:auto</tt> setting, which requests
@@ -1295,7 +1442,16 @@ class CSV
# <tt>$INPUT_RECORD_SEPARATOR</tt>
# (<tt>$/</tt>) is used. Obviously,
# discovery takes a little time. Set
- # manually if speed is important.
+ # manually if speed is important. Also
+ # note that IO objects should be opened
+ # in binary mode on Windows if this
+ # feature will be used as the
+ # line-ending translation can cause
+ # problems with resetting the document
+ # position to where it was before the
+ # read ahead. This String will be
+ # transcoded into the data's Encoding
+ # before parsing.
# <b><tt>:quote_char</tt></b>:: The character used to quote fields.
# This has to be a single character
# String. This is useful for
@@ -1304,11 +1460,31 @@ class CSV
# instead of the correct <tt>"</tt>.
# CSV will always consider a double
# sequence this character to be an
- # escaped quote.
+ # escaped quote. This String will be
+ # transcoded into the data's Encoding
+ # before parsing.
+ # <b><tt>:field_size_limit</tt></b>:: This is a maximum size CSV will read
+ # ahead looking for the closing quote
+ # for a field. (In truth, it reads to
+ # the first line ending beyond this
+ # size.) If a quote cannot be found
+ # within the limit CSV will raise a
+ # MalformedCSVError, assuming the data
+ # is faulty. You can use this limit to
+ # prevent what are effectively DoS
+ # attacks on the parser. However, this
+ # limit can cause a legitimate parse to
+ # fail and thus is set to +nil+, or off,
+ # by default.
# <b><tt>:converters</tt></b>:: An Array of names from the Converters
# Hash and/or lambdas that handle custom
# conversion. A single converter
- # doesn't have to be in an Array.
+ # doesn't have to be in an Array. All
+ # built-in converters try to transcode
+ # fields to UTF-8 before converting.
+ # The conversion will fail if the data
+ # cannot be transcoded, leaving the
+ # field unchanged.
# <b><tt>:unconverted_fields</tt></b>:: If set to +true+, an
# unconverted_fields() method will be
# added to all returned rows (Array or
@@ -1324,11 +1500,14 @@ class CSV
# headers. If set to an Array, the
# contents will be used as the headers.
# If set to a String, the String is run
- # through a call of CSV::parse_line() to
- # produce an Array of headers. This
- # setting causes CSV.shift() to return
+ # through a call of CSV::parse_line()
+ # with the same <tt>:col_sep</tt>,
+ # <tt>:row_sep</tt>, and
+ # <tt>:quote_char</tt> as this instance
+ # to produce an Array of headers. This
+ # setting causes CSV#shift() to return
# rows as CSV::Row objects instead of
- # Arrays and CSV.read() to return
+ # Arrays and CSV#read() to return
# CSV::Table objects instead of an Array
# of Arrays.
# <b><tt>:return_headers</tt></b>:: When +false+, header rows are silently
@@ -1337,10 +1516,17 @@ class CSV
# with identical headers and
# fields (save that the fields do not go
# through the converters).
+ # <b><tt>:write_headers</tt></b>:: When +true+ and <tt>:headers</tt> is
+ # set, a header row will be added to the
+ # output.
# <b><tt>:header_converters</tt></b>:: Identical in functionality to
# <tt>:converters</tt> save that the
# conversions are only made to header
- # rows.
+ # rows. All built-in converters try to
+ # transcode headers to UTF-8 before
+ # converting. The conversion will fail
+ # if the data cannot be transcoded,
+ # leaving the header unchanged.
# <b><tt>:skip_blanks</tt></b>:: When set to a +true+ value, CSV will
# skip over any rows with no content.
# <b><tt>:force_quotes</tt></b>:: When set to a +true+ value, CSV will
@@ -1356,8 +1542,24 @@ class CSV
options = DEFAULT_OPTIONS.merge(options)
# create the IO object we will read from
- @io = if data.is_a? String then StringIO.new(data) else data end
-
+ @io = if data.is_a? String then StringIO.new(data) else data end
+ # honor the IO encoding if we can, otherwise default to ASCII-8BIT
+ @encoding = if @io.respond_to? :internal_encoding
+ @io.internal_encoding || @io.external_encoding
+ elsif @io.is_a? StringIO
+ @io.string.encoding
+ end
+ @encoding ||= Encoding.default_internal || Encoding.default_external
+ #
+ # prepare for building safe regular expressions in the target encoding,
+ # if we can transcode the needed characters
+ #
+ @re_esc = "\\".encode(@encoding) rescue ""
+ @re_chars = %w[ \\ . [ ] - ^ $ ?
+ * + { } ( ) | #
+ \ \r \n \t \f \v ].
+ map { |s| s.encode(@encoding) rescue nil }.compact
+
init_separators(options)
init_parsers(options)
init_converters(options)
@@ -1372,6 +1574,79 @@ class CSV
end
#
+ # The encoded <tt>:col_sep</tt> used in parsing and writing. See CSV::new
+ # for details.
+ #
+ attr_reader :col_sep
+ #
+ # The encoded <tt>:row_sep</tt> used in parsing and writing. See CSV::new
+ # for details.
+ #
+ attr_reader :row_sep
+ #
+ # The encoded <tt>:quote_char</tt> used in parsing and writing. See CSV::new
+ # for details.
+ #
+ attr_reader :quote_char
+ # The limit for field size, if any. See CSV::new for details.
+ attr_reader :field_size_limit
+ #
+ # Returns the current list of converters in effect. See CSV::new for details.
+ # Built-in converters will be returned by name, while others will be returned
+ # as is.
+ #
+ def converters
+ @converters.map do |converter|
+ name = Converters.rassoc(converter)
+ name ? name.first : converter
+ end
+ end
+ #
+ # Returns +true+ if unconverted_fields() to parsed results. See CSV::new
+ # for details.
+ #
+ def unconverted_fields?() @unconverted_fields end
+ #
+ # Returns +nil+ if headers will not be used, +true+ if they will but have not
+ # yet been read, or the actual headers after they have been read. See
+ # CSV::new for details.
+ #
+ def headers
+ @headers || true if @use_headers
+ end
+ #
+ # Returns +true+ if headers will be returned as a row of results.
+ # See CSV::new for details.
+ #
+ def return_headers?() @return_headers end
+ # Returns +true+ if headers are written in output. See CSV::new for details.
+ def write_headers?() @write_headers end
+ #
+ # Returns the current list of converters in effect for headers. See CSV::new
+ # for details. Built-in converters will be returned by name, while others
+ # will be returned as is.
+ #
+ def header_converters
+ @header_converters.map do |converter|
+ name = HeaderConverters.rassoc(converter)
+ name ? name.first : converter
+ end
+ end
+ #
+ # Returns +true+ blank lines are skipped by the parser. See CSV::new
+ # for details.
+ #
+ def skip_blanks?() @skip_blanks end
+ # Returns +true+ if all output fields are quoted. See CSV::new for details.
+ def force_quotes?() @force_quotes end
+
+ #
+ # The Encoding CSV is parsing or writing in. This will be the Encoding you
+ # receive parsed data in and/or the Encoding data will be written in.
+ #
+ attr_reader :encoding
+
+ #
# The line number of the last row read from this file. Fields with nested
# line-end characters will not affect this count.
#
@@ -1380,10 +1655,12 @@ class CSV
### IO and StringIO Delegation ###
extend Forwardable
- def_delegators :@io, :binmode, :close, :close_read, :close_write, :closed?,
- :eof, :eof?, :fcntl, :fileno, :flush, :fsync, :ioctl,
- :isatty, :pid, :pos, :reopen, :seek, :stat, :string,
- :sync, :sync=, :tell, :to_i, :to_io, :tty?
+ def_delegators :@io, :binmode, :binmode?, :close, :close_read, :close_write,
+ :closed?, :eof, :eof?, :external_encoding, :fcntl,
+ :fileno, :flock, :flush, :fsync, :internal_encoding,
+ :ioctl, :isatty, :path, :pid, :pos, :pos=, :reopen,
+ :seek, :stat, :string, :sync, :sync=, :tell, :to_i,
+ :to_io, :truncate, :tty?
# Rewinds the underlying IO object and resets CSV's lineno() counter.
def rewind
@@ -1403,12 +1680,18 @@ class CSV
# The data source must be open for writing.
#
def <<(row)
+ # make sure headers have been assigned
+ if header_row? and [Array, String].include? @use_headers.class
+ parse_headers # won't read data for Array or String
+ self << @headers if @write_headers
+ end
+
# handle CSV::Row objects and Hashes
row = case row
- when self.class::Row then row.fields
- when Hash then @headers.map { |header| row[header] }
- else row
- end
+ when self.class::Row then row.fields
+ when Hash then @headers.map { |header| row[header] }
+ else row
+ end
@headers = row if header_row?
@lineno += 1
@@ -1431,7 +1714,7 @@ class CSV
#
# If you provide a block that takes one argument, it will be passed the field
# and is expected to return the converted value or the field itself. If your
- # block takes two arguments, it will also be passed a FieldInfo Struct,
+ # block takes two arguments, it will also be passed a CSV::FieldInfo Struct,
# containing details about the field. Again, the block should return a
# converted field or the field itself.
#
@@ -1445,7 +1728,7 @@ class CSV
# header_convert { |field| ... }
# header_convert { |field, field_info| ... }
#
- # Identical to CSV.convert(), but for header rows.
+ # Identical to CSV#convert(), but for header rows.
#
# Note that this method must be called before header rows are read to have any
# effect.
@@ -1526,7 +1809,7 @@ class CSV
# add another read to the line
(line += @io.gets(@row_sep)) rescue return nil
# copy the line so we can chop it up in parsing
- parse = line.dup
+ parse = line.dup
parse.sub!(@parsers[:line_end], "")
#
@@ -1566,7 +1849,7 @@ class CSV
nil # for Ruby 1.8 CSV compatibility
else
# I decided to take a strict approach to CSV parsing...
- if $2.count("\r\n").zero? # verify correctness of field...
+ if $2.count(@parsers[:return_newline]).zero? # verify correctness
$2
else
# or throw an Exception
@@ -1603,6 +1886,10 @@ class CSV
# if we're not empty?() but at eof?(), a quoted field wasn't closed...
if @io.eof?
raise MalformedCSVError, "Unclosed quoted field on line #{lineno + 1}."
+ elsif parse =~ @parsers[:bad_field]
+ raise MalformedCSVError, "Illegal quoting on line #{lineno + 1}."
+ elsif @field_size_limit and parse.length >= @field_size_limit
+ raise MalformedCSVError, "Field size exceeded on line #{lineno + 1}."
end
# otherwise, we need to loop and pull some more data to complete the row
end
@@ -1610,6 +1897,38 @@ class CSV
alias_method :gets, :shift
alias_method :readline, :shift
+ #
+ # Returns a simplified description of the key FasterCSV attributes in an
+ # ASCII-8BIT String.
+ #
+ def inspect
+ str = ["<#", self.class.to_s, " io_type:"]
+ # show type of wrapped IO
+ if @io == $stdout then str << "$stdout"
+ elsif @io == $stdin then str << "$stdin"
+ elsif @io == $stderr then str << "$stderr"
+ else str << @io.class.to_s
+ end
+ # show IO.path(), if available
+ if @io.respond_to?(:path) and (p = @io.path)
+ str << " io_path:" << p.inspect
+ end
+ # show encoding
+ str << " encoding:" << @encoding.name
+ # show other attributes
+ %w[ lineno col_sep row_sep
+ quote_char skip_blanks ].each do |attr_name|
+ if a = instance_variable_get("@#{attr_name}")
+ str << " " << attr_name << ":" << a.inspect
+ end
+ end
+ if @use_headers
+ str << " headers:" << headers.inspect
+ end
+ str << ">"
+ str.map { |s| s.encode("ASCII-8BIT") }.join
+ end
+
private
#
@@ -1624,15 +1943,18 @@ class CSV
#
def init_separators(options)
# store the selected separators
- @col_sep = options.delete(:col_sep)
- @row_sep = options.delete(:row_sep)
- @quote_char = options.delete(:quote_char)
+ @col_sep = options.delete(:col_sep).to_s.encode(@encoding)
+ @row_sep = options.delete(:row_sep) # encode after resolving :auto
+ @quote_char = options.delete(:quote_char).to_s.encode(@encoding)
if @quote_char.length != 1
raise ArgumentError, ":quote_char has to be a single character String"
end
+ #
# automatically discover row separator when requested
+ # (not fully encoding safe)
+ #
if @row_sep == :auto
if [ARGF, STDIN, STDOUT, STDERR].include?(@io) or
(defined?(Zlib) and @io.class == Zlib::GzipWriter)
@@ -1651,11 +1973,12 @@ class CSV
end
# read ahead a bit
- sample = @io.read(1024)
- sample += @io.read(1) if sample[-1..-1] == "\r" and not @io.eof?
+ sample = read_to_char(1024)
+ sample += read_to_char(1) if sample[-1..-1] == encode_str("\r") and
+ not @io.eof?
# try to find a standard separator
- if sample =~ /\r\n?|\n/
+ if sample =~ encode_re("\r\n?|\n")
@row_sep = $&
break
end
@@ -1673,14 +1996,17 @@ class CSV
end
end
end
+ @row_sep = @row_sep.to_s.encode(@encoding)
# establish quoting rules
- do_quote = lambda do |field|
+ @force_quotes = options.delete(:force_quotes)
+ do_quote = lambda do |field|
@quote_char +
String(field).gsub(@quote_char, @quote_char * 2) +
@quote_char
end
- @quote = if options.delete(:force_quotes)
+ quotable_chars = encode_str("\r\n", @col_sep, @quote_char)
+ @quote = if @force_quotes
do_quote
else
lambda do |field|
@@ -1690,7 +2016,7 @@ class CSV
field = String(field) # Stringify fields
# represent empty fields as empty quoted fields
if field.empty? or
- field.count("\r\n#{@col_sep}#{@quote_char}").nonzero?
+ field.count(quotable_chars).nonzero?
do_quote.call(field)
else
field # unquoted field
@@ -1703,27 +2029,45 @@ class CSV
# Pre-compiles parsers and stores them by name for access during reads.
def init_parsers(options)
# store the parser behaviors
- @skip_blanks = options.delete(:skip_blanks)
+ @skip_blanks = options.delete(:skip_blanks)
+ @field_size_limit = options.delete(:field_size_limit)
# prebuild Regexps for faster parsing
- esc_col_sep = Regexp.escape(@col_sep)
- esc_row_sep = Regexp.escape(@row_sep)
- esc_quote = Regexp.escape(@quote_char)
+ esc_col_sep = escape_re(@col_sep)
+ esc_row_sep = escape_re(@row_sep)
+ esc_quote = escape_re(@quote_char)
@parsers = {
- :leading_fields =>
- /\A(?:#{esc_col_sep})+/, # for empty leading fields
- :csv_row =>
- ### The Primary Parser ###
- / \G(?:^|#{esc_col_sep}) # anchor the match
- (?: #{esc_quote}( (?>[^#{esc_quote}]*) # find quoted fields
- (?> #{esc_quote*2}
- [^#{esc_quote}]* )* )#{esc_quote}
- | # ... or ...
- ([^#{esc_quote}#{esc_col_sep}]*) # unquoted fields
- )/x,
- ### End Primary Parser ###
- :line_end =>
- /#{esc_row_sep}\z/ # safer than chomp!()
+ # for empty leading fields
+ leading_fields: encode_re("\\A(?:", esc_col_sep, ")+"),
+ # The Primary Parser
+ csv_row: encode_re(
+ "\\G(?:\\A|", esc_col_sep, ")", # anchor the match
+ "(?:", esc_quote, # find quoted fields
+ "((?>[^", esc_quote, "]*)", # "unrolling the loop"
+ "(?>", esc_quote * 2, # double for escaping
+ "[^", esc_quote, "]*)*)",
+ esc_quote,
+ "|", # ... or ...
+ "([^", esc_quote, esc_col_sep, "]*))", # unquoted fields
+ "(?=", esc_col_sep, "|\\z)" # ensure field is ended
+ ),
+ # a test for unescaped quotes
+ bad_field: encode_re(
+ "\\A", esc_col_sep, "?", # an optional comma
+ "(?:", esc_quote, # a quoted field
+ "(?>[^", esc_quote, "]*)", # "unrolling the loop"
+ "(?>", esc_quote * 2, # double for escaping
+ "[^", esc_quote, "]*)*",
+ esc_quote, # the closing quote
+ "[^", esc_quote, "]", # an extra character
+ "|", # ... or ...
+ "[^", esc_quote, esc_col_sep, "]+", # an unquoted field
+ esc_quote, ")" # an extra quote
+ ),
+ # safer than chomp!()
+ line_end: encode_re(esc_row_sep, "\\z"),
+ # illegal unquoted characters
+ return_newline: encode_str("\r\n")
}
end
@@ -1770,6 +2114,7 @@ class CSV
def init_headers(options)
@use_headers = options.delete(:headers)
@return_headers = options.delete(:return_headers)
+ @write_headers = options.delete(:write_headers)
# headers must be delayed until shift(), in case they need a row of content
@headers = nil
@@ -1812,7 +2157,7 @@ class CSV
# see if we are converting headers or fields
converters = headers ? @header_converters : @converters
- fields.each_with_index.map do |field, index| # map_with_index
+ fields.map.with_index do |field, index|
converters.each do |converter|
field = if converter.arity == 1 # straight field converter
converter[field]
@@ -1839,10 +2184,17 @@ class CSV
def parse_headers(row = nil)
if @headers.nil? # header row
@headers = case @use_headers # save headers
- when Array then @use_headers # Array of headers
- when String then self.class.parse_line(@use_headers) # CSV header String
- else row # first row headers
- end
+ # Array of headers
+ when Array then @use_headers
+ # CSV header String
+ when String
+ self.class.parse_line( @use_headers,
+ col_sep: @col_sep,
+ row_sep: @row_sep,
+ quote_char: @quote_char )
+ # first row is headers
+ else row
+ end
# prepare converted and unconverted copies
row = @headers if row.nil?
@@ -1870,6 +2222,59 @@ class CSV
row.instance_eval { @unconverted_fields = fields }
row
end
+
+ #
+ # This method is an encoding safe version of Regexp::escape(). I will escape
+ # any characters that would change the meaning of a regular expression in the
+ # encoding of +str+. Regular expression characters that cannot be transcoded
+ # to the target encodign will be skipped and no escaping will be performed if
+ # a backslash cannot be transcoded.
+ #
+ def escape_re(str)
+ str.chars.map { |c| @re_chars.include?(c) ? @re_esc + c : c }.join
+ end
+
+ #
+ # Builds a regular expression in <tt>@encoding</tt>. All +chunks+ will be
+ # transcoded to that encoding.
+ #
+ def encode_re(*chunks)
+ Regexp.new(encode_str(*chunks))
+ end
+
+ #
+ # Builds a String in <tt>@encoding</tt>. All +chunks+ will be transcoded to
+ # that encoding.
+ #
+ def encode_str(*chunks)
+ chunks.map { |chunk| chunk.encode(@encoding.name) }.join
+ end
+
+ #
+ # Reads at least +bytes+ from <tt>@io</tt>, but will read up 10 bytes ahead if
+ # needed to ensure the data read is valid in the ecoding of that data. This
+ # should ensure that it is safe to use regular expressions on the read data,
+ # unless it is actually a broken encoding. The read data will be returned in
+ # <tt>@encoding</tt>.
+ #
+ def read_to_char(bytes)
+ return "" if @io.eof?
+ data = @io.read(bytes)
+ begin
+ encoded = encode_str(data)
+ raise unless encoded.valid_encoding?
+ return encoded
+ rescue # encoding error or my invalid data raise
+ if @io.eof? or data.size >= bytes + 10
+ return data
+ else
+ data += @io.read(1) until data.valid_encoding? or
+ @io.eof? or
+ data.size >= bytes + 10
+ retry
+ end
+ end
+ end
end
# Another name for CSV::instance().
diff --git a/lib/date.rb b/lib/date.rb
index 5ac8bf03d6..3da3d21f8b 100644
--- a/lib/date.rb
+++ b/lib/date.rb
@@ -1790,12 +1790,23 @@ class Date
# Create a new Date object representing today.
#
# +sg+ specifies the Day of Calendar Reform.
- def self.today(sg=ITALY) Time.now.to_date .new_start(sg) end
+ def self.today(sg=ITALY)
+ t = Time.now
+ jd = civil_to_jd(t.year, t.mon, t.mday, sg)
+ new!(jd_to_ajd(jd, 0, 0), 0, sg)
+ end
# Create a new DateTime object representing the current time.
#
# +sg+ specifies the Day of Calendar Reform.
- def self.now (sg=ITALY) Time.now.to_datetime.new_start(sg) end
+ def self.now(sg=ITALY)
+ t = Time.now
+ jd = civil_to_jd(t.year, t.mon, t.mday, sg)
+ fr = time_to_day_fraction(t.hour, t.min, [t.sec, 59].min) +
+ Rational(t.nsec, 86400_000_000_000)
+ of = Rational(t.utc_offset, 86400)
+ new!(jd_to_ajd(jd, fr, of), of, sg)
+ end
private_class_method :now
diff --git a/lib/date/format.rb b/lib/date/format.rb
index baba8dcbf6..c8bc10fbac 100644
--- a/lib/date/format.rb
+++ b/lib/date/format.rb
@@ -1,8 +1,6 @@
# format.rb: Written by Tadayoshi Funaba 1999-2008
# $Id: format.rb,v 2.43 2008-01-17 20:16:31+09 tadf Exp $
-require 'rational'
-
class Date
module Format # :nodoc:
diff --git a/lib/debug.rb b/lib/debug.rb
index 8a2f4f1a12..77be345a07 100644
--- a/lib/debug.rb
+++ b/lib/debug.rb
@@ -711,9 +711,6 @@ EOHELP
end
@frames.shift
- when 'end'
- @frames.shift
-
when 'raise'
excn_handle(file, line, id, binding)
diff --git a/lib/delegate.rb b/lib/delegate.rb
index 629753fe3a..025e901a89 100644
--- a/lib/delegate.rb
+++ b/lib/delegate.rb
@@ -115,102 +115,87 @@
# implementation, see SimpleDelegator.
#
class Delegator
- preserved = [
- :__id__, :object_id, :__send__, :public_send, :respond_to?, :send,
- :instance_eval, :instance_exec, :extend,
- ]
- instance_methods.each do |m|
- next if preserved.include?(m)
+ [:to_s,:inspect,:=~,:!~,:===].each do |m|
undef_method m
end
- module MethodDelegation
- #
- # Pass in the _obj_ to delegate method calls to. All methods supported by
- # _obj_ will be delegated to.
- #
- def initialize(obj)
- __setobj__(obj)
- end
+ #
+ # Pass in the _obj_ to delegate method calls to. All methods supported by
+ # _obj_ will be delegated to.
+ #
+ def initialize(obj)
+ __setobj__(obj)
+ end
- # Handles the magic of delegation through \_\_getobj\_\_.
- def method_missing(m, *args, &block)
- begin
- target = self.__getobj__
- unless target.respond_to?(m)
- super(m, *args, &block)
- else
- target.__send__(m, *args, &block)
- end
- rescue Exception
- $@.delete_if{|s| %r"\A#{__FILE__}:\d+:in `method_missing'\z"o =~ s}
- ::Kernel::raise
+ # Handles the magic of delegation through \_\_getobj\_\_.
+ def method_missing(m, *args, &block)
+ begin
+ target = self.__getobj__
+ unless target.respond_to?(m)
+ super(m, *args, &block)
+ else
+ target.__send__(m, *args, &block)
end
+ rescue Exception
+ $@.delete_if{|s| %r"\A#{__FILE__}:\d+:in `method_missing'\z"o =~ s}
+ ::Kernel::raise
end
+ end
- #
- # Checks for a method provided by this the delegate object by fowarding the
- # call through \_\_getobj\_\_.
- #
- def respond_to?(m, include_private = false)
- return true if super
- return self.__getobj__.respond_to?(m, include_private)
- end
-
- #
- # Returns true if two objects are considered same.
- #
- def ==(obj)
- return true if obj.equal?(self)
- self.__getobj__ == obj
- end
+ #
+ # Checks for a method provided by this the delegate object by fowarding the
+ # call through \_\_getobj\_\_.
+ #
+ def respond_to?(m, include_private = false)
+ return true if super
+ return self.__getobj__.respond_to?(m, include_private)
+ end
- #
- # Returns true only if two objects are identical.
- #
- def equal?(obj)
- self.object_id == obj.object_id
- end
+ #
+ # Returns true if two objects are considered same.
+ #
+ def ==(obj)
+ return true if obj.equal?(self)
+ self.__getobj__ == obj
+ end
- #
- # This method must be overridden by subclasses and should return the object
- # method calls are being delegated to.
- #
- def __getobj__
- raise NotImplementedError, "need to define `__getobj__'"
- end
+ #
+ # This method must be overridden by subclasses and should return the object
+ # method calls are being delegated to.
+ #
+ def __getobj__
+ raise NotImplementedError, "need to define `__getobj__'"
+ end
- #
- # This method must be overridden by subclasses and change the object delegate
- # to _obj_.
- #
- def __setobj__(obj)
- raise NotImplementedError, "need to define `__setobj__'"
- end
+ #
+ # This method must be overridden by subclasses and change the object delegate
+ # to _obj_.
+ #
+ def __setobj__(obj)
+ raise NotImplementedError, "need to define `__setobj__'"
+ end
- # Serialization support for the object returned by \_\_getobj\_\_.
- def marshal_dump
- __getobj__
- end
- # Reinitializes delegation from a serialized object.
- def marshal_load(obj)
- __setobj__(obj)
- end
+ # Serialization support for the object returned by \_\_getobj\_\_.
+ def marshal_dump
+ __getobj__
+ end
+ # Reinitializes delegation from a serialized object.
+ def marshal_load(obj)
+ __setobj__(obj)
+ end
- # Clone support for the object returned by \_\_getobj\_\_.
- def clone
- new = super
- new.__setobj__(__getobj__.clone)
- new
- end
- # Duplication support for the object returned by \_\_getobj\_\_.
- def dup
- new = super
- new.__setobj__(__getobj__.dup)
- new
- end
+ # Clone support for the object returned by \_\_getobj\_\_.
+ def clone
+ new = super
+ new.__setobj__(__getobj__.clone)
+ new
+ end
+ # Duplication support for the object returned by \_\_getobj\_\_.
+ def dup
+ new = super
+ new.__setobj__(__getobj__.dup)
+ new
end
- include MethodDelegation
end
#
@@ -249,7 +234,7 @@ end
def Delegator.delegating_block(mid)
lambda do |*args, &block|
begin
- @delegate_dc_obj.__send__(mid, *args, &block)
+ __getobj__.__send__(mid, *args, &block)
rescue
re = /\A#{Regexp.quote(__FILE__)}:#{__LINE__-2}:/o
$!.backtrace.delete_if {|t| re =~ t}
@@ -270,16 +255,11 @@ end
# end
#
def DelegateClass(superclass)
- klass = Class.new
+ klass = Class.new(Delegator)
methods = superclass.public_instance_methods(true)
- methods -= [
- :__id__, :object_id, :__send__, :public_send, :respond_to?, :send,
- :==, :equal?, :initialize, :method_missing, :__getobj__, :__setobj__,
- :clone, :dup, :marshal_dump, :marshal_load, :instance_eval, :instance_exec,
- :extend,
- ]
+ methods -= ::Delegator.public_instance_methods
+ methods -= [:to_s,:inspect,:=~,:!~,:===]
klass.module_eval {
- include Delegator::MethodDelegation
def __getobj__ # :nodoc:
@delegate_dc_obj
end
diff --git a/lib/drb/drb.rb b/lib/drb/drb.rb
index 0e6212838e..13a89de07f 100644
--- a/lib/drb/drb.rb
+++ b/lib/drb/drb.rb
@@ -1208,6 +1208,7 @@ module DRb
end
def alive? # :nodoc:
+ return false unless @protocol
@protocol.alive?
end
end
diff --git a/lib/fileutils.rb b/lib/fileutils.rb
index 83f1be82c5..56fb19beb2 100644
--- a/lib/fileutils.rb
+++ b/lib/fileutils.rb
@@ -524,7 +524,7 @@ module FileUtils
OPT_TABLE['move'] = [:force, :noop, :verbose, :secure]
def rename_cannot_overwrite_file? #:nodoc:
- /djgpp|cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM
+ /cygwin|mswin|mingw|bccwin|emx/ =~ RUBY_PLATFORM
end
private_module_function :rename_cannot_overwrite_file?
@@ -1041,7 +1041,7 @@ module FileUtils
private
def fu_windows?
- /mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM
+ /mswin|mingw|bccwin|emx/ =~ RUBY_PLATFORM
end
def fu_copy_stream0(src, dest, blksize = nil) #:nodoc:
diff --git a/lib/ipaddr.rb b/lib/ipaddr.rb
index 7c246326ca..26364cd9ce 100644
--- a/lib/ipaddr.rb
+++ b/lib/ipaddr.rb
@@ -577,7 +577,6 @@ end
__END__
require 'test/unit'
-require 'test/unit/ui/console/testrunner'
class TC_IPAddr < Test::Unit::TestCase
def test_s_new
diff --git a/lib/irb.rb b/lib/irb.rb
index 7fe3d7dc51..f5e662ac51 100644
--- a/lib/irb.rb
+++ b/lib/irb.rb
@@ -107,7 +107,7 @@ module IRB
f = @context.prompt_c
elsif indent > 0
f = @context.prompt_n
- else @context.prompt_i
+ else
f = @context.prompt_i
end
f = "" unless f
diff --git a/lib/irb/context.rb b/lib/irb/context.rb
index 6a5e77fb70..e2ab05a341 100644
--- a/lib/irb/context.rb
+++ b/lib/irb/context.rb
@@ -233,6 +233,7 @@ module IRB
def inspect
array = []
for ivar in instance_variables.sort{|e1, e2| e1 <=> e2}
+ ivar = ivar.to_s
name = ivar.sub(/^@(.*)$/, '\1')
val = instance_eval(ivar)
case ivar
diff --git a/lib/irb/ext/save-history.rb b/lib/irb/ext/save-history.rb
index fdb0a74a86..88610fe9c9 100644
--- a/lib/irb/ext/save-history.rb
+++ b/lib/irb/ext/save-history.rb
@@ -3,7 +3,7 @@
# save-history.rb -
# $Release Version: 0.9.5$
# $Revision$
-# by Keiju ISHITSUKAkeiju@ruby-lang.org)
+# by Keiju ISHITSUKA(keiju@ruby-lang.org)
#
# --
#
@@ -52,11 +52,11 @@ module IRB
def HistorySavingAbility.create_finalizer
proc do
if num = IRB.conf[:SAVE_HISTORY] and (num = num.to_i) > 0
- if hf = IRB.conf[:HISTORY_FILE]
- file = File.expand_path(hf)
+ if history_file = IRB.conf[:HISTORY_FILE]
+ history_file = File.expand_path(history_file)
end
- file = IRB.rc_file("_history") unless file
- open(file, 'w' ) do |f|
+ history_file = IRB.rc_file("_history") unless history_file
+ open(history_file, 'w' ) do |f|
hist = HISTORY.to_a
f.puts(hist[-num..-1] || hist)
end
@@ -71,10 +71,12 @@ module IRB
end
def load_history
- hist = IRB.conf[:HISTORY_FILE]
- hist = IRB.rc_file("_history") unless hist
- if File.exist?(hist)
- open(hist) do |f|
+ if history_file = IRB.conf[:HISTORY_FILE]
+ history_file = File.expand_path(history_file)
+ end
+ history_file = IRB.rc_file("_history") unless history_file
+ if File.exist?(history_file)
+ open(history_file) do |f|
f.each {|l| HISTORY << l.chomp}
end
end
diff --git a/lib/irb/init.rb b/lib/irb/init.rb
index 84d2e9e76f..576b99d1c8 100644
--- a/lib/irb/init.rb
+++ b/lib/irb/init.rb
@@ -247,8 +247,8 @@ module IRB
for m in @CONF[:LOAD_MODULES]
begin
require m
- rescue # StandardError, ScriptError
- print $@[0], ":", $!.class, ": ", $!, "\n"
+ rescue LoadError => err
+ warn err.backtrace[0] << ":#{err.class}: #{err}"
end
end
end
diff --git a/lib/logger.rb b/lib/logger.rb
index 5399e13ead..26d7d9d560 100644
--- a/lib/logger.rb
+++ b/lib/logger.rb
@@ -181,8 +181,8 @@ require 'monitor'
class Logger
VERSION = "1.2.6"
- /: (\S+),v (\S+)/ =~ %q$Id$
- ProgName = "#{$1}/#{$2}"
+ id, name, rev = %w$Id$
+ ProgName = "#{name.chomp(",v")}/#{rev}"
class Error < RuntimeError; end
class ShiftingError < Error; end
diff --git a/lib/mathn.rb b/lib/mathn.rb
index 2af2b83da3..48cb99f8c6 100644
--- a/lib/mathn.rb
+++ b/lib/mathn.rb
@@ -9,31 +9,56 @@
#
#
-require "complex.rb"
-require "rational.rb"
+require "cmath.rb"
require "matrix.rb"
require "prime.rb"
+require "mathn/rational"
+require "mathn/complex"
+
+unless defined?(Math.exp!)
+ Object.instance_eval{remove_const :Math}
+ Math = CMath
+end
+
class Fixnum
remove_method :/
alias / quo
+
+ alias power! ** unless defined?(0.power!)
+
+ def ** (other)
+ if self < 0 && other.round != other
+ Complex(self, 0.0) ** other
+ else
+ power!(other)
+ end
+ end
+
end
class Bignum
remove_method :/
alias / quo
-end
-class Rational
- Unify = true
+ alias power! ** unless defined?(0.power!)
- alias power! **
+ def ** (other)
+ if self < 0 && other.round != other
+ Complex(self, 0.0) ** other
+ else
+ power!(other)
+ end
+ end
+end
+
+class Rational
def ** (other)
if other.kind_of?(Rational)
other2 = other
if self < 0
- return Complex.__send__(:new!, self, 0) ** other
+ return Complex(self, 0.0) ** other
elsif other == 0
return Rational(1,1)
elsif self == 0
@@ -95,7 +120,7 @@ module Math
remove_method(:sqrt)
def sqrt(a)
if a.kind_of?(Complex)
- abs = sqrt(a.real*a.real + a.image*a.image)
+ abs = sqrt(a.real*a.real + a.imag*a.imag)
# if not abs.kind_of?(Rational)
# return a**Rational(1,2)
# end
@@ -104,7 +129,7 @@ module Math
# if !(x.kind_of?(Rational) and y.kind_of?(Rational))
# return a**Rational(1,2)
# end
- if a.image >= 0
+ if a.imag >= 0
Complex(x, y)
else
Complex(x, -y)
@@ -165,6 +190,15 @@ module Math
module_function :rsqrt
end
-class Complex
- Unify = true
+class Float
+ alias power! **
+
+ def ** (other)
+ if self < 0 && other.round != other
+ Complex(self, 0.0) ** other
+ else
+ power!(other)
+ end
+ end
+
end
diff --git a/lib/matrix.rb b/lib/matrix.rb
index d31fcc5464..c672ee5198 100644
--- a/lib/matrix.rb
+++ b/lib/matrix.rb
@@ -410,17 +410,21 @@ class Matrix
other.compare_by_row_vectors(@rows)
end
- alias eql? ==
+ def eql?(other)
+ return false unless Matrix === other
+
+ other.compare_by_row_vectors(@rows, :eql?)
+ end
#
# Not really intended for general consumption.
#
- def compare_by_row_vectors(rows)
+ def compare_by_row_vectors(rows, comparison = :==)
return false unless @rows.size == rows.size
0.upto(@rows.size - 1) do
|i|
- return false unless @rows[i] == rows[i]
+ return false unless @rows[i].send(comparison, rows[i])
end
true
end
@@ -1200,13 +1204,17 @@ class Vector
other.compare_by(@elements)
end
- alias eqn? ==
+ def eql?(other)
+ return false unless Vector === other
+
+ other.compare_by(@elements, :eql?)
+ end
#
# For internal use.
#
- def compare_by(elements)
- @elements == elements
+ def compare_by(elements, comparison = :==)
+ @elements.send(comparison, elements)
end
#
diff --git a/lib/minitest/mock.rb b/lib/minitest/mock.rb
new file mode 100644
index 0000000000..54af28c453
--- /dev/null
+++ b/lib/minitest/mock.rb
@@ -0,0 +1,37 @@
+############################################################
+# This file is imported from a different project.
+# DO NOT make modifications in this repo.
+# File a patch instead and assign it to Ryan Davis
+############################################################
+
+class MockExpectationError < StandardError; end
+
+module MiniTest
+ class Mock
+ def initialize
+ @expected_calls = {}
+ @actual_calls = Hash.new {|h,k| h[k] = [] }
+ end
+
+ def expect(name, retval, args=[])
+ n, r, a = name, retval, args # for the closure below
+ @expected_calls[name] = { :retval => retval, :args => args }
+ self.class.__send__(:define_method, name) { |*x|
+ raise ArgumentError unless @expected_calls[n][:args].size == x.size
+ @actual_calls[n] << { :retval => r, :args => x }
+ retval
+ }
+ self
+ end
+
+ def verify
+ @expected_calls.each_key do |name|
+ expected = @expected_calls[name]
+ msg = "expected #{name}, #{expected.inspect}"
+ raise MockExpectationError, msg unless
+ @actual_calls.has_key? name and @actual_calls[name].include?(expected)
+ end
+ true
+ end
+ end
+end
diff --git a/lib/minitest/spec.rb b/lib/minitest/spec.rb
new file mode 100644
index 0000000000..130910ed85
--- /dev/null
+++ b/lib/minitest/spec.rb
@@ -0,0 +1,88 @@
+############################################################
+# This file is imported from a different project.
+# DO NOT make modifications in this repo.
+# File a patch instead and assign it to Ryan Davis
+############################################################
+
+#!/usr/bin/ruby -w
+
+require 'minitest/unit'
+
+class Module
+ def infect_with_assertions pos_prefix, neg_prefix, skip_re, map = {}
+ MiniTest::Assertions.public_instance_methods(false).each do |meth|
+ meth = meth.to_s
+
+ new_name = case meth
+ when /^assert/ then
+ meth.sub(/^assert/, pos_prefix.to_s)
+ when /^refute/ then
+ meth.sub(/^refute/, neg_prefix.to_s)
+ end
+ next unless new_name
+ next if new_name =~ skip_re
+
+ regexp, replacement = map.find { |re, _| new_name =~ re }
+ new_name.sub! regexp, replacement if replacement
+
+ # warn "%-22p -> %p %p" % [meth, new_name, regexp]
+ self.class_eval <<-EOM
+ def #{new_name} *args, &block
+ return MiniTest::Spec.current.#{meth}(*args, &self) if Proc === self
+ return MiniTest::Spec.current.#{meth}(args.first, self) if args.size == 1
+ return MiniTest::Spec.current.#{meth}(self, *args)
+ end
+ EOM
+ end
+ end
+end
+
+Object.infect_with_assertions(:must, :wont,
+ /^(must|wont)$|wont_(throw)|
+ must_(block|not?_|nothing|raise$)/x,
+ /(must_throw)s/ => '\1',
+ /(?!not)_same/ => '_be_same_as',
+ /_in_/ => '_be_within_',
+ /_operator/ => '_be',
+ /_includes/ => '_include',
+ /(must|wont)_(.*_of|nil|empty)/ => '\1_be_\2',
+ /must_raises/ => 'must_raise')
+
+class Object
+ alias :must_be_close_to :must_be_within_delta
+ alias :wont_be_close_to :wont_be_within_delta
+end
+
+module Kernel
+ def describe desc, &block
+ cls = Class.new(MiniTest::Spec)
+ Object.const_set desc.to_s.split(/\W+/).map { |s| s.capitalize }.join, cls
+
+ cls.class_eval(&block)
+ end
+end
+
+class MiniTest::Spec < MiniTest::Unit::TestCase
+ def self.current
+ @@current_spec
+ end
+
+ def initialize name
+ super
+ @@current_spec = self
+ end
+
+ def self.before(type = :each, &block)
+ raise "unsupported before type: #{type}" unless type == :each
+ define_method :setup, &block
+ end
+
+ def self.after(type = :each, &block)
+ raise "unsupported after type: #{type}" unless type == :each
+ define_method :teardown, &block
+ end
+
+ def self.it desc, &block
+ define_method "test_#{desc.gsub(/\W+/, '_').downcase}", &block
+ end
+end
diff --git a/lib/minitest/unit.rb b/lib/minitest/unit.rb
new file mode 100644
index 0000000000..460258cdf2
--- /dev/null
+++ b/lib/minitest/unit.rb
@@ -0,0 +1,495 @@
+############################################################
+# This file is imported from a different project.
+# DO NOT make modifications in this repo.
+# File a patch instead and assign it to Ryan Davis
+############################################################
+
+##
+#
+# Totally minimal drop-in replacement for test-unit
+#
+# TODO: refute -> debunk, prove/rebut, show/deny... lots of possibilities
+
+module MiniTest
+ class Assertion < Exception; end
+ class Skip < Assertion; end
+
+ file = if RUBY_VERSION =~ /^1\.9/ then # bt's expanded, but __FILE__ isn't :(
+ File.expand_path __FILE__
+ elsif __FILE__ =~ /^[^\.]/ then # assume both relative
+ require 'pathname'
+ pwd = Pathname.new Dir.pwd
+ pn = Pathname.new File.expand_path(__FILE__)
+ pn = File.join(".", pn.relative_path_from(pwd)) unless pn.relative?
+ pn.to_s
+ else # assume both are expanded
+ __FILE__
+ end
+
+ # './lib' in project dir, or '/usr/local/blahblah' if installed
+ MINI_DIR = File.dirname(File.dirname(file))
+
+ def self.filter_backtrace bt
+ return ["No backtrace"] unless bt
+
+ new_bt = []
+ bt.each do |line|
+ break if line.rindex(MINI_DIR, 0)
+ new_bt << line
+ end
+
+ new_bt = bt.reject { |line| line.rindex(MINI_DIR, 0) } if new_bt.empty?
+ new_bt = bt.dup if new_bt.empty?
+ new_bt
+ end
+
+ module Assertions
+ def mu_pp(obj)
+ s = obj.inspect
+ s = s.force_encoding(Encoding.default_external) if defined? Encoding
+ s
+ end
+
+ def _assertions= n
+ @_assertions = n
+ end
+
+ def _assertions
+ @_assertions ||= 0
+ end
+
+ def assert test, msg = nil
+ msg ||= "Failed assertion, no message given."
+ self._assertions += 1
+ unless test then
+ msg = msg.call if Proc === msg
+ raise MiniTest::Assertion, msg
+ end
+ true
+ end
+
+ def assert_block msg = nil
+ msg = message(msg) { "Expected block to return true value" }
+ assert yield, msg
+ end
+
+ def assert_empty obj, msg = nil
+ msg = message(msg) { "Expected #{obj.inspect} to be empty" }
+ assert_respond_to obj, :empty?
+ assert obj.empty?, msg
+ end
+
+ def assert_equal exp, act, msg = nil
+ msg = message(msg) { "Expected #{mu_pp(exp)}, not #{mu_pp(act)}" }
+ assert(exp == act, msg)
+ end
+
+ def assert_in_delta exp, act, delta = 0.001, msg = nil
+ n = (exp - act).abs
+ msg = message(msg) { "Expected #{exp} - #{act} (#{n}) to be < #{delta}" }
+ assert delta >= n, msg
+ end
+
+ def assert_in_epsilon a, b, epsilon = 0.001, msg = nil
+ assert_in_delta a, b, [a, b].min * epsilon, msg
+ end
+
+ def assert_includes collection, obj, msg = nil
+ msg = message(msg) { "Expected #{mu_pp(collection)} to include #{mu_pp(obj)}" }
+ assert_respond_to collection, :include?
+ assert collection.include?(obj), msg
+ end
+
+ def assert_instance_of cls, obj, msg = nil
+ msg = message(msg) { "Expected #{mu_pp(obj)} to be an instance of #{cls}, not #{obj.class}" }
+ flip = (Module === obj) && ! (Module === cls) # HACK for specs
+ obj, cls = cls, obj if flip
+ assert cls === obj, msg
+ end
+
+ def assert_kind_of cls, obj, msg = nil # TODO: merge with instance_of
+ msg = message(msg) {
+ "Expected #{mu_pp(obj)} to be a kind of #{cls}, not #{obj.class}" }
+ flip = (Module === obj) && ! (Module === cls) # HACK for specs
+ obj, cls = cls, obj if flip
+ assert obj.kind_of?(cls), msg
+ end
+
+ def assert_match exp, act, msg = nil
+ msg = message(msg) { "Expected #{mu_pp(act)} to match #{mu_pp(exp)}" }
+ assert_respond_to act, :"=~"
+ (exp = /#{exp}/) if String === exp && String === act
+ assert act =~ exp, msg
+ end
+
+ def assert_nil obj, msg = nil
+ msg = message(msg) { "Expected #{mu_pp(obj)} to be nil" }
+ assert obj.nil?, msg
+ end
+
+ def assert_operator o1, op, o2, msg = nil
+ msg = message(msg) { "Expected #{mu_pp(o1)} to be #{op} #{mu_pp(o2)}" }
+ assert o1.__send__(op, o2), msg
+ end
+
+ def assert_raises *exp
+ msg = String === exp.last ? exp.pop : nil
+ should_raise = false
+ begin
+ yield
+ should_raise = true
+ rescue Exception => e
+ assert(exp.any? { |ex|
+ ex.instance_of?(Module) ? e.kind_of?(ex) : ex == e.class
+ }, exception_details(e, "#{mu_pp(exp)} exception expected, not"))
+
+ return e
+ end
+
+ exp = exp.first if exp.size == 1
+ flunk "#{mu_pp(exp)} expected but nothing was raised." if should_raise
+ end
+
+ def assert_respond_to obj, meth, msg = nil
+ msg = message(msg) {
+ "Expected #{mu_pp(obj)} (#{obj.class}) to respond to ##{meth}"
+ }
+ flip = (Symbol === obj) && ! (Symbol === meth) # HACK for specs
+ obj, meth = meth, obj if flip
+ assert obj.respond_to?(meth), msg
+ end
+
+ def assert_same exp, act, msg = nil
+ msg = message(msg) {
+ data = [mu_pp(act), act.object_id, mu_pp(exp), exp.object_id]
+ "Expected %s (0x%x) to be the same as %s (0x%x)" % data
+ }
+ assert exp.equal?(act), msg
+ end
+
+ def assert_send send_ary, m = nil
+ recv, msg, *args = send_ary
+ m = message(m) {
+ "Expected #{mu_pp(recv)}.#{msg}(*#{mu_pp(args)}) to return true" }
+ assert recv.__send__(msg, *args), m
+ end
+
+ def assert_throws sym, msg = nil
+ default = "Expected #{mu_pp(sym)} to have been thrown"
+ caught = true
+ catch(sym) do
+ begin
+ yield
+ rescue ArgumentError => e # 1.9 exception
+ default += ", not #{e.message.split(/ /).last}"
+ rescue NameError => e # 1.8 exception
+ default += ", not #{e.name.inspect}"
+ end
+ caught = false
+ end
+
+ assert caught, message(msg) { default }
+ end
+
+ def capture_io
+ require 'stringio'
+
+ orig_stdout, orig_stderr = $stdout, $stderr
+ captured_stdout, captured_stderr = StringIO.new, StringIO.new
+ $stdout, $stderr = captured_stdout, captured_stderr
+
+ yield
+
+ return captured_stdout.string, captured_stderr.string
+ ensure
+ $stdout = orig_stdout
+ $stderr = orig_stderr
+ end
+
+ def exception_details e, msg
+ "#{msg}\nClass: <#{e.class}>\nMessage: <#{e.message.inspect}>\n---Backtrace---\n#{MiniTest::filter_backtrace(e.backtrace).join("\n")}\n---------------"
+ end
+
+ def flunk msg = nil
+ msg ||= "Epic Fail!"
+ assert false, msg
+ end
+
+ def message msg = nil, &default
+ proc {
+ if msg then
+ msg = msg.to_s unless String === msg
+ msg += '.' unless msg.empty?
+ msg += "\n#{default.call}."
+ msg.strip
+ else
+ "#{default.call}."
+ end
+ }
+ end
+
+ # used for counting assertions
+ def pass msg = nil
+ assert true
+ end
+
+ def refute test, msg = nil
+ msg ||= "Failed refutation, no message given"
+ not assert(! test, msg)
+ end
+
+ def refute_empty obj, msg = nil
+ msg = message(msg) { "Expected #{obj.inspect} to not be empty" }
+ assert_respond_to obj, :empty?
+ refute obj.empty?, msg
+ end
+
+ def refute_equal exp, act, msg = nil
+ msg = message(msg) { "Expected #{mu_pp(act)} to not be equal to #{mu_pp(exp)}" }
+ refute exp == act, msg
+ end
+
+ def refute_in_delta exp, act, delta = 0.001, msg = nil
+ n = (exp - act).abs
+ msg = message(msg) { "Expected #{exp} - #{act} (#{n}) to not be < #{delta}" }
+ refute delta > n, msg
+ end
+
+ def refute_in_epsilon a, b, epsilon = 0.001, msg = nil
+ refute_in_delta a, b, a * epsilon, msg
+ end
+
+ def refute_includes collection, obj, msg = nil
+ msg = message(msg) { "Expected #{mu_pp(collection)} to not include #{mu_pp(obj)}" }
+ assert_respond_to collection, :include?
+ refute collection.include?(obj), msg
+ end
+
+ def refute_instance_of cls, obj, msg = nil
+ msg = message(msg) { "Expected #{mu_pp(obj)} to not be an instance of #{cls}" }
+ flip = (Module === obj) && ! (Module === cls) # HACK for specs
+ obj, cls = cls, obj if flip
+ refute cls === obj, msg
+ end
+
+ def refute_kind_of cls, obj, msg = nil # TODO: merge with instance_of
+ msg = message(msg) { "Expected #{mu_pp(obj)} to not be a kind of #{cls}" }
+ flip = (Module === obj) && ! (Module === cls) # HACK for specs
+ obj, cls = cls, obj if flip
+ refute obj.kind_of?(cls), msg
+ end
+
+ def refute_match exp, act, msg = nil
+ msg = message(msg) { "Expected #{mu_pp(act)} to not match #{mu_pp(exp)}" }
+ refute act =~ exp, msg
+ end
+
+ def refute_nil obj, msg = nil
+ msg = message(msg) { "Expected #{mu_pp(obj)} to not be nil" }
+ refute obj.nil?, msg
+ end
+
+ def refute_operator o1, op, o2, msg = nil
+ msg = message(msg) { "Expected #{mu_pp(o1)} to not be #{op} #{mu_pp(o2)}" }
+ refute o1.__send__(op, o2), msg
+ end
+
+ def refute_respond_to obj, meth, msg = nil
+ msg = message(msg) { "Expected #{mu_pp(obj)} to not respond to #{meth}" }
+ flip = (Symbol === obj) && ! (Symbol === meth) # HACK for specs
+ obj, meth = meth, obj if flip
+ refute obj.respond_to?(meth), msg
+ end
+
+ def refute_same exp, act, msg = nil
+ msg = message(msg) { "Expected #{mu_pp(act)} to not be the same as #{mu_pp(exp)}" }
+ refute exp.equal?(act), msg
+ end
+
+ def skip msg = nil, bt = caller
+ msg ||= "Skipped, no message given"
+ raise MiniTest::Skip, msg, bt
+ end
+ end
+
+ class Unit
+ VERSION = "1.3.1"
+
+ attr_accessor :report, :failures, :errors, :skips
+ attr_accessor :test_count, :assertion_count
+
+ @@installed_at_exit ||= false
+ @@out = $stdout
+
+ def self.disable_autorun
+ @@installed_at_exit = true
+ end
+
+ def self.autorun
+ at_exit {
+ exit_code = MiniTest::Unit.new.run(ARGV)
+ exit false if exit_code && exit_code != 0
+ } unless @@installed_at_exit
+ disable_autorun
+ end
+
+ def self.output= stream
+ @@out = stream
+ end
+
+ def location e
+ e.backtrace.find { |s|
+ s !~ /in .(assert|refute|flunk|pass|fail|raise)/
+ }.sub(/:in .*$/, '')
+ end
+
+ def puke klass, meth, e
+ e = case e
+ when MiniTest::Skip then
+ @skips += 1
+ "Skipped:\n#{meth}(#{klass}) [#{location e}]:\n#{e.message}\n"
+ when MiniTest::Assertion then
+ @failures += 1
+ "Failure:\n#{meth}(#{klass}) [#{location e}]:\n#{e.message}\n"
+ else
+ @errors += 1
+ bt = MiniTest::filter_backtrace(e.backtrace).join("\n ")
+ "Error:\n#{meth}(#{klass}):\n#{e.class}: #{e.message}\n #{bt}\n"
+ end
+ @report << e
+ e[0, 1]
+ end
+
+ def initialize
+ @report = []
+ @errors = @failures = @skips = 0
+ @verbose = false
+ end
+
+ ##
+ # Top level driver, controls all output and filtering.
+
+ def run args = []
+ @verbose = args.delete('-v')
+
+ filter = if args.first =~ /^(-n|--name)$/ then
+ args.shift
+ arg = args.shift
+ arg =~ /\/(.*)\// ? Regexp.new($1) : arg
+ else
+ /./ # anything - ^test_ already filtered by #tests
+ end
+
+ @@out.puts "Loaded suite #{$0.sub(/\.rb$/, '')}\nStarted"
+
+ start = Time.now
+ run_test_suites filter
+
+ @@out.puts
+ @@out.puts "Finished in #{'%.6f' % (Time.now - start)} seconds."
+
+ @report.each_with_index do |msg, i|
+ @@out.puts "\n%3d) %s" % [i + 1, msg]
+ end
+
+ @@out.puts
+
+ format = "%d tests, %d assertions, %d failures, %d errors, %d skips"
+ @@out.puts format % [test_count, assertion_count, failures, errors, skips]
+
+ return failures + errors if @test_count > 0 # or return nil...
+ end
+
+ def run_test_suites filter = /./
+ @test_count, @assertion_count = 0, 0
+ old_sync, @@out.sync = @@out.sync, true if @@out.respond_to? :sync=
+ TestCase.test_suites.each do |suite|
+ suite.test_methods.grep(filter).each do |test|
+ inst = suite.new test
+ inst._assertions = 0
+ @@out.print "#{suite}##{test}: " if @verbose
+
+ t = Time.now if @verbose
+ result = inst.run(self)
+
+ @@out.print "%.2f s: " % (Time.now - t) if @verbose
+ @@out.print result
+ @@out.puts if @verbose
+ @test_count += 1
+ @assertion_count += inst._assertions
+ end
+ end
+ @@out.sync = old_sync if @@out.respond_to? :sync=
+ [@test_count, @assertion_count]
+ end
+
+ class TestCase
+ attr_reader :name
+
+ def run runner
+ result = '.'
+ begin
+ @passed = nil
+ self.setup
+ self.__send__ self.name
+ @passed = true
+ rescue Exception => e
+ @passed = false
+ result = runner.puke(self.class, self.name, e)
+ ensure
+ begin
+ self.teardown
+ rescue Exception => e
+ result = runner.puke(self.class, self.name, e)
+ end
+ end
+ result
+ end
+
+ def initialize name
+ @name = name
+ @passed = nil
+ end
+
+ def self.reset
+ @@test_suites = {}
+ end
+
+ reset
+
+ def self.inherited klass
+ @@test_suites[klass] = true
+ end
+
+ def self.test_order
+ :random
+ end
+
+ def self.test_suites
+ @@test_suites.keys.sort_by { |ts| ts.name }
+ end
+
+ def self.test_methods
+ methods = public_instance_methods(true).grep(/^test/).map { |m|
+ m.to_s
+ }.sort
+
+ if self.test_order == :random then
+ max = methods.size
+ methods = methods.sort_by { rand(max) }
+ end
+
+ methods
+ end
+
+ def setup; end
+ def teardown; end
+
+ def passed?
+ @passed
+ end
+
+ include MiniTest::Assertions
+ end # class TestCase
+ end # class Test
+end # module Mini
diff --git a/lib/mkmf.rb b/lib/mkmf.rb
index 6ef66344dd..615b898429 100644
--- a/lib/mkmf.rb
+++ b/lib/mkmf.rb
@@ -9,11 +9,12 @@ CONFIG = RbConfig::MAKEFILE_CONFIG
ORIG_LIBPATH = ENV['LIB']
CXX_EXT = %w[cc cxx cpp]
-if /mswin|bccwin|mingw|msdosdjgpp|human|os2/ !~ CONFIG['build_os']
+if /mswin|bccwin|mingw|os2/ !~ CONFIG['build_os']
CXX_EXT.concat(%w[C])
end
SRC_EXT = %w[c m] << CXX_EXT
-$static = $config_h = nil
+$static = nil
+$config_h = '$(arch_hdrdir)/ruby/config.h'
$default_static = $static
unless defined? $configure_args
@@ -59,7 +60,6 @@ $mswin = /mswin/ =~ RUBY_PLATFORM
$bccwin = /bccwin/ =~ RUBY_PLATFORM
$mingw = /mingw/ =~ RUBY_PLATFORM
$cygwin = /cygwin/ =~ RUBY_PLATFORM
-$human = /human/ =~ RUBY_PLATFORM
$netbsd = /netbsd/ =~ RUBY_PLATFORM
$os2 = /os2/ =~ RUBY_PLATFORM
$beos = /beos/ =~ RUBY_PLATFORM
@@ -323,9 +323,11 @@ EOM
end
def create_tmpsrc(src)
+ src = "#{COMMON_HEADERS}\n#{src}"
src = yield(src) if block_given?
- src[0, 0] = COMMON_HEADERS + "\n"
- src = src.gsub(/[ \t]+$/, '').gsub(/\A\n+|^\n+$/, '').sub(/[^\n]\z/, "\\&\n")
+ src.gsub!(/[ \t]+$/, '')
+ src.gsub!(/\A\n+|^\n+$/, '')
+ src.sub!(/[^\n]\z/, "\\&\n")
count = 0
begin
open(CONFTEST_C, "wb") do |cfile|
@@ -1300,7 +1302,7 @@ def configuration(srcdir)
if CONFIG['target_os'] != 'cygwin'
vpath = vpath.map {|p| p.sub(/.*/, '$(shell cygpath -u \&)')}
end
- when 'msdosdjgpp', 'mingw32'
+ when 'mingw32'
CONFIG['PATH_SEPARATOR'] = ';'
end
end
@@ -1342,7 +1344,7 @@ VPATH = #{vpath.join(CONFIG['PATH_SEPARATOR'])}
else
sep = ""
end
- extconf_h = $extconf_h ? "-DRUBY_EXTCONF_H=\\\"$(RUBY_EXTCONF_H)\\\" " : $defs.join(" ")<<" "
+ extconf_h = $extconf_h ? "-DRUBY_EXTCONF_H=\\\"$(RUBY_EXTCONF_H)\\\" " : $defs.join(" ") << " "
mk << %{
CC = #{CONFIG['CC']}
CXX = #{CONFIG['CXX']}
@@ -1442,7 +1444,7 @@ def depend_rules(depend)
end
depend.each_line do |line|
line.gsub!(/\.o\b/, ".#{$OBJEXT}")
- line.gsub!(/\$\((?:hdr|top)dir\)\/config.h/, $config_h) if $config_h
+ line.gsub!(/\$\((?:hdr|top)dir\)\/config.h/, $config_h)
line.gsub!(%r"\$\(hdrdir\)/(?!ruby(?![^:;/\s]))(?=[-\w]+\.h)", '\&ruby/')
if $nmake && /\A\s*\$\(RM|COPY\)/ =~ line
line.gsub!(%r"[-\w\./]{2,}"){$&.tr("/", "\\")}
@@ -1618,8 +1620,8 @@ TARGET_SO = #{($extout ? '$(RUBYARCHDIR)/' : '')}$(DLLIB)
CLEANLIBS = #{n}.#{CONFIG['DLEXT']} #{config_string('cleanlibs') {|t| t.gsub(/\$\*/) {n}}}
CLEANOBJS = *.#{$OBJEXT} #{config_string('cleanobjs') {|t| t.gsub(/\$\*/, '$(TARGET)')}} *.bak
-all: #{$extout ? "install" : target ? "$(DLLIB)" : "Makefile"}
-static: $(STATIC_LIB)#{$extout ? " install-rb" : ""}
+all: #{$extout ? "install" : target ? "$(DLLIB)" : "Makefile"}
+static: $(STATIC_LIB)#{$extout ? " install-rb" : ""}
"
mfile.print CLEANINGS
dirs = []
@@ -1743,7 +1745,7 @@ site-install-rb: install-rb
if RULE_SUBST
headers.each {|h| h.sub!(/.*/, &RULE_SUBST.method(:%))}
end
- headers << $config_h if $config_h
+ headers << $config_h
headers << '$(RUBY_EXTCONF_H)' if $extconf_h
mfile.print "$(OBJS): ", headers.join(' '), "\n"
end
@@ -1889,14 +1891,14 @@ MAIN_DOES_NOTHING = config_string('MAIN_DOES_NOTHING') || 'int main() {return 0;
sep = config_string('BUILD_FILE_SEPARATOR') {|s| ":/=#{s}" if sep != "/"} || ""
CLEANINGS = "
clean:
- @-$(RM) $(CLEANLIBS#{sep}) $(CLEANOBJS#{sep}) $(CLEANFILES#{sep})
+\t\t@-$(RM) $(CLEANLIBS#{sep}) $(CLEANOBJS#{sep}) $(CLEANFILES#{sep})
-distclean: clean
- @-$(RM_RF) conftest.dSYM
- @-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
- @-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES#{sep})
+distclean: clean
+\t\t@-$(RM_RF) conftest.dSYM
+\t\t@-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
+\t\t@-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES#{sep})
-realclean: distclean
+realclean: distclean
"
if not $extmk and /\A(extconf|makefile).rb\z/ =~ File.basename($0)
diff --git a/lib/net/ftp.rb b/lib/net/ftp.rb
index e0aa6f6adb..06cc3eafa2 100644
--- a/lib/net/ftp.rb
+++ b/lib/net/ftp.rb
@@ -170,9 +170,9 @@ module Net
end
def open_socket(host, port)
- if defined? SOCKSsocket and ENV["SOCKS_SERVER"]
+ if defined? SOCKSSocket and ENV["SOCKS_SERVER"]
@passive = true
- return SOCKSsocket.open(host, port)
+ return SOCKSSocket.open(host, port)
else
return TCPSocket.open(host, port)
end
diff --git a/lib/net/pop.rb b/lib/net/pop.rb
index a8e9987236..7d234c191c 100644
--- a/lib/net/pop.rb
+++ b/lib/net/pop.rb
@@ -870,7 +870,7 @@ module Net
@socket = sock
@error_occured = false
res = check_response(critical { recv_response() })
- @apop_stamp = res.slice(/<.+>/)
+ @apop_stamp = res.slice(/<[!-~]+@[!-~]+>/)
end
attr_reader :socket
diff --git a/lib/open-uri.rb b/lib/open-uri.rb
index 238d759d5f..2a6c544fe6 100644
--- a/lib/open-uri.rb
+++ b/lib/open-uri.rb
@@ -132,6 +132,11 @@ module OpenURI
options ||= {}
OpenURI.check_options(options)
+ if /\Arb?(?:\Z|:([^:]+))/ =~ mode
+ encoding, = $1,Encoding.find($1) if $1
+ mode = nil
+ end
+
unless mode == nil ||
mode == 'r' || mode == 'rb' ||
mode == File::RDONLY
@@ -139,6 +144,7 @@ module OpenURI
end
io = open_loop(uri, options)
+ io.set_encoding(encoding) if encoding
if block_given?
begin
yield io
@@ -542,7 +548,7 @@ module OpenURI
# :proxy => true
# :proxy => false
# :proxy => nil
- #
+ #
# If :proxy option is specified, the value should be String, URI,
# boolean or nil.
# When String or URI is given, it is treated as proxy URI.
@@ -556,7 +562,7 @@ module OpenURI
# Synopsis:
# :proxy_http_basic_authentication => ["http://proxy.foo.com:8000/", "proxy-user", "proxy-password"]
# :proxy_http_basic_authentication => [URI.parse("http://proxy.foo.com:8000/"), "proxy-user", "proxy-password"]
- #
+ #
# If :proxy option is specified, the value should be an Array with 3 elements.
# It should contain a proxy URI, a proxy user name and a proxy password.
# The proxy URI should be a String, an URI or nil.
@@ -564,7 +570,7 @@ module OpenURI
#
# If nil is given for the proxy URI, this option is just ignored.
#
- # If :proxy and :proxy_http_basic_authentication is specified,
+ # If :proxy and :proxy_http_basic_authentication is specified,
# ArgumentError is raised.
#
# [:http_basic_authentication]
@@ -579,14 +585,14 @@ module OpenURI
# [:content_length_proc]
# Synopsis:
# :content_length_proc => lambda {|content_length| ... }
- #
+ #
# If :content_length_proc option is specified, the option value procedure
# is called before actual transfer is started.
# It takes one argument which is expected content length in bytes.
- #
+ #
# If two or more transfer is done by HTTP redirection, the procedure
# is called only one for a last transfer.
- #
+ #
# When expected content length is unknown, the procedure is called with
# nil.
# It is happen when HTTP response has no Content-Length header.
diff --git a/lib/optparse.rb b/lib/optparse.rb
index 86681235a0..0548a29cac 100644
--- a/lib/optparse.rb
+++ b/lib/optparse.rb
@@ -301,7 +301,8 @@ class OptionParser
end
def self.incompatible_argument_styles(arg, t)
- raise ArgumentError, "#{arg}: incompatible argument styles\n #{self}, #{t}"
+ raise(ArgumentError, "#{arg}: incompatible argument styles\n #{self}, #{t}",
+ ParseError.filter_backtrace(caller(2)))
end
def self.pattern
@@ -529,7 +530,8 @@ class OptionParser
#
def accept(t, pat = /.*/nm, &block)
if pat
- pat.respond_to?(:match) or raise TypeError, "has no `match'"
+ pat.respond_to?(:match) or
+ raise TypeError, "has no `match'", ParseError.filter_backtrace(caller(2))
else
pat = t if t.respond_to?(:match)
end
@@ -632,7 +634,7 @@ class OptionParser
list.each do |opt|
if opt.respond_to?(:summarize) # perhaps OptionParser::Switch
opt.summarize(*args, &block)
- elsif !opt
+ elsif !opt or opt.empty?
yield("")
elsif opt.respond_to?(:each_line)
opt.each_line(&block)
@@ -987,17 +989,14 @@ class OptionParser
#
def notwice(obj, prv, msg)
unless !prv or prv == obj
- begin
- raise ArgumentError, "argument #{msg} given twice: #{obj}"
- rescue
- $@[0, 2] = nil
- raise
- end
+ raise(ArgumentError, "argument #{msg} given twice: #{obj}",
+ ParseError.filter_backtrace(caller(2)))
end
obj
end
private :notwice
+ SPLAT_PROC = proc {|*a| a}
#
# Creates an OptionParser::Switch from the parameters. The parsed argument
# value is passed to the given block, where it can be processed.
@@ -1076,9 +1075,13 @@ class OptionParser
end
# directly specified pattern(any object possible to match)
- if !(String === o) and o.respond_to?(:match)
+ if (!(String === o || Symbol === o)) and o.respond_to?(:match)
pattern = notwice(o, pattern, 'pattern')
- conv = pattern.method(:convert).to_proc if pattern.respond_to?(:convert)
+ if pattern.respond_to?(:convert)
+ conv = pattern.method(:convert).to_proc
+ else
+ conv = SPLAT_PROC
+ end
next
end
@@ -1097,7 +1100,7 @@ class OptionParser
end
o.each {|pat, *v| pattern[pat] = v.fetch(0) {pat}}
when Module
- raise ArgumentError, "unsupported argument type: #{o}"
+ raise ArgumentError, "unsupported argument type: #{o}", ParseError.filter_backtrace(caller(4))
when *ArgumentStyle.keys
style = notwice(ArgumentStyle[o], style, 'style')
when /^--no-([^\[\]=\s]*)(.+)?/
@@ -1162,7 +1165,9 @@ class OptionParser
s = (style || default_style).new(pattern || default_pattern,
conv, sdesc, ldesc, arg, desc, block)
elsif !block
- raise ArgumentError, "no switch given" if style or pattern
+ if style or pattern
+ raise ArgumentError, "no switch given", ParseError.filter_backtrace(caller)
+ end
s = desc
else
short << pattern
@@ -1605,6 +1610,17 @@ class OptionParser
argv
end
+ def self.filter_backtrace(array)
+ unless $DEBUG
+ array.delete_if(&%r"\A#{Regexp.quote(__FILE__)}:"o.method(:=~))
+ end
+ array
+ end
+
+ def set_backtrace(array)
+ super(self.class.filter_backtrace(array))
+ end
+
def set_option(opt, eq)
if eq
@args[0] = opt
diff --git a/lib/pathname.rb b/lib/pathname.rb
index 7bee22b58f..1bc0063bb0 100644
--- a/lib/pathname.rb
+++ b/lib/pathname.rb
@@ -43,7 +43,7 @@
# base = p.basename # Pathname:ruby
# dir, base = p.split # [Pathname:/usr/bin, Pathname:ruby]
# data = p.read
-# p.open { |f| _ }
+# p.open { |f| _ }
# p.each_line { |line| _ }
#
# === Example 2: Using standard Ruby
@@ -55,7 +55,7 @@
# base = File.basename(p) # "ruby"
# dir, base = File.split(p) # ["/usr/bin", "ruby"]
# data = File.read(p)
-# File.open(p) { |f| _ }
+# File.open(p) { |f| _ }
# File.foreach(p) { |line| _ }
#
# === Example 3: Special features
@@ -71,7 +71,7 @@
# p5.cleanpath # Pathname:articles
# p5.realpath # Pathname:/home/gavin/articles
# p5.children # [Pathname:/home/gavin/articles/linux, ...]
-#
+#
# == Breakdown of functionality
#
# === Core methods
@@ -452,7 +452,7 @@ class Pathname
# Returns a real (absolute) pathname of +self+ in the actual filesystem.
# The real pathname doesn't contain symlinks or useless dots.
#
- # No arguments should be given; the old behaviour is *obsoleted*.
+ # No arguments should be given; the old behaviour is *obsoleted*.
#
def realpath
path = @path
@@ -517,6 +517,7 @@ class Pathname
# # yields "usr", "bin", and "ruby".
#
def each_filename # :yield: filename
+ return to_enum(__method__) unless block_given?
prefix, names = split_names(@path)
names.each {|filename| yield filename }
nil
@@ -587,7 +588,7 @@ class Pathname
# p2 = p1 + "bin/ruby" # Pathname:/usr/bin/ruby
# p3 = p1 + "/etc/passwd" # Pathname:/etc/passwd
#
- # This method doesn't access the file system; it is pure string manipulation.
+ # This method doesn't access the file system; it is pure string manipulation.
#
def +(other)
other = Pathname.new(other) unless Pathname === other
diff --git a/lib/pp.rb b/lib/pp.rb
index ec896b3ce5..41f51b0046 100644
--- a/lib/pp.rb
+++ b/lib/pp.rb
@@ -1,10 +1,10 @@
# == Pretty-printer for Ruby objects.
-#
+#
# = Which seems better?
-#
+#
# non-pretty-printed output by #p is:
# #<PP:0x81fedf0 @genspace=#<Proc:0x81feda0>, @group_queue=#<PrettyPrint::GroupQueue:0x81fed3c @queue=[[#<PrettyPrint::Group:0x81fed78 @breakables=[], @depth=0, @break=false>], []]>, @buffer=[], @newline="\n", @group_stack=[#<PrettyPrint::Group:0x81fed78 @breakables=[], @depth=0, @break=false>], @buffer_width=0, @indent=0, @maxwidth=79, @output_width=2, @output=#<IO:0x8114ee4>>
-#
+#
# pretty-printed output by #pp is:
# #<PP:0x81fedf0
# @buffer=[],
@@ -22,17 +22,17 @@
# @newline="\n",
# @output=#<IO:0x8114ee4>,
# @output_width=2>
-#
+#
# I like the latter. If you do too, this library is for you.
-#
+#
# = Usage
-#
+#
# pp(obj)
#
# output +obj+ to +$>+ in pretty printed format.
-#
+#
# It returns +nil+.
-#
+#
# = Output Customization
# To define your customized pretty printing function for your classes,
# redefine a method #pretty_print(+pp+) in the class.
@@ -67,10 +67,10 @@ end
class PP < PrettyPrint
# Outputs +obj+ to +out+ in pretty printed format of
# +width+ columns in width.
- #
+ #
# If +out+ is omitted, +$>+ is assumed.
# If +width+ is omitted, 79 is assumed.
- #
+ #
# PP.pp returns +out+.
def PP.pp(obj, out=$>, width=79)
q = PP.new(out, width)
@@ -82,7 +82,7 @@ class PP < PrettyPrint
# Outputs +obj+ to +out+ like PP.pp but with no indent and
# newline.
- #
+ #
# PP.singleline_pp returns +out+.
def PP.singleline_pp(obj, out=$>)
q = SingleLine.new(out)
@@ -138,12 +138,12 @@ class PP < PrettyPrint
# Adds +obj+ to the pretty printing buffer
# using Object#pretty_print or Object#pretty_print_cycle.
- #
+ #
# Object#pretty_print_cycle is used when +obj+ is already
# printed, a.k.a the object reference chain has a cycle.
def pp(obj)
id = obj.object_id
-
+
if check_inspect_key(id)
group {obj.pretty_print_cycle self}
return
@@ -158,7 +158,7 @@ class PP < PrettyPrint
end
# A convenience method which is same as follows:
- #
+ #
# group(1, '#<' + obj.class.name, '>') { ... }
def object_group(obj, &block) # :yield:
group(1, '#<' + obj.class.name, '>', &block)
@@ -185,7 +185,7 @@ class PP < PrettyPrint
end
# A convenience method which is same as follows:
- #
+ #
# text ','
# breakable
def comma_breakable
@@ -195,23 +195,23 @@ class PP < PrettyPrint
# Adds a separated list.
# The list is separated by comma with breakable space, by default.
- #
+ #
# #seplist iterates the +list+ using +iter_method+.
# It yields each object to the block given for #seplist.
# The procedure +separator_proc+ is called between each yields.
- #
+ #
# If the iteration is zero times, +separator_proc+ is not called at all.
- #
+ #
# If +separator_proc+ is nil or not given,
# +lambda { comma_breakable }+ is used.
# If +iter_method+ is not given, :each is used.
- #
+ #
# For example, following 3 code fragments has similar effect.
- #
+ #
# q.seplist([1,2,3]) {|v| xxx v }
- #
+ #
# q.seplist([1,2,3], lambda { q.comma_breakable }, :each) {|v| xxx v }
- #
+ #
# xxx 1
# q.comma_breakable
# xxx 2
@@ -275,11 +275,11 @@ class PP < PrettyPrint
# A default pretty printing method for general objects.
# It calls #pretty_print_instance_variables to list instance variables.
- #
+ #
# If +self+ has a customized (redefined) #inspect method,
# the result of self.inspect is used but it obviously has no
# line break hints.
- #
+ #
# This module provides predefined #pretty_print methods for some of
# the most commonly used built-in classes for convenience.
def pretty_print(q)
@@ -302,7 +302,7 @@ class PP < PrettyPrint
end
# Returns a sorted array of instance variable names.
- #
+ #
# This method should return an array of names of instance variables as symbols or strings as:
# +[:@a, :@b]+.
def pretty_print_instance_variables
@@ -311,7 +311,7 @@ class PP < PrettyPrint
# Is #inspect implementation using #pretty_print.
# If you implement #pretty_print, it can be used as follows.
- #
+ #
# alias inspect pretty_print_inspect
#
# However, doing this requires that every class that #inspect is called on
@@ -629,7 +629,7 @@ if __FILE__ == $0
result = PP.pp(a, '')
assert_equal("#{a.inspect}\n", result)
end
-
+
def test_to_s_without_iv
a = Object.new
def a.to_s() "aaa" end
diff --git a/lib/prettyprint.rb b/lib/prettyprint.rb
index 315c422e9e..48f2ebf1e4 100644
--- a/lib/prettyprint.rb
+++ b/lib/prettyprint.rb
@@ -2,7 +2,7 @@
# This class implements a pretty printing algorithm. It finds line breaks and
# nice indentations for grouped structure.
-#
+#
# By default, the class assumes that primitive elements are strings and each
# byte in the strings have single column in width. But it can be used for
# other situations by giving suitable arguments for some methods:
@@ -18,28 +18,28 @@
# == Bugs
# * Box based formatting?
# * Other (better) model/algorithm?
-#
+#
# == References
# Christian Lindig, Strictly Pretty, March 2000,
# http://www.st.cs.uni-sb.de/~lindig/papers/#pretty
-#
+#
# Philip Wadler, A prettier printer, March 1998,
# http://homepages.inf.ed.ac.uk/wadler/topics/language-design.html#prettier
-#
+#
# == Author
# Tanaka Akira <akr@m17n.org>
-#
+#
class PrettyPrint
# This is a convenience method which is same as follows:
- #
+ #
# begin
# q = PrettyPrint.new(output, maxwidth, newline, &genspace)
# ...
# q.flush
# output
# end
- #
+ #
def PrettyPrint.format(output='', maxwidth=79, newline="\n", genspace=lambda {|n| ' ' * n})
q = PrettyPrint.new(output, maxwidth, newline, &genspace)
yield q
diff --git a/lib/rake.rb b/lib/rake.rb
index 0b21eb7350..480068be7a 100755
--- a/lib/rake.rb
+++ b/lib/rake.rb
@@ -29,15 +29,17 @@
# as a library via a require statement, but it can be distributed
# independently as an application.
-RAKEVERSION = '0.8.0'
+RAKEVERSION = '0.8.3'
require 'rbconfig'
-require 'getoptlong'
require 'fileutils'
require 'singleton'
-require 'thread'
+require 'monitor'
+require 'optparse'
require 'ostruct'
+require 'rake/win32'
+
######################################################################
# Rake extensions to Module.
#
@@ -58,7 +60,7 @@ class Module
# end
#
def rake_extension(method)
- if instance_methods.include?(method.to_s) || instance_methods.include?(method.to_sym)
+ if method_defined?(method)
$stderr.puts "WARNING: Possible conflict with Rake extension: #{self}##{method} already exists"
else
yield
@@ -72,7 +74,7 @@ end # module Module
#
class String
rake_extension("ext") do
- # Replace the file extension with +newext+. If there is no extension on
+ # Replace the file extension with +newext+. If there is no extenson on
# the string, append the new extension to the end. If the new extension
# is not given, or is the empty string, remove any existing extension.
#
@@ -82,7 +84,7 @@ class String
if newext != ''
newext = (newext =~ /^\./) ? newext : ("." + newext)
end
- dup.sub!(%r(([^/\\])\.[^./\\]*$)) { $1 + newext } || self + newext
+ self.chomp(File.extname(self)) << newext
end
end
@@ -145,7 +147,7 @@ class String
# * <b>%x</b> -- The file extension of the path. An empty string if there
# is no extension.
# * <b>%X</b> -- Everything *but* the file extension.
- # * <b>%s</b> -- The alternate file separator if defined, otherwise use
+ # * <b>%s</b> -- The alternate file separater if defined, otherwise use
# the standard file separator.
# * <b>%%</b> -- A percent sign.
#
@@ -159,9 +161,9 @@ class String
# 'a/b/c/d/file.txt'.pathmap("%2d") => 'a/b'
# 'a/b/c/d/file.txt'.pathmap("%-2d") => 'c/d'
#
- # Also the %d, %p, $f, $n, %x, and %X operators can take a
- # pattern/replacement argument to perform simple string substitutions on a
- # particular part of the path. The pattern and replacement are separated
+ # Also the %d, %p, %f, %n, %x, and %X operators can take a
+ # pattern/replacement argument to perform simple string substititions on a
+ # particular part of the path. The pattern and replacement are speparated
# by a comma and are enclosed by curly braces. The replacement spec comes
# after the % character but before the operator letter. (e.g.
# "%{old,new}d"). Muliple replacement specs should be separated by
@@ -201,17 +203,13 @@ class String
when '%f'
result << File.basename(self)
when '%n'
- result << File.basename(self).ext
+ result << File.basename(self, '.*')
when '%d'
result << File.dirname(self)
when '%x'
- result << $1 if self =~ /[^\/](\.[^.]+)$/
+ result << File.extname(self)
when '%X'
- if self =~ /^(.*[^\/])(\.[^.]+)$/
- result << $1
- else
- result << self
- end
+ result << self.ext
when '%p'
result << self
when '%s'
@@ -239,6 +237,28 @@ end # class String
##############################################################################
module Rake
+ # Errors -----------------------------------------------------------
+
+ # Error indicating an ill-formed task declaration.
+ class TaskArgumentError < ArgumentError
+ end
+
+ # Error indicating a recursion overflow error in task selection.
+ class RuleRecursionOverflowError < StandardError
+ def initialize(*args)
+ super
+ @targets = []
+ end
+
+ def add_target(target)
+ @targets << target
+ end
+
+ def message
+ super + ": [" + @targets.reverse.join(' => ') + "]"
+ end
+ end
+
# --------------------------------------------------------------------------
# Rake module singleton methods.
#
@@ -266,16 +286,22 @@ module Rake
module Cloneable
# Clone an object by making a new object and setting all the instance
# variables to the same values.
- def clone
+ def dup
sibling = self.class.new
instance_variables.each do |ivar|
value = self.instance_variable_get(ivar)
new_value = value.clone rescue value
sibling.instance_variable_set(ivar, new_value)
end
+ sibling.taint if tainted?
+ sibling
+ end
+
+ def clone
+ sibling = dup
+ sibling.freeze if frozen?
sibling
end
- alias dup clone
end
####################################################################
@@ -286,12 +312,15 @@ module Rake
attr_reader :names
+ # Create a TaskArgument object with a list of named arguments
+ # (given by :names) and a set of associated values (given by
+ # :values). :parent is the parent argument object.
def initialize(names, values, parent=nil)
@names = names
@parent = parent
@hash = {}
names.each_with_index { |name, i|
- @hash[name.to_sym] = values[i]
+ @hash[name.to_sym] = values[i] unless values[i].nil?
}
end
@@ -307,6 +336,13 @@ module Rake
lookup(index.to_sym)
end
+ # Specify a hash of default values for task arguments. Use the
+ # defaults only if there is no specific value for the given
+ # argument.
+ def with_defaults(defaults)
+ @hash = defaults.merge(@hash)
+ end
+
def each(&block)
@hash.each(&block)
end
@@ -342,6 +378,8 @@ module Rake
end
end
+ EMPTY_TASK_ARGS = TaskArguments.new([], [])
+
####################################################################
# InvocationChain tracks the chain of task invocations to detect
# circular dependencies.
@@ -409,6 +447,9 @@ module Rake
# List of prerequisites for a task.
attr_reader :prerequisites
+ # List of actions attached to a task.
+ attr_reader :actions
+
# Application owning this task.
attr_accessor :application
@@ -446,12 +487,12 @@ module Rake
# +enhance+ to add actions and prerequisites.
def initialize(task_name, app)
@name = task_name.to_s
- @prerequisites = FileList[]
+ @prerequisites = []
@actions = []
@already_invoked = false
@full_comment = nil
@comment = nil
- @lock = Mutex.new
+ @lock = Monitor.new
@application = app
@scope = app.current_scope
@arg_names = nil
@@ -488,6 +529,31 @@ module Rake
@arg_names || []
end
+ # Reenable the task, allowing its tasks to be executed if the task
+ # is invoked again.
+ def reenable
+ @already_invoked = false
+ end
+
+ # Clear the existing prerequisites and actions of a rake task.
+ def clear
+ clear_prerequisites
+ clear_actions
+ self
+ end
+
+ # Clear the existing prerequisites of a rake task.
+ def clear_prerequisites
+ prerequisites.clear
+ self
+ end
+
+ # Clear the existing actions on a rake task.
+ def clear_actions
+ actions.clear
+ self
+ end
+
# Invoke the task if it is needed. Prerequites are invoked first.
def invoke(*args)
task_args = TaskArguments.new(arg_names, args)
@@ -496,7 +562,7 @@ module Rake
# Same as invoke, but explicitly pass a call chain to detect
# circular dependencies.
- def invoke_with_call_chain(task_args, invocation_chain)
+ def invoke_with_call_chain(task_args, invocation_chain) # :nodoc:
new_chain = InvocationChain.append(self, invocation_chain)
@lock.synchronize do
if application.options.trace
@@ -511,7 +577,7 @@ module Rake
protected :invoke_with_call_chain
# Invoke all the prerequisites of a task.
- def invoke_prerequisites(task_args, invocation_chain)
+ def invoke_prerequisites(task_args, invocation_chain) # :nodoc:
@prerequisites.each { |n|
prereq = application[n, @scope]
prereq_args = task_args.new_scope(prereq.arg_names)
@@ -529,7 +595,8 @@ module Rake
private :format_trace_flags
# Execute the actions associated with this task.
- def execute(args)
+ def execute(args=nil)
+ args ||= EMPTY_TASK_ARGS
if application.options.dryrun
puts "** Execute (dry run) #{name}"
return
@@ -772,8 +839,8 @@ end
# end
# end
#
-def file(args, &block)
- Rake::FileTask.define_task(args, &block)
+def file(*args, &block)
+ Rake::FileTask.define_task(*args, &block)
end
# Declare a file creation task.
@@ -868,7 +935,8 @@ end
# added to the FileUtils utility functions.
#
module FileUtils
- RUBY = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name'])
+ RUBY = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name']).
+ sub(/.*\s.*/m, '"\&"')
OPT_TABLE['sh'] = %w(noop verbose)
OPT_TABLE['ruby'] = %w(noop verbose)
@@ -899,14 +967,29 @@ module FileUtils
ok or fail "Command failed with status (#{status.exitstatus}): [#{show_command}]"
}
end
+ if RakeFileUtils.verbose_flag == :default
+ options[:verbose] = false
+ else
+ options[:verbose] ||= RakeFileUtils.verbose_flag
+ end
+ options[:noop] ||= RakeFileUtils.nowrite_flag
rake_check_options options, :noop, :verbose
rake_output_message cmd.join(" ") if options[:verbose]
unless options[:noop]
- res = system(*cmd)
+ res = rake_system(*cmd)
block.call(res, $?)
end
end
+ def rake_system(*cmd)
+ if Rake::Win32.windows?
+ Rake::Win32.rake_system(*cmd)
+ else
+ system(*cmd)
+ end
+ end
+ private :rake_system
+
# Run a Ruby interpreter with the given arguments.
#
# Example:
@@ -917,7 +1000,7 @@ module FileUtils
if args.length > 1 then
sh(*([RUBY] + args + [options]), &block)
else
- sh("#{RUBY.sub(/.*\s.*/m, '"\&"')} #{args.first}", options, &block)
+ sh("#{RUBY} #{args.first}", options, &block)
end
end
@@ -961,7 +1044,7 @@ module RakeFileUtils
class << self
attr_accessor :verbose_flag, :nowrite_flag
end
- RakeFileUtils.verbose_flag = true
+ RakeFileUtils.verbose_flag = :default
RakeFileUtils.nowrite_flag = false
$fileutils_verbose = true
@@ -969,10 +1052,10 @@ module RakeFileUtils
FileUtils::OPT_TABLE.each do |name, opts|
default_options = []
- if opts.include?('verbose')
+ if opts.include?(:verbose) || opts.include?("verbose")
default_options << ':verbose => RakeFileUtils.verbose_flag'
end
- if opts.include?('noop')
+ if opts.include?(:noop) || opts.include?("noop")
default_options << ':noop => RakeFileUtils.nowrite_flag'
end
@@ -1029,7 +1112,7 @@ module RakeFileUtils
oldvalue
end
- # Use this function to prevent potentially destructive ruby code from
+ # Use this function to prevent protentially destructive ruby code from
# running when the :nowrite flag is set.
#
# Example:
@@ -1094,21 +1177,6 @@ private(*RakeFileUtils.instance_methods(false))
######################################################################
module Rake
- class RuleRecursionOverflowError < StandardError
- def initialize(*args)
- super
- @targets = []
- end
-
- def add_target(target)
- @targets << target
- end
-
- def message
- super + ": [" + @targets.reverse.join(' => ') + "]"
- end
- end
-
# #########################################################################
# A FileList is essentially an array with a few helper methods defined to
# make file manipulation a bit easier.
@@ -1352,7 +1420,7 @@ module Rake
private :resolve_exclude
# Return a new FileList with the results of running +sub+ against each
- # element of the original list.
+ # element of the oringal list.
#
# Example:
# FileList['a.c', 'b.c'].sub(/\.c$/, '.o') => ['a.o', 'b.o']
@@ -1503,7 +1571,7 @@ module Rake
class << self
# Yield each file or directory component.
- def each_dir_parent(dir)
+ def each_dir_parent(dir) # :nodoc:
old_length = nil
while dir != '.' && dir.length != old_length
yield(dir)
@@ -1642,23 +1710,65 @@ module Rake
# Resolve the arguments for a task/rule. Returns a triplet of
# [task_name, arg_name_list, prerequisites].
def resolve_args(args)
+ if args.last.is_a?(Hash)
+ deps = args.pop
+ resolve_args_with_dependencies(args, deps)
+ else
+ resolve_args_without_dependencies(args)
+ end
+ end
+
+ # Resolve task arguments for a task or rule when there are no
+ # dependencies declared.
+ #
+ # The patterns recognized by this argument resolving function are:
+ #
+ # task :t
+ # task :t, [:a]
+ # task :t, :a (deprecated)
+ #
+ def resolve_args_without_dependencies(args)
task_name = args.shift
- arg_names = args #.map { |a| a.to_sym }
- needs = []
- if task_name.is_a?(Hash)
- hash = task_name
- task_name = hash.keys[0]
- needs = hash[task_name]
+ if args.size == 1 && args.first.respond_to?(:to_ary)
+ arg_names = args.first.to_ary
+ else
+ arg_names = args
end
- if arg_names.last.is_a?(Hash)
- hash = arg_names.pop
- needs = hash[:needs]
- fail "Unrecognized keys in task hash: #{hash.keys.inspect}" if hash.size > 1
+ [task_name, arg_names, []]
+ end
+ private :resolve_args_without_dependencies
+
+ # Resolve task arguments for a task or rule when there are
+ # dependencies declared.
+ #
+ # The patterns recognized by this argument resolving function are:
+ #
+ # task :t => [:d]
+ # task :t, [a] => [:d]
+ # task :t, :needs => [:d] (deprecated)
+ # task :t, :a, :needs => [:d] (deprecated)
+ #
+ def resolve_args_with_dependencies(args, hash) # :nodoc:
+ fail "Task Argument Error" if hash.size != 1
+ key, value = hash.map { |k, v| [k,v] }.first
+ if args.empty?
+ task_name = key
+ arg_names = []
+ deps = value
+ elsif key == :needs
+ task_name = args.shift
+ arg_names = args
+ deps = value
+ else
+ task_name = args.shift
+ arg_names = key
+ deps = value
end
- needs = [needs] unless needs.respond_to?(:to_ary)
- [task_name, arg_names, needs]
+ deps = [deps] unless deps.respond_to?(:to_ary)
+ [task_name, arg_names, deps]
end
-
+ private :resolve_args_with_dependencies
+
# If a rule can be found that matches the task name, enhance the
# task with the prerequisites and actions from the rule. Set the
# source attribute of the task appropriately for the rule. Return
@@ -1749,15 +1859,23 @@ module Rake
"_anon_#{@seed}"
end
+ def trace_rule(level, message)
+ puts "#{" "*level}#{message}" if Rake.application.options.trace_rules
+ end
+
# Attempt to create a rule given the list of prerequisites.
def attempt_rule(task_name, extensions, block, level)
sources = make_sources(task_name, extensions)
prereqs = sources.collect { |source|
+ trace_rule level, "Attempting Rule #{task_name} => #{source}"
if File.exist?(source) || Rake::Task.task_defined?(source)
+ trace_rule level, "(#{task_name} => #{source} ... EXIST)"
source
- elsif parent = enhance_with_matching_rule(sources.first, level+1)
+ elsif parent = enhance_with_matching_rule(source, level+1)
+ trace_rule level, "(#{task_name} => #{source} ... ENHANCE)"
parent.name
else
+ trace_rule level, "(#{task_name} => #{source} ... FAIL)"
return nil
end
}
@@ -1814,41 +1932,6 @@ module Rake
DEFAULT_RAKEFILES = ['rakefile', 'Rakefile', 'rakefile.rb', 'Rakefile.rb'].freeze
- OPTIONS = [ # :nodoc:
- ['--classic-namespace', '-C', GetoptLong::NO_ARGUMENT,
- "Put Task and FileTask in the top level namespace"],
- ['--describe', '-D', GetoptLong::OPTIONAL_ARGUMENT,
- "Describe the tasks (matching optional PATTERN), then exit."],
- ['--rakefile', '-f', GetoptLong::OPTIONAL_ARGUMENT,
- "Use FILE as the rakefile."],
- ['--help', '-h', '-H', GetoptLong::NO_ARGUMENT,
- "Display this help message."],
- ['--libdir', '-I', GetoptLong::REQUIRED_ARGUMENT,
- "Include LIBDIR in the search path for required modules."],
- ['--dry-run', '-n', GetoptLong::NO_ARGUMENT,
- "Do a dry run without executing actions."],
- ['--nosearch', '-N', GetoptLong::NO_ARGUMENT,
- "Do not search parent directories for the Rakefile."],
- ['--prereqs', '-P', GetoptLong::NO_ARGUMENT,
- "Display the tasks and dependencies, then exit."],
- ['--quiet', '-q', GetoptLong::NO_ARGUMENT,
- "Do not log messages to standard output."],
- ['--require', '-r', GetoptLong::REQUIRED_ARGUMENT,
- "Require MODULE before executing rakefile."],
- ['--rakelibdir', '-R', GetoptLong::REQUIRED_ARGUMENT,
- "Auto-import any .rake files in RAKELIBDIR. (default is 'rakelib')"],
- ['--silent', '-s', GetoptLong::NO_ARGUMENT,
- "Like --quiet, but also suppresses the 'in directory' announcement."],
- ['--tasks', '-T', GetoptLong::OPTIONAL_ARGUMENT,
- "Display the tasks (matching optional PATTERN) with descriptions, then exit."],
- ['--trace', '-t', GetoptLong::NO_ARGUMENT,
- "Turn on invoke/execute tracing, enable full backtrace."],
- ['--verbose', '-v', GetoptLong::NO_ARGUMENT,
- "Log message to standard output (default)."],
- ['--version', '-V', GetoptLong::NO_ARGUMENT,
- "Display the program version."],
- ]
-
# Initialize a Rake::Application object.
def initialize
super
@@ -1861,8 +1944,10 @@ module Rake
@default_loader = Rake::DefaultLoader.new
@original_dir = Dir.pwd
@top_level_tasks = []
+ add_loader('rb', DefaultLoader.new)
add_loader('rf', DefaultLoader.new)
add_loader('rake', DefaultLoader.new)
+ @tty_output = STDOUT.tty?
end
# Run the Rake application. The run method performs the following three steps:
@@ -1886,8 +1971,7 @@ module Rake
def init(app_name='rake')
standard_exception_handling do
@name = app_name
- handle_options
- collect_tasks
+ collect_tasks handle_options
end
end
@@ -1942,16 +2026,16 @@ module Rake
[name, args]
end
- # Provide standard exception handling for the given block.
+ # Provide standard execption handling for the given block.
def standard_exception_handling
begin
yield
rescue SystemExit => ex
# Exit silently with current status
- exit(ex.status)
- rescue SystemExit, GetoptLong::InvalidOption => ex
+ raise
+ rescue OptionParser::InvalidOption => ex
# Exit silently
- exit(1)
+ exit(false)
rescue Exception => ex
# Exit with error message
$stderr.puts "rake aborted!"
@@ -1962,7 +2046,7 @@ module Rake
$stderr.puts ex.backtrace.find {|str| str =~ /#{@rakefile}/ } || ""
$stderr.puts "(See full trace by running task with --trace)"
end
- exit(1)
+ exit(false)
end
end
@@ -1971,33 +2055,26 @@ module Rake
def have_rakefile
@rakefiles.each do |fn|
if File.exist?(fn) || fn == ''
- @rakefile = fn
- return true
+ return fn
end
end
- return false
+ return nil
end
- # Display the rake command line help.
- def help
- puts "rake [-f rakefile] {options} targets..."
- puts
- puts "Options are ..."
- puts
- OPTIONS.sort.each do |long, *short, mode, desc|
- case mode
- when GetoptLong::REQUIRED_ARGUMENT
- if desc =~ /\b([A-Z]{2,})\b/
- long = long + "=#{$1}"
- end
- when GetoptLong::OPTIONAL_ARGUMENT
- if desc =~ /\b([A-Z]{2,})\b/
- long = long + "[=#{$1}]"
- end
- end
- printf " %-20s (%s)\n", long, short.join(", ")
- printf " %s\n", desc
- end
+ # True if we are outputting to TTY, false otherwise
+ def tty_output?
+ @tty_output
+ end
+
+ # Override the detected TTY output state (mostly for testing)
+ def tty_output=( tty_output_state )
+ @tty_output = tty_output_state
+ end
+
+ # We will truncate output if we are outputting to a TTY or if we've been
+ # given an explicit column width to honor
+ def truncate_output?
+ tty_output? || ENV['RAKE_COLUMNS']
end
# Display the tasks and dependencies.
@@ -2015,19 +2092,51 @@ module Rake
end
else
width = displayable_tasks.collect { |t| t.name_with_args.length }.max || 10
- max_column = 80 - name.size - width - 7
+ max_column = truncate_output? ? terminal_width - name.size - width - 7 : nil
displayable_tasks.each do |t|
printf "#{name} %-#{width}s # %s\n",
- t.name_with_args, truncate(t.comment, max_column)
+ t.name_with_args, max_column ? truncate(t.comment, max_column) : t.comment
end
end
end
+ def terminal_width
+ if ENV['RAKE_COLUMNS']
+ result = ENV['RAKE_COLUMNS'].to_i
+ else
+ result = unix? ? dynamic_width : 80
+ end
+ (result < 10) ? 80 : result
+ rescue
+ 80
+ end
+
+ # Calculate the dynamic width of the
+ def dynamic_width
+ @dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput)
+ end
+
+ def dynamic_width_stty
+ %x{stty size 2>/dev/null}.split[1].to_i
+ end
+
+ def dynamic_width_tput
+ %x{tput cols 2>/dev/null}.to_i
+ end
+
+ def unix?
+ RUBY_PLATFORM =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i
+ end
+
+ def windows?
+ Win32.windows?
+ end
+
def truncate(string, width)
if string.length <= width
string
else
- string[0, width-3] + "..."
+ ( string[0, width-3] || "" ) + "..."
end
end
@@ -2039,77 +2148,141 @@ module Rake
end
end
- # Return a list of the command line options supported by the
- # program.
- def command_line_options
- OPTIONS.collect { |lst| lst[0..-2] }
- end
-
- # Do the option defined by +opt+ and +value+.
- def do_option(opt, value)
- case opt
- when '--describe'
- options.show_tasks = true
- options.show_task_pattern = Regexp.new(value || '.')
- options.full_description = true
- when '--dry-run'
- verbose(true)
- nowrite(true)
- options.dryrun = true
- options.trace = true
- when '--help'
- help
- exit
- when '--libdir'
- $:.push(value)
- when '--nosearch'
- options.nosearch = true
- when '--prereqs'
- options.show_prereqs = true
- when '--quiet'
- verbose(false)
- when '--rakefile'
- @rakefiles.clear
- @rakefiles << value
- when '--rakelibdir'
- options.rakelib = value.split(':')
- when '--require'
- begin
- require value
- rescue LoadError => ex
- begin
- rake_require value
- rescue LoadError => ex2
- raise ex
- end
- end
- when '--silent'
- verbose(false)
- options.silent = true
- when '--tasks'
- options.show_tasks = true
- options.show_task_pattern = Regexp.new(value || '.')
- options.full_description = false
- when '--trace'
- options.trace = true
- verbose(true)
- when '--verbose'
- verbose(true)
- when '--version'
- puts "rake, version #{RAKEVERSION}"
- exit
- when '--classic-namespace'
- require 'rake/classic_namespace'
- options.classic_namespace = true
- end
+ # A list of all the standard options used in rake, suitable for
+ # passing to OptionParser.
+ def standard_rake_options
+ [
+ ['--classic-namespace', '-C', "Put Task and FileTask in the top level namespace",
+ lambda { |value|
+ require 'rake/classic_namespace'
+ options.classic_namespace = true
+ }
+ ],
+ ['--describe', '-D [PATTERN]', "Describe the tasks (matching optional PATTERN), then exit.",
+ lambda { |value|
+ options.show_tasks = true
+ options.full_description = true
+ options.show_task_pattern = Regexp.new(value || '')
+ }
+ ],
+ ['--dry-run', '-n', "Do a dry run without executing actions.",
+ lambda { |value|
+ verbose(true)
+ nowrite(true)
+ options.dryrun = true
+ options.trace = true
+ }
+ ],
+ ['--execute', '-e CODE', "Execute some Ruby code and exit.",
+ lambda { |value|
+ eval(value)
+ exit
+ }
+ ],
+ ['--execute-print', '-p CODE', "Execute some Ruby code, print the result, then exit.",
+ lambda { |value|
+ puts eval(value)
+ exit
+ }
+ ],
+ ['--execute-continue', '-E CODE',
+ "Execute some Ruby code, then continue with normal task processing.",
+ lambda { |value| eval(value) }
+ ],
+ ['--libdir', '-I LIBDIR', "Include LIBDIR in the search path for required modules.",
+ lambda { |value| $:.push(value) }
+ ],
+ ['--prereqs', '-P', "Display the tasks and dependencies, then exit.",
+ lambda { |value| options.show_prereqs = true }
+ ],
+ ['--quiet', '-q', "Do not log messages to standard output.",
+ lambda { |value| verbose(false) }
+ ],
+ ['--rakefile', '-f [FILE]', "Use FILE as the rakefile.",
+ lambda { |value|
+ value ||= ''
+ @rakefiles.clear
+ @rakefiles << value
+ }
+ ],
+ ['--rakelibdir', '--rakelib', '-R RAKELIBDIR',
+ "Auto-import any .rake files in RAKELIBDIR. (default is 'rakelib')",
+ lambda { |value| options.rakelib = value.split(':') }
+ ],
+ ['--require', '-r MODULE', "Require MODULE before executing rakefile.",
+ lambda { |value|
+ begin
+ require value
+ rescue LoadError => ex
+ begin
+ rake_require value
+ rescue LoadError => ex2
+ raise ex
+ end
+ end
+ }
+ ],
+ ['--rules', "Trace the rules resolution.",
+ lambda { |value| options.trace_rules = true }
+ ],
+ ['--no-search', '--nosearch', '-N', "Do not search parent directories for the Rakefile.",
+ lambda { |value| options.nosearch = true }
+ ],
+ ['--silent', '-s', "Like --quiet, but also suppresses the 'in directory' announcement.",
+ lambda { |value|
+ verbose(false)
+ options.silent = true
+ }
+ ],
+ ['--system', '-g',
+ "Using system wide (global) rakefiles (usually '~/.rake/*.rake').",
+ lambda { |value| options.load_system = true }
+ ],
+ ['--no-system', '--nosystem', '-G',
+ "Use standard project Rakefile search paths, ignore system wide rakefiles.",
+ lambda { |value| options.ignore_system = true }
+ ],
+ ['--tasks', '-T [PATTERN]', "Display the tasks (matching optional PATTERN) with descriptions, then exit.",
+ lambda { |value|
+ options.show_tasks = true
+ options.show_task_pattern = Regexp.new(value || '')
+ options.full_description = false
+ }
+ ],
+ ['--trace', '-t', "Turn on invoke/execute tracing, enable full backtrace.",
+ lambda { |value|
+ options.trace = true
+ verbose(true)
+ }
+ ],
+ ['--verbose', '-v', "Log message to standard output (default).",
+ lambda { |value| verbose(true) }
+ ],
+ ['--version', '-V', "Display the program version.",
+ lambda { |value|
+ puts "rake, version #{RAKEVERSION}"
+ exit
+ }
+ ]
+ ]
end
# Read and handle the command line options.
def handle_options
options.rakelib = ['rakelib']
- opts = GetoptLong.new(*command_line_options)
- opts.each { |opt, value| do_option(opt, value) }
+ opts = OptionParser.new
+ opts.banner = "rake [-f rakefile] {options} targets..."
+ opts.separator ""
+ opts.separator "Options are ..."
+
+ opts.on_tail("-h", "--help", "-H", "Display this help message.") do
+ puts opts
+ exit
+ end
+
+ standard_rake_options.each { |args| opts.on(*args) }
+ parsed_argv = opts.parse(ARGV)
# If class namespaces are requested, set the global options
# according to the values in the options structure.
@@ -2120,12 +2293,11 @@ module Rake
$dryrun = options.dryrun
$silent = options.silent
end
- rescue NoMethodError => ex
- raise GetoptLong::InvalidOption, "While parsing options, error = #{ex.class}:#{ex.message}"
+ parsed_argv
end
# Similar to the regular Ruby +require+ command, but will check
- # for .rake files in addition to .rb files.
+ # for *.rake files in addition to *.rb files.
def rake_require(file_name, paths=$LOAD_PATH, loaded=$")
return false if loaded.include?(file_name)
paths.each do |path|
@@ -2140,34 +2312,81 @@ module Rake
fail LoadError, "Can't find #{file_name}"
end
- def raw_load_rakefile # :nodoc:
+ def find_rakefile_location
here = Dir.pwd
- while ! have_rakefile
+ while ! (fn = have_rakefile)
Dir.chdir("..")
if Dir.pwd == here || options.nosearch
- fail "No Rakefile found (looking for: #{@rakefiles.join(', ')})"
+ return nil
end
here = Dir.pwd
end
- puts "(in #{Dir.pwd})" unless options.silent
- $rakefile = @rakefile
- load File.expand_path(@rakefile) if @rakefile != ''
- options.rakelib.each do |rlib|
- Dir["#{rlib}/*.rake"].each do |name| add_import name end
+ [fn, here]
+ ensure
+ Dir.chdir(Rake.original_dir)
+ end
+
+ def raw_load_rakefile # :nodoc:
+ rakefile, location = find_rakefile_location
+ if (! options.ignore_system) &&
+ (options.load_system || rakefile.nil?) &&
+ system_dir && File.directory?(system_dir)
+ puts "(in #{Dir.pwd})" unless options.silent
+ glob("#{system_dir}/*.rake") do |name|
+ add_import name
+ end
+ else
+ fail "No Rakefile found (looking for: #{@rakefiles.join(', ')})" if
+ rakefile.nil?
+ @rakefile = rakefile
+ Dir.chdir(location)
+ puts "(in #{Dir.pwd})" unless options.silent
+ $rakefile = @rakefile if options.classic_namespace
+ load File.expand_path(@rakefile) if @rakefile && @rakefile != ''
+ options.rakelib.each do |rlib|
+ glob("#{rlib}/*.rake") do |name|
+ add_import name
+ end
+ end
end
load_imports
end
+ def glob(path, &block)
+ Dir[path.gsub("\\", '/')].each(&block)
+ end
+ private :glob
+
+ # The directory path containing the system wide rakefiles.
+ def system_dir
+ @system_dir ||=
+ begin
+ if ENV['RAKE_SYSTEM']
+ ENV['RAKE_SYSTEM']
+ elsif Win32.windows?
+ Win32.win32_system_dir
+ else
+ standard_system_dir
+ end
+ end
+ end
+
+ # The standard directory containing system wide rake files.
+ def standard_system_dir #:nodoc:
+ File.join(File.expand_path('~'), '.rake')
+ end
+ private :standard_system_dir
+
# Collect the list of tasks on the command line. If no tasks are
# given, return a list containing only the default task.
# Environmental assignments are processed at this time as well.
- def collect_tasks
+ def collect_tasks(argv)
@top_level_tasks = []
- ARGV.each do |arg|
+ argv.each do |arg|
if arg =~ /^(\w+)=(.*)$/
ENV[$1] = $2
else
- @top_level_tasks << arg
+ @top_level_tasks << arg unless arg =~ /^-/
end
end
@top_level_tasks.push("default") if @top_level_tasks.size == 0
diff --git a/lib/rake/gempackagetask.rb b/lib/rake/gempackagetask.rb
index a4e5cd1907..1e4632a26b 100644
--- a/lib/rake/gempackagetask.rb
+++ b/lib/rake/gempackagetask.rb
@@ -9,12 +9,6 @@ require 'rake/packagetask'
require 'rubygems/user_interaction'
require 'rubygems/builder'
-begin
- Gem.manage_gems
-rescue NoMethodError => ex
- # Using rubygems prior to 0.6.1
-end
-
module Rake
# Create a package based upon a Gem spec. Gem packages, as well as
diff --git a/lib/rake/loaders/makefile.rb b/lib/rake/loaders/makefile.rb
index f66eb3b35f..9ade098a1b 100644
--- a/lib/rake/loaders/makefile.rb
+++ b/lib/rake/loaders/makefile.rb
@@ -7,31 +7,26 @@ module Rake
# Load the makefile dependencies in +fn+.
def load(fn)
- buffer = ''
open(fn) do |mf|
- mf.each do |line|
- next if line =~ /^\s*#/
- buffer << line
- if buffer =~ /\\$/
- buffer.sub!(/\\\n/, ' ')
- state = :append
- else
- process_line(buffer)
- buffer = ''
- end
+ lines = mf.read
+ lines.gsub!(/#[^\n]*\n/m, "")
+ lines.gsub!(/\\\n/, ' ')
+ lines.split("\n").each do |line|
+ process_line(line)
end
end
- process_line(buffer) if buffer != ''
end
private
# Process one logical line of makefile data.
def process_line(line)
- file_task, args = line.split(':')
+ file_tasks, args = line.split(':')
return if args.nil?
dependents = args.split
- file file_task => dependents
+ file_tasks.strip.split.each do |file_task|
+ file file_task => dependents
+ end
end
end
diff --git a/lib/rake/packagetask.rb b/lib/rake/packagetask.rb
index 71b66a6481..4b0775d09c 100644
--- a/lib/rake/packagetask.rb
+++ b/lib/rake/packagetask.rb
@@ -122,6 +122,7 @@ module Rake
task :package => ["#{package_dir}/#{file}"]
file "#{package_dir}/#{file}" => [package_dir_path] + package_files do
chdir(package_dir) do
+ sh %{env}
sh %{#{@tar_command} #{flag}cvf #{file} #{package_name}}
end
end
diff --git a/lib/rake/rdoctask.rb b/lib/rake/rdoctask.rb
index 54adc6feb5..6cfbda1d6a 100644
--- a/lib/rake/rdoctask.rb
+++ b/lib/rake/rdoctask.rb
@@ -55,7 +55,7 @@ module Rake
# RDoc. (default is none)
attr_accessor :main
- # Name of template to be used by rdoc. (default is 'html')
+ # Name of template to be used by rdoc. (defaults to rdoc's default)
attr_accessor :template
# List of files to be included in the rdoc generation. (default is [])
@@ -74,7 +74,7 @@ module Rake
@rdoc_dir = 'html'
@main = nil
@title = nil
- @template = 'html'
+ @template = nil
@external = false
@options = []
yield self if block_given?
@@ -91,18 +91,18 @@ module Rake
task name
desc "Force a rebuild of the RDOC files"
- task paste("re", name) => [paste("clobber_", name), name]
+ task "re#{name}" => ["clobber_#{name}", name]
desc "Remove rdoc products"
- task paste("clobber_", name) do
+ task "clobber_#{name}" do
rm_r rdoc_dir rescue nil
end
-
- task :clobber => [paste("clobber_", name)]
+
+ task :clobber => ["clobber_#{name}"]
directory @rdoc_dir
task name => [rdoc_target]
- file rdoc_target => @rdoc_files + [$rakefile] do
+ file rdoc_target => @rdoc_files + [Rake.application.rakefile] do
rm_r @rdoc_dir rescue nil
args = option_list + @rdoc_files
if @external
diff --git a/lib/rake/tasklib.rb b/lib/rake/tasklib.rb
index 465a58a0c7..c7fd98133c 100644
--- a/lib/rake/tasklib.rb
+++ b/lib/rake/tasklib.rb
@@ -6,11 +6,16 @@ module Rake
# Base class for Task Libraries.
class TaskLib
-
include Cloneable
- # Make a symbol by pasting two strings together.
- def paste(a,b)
+ # Make a symbol by pasting two strings together.
+ #
+ # NOTE: DEPRECATED! This method is kinda stupid. I don't know why
+ # I didn't just use string interpolation. But now other task
+ # libraries depend on this so I can't remove it without breaking
+ # other people's code. So for now it stays for backwards
+ # compatibility. BUT DON'T USE IT.
+ def paste(a,b) # :nodoc:
(a.to_s + b.to_s).intern
end
end
diff --git a/lib/rake/testtask.rb b/lib/rake/testtask.rb
index f5b77e5957..79154e422b 100644
--- a/lib/rake/testtask.rb
+++ b/lib/rake/testtask.rb
@@ -136,7 +136,12 @@ module Rake
end
def fix # :nodoc:
- ''
+ case RUBY_VERSION
+ when '1.8.2'
+ find_file 'rake/ruby182_test_unit_fix'
+ else
+ nil
+ end || ''
end
def rake_loader # :nodoc:
diff --git a/lib/rake/win32.rb b/lib/rake/win32.rb
new file mode 100644
index 0000000000..eadc585a3f
--- /dev/null
+++ b/lib/rake/win32.rb
@@ -0,0 +1,54 @@
+module Rake
+
+ # Win 32 interface methods for Rake. Windows specific functionality
+ # will be placed here to collect that knowledge in one spot.
+ module Win32
+
+ # Error indicating a problem in locating the home directory on a
+ # Win32 system.
+ class Win32HomeError < RuntimeError
+ end
+
+ class << self
+ # True if running on a windows system.
+ def windows?
+ Config::CONFIG['host_os'] =~ /mswin/
+ end
+
+ # Run a command line on windows.
+ def rake_system(*cmd)
+ if cmd.size == 1
+ system("call #{cmd}")
+ else
+ system(*cmd)
+ end
+ end
+
+ # The standard directory containing system wide rake files on
+ # Win 32 systems. Try the following environment variables (in
+ # order):
+ #
+ # * APPDATA
+ # * HOMEDRIVE + HOMEPATH
+ # * USERPROFILE
+ #
+ # If the above are not defined, the return nil.
+ def win32_system_dir #:nodoc:
+ win32_shared_path = ENV['APPDATA']
+ if win32_shared_path.nil? && ENV['HOMEDRIVE'] && ENV['HOMEPATH']
+ win32_shared_path = ENV['HOMEDRIVE'] + ENV['HOMEPATH']
+ end
+ win32_shared_path ||= ENV['USERPROFILE']
+ raise Win32HomeError, "Unable to determine home path environment variable." if
+ win32_shared_path.nil? or win32_shared_path.empty?
+ normalize(File.join(win32_shared_path, 'Rake'))
+ end
+
+ # Normalize a win32 path so that the slashes are all forward slashes.
+ def normalize(path)
+ path.gsub(/\\/, '/')
+ end
+
+ end
+ end
+end
diff --git a/lib/rational.rb b/lib/rational.rb
index 4b39f83152..5acfa5433d 100644
--- a/lib/rational.rb
+++ b/lib/rational.rb
@@ -3,7 +3,7 @@ class Fixnum
alias quof fdiv
alias rdiv quo
- alias power! **
+ alias power! ** unless defined?(0.power!)
alias rpower **
end
@@ -13,7 +13,7 @@ class Bignum
alias quof fdiv
alias rdiv quo
- alias power! **
+ alias power! ** unless defined?(0.power!)
alias rpower **
end
diff --git a/lib/rdoc.rb b/lib/rdoc.rb
index 53b72241f8..f4fc3867cf 100644
--- a/lib/rdoc.rb
+++ b/lib/rdoc.rb
@@ -1,14 +1,14 @@
$DEBUG_RDOC = nil
##
-# RDoc - Ruby Documentation System
+# = \RDoc - Ruby Documentation System
#
# This package contains RDoc and RDoc::Markup. RDoc is an application that
-# produces documentation for one or more Ruby source files. We work similarly
+# produces documentation for one or more Ruby source files. It works similarly
# to JavaDoc, parsing the source, and extracting the definition for classes,
-# modules, and methods (along with includes and requires). We associate with
+# modules, and methods (along with includes and requires). It associates with
# these optional documentation contained in the immediately preceding comment
-# block, and then render the result using a pluggable output formatter.
+# block, and then renders the result using a pluggable output formatter.
# RDoc::Markup is a library that converts plain text into various output
# formats. The markup library is used to interpret the comment blocks that
# RDoc uses to document methods, classes, and so on.
@@ -18,8 +18,6 @@ $DEBUG_RDOC = nil
# * If you want to use RDoc to create documentation for your Ruby source files,
# read on.
# * If you want to include extensions written in C, see RDoc::Parser::C
-# * For information on the various markups available in comment blocks, see
-# RDoc::Markup.
# * If you want to drive RDoc programmatically, see RDoc::RDoc.
# * If you want to use the library to format text blocks into HTML, have a look
# at RDoc::Markup.
@@ -28,21 +26,21 @@ $DEBUG_RDOC = nil
#
# == Summary
#
-# Once installed, you can create documentation using the 'rdoc' command
-# (the command is 'rdoc.bat' under Windows)
+# Once installed, you can create documentation using the +rdoc+ command
#
# % rdoc [options] [names...]
#
-# Type "rdoc --help" for an up-to-date option summary.
+# For an up-to-date option summary, type
+# % rdoc --help
#
# A typical use might be to generate documentation for a package of Ruby
-# source (such as rdoc itself).
+# source (such as RDoc itself).
#
# % rdoc
#
# This command generates documentation for all the Ruby and C source
# files in and below the current directory. These will be stored in a
-# documentation tree starting in the subdirectory 'doc'.
+# documentation tree starting in the subdirectory +doc+.
#
# You can make this slightly more useful for your readers by having the
# index page contain the documentation for the primary file. In our
@@ -54,20 +52,46 @@ $DEBUG_RDOC = nil
# in comment blocks in the documentation this generates.
#
# RDoc uses file extensions to determine how to process each file. File names
-# ending +.rb+ and <tt>.rbw</tt> are assumed to be Ruby source. Files
+# ending +.rb+ and +.rbw+ are assumed to be Ruby source. Files
# ending +.c+ are parsed as C files. All other files are assumed to
# contain just Markup-style markup (with or without leading '#' comment
# markers). If directory names are passed to RDoc, they are scanned
# recursively for C and Ruby source files only.
#
-# = Markup
+# == \Options
+# rdoc can be passed a variety of command-line options. In addition,
+# options can be specified via the +RDOCOPT+ environment variable, which
+# functions similarly to the +RUBYOPT+ environment variable.
#
-# For information on how to make lists, hyperlinks, etc. with RDoc, see
-# RDoc::Markup.
+# % export RDOCOPT="-S"
#
-# Comment blocks can be written fairly naturally, either using '#' on
+# will make rdoc default to inline method source code. Command-line options
+# always will override those in +RDOCOPT+.
+#
+# Run
+#
+# % rdoc --help
+#
+# for full details on rdoc's options.
+#
+# Here are some of the most commonly used options.
+# [-d, --diagram]
+# Generate diagrams showing modules and
+# classes. You need dot V1.8.6 or later to
+# use the --diagram option correctly. Dot is
+# available from http://graphviz.org
+#
+# [-S, --inline-source]
+# Show method source code inline, rather than via a popup link.
+#
+# [-T, --template=NAME]
+# Set the template used when generating output.
+#
+# == Documenting Source Code
+#
+# Comment blocks can be written fairly naturally, either using +#+ on
# successive lines of the comment, or by including the comment in
-# an =begin/=end block. If you use the latter form, the =begin line must be
+# a =begin/=end block. If you use the latter form, the =begin line must be
# flagged with an RDoc tag:
#
# =begin rdoc
@@ -93,7 +117,7 @@ $DEBUG_RDOC = nil
# # ...
# end
#
-# Names of classes, source files, and any method names containing an
+# Names of classes, files, and any method names containing an
# underscore or preceded by a hash character are automatically hyperlinked
# from comment text to their description.
#
@@ -124,15 +148,109 @@ $DEBUG_RDOC = nil
# +:yields:+ is an example of a documentation directive. These appear
# immediately after the start of the document element they are modifying.
#
+# == \Markup
+#
+# * The markup engine looks for a document's natural left margin. This is
+# used as the initial margin for the document.
+#
+# * Consecutive lines starting at this margin are considered to be a
+# paragraph.
+#
+# * If a paragraph starts with a "*", "-", or with "<digit>.", then it is
+# taken to be the start of a list. The margin in increased to be the first
+# non-space following the list start flag. Subsequent lines should be
+# indented to this new margin until the list ends. For example:
+#
+# * this is a list with three paragraphs in
+# the first item. This is the first paragraph.
+#
+# And this is the second paragraph.
+#
+# 1. This is an indented, numbered list.
+# 2. This is the second item in that list
+#
+# This is the third conventional paragraph in the
+# first list item.
+#
+# * This is the second item in the original list
+#
+# * You can also construct labeled lists, sometimes called description
+# or definition lists. Do this by putting the label in square brackets
+# and indenting the list body:
+#
+# [cat] a small furry mammal
+# that seems to sleep a lot
+#
+# [ant] a little insect that is known
+# to enjoy picnics
+#
+# A minor variation on labeled lists uses two colons to separate the
+# label from the list body:
+#
+# cat:: a small furry mammal
+# that seems to sleep a lot
+#
+# ant:: a little insect that is known
+# to enjoy picnics
+#
+# This latter style guarantees that the list bodies' left margins are
+# aligned: think of them as a two column table.
+#
+# * Any line that starts to the right of the current margin is treated
+# as verbatim text. This is useful for code listings. The example of a
+# list above is also verbatim text.
+#
+# * A line starting with an equals sign (=) is treated as a
+# heading. Level one headings have one equals sign, level two headings
+# have two,and so on.
+#
+# * A line starting with three or more hyphens (at the current indent)
+# generates a horizontal rule. The more hyphens, the thicker the rule
+# (within reason, and if supported by the output device)
+#
+# * You can use markup within text (except verbatim) to change the
+# appearance of parts of that text. Out of the box, RDoc::Markup
+# supports word-based and general markup.
+#
+# Word-based markup uses flag characters around individual words:
+#
+# [\*word*] displays word in a *bold* font
+# [\_word_] displays word in an _emphasized_ font
+# [\+word+] displays word in a +code+ font
+#
+# General markup affects text between a start delimiter and and end
+# delimiter. Not surprisingly, these delimiters look like HTML markup.
+#
+# [\<b>text...</b>] displays word in a *bold* font
+# [\<em>text...</em>] displays word in an _emphasized_ font
+# [\\<i>text...</i>] displays word in an <i>italicized</i> font
+# [\<tt>text...</tt>] displays word in a +code+ font
+#
+# Unlike conventional Wiki markup, general markup can cross line
+# boundaries. You can turn off the interpretation of markup by
+# preceding the first character with a backslash. This only works for
+# simple markup, not HTML-style markup.
+#
+# * Hyperlinks to the web starting http:, mailto:, ftp:, or www. are
+# recognized. An HTTP url that references an external image file is
+# converted into an inline <IMG..>. Hyperlinks starting 'link:' are
+# assumed to refer to local files whose path is relative to the --op
+# directory.
+#
+# Hyperlinks can also be of the form <tt>label</tt>[url], in which
+# case the label is used in the displayed text, and +url+ is
+# used as the target. If +label+ contains multiple words,
+# put it in braces: <em>{multi word label}[</em>url<em>]</em>.
+#
# == Directives
#
# [+:nodoc:+ / +:nodoc:+ all]
-# Don't include this element in the documentation. For classes
-# and modules, the methods, aliases, constants, and attributes
-# directly within the affected class or module will also be
-# omitted. By default, though, modules and classes within that
-# class of module _will_ be documented. This is turned off by
-# adding the +all+ modifier.
+# This directive prevents documentation for the element from
+# being generated. For classes and modules, the methods, aliases,
+# constants, and attributes directly within the affected class or
+# module also will be omitted. By default, though, modules and
+# classes within that class of module _will_ be documented. This is
+# turned off by adding the +all+ modifier.
#
# module MyModule # :nodoc:
# class Input
@@ -144,22 +262,22 @@ $DEBUG_RDOC = nil
# end
# end
#
-# In the above code, only class +MyModule::Input+ will be documented.The
-# The :nodoc: directive is global across all files the class or module
-# appears in, so use :stopdoc:/:startdoc: to only omit documentation for a
-# particular set of methods, etc.
+# In the above code, only class <tt>MyModule::Input</tt> will be documented.
+# The +:nodoc:+ directive is global across all files for the class or module
+# to which it applies, so use +:stopdoc:+/+:startdoc:+ to suppress
+# documentation only for a particular set of methods, etc.
#
# [+:doc:+]
-# Force a method or attribute to be documented even if it wouldn't otherwise
-# be. Useful if, for example, you want to include documentation of a
+# Forces a method or attribute to be documented even if it wouldn't be
+# otherwise. Useful if, for example, you want to include documentation of a
# particular private method.
#
# [+:notnew:+]
# Only applicable to the +initialize+ instance method. Normally RDoc
-# assumes that the documentation and parameters for #initialize are
-# actually for the ::new method, and so fakes out a ::new for the class.
-# The :notnew: modifier stops this. Remember that #initialize is protected,
-# so you won't see the documentation unless you use the -a command line
+# assumes that the documentation and parameters for +initialize+ are
+# actually for the +new+ method, and so fakes out a +new+ for the class.
+# The +:notnew:+ modifier stops this. Remember that +initialize+ is private,
+# so you won't see the documentation unless you use the +-a+ command line
# option.
#
# Comment blocks can contain other directives:
@@ -209,7 +327,7 @@ $DEBUG_RDOC = nil
# last. If you don't specify a +:startdoc:+ by the end of the container,
# disables documentation for the entire class or module.
#
-# = Other stuff
+# == Other stuff
#
# RDoc is currently being maintained by Eric Hodel <drbrain@segment7.net>
#
@@ -254,7 +372,7 @@ module RDoc
##
# RDoc version you are using
- VERSION = "2.1.0"
+ VERSION = "2.2.2"
##
# Name of the dotfile that contains the description of files to be processed
diff --git a/lib/rdoc/code_objects.rb b/lib/rdoc/code_objects.rb
index fbdb612b92..0916b03398 100644
--- a/lib/rdoc/code_objects.rb
+++ b/lib/rdoc/code_objects.rb
@@ -220,6 +220,22 @@ module RDoc
end
##
+ # return the classes Hash (only to be used internally)
+
+ def classes_hash
+ @classes
+ end
+ protected :classes_hash
+
+ ##
+ # return the modules Hash (only to be used internally)
+
+ def modules_hash
+ @modules
+ end
+ protected :modules_hash
+
+ ##
# Change the default visibility for new methods
def ongoing_visibility=(vis)
@@ -272,7 +288,24 @@ module RDoc
end
def add_class(class_type, name, superclass)
- add_class_or_module @classes, class_type, name, superclass
+ klass = add_class_or_module @classes, class_type, name, superclass
+
+ #
+ # If the parser encounters Container::Item before encountering
+ # Container, then it assumes that Container is a module. This
+ # may not be the case, so remove Container from the module list
+ # if present and transfer any contained classes and modules to
+ # the new class.
+ #
+ mod = @modules.delete(name)
+
+ if mod then
+ klass.classes_hash.update(mod.classes_hash)
+ klass.modules_hash.update(mod.modules_hash)
+ klass.method_list.concat(mod.method_list)
+ end
+
+ return klass
end
def add_module(class_type, name)
@@ -282,25 +315,41 @@ module RDoc
def add_method(a_method)
a_method.visibility = @visibility
add_to(@method_list, a_method)
+
+ unmatched_alias_list = @unmatched_alias_lists[a_method.name]
+ if unmatched_alias_list then
+ unmatched_alias_list.each do |unmatched_alias|
+ add_alias_impl unmatched_alias, a_method
+ @aliases.delete unmatched_alias
+ end
+
+ @unmatched_alias_lists.delete a_method.name
+ end
end
def add_attribute(an_attribute)
add_to(@attributes, an_attribute)
end
+ def add_alias_impl(an_alias, meth)
+ new_meth = AnyMethod.new(an_alias.text, an_alias.new_name)
+ new_meth.is_alias_for = meth
+ new_meth.singleton = meth.singleton
+ new_meth.params = meth.params
+ new_meth.comment = "Alias for \##{meth.name}"
+ meth.add_alias(new_meth)
+ add_method(new_meth)
+ end
+
def add_alias(an_alias)
meth = find_instance_method_named(an_alias.old_name)
if meth then
- new_meth = AnyMethod.new(an_alias.text, an_alias.new_name)
- new_meth.is_alias_for = meth
- new_meth.singleton = meth.singleton
- new_meth.params = meth.params
- new_meth.comment = "Alias for \##{meth.name}"
- meth.add_alias(new_meth)
- add_method(new_meth)
+ add_alias_impl(an_alias, meth)
else
add_to(@aliases, an_alias)
+ unmatched_alias_list = @unmatched_alias_lists[an_alias.old_name] ||= []
+ unmatched_alias_list.push(an_alias)
end
an_alias
@@ -360,6 +409,10 @@ module RDoc
@requires = []
@includes = []
@constants = []
+
+ # This Hash maps a method name to a list of unmatched
+ # aliases (aliases of a method not yet encountered).
+ @unmatched_alias_lists = {}
end
# and remove classes and modules when we see a :nodoc: all
@@ -374,9 +427,12 @@ module RDoc
# Find a named module
def find_module_named(name)
- return self if self.name == name
+ # First check the enclosed modules, then check the module itself,
+ # then check the enclosing modules (this mirrors the check done by
+ # the Ruby parser)
res = @modules[name] || @classes[name]
return res if res
+ return self if self.name == name
find_enclosing_module_named(name)
end
@@ -435,6 +491,7 @@ module RDoc
unless modules.empty? then
module_name = modules.shift
result = find_module_named(module_name)
+
if result then
modules.each do |name|
result = result.find_module_named(name)
@@ -573,9 +630,18 @@ module RDoc
cls = all[name]
- unless cls then
+ if !cls then
cls = class_type.new name, superclass
all[name] = cls unless @done_documenting
+ else
+ # If the class has been encountered already, check that its
+ # superclass has been set (it may not have been, depending on
+ # the context in which it was encountered).
+ if class_type == NormalClass
+ if !cls.superclass then
+ cls.superclass = superclass
+ end
+ end
end
collection[name] = cls unless @done_documenting
diff --git a/lib/rdoc/diagram.rb b/lib/rdoc/diagram.rb
index e235e043dc..4aa2ec5656 100644
--- a/lib/rdoc/diagram.rb
+++ b/lib/rdoc/diagram.rb
@@ -311,28 +311,30 @@ module RDoc
# inclusion on the page
def wrap_in_image_map(src, dot)
- res = %{<map id="map" name="map">\n}
+ res = ""
dot_map = `dot -Tismap #{src}`
- dot_map.split($/).each do |area|
- unless area =~ /^rectangle \((\d+),(\d+)\) \((\d+),(\d+)\) ([\/\w.]+)\s*(.*)/
- $stderr.puts "Unexpected output from dot:\n#{area}"
- return nil
- end
+
+ if(!dot_map.empty?)
+ res << %{<map id="map" name="map">\n}
+ dot_map.split($/).each do |area|
+ unless area =~ /^rectangle \((\d+),(\d+)\) \((\d+),(\d+)\) ([\/\w.]+)\s*(.*)/
+ $stderr.puts "Unexpected output from dot:\n#{area}"
+ return nil
+ end
- xs, ys = [$1.to_i, $3.to_i], [$2.to_i, $4.to_i]
- url, area_name = $5, $6
+ xs, ys = [$1.to_i, $3.to_i], [$2.to_i, $4.to_i]
+ url, area_name = $5, $6
- res << %{ <area shape="rect" coords="#{xs.min},#{ys.min},#{xs.max},#{ys.max}" }
- res << %{ href="#{url}" alt="#{area_name}" />\n}
+ res << %{ <area shape="rect" coords="#{xs.min},#{ys.min},#{xs.max},#{ys.max}" }
+ res << %{ href="#{url}" alt="#{area_name}" />\n}
+ end
+ res << "</map>\n"
end
- res << "</map>\n"
-# map_file = src.sub(/.dot/, '.map')
-# system("dot -Timap #{src} -o #{map_file}")
- res << %{<img src="#{dot}" usemap="#map" border="0" alt="#{dot}">}
+
+ res << %{<img src="#{dot}" usemap="#map" alt="#{dot}" />}
return res
end
end
end
-
diff --git a/lib/rdoc/generator.rb b/lib/rdoc/generator.rb
index fbc08c4e20..d695e661d1 100644
--- a/lib/rdoc/generator.rb
+++ b/lib/rdoc/generator.rb
@@ -127,7 +127,7 @@ module RDoc::Generator
# * a complete list of all hyperlinkable terms (file, class, module, and
# method names)
- def self.build_indicies(toplevels, options)
+ def self.build_indices(toplevels, options)
files = []
classes = []
@@ -215,7 +215,7 @@ module RDoc::Generator
@methods.sort.map do |meth|
{
"name" => CGI.escapeHTML(meth.name),
- "aref" => "#{path_prefix}\##{meth.aref}"
+ "aref" => "##{meth.aref}"
}
end
end
@@ -614,9 +614,9 @@ module RDoc::Generator
def class_attribute_values
h_name = CGI.escapeHTML(name)
- @values["path"] = @path
+ @values["href"] = @path
@values["classmod"] = @is_module ? "Module" : "Class"
- @values["title"] = "#{@values['classmod']}: #{h_name}"
+ @values["title"] = "#{@values['classmod']}: #{h_name} [#{@options.title}]"
c = @context
c = c.parent while c and not c.diagram
@@ -704,7 +704,7 @@ module RDoc::Generator
def filename_to_label
@context.file_relative_name.gsub(/%|\/|\?|\#/) do
- '%%%x' % $&[0].unpack('C')
+ ('%%%x' % $&[0]).unpack('C')
end
end
@@ -791,7 +791,7 @@ module RDoc::Generator
full_path = @context.file_absolute_name
short_name = ::File.basename full_path
- @values["title"] = CGI.escapeHTML("File: #{short_name}")
+ @values["title"] = CGI.escapeHTML("File: #{short_name} [#{@options.title}]")
if @context.diagram then
@values["diagram"] = diagram_reference(@context.diagram)
@@ -821,18 +821,18 @@ module RDoc::Generator
attr_reader :img_url
attr_reader :source_code
- @@seq = "M000000"
-
- @@all_methods = []
-
def self.all_methods
@@all_methods
end
def self.reset
@@all_methods = []
+ @@seq = "M000000"
end
+ # Initialize the class variables.
+ self.reset
+
def initialize(context, html_class, options)
# TODO: rethink the class hierarchy here...
@context = context
@@ -1043,12 +1043,18 @@ module RDoc::Generator
first = $1.to_i - 1
last = first + src.count("\n")
size = last.to_s.length
- real_fmt = "%#{size}d: "
- fmt = " " * (size+2)
+ fmt = "%#{size}d: "
+ is_first_line = true
+ line_num = first
src.gsub!(/^/) do
- res = sprintf(fmt, first)
- first += 1
- fmt = real_fmt
+ if is_first_line then
+ is_first_line = false
+ res = " " * (size+2)
+ else
+ res = sprintf(fmt, line_num)
+ end
+
+ line_num += 1
res
end
end
diff --git a/lib/rdoc/generator/chm/chm.rb b/lib/rdoc/generator/chm/chm.rb
index 0a17a9e1ea..cceeca5dfc 100644
--- a/lib/rdoc/generator/chm/chm.rb
+++ b/lib/rdoc/generator/chm/chm.rb
@@ -6,6 +6,8 @@ module RDoc::Generator::CHM::CHM
HTML = RDoc::Generator::HTML::HTML
INDEX = HTML::INDEX
+
+ STYLE = HTML::STYLE
CLASS_INDEX = HTML::CLASS_INDEX
CLASS_PAGE = HTML::CLASS_PAGE
diff --git a/lib/rdoc/generator/html.rb b/lib/rdoc/generator/html.rb
index a9e030a896..d136de7b00 100644
--- a/lib/rdoc/generator/html.rb
+++ b/lib/rdoc/generator/html.rb
@@ -68,7 +68,6 @@ class RDoc::Generator::HTML
def initialize(options) #:not-new:
@options = options
load_html_template
- @main_page_path = nil
end
##
@@ -94,6 +93,15 @@ class RDoc::Generator::HTML
# If the template name contains a slash, use it literally
def load_html_template
+ #
+ # If the template is not a path, first look for it
+ # in rdoc's HTML template directory. Perhaps this behavior should
+ # be reversed (first try to include the template and, only if that
+ # fails, try to include it in the default template directory).
+ # One danger with reversing the behavior, however, is that
+ # if something like require 'html' could load up an
+ # unrelated file in the standard library or in a gem.
+ #
template = @options.template
unless template =~ %r{/|\\} then
@@ -101,14 +109,25 @@ class RDoc::Generator::HTML
template)
end
- require template
-
- @template = self.class.const_get @options.template.upcase
- @options.template_class = @template
+ begin
+ require template
+
+ @template = self.class.const_get @options.template.upcase
+ @options.template_class = @template
+ rescue LoadError => e
+ #
+ # The template did not exist in the default template directory, so
+ # see if require can find the template elsewhere (in a gem, for
+ # instance).
+ #
+ if(e.message[template] && template != @options.template)
+ template = @options.template
+ retry
+ end
- rescue LoadError
- $stderr.puts "Could not find HTML template '#{template}'"
- exit 99
+ $stderr.puts "Could not find HTML template '#{template}': #{e.message}"
+ exit 99
+ end
end
##
@@ -146,14 +165,16 @@ class RDoc::Generator::HTML
end
def build_indices
- @files, @classes = RDoc::Generator::Context.build_indicies(@toplevels,
- @options)
+ @files, @classes = RDoc::Generator::Context.build_indices(@toplevels,
+ @options)
end
##
# Generate all the HTML
def generate_html
+ @main_url = main_url
+
# the individual descriptions for files and classes
gen_into(@files)
gen_into(@classes)
@@ -165,23 +186,50 @@ class RDoc::Generator::HTML
gen_main_index
# this method is defined in the template file
- write_extra_pages if defined? write_extra_pages
+ values = {
+ 'title_suffix' => CGI.escapeHTML("[#{@options.title}]"),
+ 'charset' => @options.charset,
+ 'style_url' => style_url('', @options.css),
+ }
+
+ @template.write_extra_pages(values) if @template.respond_to?(:write_extra_pages)
end
def gen_into(list)
- @file_list ||= index_to_links @files
- @class_list ||= index_to_links @classes
- @method_list ||= index_to_links RDoc::Generator::Method.all_methods
+ #
+ # The file, class, and method lists technically should be regenerated
+ # for every output file, in order that the relative links be correct
+ # (we are worried here about frameless templates, which need this
+ # information for every generated page). Doing this is a bit slow,
+ # however. For a medium-sized gem, this increased rdoc's runtime by
+ # about 5% (using the 'time' command-line utility). While this is not
+ # necessarily a problem, I do not want to pessimize rdoc for large
+ # projects, however, and so we only regenerate the lists when the
+ # directory of the output file changes, which seems like a reasonable
+ # optimization.
+ #
+ file_list = {}
+ class_list = {}
+ method_list = {}
+ prev_op_dir = nil
list.each do |item|
next unless item.document_self
op_file = item.path
+ op_dir = File.dirname(op_file)
+
+ if(op_dir != prev_op_dir)
+ file_list = index_to_links op_file, @files
+ class_list = index_to_links op_file, @classes
+ method_list = index_to_links op_file, RDoc::Generator::Method.all_methods
+ end
+ prev_op_dir = op_dir
- FileUtils.mkdir_p File.dirname(op_file)
+ FileUtils.mkdir_p op_dir
open op_file, 'w' do |io|
- item.write_on io, @file_list, @class_list, @method_list
+ item.write_on io, file_list, class_list, method_list
end
end
end
@@ -211,8 +259,9 @@ class RDoc::Generator::HTML
values = {
"entries" => res,
+ 'title' => CGI.escapeHTML("#{title} [#{@options.title}]"),
'list_title' => CGI.escapeHTML(title),
- 'index_url' => main_url,
+ 'index_url' => @main_url,
'charset' => @options.charset,
'style_url' => style_url('', @options.css),
}
@@ -230,47 +279,55 @@ class RDoc::Generator::HTML
def gen_main_index
if @template.const_defined? :FRAMELESS then
- main = @files.find do |file|
- @main_page == file.name
- end
-
- if main.nil? then
- main = @classes.find do |klass|
- main_page == klass.context.full_name
- end
+ #
+ # If we're using a template without frames, then just redirect
+ # to it from index.html.
+ #
+ # One alternative to this, expanding the main page's template into
+ # index.html, is tricky because the relative URLs will be different
+ # (since index.html is located in at the site's root,
+ # rather than within a files or a classes subdirectory).
+ #
+ open 'index.html', 'w' do |f|
+ f.puts(%{<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">})
+ f.puts(%{<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
+ lang="en">})
+ f.puts(%{<head>})
+ f.puts(%{<title>#{CGI.escapeHTML(@options.title)}</title>})
+ f.puts(%{<meta http-equiv="refresh" content="0; url=#{@main_url}" />})
+ f.puts(%{</head>})
+ f.puts(%{<body></body>})
+ f.puts(%{</html>})
end
else
main = RDoc::TemplatePage.new @template::INDEX
- end
- open 'index.html', 'w' do |f|
- style_url = style_url '', @options.css
+ open 'index.html', 'w' do |f|
+ style_url = style_url '', @options.css
+
+ classes = @classes.sort.map { |klass| klass.value_hash }
+
+ values = {
+ 'initial_page' => @main_url,
+ 'style_url' => style_url('', @options.css),
+ 'title' => CGI.escapeHTML(@options.title),
+ 'charset' => @options.charset,
+ 'classes' => classes,
+ }
+
+ values['inline_source'] = @options.inline_source
- classes = @classes.sort.map { |klass| klass.value_hash }
-
- values = {
- 'main_page' => @main_page,
- 'initial_page' => main_url,
- 'style_url' => style_url('', @options.css),
- 'title' => CGI.escapeHTML(@options.title),
- 'charset' => @options.charset,
- 'classes' => classes,
- }
-
- values['inline_source'] = @options.inline_source
-
- if main.respond_to? :write_on then
- main.write_on f, @file_list, @class_list, @method_list, values
- else
main.write_html_on f, values
end
end
end
- def index_to_links(collection)
+ def index_to_links(output_path, collection)
collection.sort.map do |f|
next unless f.document_self
- { "href" => f.path, "name" => f.index_name }
+ { "href" => RDoc::Markup::ToHtml.gen_relative_url(output_path, f.path),
+ "name" => f.index_name }
end.compact
end
@@ -278,32 +335,48 @@ class RDoc::Generator::HTML
# Returns the url of the main page
def main_url
- @main_page = @options.main_page
- @main_page_ref = nil
-
- if @main_page then
- @main_page_ref = RDoc::Generator::AllReferences[@main_page]
-
- if @main_page_ref then
- @main_page_path = @main_page_ref.path
+ main_page = @options.main_page
+
+ #
+ # If a main page has been specified (--main), then search for it
+ # in the AllReferences array. This allows either files or classes
+ # to be used for the main page.
+ #
+ if main_page then
+ main_page_ref = RDoc::Generator::AllReferences[main_page]
+
+ if main_page_ref then
+ return main_page_ref.path
else
- $stderr.puts "Could not find main page #{@main_page}"
+ $stderr.puts "Could not find main page #{main_page}"
end
end
- unless @main_page_path then
- file = @files.find { |context| context.document_self }
- @main_page_path = file.path if file
+ #
+ # No main page has been specified, so just use the README.
+ #
+ @files.each do |file|
+ if file.name =~ /^README/ then
+ return file.path
+ end
end
- unless @main_page_path then
- $stderr.puts "Couldn't find anything to document"
- $stderr.puts "Perhaps you've used :stopdoc: in all classes"
- exit 1
+ #
+ # There's no README (shame! shame!). Just use the first file
+ # that will be documented.
+ #
+ @files.each do |file|
+ if file.document_self then
+ return file.path
+ end
end
- @main_page_path
+ #
+ # There are no files to be documented... Something seems very wrong.
+ #
+ raise RDoc::Error, "Couldn't find anything to document (perhaps :stopdoc: has been used in all classes)!"
end
+ private :main_url
end
@@ -349,12 +422,9 @@ class RDoc::Generator::HTMLInOne < RDoc::Generator::HTML
'charset' => @options.charset,
'files' => gen_into(@files),
'classes' => gen_into(@classes),
- 'title' => CGI.escapeHTML(@options.title),
+ 'title' => CGI.escapeHTML(@options.title),
}
- # this method is defined in the template file
- write_extra_pages if defined? write_extra_pages
-
template = RDoc::TemplatePage.new @template::ONE_PAGE
if @options.op_name
@@ -372,26 +442,4 @@ class RDoc::Generator::HTMLInOne < RDoc::Generator::HTML
end
res
end
-
- def gen_file_index
- gen_an_index(@files, 'Files')
- end
-
- def gen_class_index
- gen_an_index(@classes, 'Classes')
- end
-
- def gen_method_index
- gen_an_index(RDoc::Generator::Method.all_methods, 'Methods')
- end
-
- def gen_an_index(collection, title)
- return {
- "entries" => index_to_links(collection),
- 'list_title' => title,
- 'index_url' => main_url,
- }
- end
-
end
-
diff --git a/lib/rdoc/generator/html/common.rb b/lib/rdoc/generator/html/common.rb
new file mode 100644
index 0000000000..b25f009a72
--- /dev/null
+++ b/lib/rdoc/generator/html/common.rb
@@ -0,0 +1,24 @@
+#
+# The templates require further refactoring. In particular,
+# * Some kind of HTML generation library should be used.
+#
+# Also, all of the templates require some TLC from a designer.
+#
+# Right now, this file contains some constants that are used by all
+# of the templates.
+#
+module RDoc::Generator::HTML::Common
+ XHTML_STRICT_PREAMBLE = <<-EOF
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+EOF
+
+ XHTML_FRAME_PREAMBLE = <<-EOF
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
+EOF
+
+ HTML_ELEMENT = <<-EOF
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+EOF
+end
diff --git a/lib/rdoc/generator/html/frameless.rb b/lib/rdoc/generator/html/frameless.rb
index 2af890ce04..0375fee313 100644
--- a/lib/rdoc/generator/html/frameless.rb
+++ b/lib/rdoc/generator/html/frameless.rb
@@ -1,15 +1,16 @@
-require 'rdoc/generator/html'
-require 'rdoc/generator/html/one_page_html'
+require 'rdoc/generator/html/html'
##
# = CSS2 RDoc HTML template
#
-# This is a template for RDoc that uses XHTML 1.0 Transitional and dictates a
+# This is a template for RDoc that uses XHTML 1.0 Strict and dictates a
# bit more of the appearance of the output to cascading stylesheets than the
# default. It was designed for clean inline code display, and uses DHTMl to
# toggle the visbility of each method's source with each click on the '[source]'
# link.
#
+# Frameless basically is the html template without frames.
+#
# == Authors
#
# * Michael Granger <ged@FaerieMUD.org>
@@ -25,692 +26,47 @@ module RDoc::Generator::HTML::FRAMELESS
FRAMELESS = true
- FONTS = "Verdana,Arial,Helvetica,sans-serif"
-
- STYLE = <<-EOF
-body {
- font-family: #{FONTS};
- font-size: 90%;
- margin: 0;
- margin-left: 40px;
- padding: 0;
- background: white;
-}
-
-h1, h2, h3, h4 {
- margin: 0;
- color: #efefef;
- background: transparent;
-}
-
-h1 {
- font-size: 150%;
-}
-
-h2,h3,h4 {
- margin-top: 1em;
-}
-
-:link, :visited {
- background: #eef;
- color: #039;
- text-decoration: none;
-}
-
-:link:hover, :visited:hover {
- background: #039;
- color: #eef;
-}
-
-/* Override the base stylesheet's Anchor inside a table cell */
-td > :link, td > :visited {
- background: transparent;
- color: #039;
- text-decoration: none;
-}
-
-/* and inside a section title */
-.section-title > :link, .section-title > :visited {
- background: transparent;
- color: #eee;
- text-decoration: none;
-}
-
-/* === Structural elements =================================== */
-
-.index {
- margin: 0;
- margin-left: -40px;
- padding: 0;
- font-size: 90%;
-}
-
-.index :link, .index :visited {
- margin-left: 0.7em;
-}
-
-.index .section-bar {
- margin-left: 0px;
- padding-left: 0.7em;
- background: #ccc;
- font-size: small;
-}
-
-#classHeader, #fileHeader {
- width: auto;
- color: white;
- padding: 0.5em 1.5em 0.5em 1.5em;
- margin: 0;
- margin-left: -40px;
- border-bottom: 3px solid #006;
-}
-
-#classHeader :link, #fileHeader :link,
-#classHeader :visited, #fileHeader :visited {
- background: inherit;
- color: white;
-}
-
-#classHeader td, #fileHeader td {
- background: inherit;
- color: white;
-}
-
-#fileHeader {
- background: #057;
-}
-
-#classHeader {
- background: #048;
-}
-
-.class-name-in-header {
- font-size: 180%;
- font-weight: bold;
-}
-
-#bodyContent {
- padding: 0 1.5em 0 1.5em;
-}
-
-#description {
- padding: 0.5em 1.5em;
- background: #efefef;
- border: 1px dotted #999;
-}
-
-#description h1, #description h2, #description h3,
-#description h4, #description h5, #description h6 {
- color: #125;
- background: transparent;
-}
-
-#copyright {
- color: #333;
- background: #efefef;
- font: 0.75em sans-serif;
- margin-top: 5em;
- margin-bottom: 0;
- padding: 0.5em 2em;
-}
-
-/* === Classes =================================== */
-
-table.header-table {
- color: white;
- font-size: small;
-}
-
-.type-note {
- font-size: small;
- color: #dedede;
-}
-
-.xxsection-bar {
- background: #eee;
- color: #333;
- padding: 3px;
-}
-
-.section-bar {
- color: #333;
- border-bottom: 1px solid #999;
- margin-left: -20px;
-}
-
-.section-title {
- background: #79a;
- color: #eee;
- padding: 3px;
- margin-top: 2em;
- margin-left: -30px;
- border: 1px solid #999;
-}
-
-.top-aligned-row {
- vertical-align: top
-}
-
-.bottom-aligned-row {
- vertical-align: bottom
-}
-
-/* --- Context section classes ----------------------- */
-
-.context-row { }
-
-.context-item-name {
- font-family: monospace;
- font-weight: bold;
- color: black;
-}
-
-.context-item-value {
- font-size: small;
- color: #448;
-}
-
-.context-item-desc {
- color: #333;
- padding-left: 2em;
-}
-
-/* --- Method classes -------------------------- */
-
-.method-detail {
- background: #efefef;
- padding: 0;
- margin-top: 0.5em;
- margin-bottom: 1em;
- border: 1px dotted #ccc;
-}
-
-.method-heading {
- color: black;
- background: #ccc;
- border-bottom: 1px solid #666;
- padding: 0.2em 0.5em 0 0.5em;
-}
-
-.method-signature {
- color: black;
- background: inherit;
-}
-
-.method-name {
- font-weight: bold;
-}
-
-.method-args {
- font-style: italic;
-}
+ FONTS = RDoc::Generator::HTML::HTML::FONTS
-.method-description {
- padding: 0 0.5em 0 0.5em;
-}
+ STYLE = RDoc::Generator::HTML::HTML::STYLE
-/* --- Source code sections -------------------- */
-
-:link.source-toggle, :visited.source-toggle {
- font-size: 90%;
-}
-
-div.method-source-code {
- background: #262626;
- color: #ffdead;
- margin: 1em;
- padding: 0.5em;
- border: 1px dashed #999;
- overflow: hidden;
-}
-
-div.method-source-code pre {
- color: #ffdead;
- overflow: hidden;
-}
-
-/* --- Ruby keyword styles --------------------- */
-
-.standalone-code {
- background: #221111;
- color: #ffdead;
- overflow: hidden;
-}
-
-.ruby-constant {
- color: #7fffd4;
- background: transparent;
-}
-
-.ruby-keyword {
- color: #00ffff;
- background: transparent;
-}
-
-.ruby-ivar {
- color: #eedd82;
- background: transparent;
-}
-
-.ruby-operator {
- color: #00ffee;
- background: transparent;
-}
-
-.ruby-identifier {
- color: #ffdead;
- background: transparent;
-}
-
-.ruby-node {
- color: #ffa07a;
- background: transparent;
-}
-
-.ruby-comment {
- color: #b22222;
- font-weight: bold;
- background: transparent;
-}
-
-.ruby-regexp {
- color: #ffa07a;
- background: transparent;
-}
-
-.ruby-value {
- color: #7fffd4;
- background: transparent;
-}
-
-EOF
-
- ##
- # Header template
-
- XHTML_PREAMBLE = <<-EOF
-<?xml version="1.0" encoding="<%= values["charset"] %>"?>
-<!DOCTYPE html
- PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
- EOF
-
- HEADER = XHTML_PREAMBLE + <<-EOF
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
- <title><%= values["title"] %></title>
- <meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>" />
- <meta http-equiv="Content-Script-Type" content="text/javascript" />
- <link rel="stylesheet" href="<%= values["style_url"] %>" type="text/css" media="screen" />
- <script type="text/javascript">
- // <![CDATA[
-
- function popupCode( url ) {
- window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
- }
-
- function toggleCode( id ) {
- if ( document.getElementById )
- elem = document.getElementById( id );
- else if ( document.all )
- elem = eval( "document.all." + id );
- else
- return false;
-
- elemStyle = elem.style;
-
- if ( elemStyle.display != "block" ) {
- elemStyle.display = "block"
- } else {
- elemStyle.display = "none"
- }
-
- return true;
- }
-
- // Make codeblocks hidden by default
- document.writeln( "<style type=\\"text/css\\">div.method-source-code { display: none }</style>" )
-
- // ]]>
- </script>
-
-</head>
-<body>
-EOF
-
- ##
- # Context content template
-
- CONTEXT_CONTENT = %{
-}
-
- ##
- # Footer template
+ HEADER = RDoc::Generator::HTML::HTML::HEADER
FOOTER = <<-EOF
<div id="popupmenu" class="index">
- <ul>
- <li class="index-entries section-bar">Classes
+ <br />
+ <h1 class="index-entries section-bar">Files</h1>
<ul>
-<% values["class_list"].each do |klass| %>
- <li><a href="<%= klass["href"] %>"><%= klass["name"] %></a>
+<% values["file_list"].each do |file| %>
+ <li><a href="<%= file["href"] %>"><%= file["name"] %></a></li>
<% end %>
</ul>
- </li>
- <li class="index-entries section-bar">Methods
+ <br />
+ <h1 class="index-entries section-bar">Classes</h1>
<ul>
-<% values["method_list"].each do |file| %>
- <li><a href="<%= file["href"] %>"><%= file["name"] %></a>
+<% values["class_list"].each do |klass| %>
+ <li><a href="<%= klass["href"] %>"><%= klass["name"] %></a></li>
<% end %>
</ul>
- </li>
- <li class="index-entries section-bar">Files
+ <br />
+ <h1 class="index-entries section-bar">Methods</h1>
<ul>
-<% values["file_list"].each do |file| %>
- <li><a href="<%= file["href"] %>"><%= file["name"] %></a>
+<% values["method_list"].each do |method| %>
+ <li><a href="<%= method["href"] %>"><%= method["name"] %></a></li>
<% end %>
</ul>
- </li>
- </ul>
- </li>
-
+ </div>
</body>
</html>
EOF
- ##
- # File page header template
-
- FILE_PAGE = <<-EOF
- <div id="fileHeader">
- <h1><%= values["short_name"] %></h1>
-
- <table class="header-table">
- <tr class="top-aligned-row">
- <td><strong>Path:</strong></td>
- <td><%= values["full_path"] %>
-<% if values["cvsurl"] then %>
- &nbsp;(<a href="<%= values["cvsurl"] %>"><acronym title="Concurrent Versioning System">CVS</acronym></a>)
-<% end %>
- </td>
- </tr>
-
- <tr class="top-aligned-row">
- <td><strong>Last Update:</strong></td>
- <td><%= values["dtm_modified"] %></td>
- </tr>
- </table>
- </div>
- EOF
-
- ##
- # Class page header template
-
- CLASS_PAGE = <<-EOF
- <div id="classHeader">
- <table class="header-table">
- <tr class="top-aligned-row">
- <td><strong><%= values["classmod"] %></strong></td>
- <td class="class-name-in-header"><%= values["full_name"] %></td>
- </tr>
-
- <tr class="top-aligned-row">
- <td><strong>In:</strong></td>
- <td>
-<% values["infiles"].each do |infiles| %>
-<% if infiles["full_path_url"] then %>
- <a href="<%= infiles["full_path_url"] %>">
-<% end %>
- <%= infiles["full_path"] %>
-<% if infiles["full_path_url"] then %>
- </a>
-<% end %>
-<% if infiles["cvsurl"] then %>
- &nbsp;(<a href="<%= infiles["cvsurl"] %>"><acronym title="Concurrent Versioning System">CVS</acronym></a>)
-<% end %>
- <br />
-<% end %><%# values["infiles"] %>
- </td>
- </tr>
-
-<% if values["parent"] then %>
- <tr class="top-aligned-row">
- <td><strong>Parent:</strong></td>
- <td>
-<% if values["par_url"] then %>
- <a href="<%= values["par_url"] %>">
-<% end %>
- <%= values["parent"] %>
-<% if values["par_url"] then %>
- </a>
-<% end %>
- </td>
- </tr>
-<% end %>
- </table>
- </div>
- EOF
-
- ##
- # Method list template
-
- METHOD_LIST = <<-EOF
-
- <div id="contextContent">
-<% if values["diagram"] then %>
- <div id="diagram">
- <%= values["diagram"] %>
- </div>
-<% end %>
-
-<% if values["description"] then %>
- <div id="description">
- <%= values["description"] %>
- </div>
-<% end %>
-
-<% if values["requires"] then %>
- <div id="requires-list">
- <h3 class="section-bar">Required files</h3>
-
- <div class="name-list">
-<% values["requires"].each do |requires| %>
- <%= href requires["aref"], requires["name"] %>&nbsp;&nbsp;
-<% end %><%# values["requires"] %>
- </div>
- </div>
-<% end %>
-
-<% if values["toc"] then %>
- <div id="contents-list">
- <h3 class="section-bar">Contents</h3>
- <ul>
-<% values["toc"].each do |toc| %>
- <li><a href="#<%= values["href"] %>"><%= values["secname"] %></a></li>
-<% end %><%# values["toc"] %>
- </ul>
-<% end %>
- </div>
-
-<% if values["methods"] then %>
- <div id="method-list">
- <h3 class="section-bar">Methods</h3>
+ FILE_PAGE = RDoc::Generator::HTML::HTML::FILE_PAGE
- <div class="name-list">
-<% values["methods"].each do |methods| %>
- <%= href methods["aref"], methods["name"] %>&nbsp;&nbsp;
-<% end %><%# values["methods"] %>
- </div>
- </div>
-<% end %>
+ CLASS_PAGE = RDoc::Generator::HTML::HTML::CLASS_PAGE
- </div>
-
-
- <!-- if includes -->
-<% if values["includes"] then %>
- <div id="includes">
- <h3 class="section-bar">Included Modules</h3>
-
- <div id="includes-list">
-<% values["includes"].each do |includes| %>
- <span class="include-name"><%= href includes["aref"], includes["name"] %></span>
-<% end %><%# values["includes"] %>
- </div>
- </div>
-<% end %>
-
-<% values["sections"].each do |sections| %>
- <div id="section">
-<% if sections["sectitle"] then %>
- <h2 class="section-title"><a name="<%= sections["secsequence"] %>"><%= sections["sectitle"] %></a></h2>
-<% if sections["seccomment"] then %>
- <div class="section-comment">
- <%= sections["seccomment"] %>
- </div>
-<% end %>
-<% end %>
-
-<% if values["classlist"] then %>
- <div id="class-list">
- <h3 class="section-bar">Classes and Modules</h3>
-
- <%= values["classlist"] %>
- </div>
-<% end %>
-
-<% if values["constants"] then %>
- <div id="constants-list">
- <h3 class="section-bar">Constants</h3>
-
- <div class="name-list">
- <table summary="Constants">
-<% values["constants"].each do |constants| %>
- <tr class="top-aligned-row context-row">
- <td class="context-item-name"><%= constants["name"] %></td>
- <td>=</td>
- <td class="context-item-value"><%= constants["value"] %></td>
-<% if values["desc"] then %>
- <td width="3em">&nbsp;</td>
- <td class="context-item-desc"><%= constants["desc"] %></td>
-<% end %>
- </tr>
-<% end %><%# values["constants"] %>
- </table>
- </div>
- </div>
-<% end %>
-
-<% if values["aliases"] then %>
- <div id="aliases-list">
- <h3 class="section-bar">External Aliases</h3>
-
- <div class="name-list">
- <table summary="aliases">
-<% values["aliases"].each do |aliases| $stderr.puts({ :aliases => aliases }.inspect) %>
- <tr class="top-aligned-row context-row">
- <td class="context-item-name"><%= values["old_name"] %></td>
- <td>-&gt;</td>
- <td class="context-item-value"><%= values["new_name"] %></td>
- </tr>
-<% if values["desc"] then %>
- <tr class="top-aligned-row context-row">
- <td>&nbsp;</td>
- <td colspan="2" class="context-item-desc"><%= values["desc"] %></td>
- </tr>
-<% end %>
-<% end %><%# values["aliases"] %>
- </table>
- </div>
- </div>
-<% end %>
-
-
-<% if values["attributes"] then %>
- <div id="attribute-list">
- <h3 class="section-bar">Attributes</h3>
-
- <div class="name-list">
- <table>
-<% values["attributes"].each do |attributes| $stderr.puts({ :attributes => attributes }.inspect) %>
- <tr class="top-aligned-row context-row">
- <td class="context-item-name"><%= values["name"] %></td>
-<% if values["rw"] then %>
- <td class="context-item-value">&nbsp;[<%= values["rw"] %>]&nbsp;</td>
-<% end %>
-<% unless values["rw"] then %>
- <td class="context-item-value">&nbsp;&nbsp;</td>
-<% end %>
- <td class="context-item-desc"><%= values["a_desc"] %></td>
- </tr>
-<% end %><%# values["attributes"] %>
- </table>
- </div>
- </div>
-<% end %>
-
- <!-- if method_list -->
-<% if sections["method_list"] then %>
- <div id="methods">
-<% sections["method_list"].each do |method_list| %>
-<% if method_list["methods"] then %>
- <h3 class="section-bar"><%= method_list["type"] %> <%= method_list["category"] %> methods</h3>
-
-<% method_list["methods"].each do |methods| %>
- <div id="method-<%= methods["aref"] %>" class="method-detail">
- <a name="<%= methods["aref"] %>"></a>
-
- <div class="method-heading">
-<% if methods["codeurl"] then %>
- <a href="<%= methods["codeurl"] %>" target="Code" class="method-signature"
- onclick="popupCode('<%= methods["codeurl"] %>');return false;">
-<% end %>
-<% if methods["sourcecode"] then %>
- <a href="#<%= methods["aref"] %>" class="method-signature">
-<% end %>
-<% if methods["callseq"] then %>
- <span class="method-name"><%= methods["callseq"] %></span>
-<% end %>
-<% unless methods["callseq"] then %>
- <span class="method-name"><%= methods["name"] %></span><span class="method-args"><%= methods["params"] %></span>
-<% end %>
-<% if methods["codeurl"] then %>
- </a>
-<% end %>
-<% if methods["sourcecode"] then %>
- </a>
-<% end %>
- </div>
-
- <div class="method-description">
-<% if methods["m_desc"] then %>
- <%= methods["m_desc"] %>
-<% end %>
-<% if methods["sourcecode"] then %>
- <p><a class="source-toggle" href="#"
- onclick="toggleCode('<%= methods["aref"] %>-source');return false;">[Source]</a></p>
- <div class="method-source-code" id="<%= methods["aref"] %>-source">
-<pre>
-<%= methods["sourcecode"] %>
-</pre>
- </div>
-<% end %>
- </div>
- </div>
-
-<% end %><%# method_list["methods"] %>
-<% end %>
-<% end %><%# sections["method_list"] %>
-
- </div>
-<% end %>
-<% end %><%# values["sections"] %>
- EOF
-
- ##
- # Body template
+ METHOD_LIST = RDoc::Generator::HTML::HTML::METHOD_LIST
BODY = HEADER + %{
@@ -724,72 +80,13 @@ EOF
} + FOOTER
- ##
- # Source code template
-
- SRC_PAGE = XHTML_PREAMBLE + <<-EOF
-<html>
-<head>
- <title><%= values["title"] %></title>
- <meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>" />
- <link rel="stylesheet" href="<%= values["style_url"] %>" type="text/css" media="screen" />
-</head>
-<body class="standalone-code">
- <pre><%= values["code"] %></pre>
-</body>
-</html>
- EOF
-
- ##
- # Index file templates
-
- FR_INDEX_BODY = %{
-<%= template_include %>
-}
+ SRC_PAGE = RDoc::Generator::HTML::HTML::SRC_PAGE
- FILE_INDEX = XHTML_PREAMBLE + <<-EOF
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
- <title><%= values["list_title"] %></title>
- <meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>" />
- <link rel="stylesheet" href="<%= values["style_url"] %>" type="text/css" />
- <base target="docwin" />
-</head>
-<body>
-<div class="index">
- <h1 class="section-bar"><%= values["list_title"] %></h1>
- <div class="index-entries">
-<% values["entries"].each do |entries| %>
- <a href="<%= entries["href"] %>"><%= entries["name"] %></a><br />
-<% end %><%# values["entries"] %>
- </div>
-</div>
-</body>
-</html>
- EOF
+ FR_INDEX_BODY = RDoc::Generator::HTML::HTML::FR_INDEX_BODY
- CLASS_INDEX = FILE_INDEX
- METHOD_INDEX = FILE_INDEX
+ FILE_INDEX = RDoc::Generator::HTML::HTML::FILE_INDEX
- INDEX = <<-EOF
-<?xml version="1.0" encoding="<%= values["charset"] %>"?>
-<!DOCTYPE html
- PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
- <title><%= values["title"] %></title>
- <meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>" />
-</head>
-<frameset rows="20%, 80%">
- <frameset cols="45%,55%">
- <frame src="fr_class_index.html" name="Classes" />
- <frame src="fr_method_index.html" name="Methods" />
- </frameset>
- <frame src="<%= values["initial_page"] %>" name="docwin" />
-</frameset>
-</html>
- EOF
+ CLASS_INDEX = RDoc::Generator::HTML::HTML::CLASS_INDEX
+ METHOD_INDEX = RDoc::Generator::HTML::HTML::METHOD_INDEX
end
-
diff --git a/lib/rdoc/generator/html/hefss.rb b/lib/rdoc/generator/html/hefss.rb
index e186a40384..540c23d869 100644
--- a/lib/rdoc/generator/html/hefss.rb
+++ b/lib/rdoc/generator/html/hefss.rb
@@ -1,16 +1,16 @@
require 'rdoc/generator/html'
-require 'rdoc/generator/html/html'
+require 'rdoc/generator/html/kilmerfactory'
module RDoc::Generator::HTML::HEFSS
FONTS = "Verdana, Arial, Helvetica, sans-serif"
-STYLE = <<-EOF
-body,p { font-family: Verdana, Arial, Helvetica, sans-serif;
+ CENTRAL_STYLE = <<-EOF
+body,p { font-family: <%= values["fonts"] %>;
color: #000040; background: #BBBBBB;
}
-td { font-family: Verdana, Arial, Helvetica, sans-serif;
+td { font-family: <%= values["fonts"] %>;
color: #000040;
}
@@ -21,16 +21,20 @@ td { font-family: Verdana, Arial, Helvetica, sans-serif;
}
.big-title-font { color: white;
- font-family: Verdana, Arial, Helvetica, sans-serif;
+ font-family: <%= values["fonts"] %>;
font-size: large;
height: 50px}
.small-title-font { color: purple;
- font-family: Verdana, Arial, Helvetica, sans-serif;
+ font-family: <%= values["fonts"] %>;
font-size: small; }
.aqua { color: purple }
+#diagram img {
+ border: 0;
+}
+
.method-name, attr-name {
font-family: monospace; font-weight: bold;
}
@@ -75,241 +79,6 @@ td { font-family: Verdana, Arial, Helvetica, sans-serif;
color: #0000AA;
}
-.column-title {
- font-size: medium;
- font-weight: bold;
- text_decoration: none;
- padding: 3px 3px 3px 20px;
- color: #3333CC;
- }
-
-.variable-name {
- font-family: monospace;
- font-size: medium;
- text_decoration: none;
- padding: 3px 3px 3px 20px;
- color: #0000AA;
-}
-
-.row-name {
- font-size: medium;
- font-weight: medium;
- font-family: monospace;
- text_decoration: none;
- padding: 3px 3px 3px 20px;
-}
-
-.paramsig {
- font-size: small;
-}
-
-.srcbut { float: right }
-
- EOF
-
- BODY = <<-EOF
-<html><head>
- <title><%= values["title"] %></title>
- <meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>">
- <link rel="stylesheet" href="<%= values["style_url"] %>" type="text/css" media="screen" />
- <script type="text/javascript" language="JavaScript">
- <!--
- function popCode(url) {
- parent.frames.source.location = url
- }
- //-->
- </script>
-</head>
-<body bgcolor="#BBBBBB">
-
-<%= template_include %> <!-- banner header -->
-
-<% if values["diagram"] then %>
-<table width="100%"><tr><td align="center">
-<%= values["diagram"] %>
-</td></tr></table>
-<% end %>
-
-<% if values["description"] then %>
-<div class="description"><%= values["description"] %></div>
-<% end %>
-
-<% if values["requires"] then %>
-<table cellpadding="5" width="100%">
-<tr><td class="tablesubtitle">Required files</td></tr>
-</table><br />
-<div class="name-list">
-<% values["requires"].each do |requires| %>
-<%= href requires["aref"], requires["name"] %>
-<% end %><%# values["requires"] %>
-<% end %>
-</div>
-
-<% if values["sections"] then %>
-<% values["sections"].each do |sections| %>
-<% if sections["method_list"] then %>
-<% sections["method_list"].each do |method_list| %>
-<% if method_list["methods"] then %>
-<table cellpadding="5" width="100%">
-<tr><td class="tablesubtitle">Subroutines and Functions</td></tr>
-</table><br />
-<div class="name-list">
-<% method_list["methods"].each do |methods| %>
-<a href="<%= methods["codeurl"] %>" target="source"><%= methods["name"] %></a>
-<% end %><%# values["methods"] %>
-</div>
-<% end %>
-<% end %><%# values["method_list"] %>
-<% end %>
-
-<% if sections["attributes"] then %>
-<table cellpadding="5" width="100%">
-<tr><td class="tablesubtitle">Arguments</td></tr>
-</table><br />
-<table cellspacing="5">
-<% sections["attributes"].each do |attributes| %>
- <tr valign="top">
-<% if attributes["rw"] then %>
- <td align="center" class="attr-rw">&nbsp;[<%= attributes["rw"] %>]&nbsp;</td>
-<% end %>
-<% unless attributes["rw"] then %>
- <td></td>
-<% end %>
- <td class="attr-name"><%= attributes["name"] %></td>
- <td><%= attributes["a_desc"] %></td>
- </tr>
-<% end %><%# values["attributes"] %>
-</table>
-<% end %>
-<% end %><%# values["sections"] %>
-<% end %>
-
-<% if values["classlist"] then %>
-<table cellpadding="5" width="100%">
-<tr><td class="tablesubtitle">Modules</td></tr>
-</table><br />
-<%= values["classlist"] %><br />
-<% end %>
-
- <%= template_include %> <!-- method descriptions -->
-
-</body>
-</html>
- EOF
-
- FILE_PAGE = <<-EOF
-<table width="100%">
- <tr class="title-row">
- <td><table width="100%"><tr>
- <td class="big-title-font" colspan="2"><font size="-3"><b>File</b><br /></font><%= values["short_name"] %></td>
- <td align="right"><table cellspacing="0" cellpadding="2">
- <tr>
- <td class="small-title-font">Path:</td>
- <td class="small-title-font"><%= values["full_path"] %>
-<% if values["cvsurl"] then %>
- &nbsp;(<a href="<%= values["cvsurl"] %>"><acronym title="Concurrent Versioning System">CVS</acronym></a>)
-<% end %>
- </td>
- </tr>
- <tr>
- <td class="small-title-font">Modified:</td>
- <td class="small-title-font"><%= values["dtm_modified"] %></td>
- </tr>
- </table>
- </td></tr></table></td>
- </tr>
-</table><br />
- EOF
-
- CLASS_PAGE = <<-EOF
-<table width="100%" border="0" cellspacing="0">
- <tr class="title-row">
- <td class="big-title-font">
- <font size="-3"><b><%= values["classmod"] %></b><br /></font><%= values["full_name"] %>
- </td>
- <td align="right">
- <table cellspacing="0" cellpadding="2">
- <tr valign="top">
- <td class="small-title-font">In:</td>
- <td class="small-title-font">
-<% values["infiles"].each do |infiles| %>
-<%= href infiles["full_path_url"], infiles["full_path"] %>
-<% if infiles["cvsurl"] then %>
-&nbsp;(<a href="<%= infiles["cvsurl"] %>"><acronym title="Concurrent Versioning System">CVS</acronym></a>)
-<% end %>
-<% end %><%# values["infiles"] %>
- </td>
- </tr>
-<% if values["parent"] then %>
- <tr>
- <td class="small-title-font">Parent:</td>
- <td class="small-title-font">
-<% if values["par_url"] then %>
- <a href="<%= values["par_url"] %>" class="cyan">
-<% end %>
-<%= values["parent"] %>
-<% if values["par_url"] then %>
- </a>
-<% end %>
- </td>
- </tr>
-<% end %>
- </table>
- </td>
- </tr>
-</table><br />
- EOF
-
- METHOD_LIST = <<-EOF
-<% if values["includes"] then %>
-<div class="tablesubsubtitle">Uses</div><br />
-<div class="name-list">
-<% values["includes"].each do |includes| %>
- <span class="method-name"><%= href includes["aref"], includes["name"] %></span>
-<% end %><%# values["includes"] %>
-</div>
-<% end %>
-
-<% if values["sections"] then %>
-<% values["sections"].each do |sections| %>
-<% if sections["method_list"] then %>
-<% sections["method_list"].each do |method_list| %>
-<% if method_list["methods"] then %>
-<table cellpadding="5" width="100%">
-<tr><td class="tablesubtitle"><%= method_list["type"] %> <%= method_list["category"] %> methods</td></tr>
-</table>
-<% method_list["methods"].each do |methods| %>
-<table width="100%" cellspacing="0" cellpadding="5" border="0">
-<tr><td class="methodtitle">
-<a name="<%= methods["aref"] %>">
-<b><%= methods["name"] %></b><%= methods["params"] %>
-<% if methods["codeurl"] then %>
-<a href="<%= methods["codeurl"] %>" target="source" class="srclink">src</a>
-<% end %>
-</a></td></tr>
-</table>
-<% if method_list["m_desc"] then %>
-<div class="description">
-<%= method_list["m_desc"] %>
-</div>
-<% end %>
-<% end %><%# method_list["methods"] %>
-<% end %>
-<% end %><%# sections["method_list"] %>
-<% end %>
-<% end %><%# values["sections"] %>
-<% end %>
- EOF
-
- SRC_PAGE = <<-EOF
-<html>
-<head><title><%= values["title"] %></title>
-<meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>">
-<style type="text/css">
- .kw { color: #3333FF; font-weight: bold }
- .cmt { color: green; font-style: italic }
- .str { color: #662222; font-style: italic }
- .re { color: #662222; }
.ruby-comment { color: green; font-style: italic }
.ruby-constant { color: #4433aa; font-weight: bold; }
.ruby-identifier { color: #222222; }
@@ -319,35 +88,23 @@ td { font-family: Verdana, Arial, Helvetica, sans-serif;
.ruby-operator { color: #111111; }
.ruby-regexp { color: #662222; }
.ruby-value { color: #662222; font-style: italic }
-</style>
-</head>
-<body bgcolor="#BBBBBB">
-<pre><%= values["code"] %></pre>
-</body>
-</html>
+
+.srcbut { float: right }
EOF
- FR_INDEX_BODY = %{
-<%= template_include %>
+ INDEX_STYLE = <<-EOF
+body {
+ background-color: #bbbbbb;
+ font-family: #{FONTS};
+ font-size: 11px;
+ font-style: normal;
+ line-height: 14px;
+ color: #000040;
}
- FILE_INDEX = <<-EOF
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>">
-<style type="text/css">
-<!--
- body {
-background-color: #bbbbbb;
- font-family: #{FONTS};
- font-size: 11px;
- font-style: normal;
- line-height: 14px;
- color: #000040;
- }
div.banner {
background: #bbbbcc;
- color: white;
+ color: white;
padding: 1;
margin: 0;
font-size: 90%;
@@ -356,59 +113,38 @@ div.banner {
text-align: center;
width: 100%;
}
+EOF
--->
-</style>
-<base target="docwin">
-</head>
-<body>
-<div class="banner"><%= values["list_title"] %></div>
-<% values["entries"].each do |entries| %>
-<a href="<%= entries["href"] %>"><%= entries["name"] %></a><br />
-<% end %><%# values["entries"] %>
-</body></html>
- EOF
+ FACTORY = RDoc::Generator::HTML::
+ KilmerFactory.new(:central_css => CENTRAL_STYLE,
+ :index_css => INDEX_STYLE,
+ :method_list_heading => "Subroutines and Functions",
+ :class_and_module_list_heading => "Classes and Modules",
+ :attribute_list_heading => "Arguments")
- CLASS_INDEX = FILE_INDEX
- METHOD_INDEX = FILE_INDEX
+ STYLE = FACTORY.get_STYLE()
- INDEX = <<-EOF
-<html>
-<head>
- <title><%= values["title"] %></title>
- <meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>">
-</head>
+ METHOD_LIST = FACTORY.get_METHOD_LIST()
+
+ BODY = FACTORY.get_BODY()
+
+ FILE_PAGE = FACTORY.get_FILE_PAGE()
-<frameset cols="20%,*">
- <frameset rows="15%,35%,50%">
- <frame src="fr_file_index.html" title="Files" name="Files">
- <frame src="fr_class_index.html" name="Modules">
- <frame src="fr_method_index.html" name="Subroutines and Functions">
- </frameset>
- <frameset rows="80%,20%">
- <frame src="<%= values["initial_page"] %>" name="docwin">
- <frame src="blank.html" name="source">
- </frameset>
- <noframes>
- <body bgcolor="#BBBBBB">
- Click <a href="html/index.html">here</a> for a non-frames
- version of this page.
- </body>
- </noframes>
-</frameset>
+ CLASS_PAGE = FACTORY.get_CLASS_PAGE()
-</html>
- EOF
+ SRC_PAGE = FACTORY.get_SRC_PAGE()
- # Blank page to use as a target
- BLANK = %{
-<html><body bgcolor="#BBBBBB"></body></html>
-}
+ FR_INDEX_BODY = FACTORY.get_FR_INDEX_BODY()
- def write_extra_pages
- template = TemplatePage.new(BLANK)
- File.open("blank.html", "w") { |f| template.write_html_on(f, {}) }
- end
+ FILE_INDEX = FACTORY.get_FILE_INDEX()
-end
+ CLASS_INDEX = FACTORY.get_CLASS_INDEX()
+
+ METHOD_INDEX = FACTORY.get_METHOD_INDEX()
+ INDEX = FACTORY.get_INDEX()
+
+ def self.write_extra_pages(values)
+ FACTORY.write_extra_pages(values)
+ end
+end
diff --git a/lib/rdoc/generator/html/html.rb b/lib/rdoc/generator/html/html.rb
index 1ab90c6264..823d8056e7 100644
--- a/lib/rdoc/generator/html/html.rb
+++ b/lib/rdoc/generator/html/html.rb
@@ -1,15 +1,17 @@
require 'rdoc/generator/html'
-require 'rdoc/generator/html/one_page_html'
+require 'rdoc/generator/html/common'
##
# = CSS2 RDoc HTML template
#
-# This is a template for RDoc that uses XHTML 1.0 Transitional and dictates a
+# This is a template for RDoc that uses XHTML 1.0 Strict and dictates a
# bit more of the appearance of the output to cascading stylesheets than the
# default. It was designed for clean inline code display, and uses DHTMl to
# toggle the visibility of each method's source with each click on the
# '[source]' link.
#
+# This template *also* forms the basis of the frameless template.
+#
# == Authors
#
# * Michael Granger <ged@FaerieMUD.org>
@@ -23,34 +25,54 @@ require 'rdoc/generator/html/one_page_html'
module RDoc::Generator::HTML::HTML
+ include RDoc::Generator::HTML::Common
+
FONTS = "Verdana,Arial,Helvetica,sans-serif"
STYLE = <<-EOF
body {
- font-family: Verdana,Arial,Helvetica,sans-serif;
- font-size: 90%;
- margin: 0;
- margin-left: 40px;
- padding: 0;
- background: white;
+ font-family: #{FONTS};
+ font-size: 90%;
+ margin: 0;
+ margin-left: 40px;
+ padding: 0;
+ background: white;
+ color: black;
+}
+
+h1, h2, h3, h4 {
+ margin: 0;
+ background: transparent;
+}
+
+h1 {
+ font-size: 150%;
}
-h1,h2,h3,h4 { margin: 0; color: #efefef; background: transparent; }
-h1 { font-size: 150%; }
-h2,h3,h4 { margin-top: 1em; }
+h2,h3,h4 {
+ margin-top: 1em;
+}
-a { background: #eef; color: #039; text-decoration: none; }
-a:hover { background: #039; color: #eef; }
+:link, :visited {
+ background: #eef;
+ color: #039;
+ text-decoration: none;
+}
+
+:link:hover, :visited:hover {
+ background: #039;
+ color: #eef;
+}
/* Override the base stylesheet's Anchor inside a table cell */
-td > a {
+td > :link, td > :visited {
background: transparent;
color: #039;
text-decoration: none;
}
/* and inside a section title */
-.section-title > a {
+.section-title > :link, .section-title > :visited {
background: transparent;
color: #eee;
text-decoration: none;
@@ -58,181 +80,255 @@ td > a {
/* === Structural elements =================================== */
-div#index {
- margin: 0;
- margin-left: -40px;
- padding: 0;
- font-size: 90%;
+.index {
+ margin: 0;
+ margin-left: -40px;
+ padding: 0;
+ font-size: 90%;
}
-
-div#index a {
- margin-left: 0.7em;
+.index :link, .index :visited {
+ margin-left: 0.7em;
}
-div#index .section-bar {
- margin-left: 0px;
- padding-left: 0.7em;
- background: #ccc;
- font-size: small;
+.index .section-bar {
+ margin-left: 0px;
+ padding-left: 0.7em;
+ background: #ccc;
+ font-size: small;
}
-
-div#classHeader, div#fileHeader {
- width: auto;
- color: white;
- padding: 0.5em 1.5em 0.5em 1.5em;
- margin: 0;
- margin-left: -40px;
- border-bottom: 3px solid #006;
+#classHeader, #fileHeader {
+ width: auto;
+ color: white;
+ padding: 0.5em 1.5em 0.5em 1.5em;
+ margin: 0;
+ margin-left: -40px;
+ border-bottom: 3px solid #006;
}
-div#classHeader a, div#fileHeader a {
- background: inherit;
- color: white;
+#classHeader :link, #fileHeader :link,
+#classHeader :visited, #fileHeader :visited {
+ background: inherit;
+ color: white;
}
-div#classHeader td, div#fileHeader td {
- background: inherit;
- color: white;
+#classHeader td, #fileHeader td {
+ background: inherit;
+ color: white;
}
-
-div#fileHeader {
- background: #057;
+#fileHeader {
+ background: #057;
}
-div#classHeader {
- background: #048;
+#classHeader {
+ background: #048;
}
-
.class-name-in-header {
font-size: 180%;
font-weight: bold;
}
-
-div#bodyContent {
- padding: 0 1.5em 0 1.5em;
+#bodyContent {
+ padding: 0 1.5em 0 1.5em;
}
-div#description {
- padding: 0.5em 1.5em;
- background: #efefef;
- border: 1px dotted #999;
+#description {
+ padding: 0.5em 1.5em;
+ background: #efefef;
+ border: 1px dotted #999;
}
-div#description h1,h2,h3,h4,h5,h6 {
- color: #125;;
- background: transparent;
+#description h1, #description h2, #description h3,
+#description h4, #description h5, #description h6 {
+ color: #125;
+ background: transparent;
}
-div#validator-badges {
- text-align: center;
+#validator-badges {
+ text-align: center;
}
-div#validator-badges img { border: 0; }
-div#copyright {
- color: #333;
- background: #efefef;
- font: 0.75em sans-serif;
- margin-top: 5em;
- margin-bottom: 0;
- padding: 0.5em 2em;
+#validator-badges img {
+ border: 0;
}
+#copyright {
+ color: #333;
+ background: #efefef;
+ font: 0.75em sans-serif;
+ margin-top: 5em;
+ margin-bottom: 0;
+ padding: 0.5em 2em;
+}
/* === Classes =================================== */
table.header-table {
- color: white;
- font-size: small;
+ color: white;
+ font-size: small;
}
.type-note {
- font-size: small;
- color: #DEDEDE;
+ font-size: small;
+ color: #dedede;
}
-.xxsection-bar {
- background: #eee;
- color: #333;
- padding: 3px;
+.section-bar {
+ color: #333;
+ border-bottom: 1px solid #999;
+ margin-left: -20px;
}
-.section-bar {
- color: #333;
- border-bottom: 1px solid #999;
- margin-left: -20px;
+.section-title {
+ background: #79a;
+ color: #eee;
+ padding: 3px;
+ margin-top: 2em;
+ margin-left: -30px;
+ border: 1px solid #999;
}
+.top-aligned-row {
+ vertical-align: top
+}
-.section-title {
- background: #79a;
- color: #eee;
- padding: 3px;
- margin-top: 2em;
- margin-left: -30px;
- border: 1px solid #999;
+.bottom-aligned-row {
+ vertical-align: bottom
}
-.top-aligned-row { vertical-align: top }
-.bottom-aligned-row { vertical-align: bottom }
+#diagram img {
+ border: 0;
+}
/* --- Context section classes ----------------------- */
.context-row { }
-.context-item-name { font-family: monospace; font-weight: bold; color: black; }
-.context-item-value { font-size: small; color: #448; }
-.context-item-desc { color: #333; padding-left: 2em; }
+
+.context-item-name {
+ font-family: monospace;
+ font-weight: bold;
+ color: black;
+}
+
+.context-item-value {
+ font-size: small;
+ color: #448;
+}
+
+.context-item-desc {
+ color: #333;
+ padding-left: 2em;
+}
/* --- Method classes -------------------------- */
+
.method-detail {
- background: #efefef;
- padding: 0;
- margin-top: 0.5em;
- margin-bottom: 1em;
- border: 1px dotted #ccc;
+ background: #efefef;
+ padding: 0;
+ margin-top: 0.5em;
+ margin-bottom: 1em;
+ border: 1px dotted #ccc;
}
+
.method-heading {
color: black;
background: #ccc;
border-bottom: 1px solid #666;
padding: 0.2em 0.5em 0 0.5em;
}
-.method-signature { color: black; background: inherit; }
-.method-name { font-weight: bold; }
-.method-args { font-style: italic; }
-.method-description { padding: 0 0.5em 0 0.5em; }
+
+.method-signature {
+ color: black;
+ background: inherit;
+}
+
+.method-name {
+ font-weight: bold;
+}
+
+.method-args {
+ font-style: italic;
+}
+
+.method-description {
+ padding: 0 0.5em 0 0.5em;
+}
/* --- Source code sections -------------------- */
-a.source-toggle { font-size: 90%; }
+:link.source-toggle, :visited.source-toggle {
+ font-size: 90%;
+}
+
div.method-source-code {
- background: #262626;
- color: #ffdead;
- margin: 1em;
- padding: 0.5em;
- border: 1px dashed #999;
- overflow: hidden;
+ background: #262626;
+ color: #ffdead;
+ margin: 1em;
+ padding: 0.5em;
+ border: 1px dashed #999;
+ overflow: auto;
}
-div.method-source-code pre { color: #ffdead; overflow: hidden; }
+div.method-source-code pre {
+ color: #ffdead;
+}
/* --- Ruby keyword styles --------------------- */
-.standalone-code { background: #221111; color: #ffdead; overflow: hidden; }
-
-.ruby-constant { color: #7fffd4; background: transparent; }
-.ruby-keyword { color: #00ffff; background: transparent; }
-.ruby-ivar { color: #eedd82; background: transparent; }
-.ruby-operator { color: #00ffee; background: transparent; }
-.ruby-identifier { color: #ffdead; background: transparent; }
-.ruby-node { color: #ffa07a; background: transparent; }
-.ruby-comment { color: #b22222; font-weight: bold; background: transparent; }
-.ruby-regexp { color: #ffa07a; background: transparent; }
-.ruby-value { color: #7fffd4; background: transparent; }
+.standalone-code {
+ background: #221111;
+ color: #ffdead;
+ overflow: auto;
+}
+
+.ruby-constant {
+ color: #7fffd4;
+ background: transparent;
+}
+
+.ruby-keyword {
+ color: #00ffff;
+ background: transparent;
+}
+
+.ruby-ivar {
+ color: #eedd82;
+ background: transparent;
+}
+
+.ruby-operator {
+ color: #00ffee;
+ background: transparent;
+}
+
+.ruby-identifier {
+ color: #ffdead;
+ background: transparent;
+}
+
+.ruby-node {
+ color: #ffa07a;
+ background: transparent;
+}
+
+.ruby-comment {
+ color: #b22222;
+ font-weight: bold;
+ background: transparent;
+}
+
+.ruby-regexp {
+ color: #ffa07a;
+ background: transparent;
+}
+
+.ruby-value {
+ color: #7fffd4;
+ background: transparent;
+}
EOF
@@ -240,15 +336,7 @@ EOF
### H E A D E R T E M P L A T E
#####################################################################
- XHTML_PREAMBLE = <<-EOF
-<?xml version="1.0" encoding="<%= values["charset"] %>"?>
-<!DOCTYPE html
- PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
- EOF
-
- HEADER = XHTML_PREAMBLE + <<-EOF
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ HEADER = XHTML_STRICT_PREAMBLE + HTML_ELEMENT + <<-EOF
<head>
<title><%= values["title"] %></title>
<meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>" />
@@ -281,7 +369,7 @@ EOF
}
// Make codeblocks hidden by default
- document.writeln( "<style type=\\"text/css\\">div.method-source-code { display: none }</style>" )
+ document.writeln( "<style type=\\"text/css\\">div.method-source-code { display: none }<\\/style>" )
// ]]>
</script>
@@ -291,13 +379,6 @@ EOF
EOF
#####################################################################
-### C O N T E X T C O N T E N T T E M P L A T E
-#####################################################################
-
- CONTEXT_CONTENT = %{
-}
-
-#####################################################################
### F O O T E R T E M P L A T E
#####################################################################
@@ -480,8 +561,8 @@ EOF
<td class="context-item-name"><%= constants["name"] %></td>
<td>=</td>
<td class="context-item-value"><%= constants["value"] %></td>
-<% if sections["desc"] then %>
- <td width="3em">&nbsp;</td>
+<% if constants["desc"] then %>
+ <td>&nbsp;</td>
<td class="context-item-desc"><%= constants["desc"] %></td>
<% end %>
</tr>
@@ -616,8 +697,7 @@ EOF
### S O U R C E C O D E T E M P L A T E
#####################################################################
- SRC_PAGE = XHTML_PREAMBLE + <<-EOF
-<html>
+ SRC_PAGE = XHTML_STRICT_PREAMBLE + HTML_ELEMENT + <<-EOF
<head>
<title><%= values["title"] %></title>
<meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>" />
@@ -634,25 +714,22 @@ EOF
### I N D E X F I L E T E M P L A T E S
#####################################################################
- FR_INDEX_BODY = %{
-<%= template_include %>
-}
+ FR_INDEX_BODY = %{<%= template_include %>}
- FILE_INDEX = XHTML_PREAMBLE + <<-EOF
+ FILE_INDEX = XHTML_STRICT_PREAMBLE + HTML_ELEMENT + <<-EOF
<!--
- <%= values["list_title"] %>
+ <%= values["title"] %>
-->
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
- <title><%= values["list_title"] %></title>
+ <title><%= values["title"] %></title>
<meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>" />
<link rel="stylesheet" href="<%= values["style_url"] %>" type="text/css" />
<base target="docwin" />
</head>
<body>
-<div id="index">
+<div class="index">
<h1 class="section-bar"><%= values["list_title"] %></h1>
<div id="index-entries">
<% values["entries"].each do |entries| %>
@@ -667,18 +744,12 @@ EOF
CLASS_INDEX = FILE_INDEX
METHOD_INDEX = FILE_INDEX
- INDEX = <<-EOF
-<?xml version="1.0" encoding="<%= values["charset"] %>"?>
-<!DOCTYPE html
- PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
-
+ INDEX = XHTML_FRAME_PREAMBLE + HTML_ELEMENT + <<-EOF
<!--
<%= values["title"] %>
-->
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title><%= values["title"] %></title>
<meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>" />
diff --git a/lib/rdoc/generator/html/kilmer.rb b/lib/rdoc/generator/html/kilmer.rb
index 6479abaf8b..4c5a9ee8b0 100644
--- a/lib/rdoc/generator/html/kilmer.rb
+++ b/lib/rdoc/generator/html/kilmer.rb
@@ -1,10 +1,11 @@
require 'rdoc/generator/html'
+require 'rdoc/generator/html/kilmerfactory'
module RDoc::Generator::HTML::KILMER
FONTS = "Verdana, Arial, Helvetica, sans-serif"
- STYLE = <<-EOF
+ CENTRAL_STYLE = <<-EOF
body,td,p { font-family: <%= values["fonts"] %>;
color: #000040;
}
@@ -30,6 +31,10 @@ body,td,p { font-family: <%= values["fonts"] %>;
.aqua { color: black }
+#diagram img {
+ border: 0;
+}
+
.method-name, .attr-name {
font-family: font-family: <%= values["fonts"] %>;
font-weight: bold;
@@ -67,7 +72,7 @@ body,td,p { font-family: <%= values["fonts"] %>;
font-weight: bold;
text-decoration: none;
color: #000033;
- background-color: white;
+ background: #ccc;
}
.srclink {
@@ -78,232 +83,8 @@ body,td,p { font-family: <%= values["fonts"] %>;
background-color: white;
}
-.paramsig {
- font-size: small;
-}
-
.srcbut { float: right }
- EOF
-
- BODY = <<-EOF
-<html><head>
- <title><%= values["title"] %></title>
- <meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>">
- <link rel="stylesheet" href="<%= values["style_url"] %>" type="text/css" media="screen" />
- <script type="text/javascript" language="JavaScript">
- <!--
- function popCode(url) {
- parent.frames.source.location = url
- }
- //-->
- </script>
-</head>
-<body bgcolor="white">
-
-<%= template_include %> <!-- banner header -->
-
-<% if values["diagram"] then %>
-<table width="100%"><tr><td align="center">
-<%= values["diagram"] %>
-</td></tr></table>
-<% end %>
-
-<% if values["description"] then %>
-<div class="description"><%= values["description"] %></div>
-<% end %>
-
-<% if values["requires"] then %>
-<table cellpadding="5" width="100%">
-<tr><td class="tablesubtitle">Required files</td></tr>
-</table><br />
-<div class="name-list">
-<% values["requires"].each do |requires| %>
-<%= href requires["aref"], requires["name"] %>
-<% end %><%# values["requires"] %>
-<% end %>
-</div>
-
-<% if values["methods"] then %>
-<table cellpadding="5" width="100%">
-<tr><td class="tablesubtitle">Methods</td></tr>
-</table><br />
-<div class="name-list">
-<% values["methods"].each do |methods| %>
-<%= href methods["aref"], methods["name"] %>,
-<% end %><%# values["methods"] %>
-</div>
-<% end %>
-
-
-<% values["sections"].each do |sections| %>
- <div id="section">
-<% if sections["sectitle"] then %>
- <h2 class="section-title"><a name="<%= sections["secsequence"] %>"><%= sections["sectitle"] %></a></h2>
-<% if sections["seccomment"] then %>
- <div class="section-comment">
- <%= sections["seccomment"] %>
- </div>
-<% end %>
-<% end %>
-
-<% if sections["attributes"] then %>
-<table cellpadding="5" width="100%">
-<tr><td class="tablesubtitle">Attributes</td></tr>
-</table><br />
-<table cellspacing="5">
-<% sections["attributes"].each do |attributes| %>
- <tr valign="top">
-<% if attributes["rw"] then %>
- <td align="center" class="attr-rw">&nbsp;[<%= attributes["rw"] %>]&nbsp;</td>
-<% end %>
-<% unless attributes["rw"] then %>
- <td></td>
-<% end %>
- <td class="attr-name"><%= attributes["name"] %></td>
- <td><%= attributes["a_desc"] %></td>
- </tr>
-<% end %><%# sections["attributes"] %>
-</table>
-<% end %>
-
-<% if sections["classlist"] then %>
-<table cellpadding="5" width="100%">
-<tr><td class="tablesubtitle">Classes and Modules</td></tr>
-</table><br />
-<%= sections["classlist"] %><br />
-<% end %>
-
- <%= template_include %> <!-- method descriptions -->
-
-<% end %><%# values["sections"] %>
-
-</body>
-</html>
- EOF
-
- FILE_PAGE = <<-EOF
-<table width="100%">
- <tr class="title-row">
- <td><table width="100%"><tr>
- <td class="big-title-font" colspan="2"><font size="-3"><b>File</b><br /></font><%= values["short_name"] %></td>
- <td align="right"><table cellspacing="0" cellpadding="2">
- <tr>
- <td class="small-title-font">Path:</td>
- <td class="small-title-font"><%= values["full_path"] %>
-<% if values["cvsurl"] then %>
- &nbsp;(<a href="<%= values["cvsurl"] %>"><acronym title="Concurrent Versioning System">CVS</acronym></a>)
-<% end %>
- </td>
- </tr>
- <tr>
- <td class="small-title-font">Modified:</td>
- <td class="small-title-font"><%= values["dtm_modified"] %></td>
- </tr>
- </table>
- </td></tr></table></td>
- </tr>
-</table><br />
- EOF
-
- CLASS_PAGE = <<-EOF
-<table width="100%" border="0" cellspacing="0">
- <tr class="title-row">
- <td class="big-title-font">
- <font size="-3"><b><%= values["classmod"] %></b><br /></font><%= values["full_name"] %>
- </td>
- <td align="right">
- <table cellspacing="0" cellpadding="2">
- <tr valign="top">
- <td class="small-title-font">In:</td>
- <td class="small-title-font">
-<% values["infiles"].each do |infiles| %>
-<%= href infiles["full_path_url"], infiles["full_path"] %>
-<% if infiles["cvsurl"] then %>
-&nbsp;(<a href="<%= infiles["cvsurl"] %>"><acronym title="Concurrent Versioning System">CVS</acronym></a>)
-<% end %>
-<% end %><%# values["infiles"] %>
- </td>
- </tr>
-<% if values["parent"] then %>
- <tr>
- <td class="small-title-font">Parent:</td>
- <td class="small-title-font">
-<% if values["par_url"] then %>
- <a href="<%= values["par_url"] %>" class="cyan">
-<% end %>
-<%= values["parent"] %>
-<% if values["par_url"] then %>
- </a>
-<% end %>
- </td>
- </tr>
-<% end %>
- </table>
- </td>
- </tr>
-</table><br />
- EOF
- METHOD_LIST = <<-EOF
-<% if values["includes"] then %>
-<div class="tablesubsubtitle">Included modules</div><br />
-<div class="name-list">
-<% values["includes"].each do |includes| %>
- <span class="method-name"><%= href includes["aref"], includes["name"] %></span>
-<% end %><%# values["includes"] %>
-</div>
-<% end %>
-
-<% if values["method_list"] then %>
-<% values["method_list"].each do |method_list| $stderr.puts({ :method_list => method_list }.inspect) %>
-<% if values["methods"] then %>
-<table cellpadding=5 width="100%">
-<tr><td class="tablesubtitle"><%= values["type"] %> <%= values["category"] %> methods</td></tr>
-</table>
-<% values["methods"].each do |methods| $stderr.puts({ :methods => methods }.inspect) %>
-<table width="100%" cellspacing="0" cellpadding="5" border="0">
-<tr><td class="methodtitle">
-<a name="<%= values["aref"] %>">
-<% if values["callseq"] then %>
-<b><%= values["callseq"] %></b>
-<% end %>
-<% unless values["callseq"] then %>
- <b><%= values["name"] %></b><%= values["params"] %>
-<% end %>
-<% if values["codeurl"] then %>
-<a href="<%= values["codeurl"] %>" target="source" class="srclink">src</a>
-<% end %>
-</a></td></tr>
-</table>
-<% if values["m_desc"] then %>
-<div class="description">
-<%= values["m_desc"] %>
-</div>
-<% end %>
-<% if values["aka"] then %>
-<div class="aka">
-This method is also aliased as
-<% values["aka"].each do |aka| $stderr.puts({ :aka => aka }.inspect) %>
-<a href="<%= values["aref"] %>"><%= values["name"] %></a>
-<% end %><%# values["aka"] %>
-</div>
-<% end %>
-<% if values["sourcecode"] then %>
-<pre class="source">
-<%= values["sourcecode"] %>
-</pre>
-<% end %>
-<% end %><%# values["methods"] %>
-<% end %>
-<% end %><%# values["method_list"] %>
-<% end %>
- EOF
-
- SRC_PAGE = <<-EOF
-<html>
-<head><title><%= values["title"] %></title>
-<meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>">
-<style type="text/css">
.ruby-comment { color: green; font-style: italic }
.ruby-constant { color: #4433aa; font-weight: bold; }
.ruby-identifier { color: #222222; }
@@ -313,28 +94,9 @@ This method is also aliased as
.ruby-operator { color: #111111; }
.ruby-regexp { color: #662222; }
.ruby-value { color: #662222; font-style: italic }
- .kw { color: #3333FF; font-weight: bold }
- .cmt { color: green; font-style: italic }
- .str { color: #662222; font-style: italic }
- .re { color: #662222; }
-</style>
-</head>
-<body bgcolor="white">
-<pre><%= values["code"] %></pre>
-</body>
-</html>
EOF
- FR_INDEX_BODY = %{
-<%= template_include %>
-}
-
- FILE_INDEX = <<-EOF
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>">
-<style>
-<!--
+ INDEX_STYLE = <<-EOF
body {
background-color: #ddddff;
font-family: #{FONTS};
@@ -355,64 +117,35 @@ div.banner {
text-align: center;
width: 100%;
}
+EOF
--->
-</style>
-<base target="docwin">
-</head>
-<body>
-<div class="banner"><%= values["list_title"] %></div>
-<% values["entries"].each do |entries| %>
-<a href="<%= entries["href"] %>"><%= entries["name"] %></a><br />
-<% end %><%# values["entries"] %>
-</body></html>
- EOF
+ FACTORY = RDoc::Generator::HTML::
+ KilmerFactory.new(:central_css => CENTRAL_STYLE,
+ :index_css => INDEX_STYLE)
- CLASS_INDEX = FILE_INDEX
- METHOD_INDEX = FILE_INDEX
+ STYLE = FACTORY.get_STYLE()
- INDEX = <<-EOF
-<html>
-<head>
- <title><%= values["title"] %></title>
- <meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>">
-</head>
+ METHOD_LIST = FACTORY.get_METHOD_LIST()
+
+ BODY = FACTORY.get_BODY()
+
+ FILE_PAGE = FACTORY.get_FILE_PAGE()
-<frameset cols="20%,*">
- <frameset rows="15%,35%,50%">
- <frame src="fr_file_index.html" title="Files" name="Files">
- <frame src="fr_class_index.html" name="Classes">
- <frame src="fr_method_index.html" name="Methods">
- </frameset>
-<% if values["inline_source"] then %>
- <frame src="<%= values["initial_page"] %>" name="docwin">
-<% end %>
-<% unless values["inline_source"] then %>
- <frameset rows="80%,20%">
- <frame src="<%= values["initial_page"] %>" name="docwin">
- <frame src="blank.html" name="source">
- </frameset>
-<% end %>
- <noframes>
- <body bgcolor="white">
- Click <a href="html/index.html">here</a> for a non-frames
- version of this page.
- </body>
- </noframes>
-</frameset>
+ CLASS_PAGE = FACTORY.get_CLASS_PAGE()
-</html>
- EOF
+ SRC_PAGE = FACTORY.get_SRC_PAGE()
- # A blank page to use as a target
- BLANK = %{
-<html><body bgcolor="white"></body></html>
-}
+ FR_INDEX_BODY = FACTORY.get_FR_INDEX_BODY()
- def write_extra_pages
- template = TemplatePage.new(BLANK)
- File.open("blank.html", "w") { |f| template.write_html_on(f, {}) }
- end
+ FILE_INDEX = FACTORY.get_FILE_INDEX()
-end
+ CLASS_INDEX = FACTORY.get_CLASS_INDEX()
+ METHOD_INDEX = FACTORY.get_METHOD_INDEX()
+
+ INDEX = FACTORY.get_INDEX()
+
+ def self.write_extra_pages(values)
+ FACTORY.write_extra_pages(values)
+ end
+end
diff --git a/lib/rdoc/generator/html/kilmerfactory.rb b/lib/rdoc/generator/html/kilmerfactory.rb
new file mode 100644
index 0000000000..ef6f3f3b4d
--- /dev/null
+++ b/lib/rdoc/generator/html/kilmerfactory.rb
@@ -0,0 +1,427 @@
+require 'rdoc/generator/html'
+require 'rdoc/generator/html/common'
+
+#
+# This class generates Kilmer-style templates. Right now,
+# rdoc is shipped with two such templates:
+# * kilmer
+# * hefss
+#
+# Kilmer-style templates use frames. The left side of the page has
+# three frames stacked on top of each other: one lists
+# files, one lists classes, and one lists methods. If source code
+# is not inlined, an additional frame runs across the bottom of
+# the page and will be used to display method source code.
+# The central (and largest frame) display class and file
+# pages.
+#
+# The constructor of this class accepts a Hash containing stylistic
+# attributes. Then, a get_BLAH instance method of this class returns a
+# value for the template's BLAH constant. get_BODY, for instance, returns
+# the value of the template's BODY constant.
+#
+class RDoc::Generator::HTML::KilmerFactory
+
+ include RDoc::Generator::HTML::Common
+
+ #
+ # The contents of the stylesheet that should be used for the
+ # central frame (for the class and file pages).
+ #
+ # This must be specified in the Hash passed to the constructor.
+ #
+ attr_reader :central_css
+
+ #
+ # The contents of the stylesheet that should be used for the
+ # index pages.
+ #
+ # This must be specified in the Hash passed to the constructor.
+ #
+ attr_reader :index_css
+
+ #
+ # The heading that should be displayed before listing methods.
+ #
+ # If not supplied, this defaults to "Methods".
+ #
+ attr_reader :method_list_heading
+
+ #
+ # The heading that should be displayed before listing classes and
+ # modules.
+ #
+ # If not supplied, this defaults to "Classes and Modules".
+ #
+ attr_reader :class_and_module_list_heading
+
+ #
+ # The heading that should be displayed before listing attributes.
+ #
+ # If not supplied, this defaults to "Attributes".
+ #
+ attr_reader :attribute_list_heading
+
+ #
+ # ====Description:
+ # This method constructs a KilmerFactory instance, which
+ # can be used to build Kilmer-style template classes.
+ # The +style_attributes+ argument is a Hash that contains the
+ # values of the classes attributes (Symbols mapped to Strings).
+ #
+ # ====Parameters:
+ # [style_attributes]
+ # A Hash describing the appearance of the Kilmer-style.
+ #
+ def initialize(style_attributes)
+ @central_css = style_attributes[:central_css]
+ if(!@central_css)
+ raise ArgumentError, "did not specify a value for :central_css"
+ end
+
+ @index_css = style_attributes[:index_css]
+ if(!@index_css)
+ raise ArgumentError, "did not specify a value for :index_css"
+ end
+
+ @method_list_heading = style_attributes[:method_list_heading]
+ if(!@method_list_heading)
+ @method_list_heading = "Methods"
+ end
+
+ @class_and_module_list_heading = style_attributes[:class_and_module_list_heading]
+ if(!@class_and_module_list_heading)
+ @class_and_module_list_heading = "Classes and Modules"
+ end
+
+ @attribute_list_heading = style_attributes[:attribute_list_heading]
+ if(!@attribute_list_heading)
+ @attribute_list_heading = "Attributes"
+ end
+ end
+
+ def get_STYLE
+ return @central_css
+ end
+
+ def get_METHOD_LIST
+ return %{
+<% if values["diagram"] then %>
+<div id="diagram">
+<table width="100%"><tr><td align="center">
+<%= values["diagram"] %>
+</td></tr></table>
+</div>
+<% end %>
+
+<% if values["description"] then %>
+<div class="description"><%= values["description"] %></div>
+<% end %>
+
+<% if values["requires"] then %>
+<table cellpadding="5" width="100%">
+<tr><td class="tablesubtitle">Required files</td></tr>
+</table><br />
+<div class="name-list">
+<% values["requires"].each do |requires| %>
+<%= href requires["aref"], requires["name"] %>
+<% end %><%# values["requires"] %>
+</div>
+<% end %>
+
+<% if values["methods"] then %>
+<table cellpadding="5" width="100%">
+<tr><td class="tablesubtitle">#{@method_list_heading}</td></tr>
+</table><br />
+<div class="name-list">
+<% values["methods"].each do |methods| %>
+<%= href methods["aref"], methods["name"] %>,
+<% end %><%# values["methods"] %>
+</div>
+<% end %>
+
+<% if values["includes"] then %>
+<div class="tablesubsubtitle">Included modules</div><br />
+<div class="name-list">
+<% values["includes"].each do |includes| %>
+ <span class="method-name"><%= href includes["aref"], includes["name"] %></span>
+<% end %><%# values["includes"] %>
+</div>
+<% end %>
+
+<% values["sections"].each do |sections| %>
+ <div id="section">
+<% if sections["sectitle"] then %>
+ <h2 class="section-title"><a name="<%= sections["secsequence"] %>"><%= sections["sectitle"] %></a></h2>
+<% if sections["seccomment"] then %>
+ <div class="section-comment">
+ <%= sections["seccomment"] %>
+ </div>
+<% end %>
+<% end %>
+<% if sections["attributes"] then %>
+<table cellpadding="5" width="100%">
+<tr><td class="tablesubtitle">#{@attribute_list_heading}</td></tr>
+</table><br />
+<table cellspacing="5">
+<% sections["attributes"].each do |attributes| %>
+ <tr valign="top">
+<% if attributes["rw"] then %>
+ <td align="center" class="attr-rw">&nbsp;[<%= attributes["rw"] %>]&nbsp;</td>
+<% end %>
+<% unless attributes["rw"] then %>
+ <td></td>
+<% end %>
+ <td class="attr-name"><%= attributes["name"] %></td>
+ <td><%= attributes["a_desc"] %></td>
+ </tr>
+<% end %><%# sections["attributes"] %>
+</table>
+<% end %>
+
+<% if sections["classlist"] then %>
+<table cellpadding="5" width="100%">
+<tr><td class="tablesubtitle">#{@class_and_module_list_heading}</td></tr>
+</table><br />
+<%= sections["classlist"] %><br />
+<% end %>
+
+<% if sections["method_list"] then %>
+<% sections["method_list"].each do |method_list| %>
+<% if method_list["methods"] then %>
+<table cellpadding="5" width="100%">
+<tr><td class="tablesubtitle"><%= method_list["type"] %> <%= method_list["category"] %> methods</td></tr>
+</table>
+<% method_list["methods"].each do |methods| %>
+<table width="100%" cellspacing="0" cellpadding="5" border="0">
+<tr><td class="methodtitle">
+<a name="<%= methods["aref"] %>">
+<% if methods["callseq"] then %>
+<b><%= methods["callseq"] %></b>
+<% end %>
+<% unless methods["callseq"] then %>
+ <b><%= methods["name"] %></b><%= methods["params"] %>
+<% end %>
+</a>
+<% if methods["codeurl"] then %>
+<a href="<%= methods["codeurl"] %>" target="source" class="srclink">src</a>
+<% end %>
+</td></tr>
+</table>
+<% if methods["m_desc"] then %>
+<div class="description">
+<%= methods["m_desc"] %>
+</div>
+<% end %>
+<% if methods["aka"] then %>
+<div class="aka">
+This method is also aliased as
+<% methods["aka"].each do |aka| %>
+<a href="<%= methods["aref"] %>"><%= methods["name"] %></a>
+<% end %><%# methods["aka"] %>
+</div>
+<% end %>
+<% if methods["sourcecode"] then %>
+<pre class="source">
+<%= methods["sourcecode"] %>
+</pre>
+<% end %>
+<% end %><%# method_list["methods"] %>
+<% end %>
+<% end %><%# sections["method_list"] %>
+<% end %>
+
+<% end %><%# values["sections"] %>
+</div>
+}
+ end
+
+ def get_BODY
+ return XHTML_STRICT_PREAMBLE + HTML_ELEMENT + %{
+<head>
+ <title><%= values["title"] %></title>
+ <meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>" />
+ <link rel="stylesheet" href="<%= values["style_url"] %>" type="text/css" media="screen" />
+ <script type="text/javascript">
+ <!--
+ function popCode(url) {
+ parent.frames.source.location = url
+ }
+ //-->
+ </script>
+</head>
+<body>
+<div class="bodyContent">
+<%= template_include %> <!-- banner header -->
+
+#{get_METHOD_LIST()}
+</div>
+</body>
+</html>
+}
+ end
+
+def get_FILE_PAGE
+ return %{
+<table width="100%">
+ <tr class="title-row">
+ <td><table width="100%"><tr>
+ <td class="big-title-font" colspan="2">File<br /><%= values["short_name"] %></td>
+ <td align="right"><table cellspacing="0" cellpadding="2">
+ <tr>
+ <td class="small-title-font">Path:</td>
+ <td class="small-title-font"><%= values["full_path"] %>
+<% if values["cvsurl"] then %>
+ &nbsp;(<a href="<%= values["cvsurl"] %>"><acronym title="Concurrent Versioning System">CVS</acronym></a>)
+<% end %>
+ </td>
+ </tr>
+ <tr>
+ <td class="small-title-font">Modified:</td>
+ <td class="small-title-font"><%= values["dtm_modified"] %></td>
+ </tr>
+ </table>
+ </td></tr></table></td>
+ </tr>
+</table><br />
+}
+end
+
+def get_CLASS_PAGE
+ return %{
+<table width="100%" border="0" cellspacing="0">
+ <tr class="title-row">
+ <td class="big-title-font">
+ <%= values["classmod"] %><br /><%= values["full_name"] %>
+ </td>
+ <td align="right">
+ <table cellspacing="0" cellpadding="2">
+ <tr valign="top">
+ <td class="small-title-font">In:</td>
+ <td class="small-title-font">
+<% values["infiles"].each do |infiles| %>
+<%= href infiles["full_path_url"], infiles["full_path"] %>
+<% if infiles["cvsurl"] then %>
+&nbsp;(<a href="<%= infiles["cvsurl"] %>"><acronym title="Concurrent Versioning System">CVS</acronym></a>)
+<% end %>
+<% end %><%# values["infiles"] %>
+ </td>
+ </tr>
+<% if values["parent"] then %>
+ <tr>
+ <td class="small-title-font">Parent:</td>
+ <td class="small-title-font">
+<% if values["par_url"] then %>
+ <a href="<%= values["par_url"] %>" class="cyan">
+<% end %>
+<%= values["parent"] %>
+<% if values["par_url"] then %>
+ </a>
+<% end %>
+ </td>
+ </tr>
+<% end %>
+ </table>
+ </td>
+ </tr>
+</table><br />
+}
+end
+
+def get_SRC_PAGE
+ return XHTML_STRICT_PREAMBLE + HTML_ELEMENT + %{
+<head><title><%= values["title"] %></title>
+<meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>" />
+<link rel="stylesheet" href="<%= values["style_url"] %>" type="text/css" media="screen" />
+</head>
+<body>
+<pre><%= values["code"] %></pre>
+</body>
+</html>
+}
+end
+
+def get_FR_INDEX_BODY
+ return %{<%= template_include %>}
+end
+
+def get_FILE_INDEX
+ return XHTML_STRICT_PREAMBLE + HTML_ELEMENT + %{
+<head>
+<title><%= values["title"] %></title>
+<meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>" />
+<style type="text/css">
+<!--
+#{@index_css}
+-->
+</style>
+<base target="docwin" />
+</head>
+<body>
+<div class="index">
+<div class="banner"><%= values["list_title"] %></div>
+<% values["entries"].each do |entries| %>
+<a href="<%= entries["href"] %>"><%= entries["name"] %></a><br />
+<% end %><%# values["entries"] %>
+</div>
+</body></html>
+}
+end
+
+def get_CLASS_INDEX
+ return get_FILE_INDEX
+end
+
+def get_METHOD_INDEX
+ return get_FILE_INDEX
+end
+
+def get_INDEX
+ return XHTML_FRAME_PREAMBLE + HTML_ELEMENT + %{
+<head>
+ <title><%= values["title"] %></title>
+ <meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>" />
+</head>
+
+<frameset cols="20%,*">
+ <frameset rows="15%,35%,50%">
+ <frame src="fr_file_index.html" title="Files" name="Files" />
+ <frame src="fr_class_index.html" name="Classes" />
+ <frame src="fr_method_index.html" name="Methods" />
+ </frameset>
+<% if values["inline_source"] then %>
+ <frame src="<%= values["initial_page"] %>" name="docwin" />
+<% end %>
+<% unless values["inline_source"] then %>
+ <frameset rows="80%,20%">
+ <frame src="<%= values["initial_page"] %>" name="docwin" />
+ <frame src="blank.html" name="source" />
+ </frameset>
+<% end %>
+</frameset>
+
+</html>
+}
+end
+
+def get_BLANK
+ # This will be displayed in the source code frame before
+ # any source code has been selected.
+ return XHTML_STRICT_PREAMBLE + HTML_ELEMENT + %{
+<head>
+ <title>Source Code Frame <%= values["title_suffix"] %></title>
+ <meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>" />
+ <link rel="stylesheet" href="<%= values["style_url"] %>" type="text/css" media="screen" />
+</head>
+<body>
+</body>
+</html>
+}
+end
+
+def write_extra_pages(values)
+ template = RDoc::TemplatePage.new(get_BLANK())
+ File.open("blank.html", "w") { |f| template.write_html_on(f, values) }
+end
+
+end
diff --git a/lib/rdoc/generator/html/one_page_html.rb b/lib/rdoc/generator/html/one_page_html.rb
index c4dd95529d..51ae32351a 100644
--- a/lib/rdoc/generator/html/one_page_html.rb
+++ b/lib/rdoc/generator/html/one_page_html.rb
@@ -1,7 +1,10 @@
require 'rdoc/generator/html'
+require 'rdoc/generator/html/common'
module RDoc::Generator::HTML::ONE_PAGE_HTML
+ include RDoc::Generator::HTML::Common
+
CONTENTS_XML = <<-EOF
<% if defined? classes and classes["description"] then %>
<%= classes["description"] %>
@@ -76,16 +79,14 @@ module RDoc::Generator::HTML::ONE_PAGE_HTML
<% end %>
EOF
- ONE_PAGE = %{
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
+ ONE_PAGE = XHTML_STRICT_PREAMBLE + HTML_ELEMENT + %{
<head>
<title><%= values["title"] %></title>
<meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>" />
</head>
<body>
<% values["files"].each do |files| %>
-<h2>File: <%= files["short_name"] %></h2>
+<h2>File: <a name="<%= files["href"] %>"><%= files["short_name"] %></a></h2>
<table>
<tr><td>Path:</td><td><%= files["full_path"] %></td></tr>
<tr><td>Modified:</td><td><%= files["dtm_modified"] %></td></tr>
@@ -97,7 +98,7 @@ module RDoc::Generator::HTML::ONE_PAGE_HTML
<h2>Classes</h2>
<% values["classes"].each do |classes| %>
<% if classes["parent"] then %>
-<h3><%= classes["classmod"] %> <%= classes["full_name"] %> &lt; <%= href classes["par_url"], classes["parent"] %></h3>
+<h3><%= classes["classmod"] %> <a name="<%= classes["href"] %>"><%= classes["full_name"] %></a> &lt; <%= href classes["par_url"], classes["parent"] %></h3>
<% end %>
<% unless classes["parent"] then %>
<h3><%= classes["classmod"] %> <%= classes["full_name"] %></h3>
diff --git a/lib/rdoc/generator/texinfo.rb b/lib/rdoc/generator/texinfo.rb
index 0b79820228..70db875af9 100644
--- a/lib/rdoc/generator/texinfo.rb
+++ b/lib/rdoc/generator/texinfo.rb
@@ -3,13 +3,10 @@ require 'rdoc/generator'
require 'rdoc/markup/to_texinfo'
module RDoc
- RDoc::GENERATORS['texinfo'] = RDoc::Generator.new("rdoc/generator/texinfo",
- :Texinfo,
- 'texinfo')
module Generator
# This generates Texinfo files for viewing with GNU Info or Emacs
# from RDoc extracted from Ruby source files.
- class Texinfo
+ class TEXINFO
# What should the .info file be named by default?
DEFAULT_INFO_FILENAME = 'rdoc.info'
@@ -26,8 +23,8 @@ module RDoc
# Generate the +texinfo+ files
def generate(toplevels)
@toplevels = toplevels
- @files, @classes = ::RDoc::Generator::Context.build_indicies(@toplevels,
- @options)
+ @files, @classes = ::RDoc::Generator::Context.build_indices(@toplevels,
+ @options)
(@files + @classes).each { |x| x.value_hash }
diff --git a/lib/rdoc/generator/texinfo/class.texinfo.erb b/lib/rdoc/generator/texinfo/class.texinfo.erb
index 07f17eaef2..74ecc59f7d 100644
--- a/lib/rdoc/generator/texinfo/class.texinfo.erb
+++ b/lib/rdoc/generator/texinfo/class.texinfo.erb
@@ -38,7 +38,7 @@ Methods
<% (method_list["methods"] || []).uniq.each do |method| %>
<%= TexinfoTemplate.new(@v.merge({'method' => method, 'list' => method_list}),
'method.texinfo.erb').render %><% end %>
-<% end # section["method_list"] %>
-<% end %>
+<% end %>
+<% end # if section["method_list"] %>
<% end # @v['class']["sections"] %>
<% end %>
diff --git a/lib/rdoc/generator/xml.rb b/lib/rdoc/generator/xml.rb
index 3335f2ce7c..0d4c5a7ea1 100644
--- a/lib/rdoc/generator/xml.rb
+++ b/lib/rdoc/generator/xml.rb
@@ -34,15 +34,15 @@ class RDoc::Generator::XML < RDoc::Generator::HTML
##
# Generate:
#
- # * a list of HtmlFile objects for each TopLevel object.
- # * a list of HtmlClass objects for each first level
+ # * a list of File objects for each TopLevel object.
+ # * a list of Class objects for each first level
# class or module in the TopLevel objects
# * a complete list of all hyperlinkable terms (file,
# class, module, and method names)
def build_indices
@info.each do |toplevel|
- @files << RDoc::Generator::HtmlFile.new(toplevel, @options, RDoc::Generator::FILE_DIR)
+ @files << RDoc::Generator::File.new(toplevel, @options, RDoc::Generator::FILE_DIR)
end
RDoc::TopLevel.all_classes_and_modules.each do |cls|
@@ -51,7 +51,7 @@ class RDoc::Generator::XML < RDoc::Generator::HTML
end
def build_class_list(from, html_file, class_dir)
- @classes << RDoc::Generator::HtmlClass.new(from, html_file, class_dir, @options)
+ @classes << RDoc::Generator::Class.new(from, html_file, class_dir, @options)
from.each_classmodule do |mod|
build_class_list(mod, html_file, class_dir)
end
@@ -68,9 +68,6 @@ class RDoc::Generator::XML < RDoc::Generator::HTML
'classes' => gen_into(@classes)
}
- # this method is defined in the template file
- write_extra_pages if defined? write_extra_pages
-
template = RDoc::TemplatePage.new @template::ONE_PAGE
if @options.op_name
diff --git a/lib/rdoc/generator/xml/xml.rb b/lib/rdoc/generator/xml/xml.rb
index ffb1329c4e..4b54e7350f 100644
--- a/lib/rdoc/generator/xml/xml.rb
+++ b/lib/rdoc/generator/xml/xml.rb
@@ -17,11 +17,23 @@ module RDoc::Generator::XML::XML
href="<%= requires["aref"] %>"
<% end %>
/>
-<% end # files["requires"] %>
+<% end %><%# files["requires"] %>
</required-file-list>
<% end %>
<% if defined? classes and classes["sections"] then %>
<% classes["sections"].each do |sections| %>
+<% if sections["constants"] then %>
+ <constant-list>
+<% sections["constants"].each do |constant| %>
+ <constant name="<%= constant["name"] %>">
+<% if constant["value"] then %>
+ <value><%= constant["value"] %></value>
+<% end %>
+ <description><%= constant["a_desc"] %></description>
+ </constant>
+<% end %><%# sections["constants"] %>
+ </constant-list>
+<% end %>
<% if sections["attributes"] then %>
<attribute-list>
<% sections["attributes"].each do |attributes| %>
@@ -31,7 +43,7 @@ module RDoc::Generator::XML::XML
<% end %>
<description><%= attributes["a_desc"] %></description>
</attribute>
-<% end # sections["attributes"] %>
+<% end %><%# sections["attributes"] %>
</attribute-list>
<% end %>
<% if sections["method_list"] then %>
@@ -52,12 +64,12 @@ module RDoc::Generator::XML::XML
</source-code-listing>
<% end %>
</method>
-<% end # method_list["methods"] %>
+<% end %><%# method_list["methods"] %>
<% end %>
-<% end # sections["method_list"] %>
+<% end %><%# sections["method_list"] %>
</method-list>
<% end %>
-<% end # classes["sections"] %>
+<% end %><%# classes["sections"] %>
<% end %>
<% if defined? classes and classes["includes"] then %>
<included-module-list>
@@ -67,7 +79,7 @@ module RDoc::Generator::XML::XML
href="<%= includes["aref"] %>"
<% end %>
/>
-<% end # classes["includes"] %>
+<% end %><%# classes["includes"] %>
</included-module-list>
<% end %>
</contents>
@@ -84,7 +96,7 @@ module RDoc::Generator::XML::XML
</file-info>
} + CONTENTS_XML + %{
</file>
-<% end # values["files"] %>
+<% end %><%# values["files"] %>
</file-list>
<class-module-list>
<% values["classes"].each do |classes| %>
@@ -94,7 +106,7 @@ module RDoc::Generator::XML::XML
<infiles>
<% classes["infiles"].each do |infiles| %>
<infile><%= href infiles["full_path_url"], infiles["full_path"] %></infile>
-<% end # classes["infiles"] %>
+<% end %><%# classes["infiles"] %>
</infiles>
<% end %>
<% if classes["parent"] then %>
@@ -103,7 +115,7 @@ module RDoc::Generator::XML::XML
</classmod-info>
} + CONTENTS_XML + %{
</<%= classes["classmod"] %>>
-<% end # values["classes"] %>
+<% end %><%# values["classes"] %>
</class-module-list>
</rdoc>
}
diff --git a/lib/rdoc/known_classes.rb b/lib/rdoc/known_classes.rb
index 4c52f58ad2..dbb1802f5a 100644
--- a/lib/rdoc/known_classes.rb
+++ b/lib/rdoc/known_classes.rb
@@ -62,7 +62,6 @@ module RDoc
"rb_mGC" => "GC",
"rb_mKernel" => "Kernel",
"rb_mMath" => "Math",
- "rb_mPrecision" => "Precision",
"rb_mProcess" => "Process"
}
diff --git a/lib/rdoc/markup.rb b/lib/rdoc/markup.rb
index 0e1b596255..9d22b38946 100644
--- a/lib/rdoc/markup.rb
+++ b/lib/rdoc/markup.rb
@@ -20,101 +20,6 @@ require 'rdoc'
# RDoc::Markup could be the basis for formatting RDoc style comment blocks,
# Wiki entries, and online FAQs.
#
-# = Basic Formatting
-#
-# * RDoc::Markup looks for a document's natural left margin. This is
-# used as the initial margin for the document.
-#
-# * Consecutive lines starting at this margin are considered to be a
-# paragraph.
-#
-# * If a paragraph starts with a "*", "-", or with "<digit>.", then it is
-# taken to be the start of a list. The margin in increased to be the first
-# non-space following the list start flag. Subsequent lines should be
-# indented to this \new margin until the list ends. For example:
-#
-# * this is a list with three paragraphs in
-# the first item. This is the first paragraph.
-#
-# And this is the second paragraph.
-#
-# 1. This is an indented, numbered list.
-# 2. This is the second item in that list
-#
-# This is the third conventional paragraph in the
-# first list item.
-#
-# * This is the second item in the original list
-#
-# * You can also construct labeled lists, sometimes called description
-# or definition lists. Do this by putting the label in square brackets
-# and indenting the list body:
-#
-# [cat] a small furry mammal
-# that seems to sleep a lot
-#
-# [ant] a little insect that is known
-# to enjoy picnics
-#
-# A minor variation on labeled lists uses two colons to separate the
-# label from the list body:
-#
-# cat:: a small furry mammal
-# that seems to sleep a lot
-#
-# ant:: a little insect that is known
-# to enjoy picnics
-#
-# This latter style guarantees that the list bodies' left margins are
-# aligned: think of them as a two column table.
-#
-# * Any line that starts to the right of the current margin is treated
-# as verbatim text. This is useful for code listings. The example of a
-# list above is also verbatim text.
-#
-# * A line starting with an equals sign (=) is treated as a
-# heading. Level one headings have one equals sign, level two headings
-# have two,and so on.
-#
-# * A line starting with three or more hyphens (at the current indent)
-# generates a horizontal rule. The more hyphens, the thicker the rule
-# (within reason, and if supported by the output device)
-#
-# * You can use markup within text (except verbatim) to change the
-# appearance of parts of that text. Out of the box, RDoc::Markup
-# supports word-based and general markup.
-#
-# Word-based markup uses flag characters around individual words:
-#
-# [\*word*] displays word in a *bold* font
-# [\_word_] displays word in an _emphasized_ font
-# [\+word+] displays word in a +code+ font
-#
-# General markup affects text between a start delimiter and and end
-# delimiter. Not surprisingly, these delimiters look like HTML markup.
-#
-# [\<b>text...</b>] displays word in a *bold* font
-# [\<em>text...</em>] displays word in an _emphasized_ font
-# [\<i>text...</i>] displays word in an _emphasized_ font
-# [\<tt>text...</tt>] displays word in a +code+ font
-#
-# Unlike conventional Wiki markup, general markup can cross line
-# boundaries. You can turn off the interpretation of markup by
-# preceding the first character with a backslash, so \\\<b>bold
-# text</b> and \\\*bold* produce \<b>bold text</b> and \*bold*
-# respectively.
-#
-# * Hyperlinks to the web starting http:, mailto:, ftp:, or www. are
-# recognized. An HTTP url that references an external image file is
-# converted into an inline <IMG..>. Hyperlinks starting 'link:' are
-# assumed to refer to local files whose path is relative to the --op
-# directory.
-#
-# Hyperlinks can also be of the form <tt>label</tt>[url], in which
-# case the label is used in the displayed text, and <tt>url</tt> is
-# used as the target. If <tt>label</tt> contains multiple words,
-# put it in braces: <em>{multi word label}[</em>url<em>]</em>.
-#
# == Synopsis
#
# This code converts +input_string+ to HTML. The conversion takes place in
diff --git a/lib/rdoc/markup/inline.rb b/lib/rdoc/markup/inline.rb
index ee77679a11..46c9b5822c 100644
--- a/lib/rdoc/markup/inline.rb
+++ b/lib/rdoc/markup/inline.rb
@@ -47,7 +47,7 @@ class RDoc::Markup
class AttrChanger
def to_s
- "Attr: +#{Attribute.as_string(@turn_on)}/-#{Attribute.as_string(@turn_on)}"
+ "Attr: +#{Attribute.as_string(turn_on)}/-#{Attribute.as_string(turn_on)}"
end
end
diff --git a/lib/rdoc/markup/to_html.rb b/lib/rdoc/markup/to_html.rb
index ca29373db1..dce7a69b12 100644
--- a/lib/rdoc/markup/to_html.rb
+++ b/lib/rdoc/markup/to_html.rb
@@ -57,7 +57,7 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
##
# Generate a hyperlink for url, labeled with text. Handle the
- # special cases for img: and link: described under handle_special_HYPEDLINK
+ # special cases for img: and link: described under handle_special_HYPERLINK
def gen_url(url, text)
if url =~ /([A-Za-z]+):(.*)/ then
@@ -304,9 +304,12 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
# some of these patterns are taken from SmartyPants...
def convert_string_fancy(item)
- # convert -- to em-dash, (-- to en-dash)
- item.gsub(/---?/, '&#8212;'). #gsub(/--/, '&#8211;').
+ # convert ampersand before doing anything else
+ item.gsub(/&/, '&amp;').
+ # convert -- to em-dash, (-- to en-dash)
+ gsub(/---?/, '&#8212;'). #gsub(/--/, '&#8211;').
+
# convert ... to elipsis (and make sure .... becomes .<elipsis>)
gsub(/\.\.\.\./, '.&#8230;').gsub(/\.\.\./, '&#8230;').
@@ -318,15 +321,15 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
gsub(/'/, '&#8216;').
# convert double closing quote
- gsub(%r{([^ \t\r\n\[\{\(])\'(?=\W)}, '\1&#8221;'). # }
+ gsub(%r{([^ \t\r\n\[\{\(])\"(?=\W)}, '\1&#8221;'). # }
# convert double opening quote
- gsub(/'/, '&#8220;').
+ gsub(/"/, '&#8220;').
# convert copyright
gsub(/\(c\)/, '&#169;').
- # convert and registered trademark
+ # convert registered trademark
gsub(/\(r\)/, '&#174;')
end
diff --git a/lib/rdoc/markup/to_html_crossref.rb b/lib/rdoc/markup/to_html_crossref.rb
index a6f29c5c2c..dc64b30da1 100644
--- a/lib/rdoc/markup/to_html_crossref.rb
+++ b/lib/rdoc/markup/to_html_crossref.rb
@@ -9,6 +9,68 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
attr_accessor :context
+ # Regular expressions to match class and method references.
+ #
+ # 1.) There can be a '\' in front of text to suppress
+ # any cross-references (note, however, that the single '\'
+ # is written as '\\\\' in order to escape it twice, once
+ # in the Ruby String literal and once in the regexp).
+ # 2.) There can be a '::' in front of class names to reference
+ # from the top-level namespace.
+ # 3.) The method can be followed by parenthesis,
+ # which may or may not have things inside (this
+ # apparently is allowed for Fortran 95, but I also think that this
+ # is a good idea for Ruby, as it is very reasonable to want to
+ # reference a call with arguments).
+ #
+ # NOTE: In order to support Fortran 95 properly, the [A-Z] below
+ # should be changed to [A-Za-z]. This slows down rdoc significantly,
+ # however, and the Fortran 95 support is broken in any case due to
+ # the return in handle_special_CROSSREF if the token consists
+ # entirely of lowercase letters.
+ #
+ # The markup/cross-referencing engine needs a rewrite for
+ # Fortran 95 to be supported properly.
+ CLASS_REGEXP_STR = '\\\\?((?:\:{2})?[A-Z]\w*(?:\:\:\w+)*)'
+ METHOD_REGEXP_STR = '(\w+[!?=]?)(?:\([\.\w+\*\/\+\-\=\<\>]*\))?'
+
+ # Regular expressions matching text that should potentially have
+ # cross-reference links generated are passed to add_special.
+ # Note that these expressions are meant to pick up text for which
+ # cross-references have been suppressed, since the suppression
+ # characters are removed by the code that is triggered.
+ CROSSREF_REGEXP = /(
+ # A::B::C.meth
+ #{CLASS_REGEXP_STR}[\.\#]#{METHOD_REGEXP_STR}
+
+ # Stand-alone method (proceeded by a #)
+ | \\?\##{METHOD_REGEXP_STR}
+
+ # A::B::C
+ # The stuff after CLASS_REGEXP_STR is a
+ # nasty hack. CLASS_REGEXP_STR unfortunately matches
+ # words like dog and cat (these are legal "class"
+ # names in Fortran 95). When a word is flagged as a
+ # potential cross-reference, limitations in the markup
+ # engine suppress other processing, such as typesetting.
+ # This is particularly noticeable for contractions.
+ # In order that words like "can't" not
+ # be flagged as potential cross-references, only
+ # flag potential class cross-references if the character
+ # after the cross-referece is a space or sentence
+ # punctuation.
+ | #{CLASS_REGEXP_STR}(?=[\s\)\.\?\!\,\;]|\z)
+
+ # Things that look like filenames
+ # The key thing is that there must be at least
+ # one special character (period, slash, or
+ # underscore).
+ | [\/\w]+[_\/\.][\w\/\.]+
+
+ # Things that have markup suppressed
+ | \\[^\s]
+ )/x
+
##
# We need to record the html path of our caller so we can generate
# correct relative paths for any hyperlinks that we find
@@ -17,18 +79,7 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
raise ArgumentError, 'from_path cannot be nil' if from_path.nil?
super()
- # class names, variable names, or instance variables
- @markup.add_special(/(
- # A::B.meth(**) (for operator in Fortran95)
- \w+(::\w+)*[.\#]\w+(\([\.\w+\*\/\+\-\=\<\>]+\))?
- # meth(**) (for operator in Fortran95)
- | \#\w+(\([.\w\*\/\+\-\=\<\>]+\))?
- | \b([A-Z]\w*(::\w+)*[.\#]\w+) # A::B.meth
- | \b([A-Z]\w+(::\w+)*) # A::B
- | \#\w+[!?=]? # #meth_name
- | \\?\b\w+([_\/\.]+\w+)*[!?=]? # meth_name
- )/x,
- :CROSSREF)
+ @markup.add_special(CROSSREF_REGEXP, :CROSSREF)
@from_path = from_path
@context = context
@@ -48,6 +99,9 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
def handle_special_CROSSREF(special)
name = special.text
+ # This ensures that words entirely consisting of lowercase letters will
+ # not have cross-references generated (to suppress lots of
+ # erroneous cross-references to "new" in text, for instance)
return name if name =~ /\A[a-z]*\z/
return @seen[name] if @seen.include? name
@@ -70,14 +124,7 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
# (in which case it would match the last pattern, which just checks
# whether the string as a whole is a known symbol).
- if /([A-Z][\w:]*)[.\#](\w+[!?=]?)/ =~ lookup then
- container = $1
- method = $2
- ref = @context.find_symbol container, method
- end
-
- if !ref and
- /([A-Za-z][\w:]*)[.\#](\w+(\([\.\w+\*\/\+\-\=\<\>]+\))?)/ =~ lookup then
+ if /#{CLASS_REGEXP_STR}[\.\#]#{METHOD_REGEXP_STR}/ =~ lookup then
container = $1
method = $2
ref = @context.find_symbol container, method
@@ -99,4 +146,3 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
end
end
-
diff --git a/lib/rdoc/markup/to_texinfo.rb b/lib/rdoc/markup/to_texinfo.rb
index 533d3e34a0..65a1608c4d 100644
--- a/lib/rdoc/markup/to_texinfo.rb
+++ b/lib/rdoc/markup/to_texinfo.rb
@@ -30,7 +30,7 @@ class RDoc::Markup::ToTexInfo < RDoc::Markup::Formatter
def accept_heading(attributes, text)
heading = ['@majorheading', '@chapheading'][text.head_level - 1] || '@heading'
- @text << "#{heading}{#{format(text)}}"
+ @text << "#{heading} #{format(text)}"
end
def accept_list_start(attributes, text)
diff --git a/lib/rdoc/options.rb b/lib/rdoc/options.rb
index d683a14022..1d92bd4748 100644
--- a/lib/rdoc/options.rb
+++ b/lib/rdoc/options.rb
@@ -184,7 +184,7 @@ class RDoc::Options
@css = nil
@webcvs = nil
- @charset = 'iso-8859-1'
+ @charset = 'utf-8'
end
##
@@ -196,6 +196,7 @@ class RDoc::Options
opts = OptionParser.new do |opt|
opt.program_name = File.basename $0
opt.version = RDoc::VERSION
+ opt.release = nil
opt.summary_indent = ' ' * 4
opt.banner = <<-EOF
Usage: #{opt.program_name} [options] [names...]
@@ -257,7 +258,7 @@ Usage: #{opt.program_name} [options] [names...]
opt.separator nil
opt.on("--charset=CHARSET", "-c",
- "Specifies the HTML character-set.") do |value|
+ "Specifies the output HTML character-set.") do |value|
@charset = value
end
@@ -283,9 +284,7 @@ Usage: #{opt.program_name} [options] [names...]
opt.on("--exclude=PATTERN", "-x", Regexp,
"Do not process files or directories",
- "matching PATTERN. Files given explicitly",
- "on the command line will never be",
- "excluded.") do |value|
+ "matching PATTERN.") do |value|
@exclude << value
end
diff --git a/lib/rdoc/parser.rb b/lib/rdoc/parser.rb
index 794fad00e9..c37256dbd8 100644
--- a/lib/rdoc/parser.rb
+++ b/lib/rdoc/parser.rb
@@ -63,10 +63,36 @@ class RDoc::Parser
end
##
+ # Shamelessly stolen from the ptools gem (since RDoc cannot depend on
+ # the gem).
+
+ def self.binary?(file)
+ s = (File.read(file, File.stat(file).blksize) || "").split(//)
+
+ if s.size > 0 then
+ ((s.size - s.grep(" ".."~").size) / s.size.to_f) > 0.30
+ else
+ false
+ end
+ end
+ private_class_method :binary?
+
+ ##
# Return a parser that can handle a particular extension
def self.can_parse(file_name)
- RDoc::Parser.parsers.find { |regexp, parser| regexp =~ file_name }.last
+ parser = RDoc::Parser.parsers.find { |regexp,| regexp =~ file_name }.last
+
+ #
+ # The default parser should *NOT* parse binary files.
+ #
+ if parser == RDoc::Parser::Simple then
+ if binary? file_name then
+ return nil
+ end
+ end
+
+ return parser
end
##
@@ -85,6 +111,13 @@ class RDoc::Parser
parser = can_parse file_name
+ #
+ # This method must return a parser.
+ #
+ if !parser then
+ parser = RDoc::Parser::Simple
+ end
+
parser.new top_level, file_name, body, options, stats
end
diff --git a/lib/rdoc/parser/c.rb b/lib/rdoc/parser/c.rb
index 43bb767da9..9061841bec 100644
--- a/lib/rdoc/parser/c.rb
+++ b/lib/rdoc/parser/c.rb
@@ -1,4 +1,5 @@
require 'rdoc/parser'
+require 'rdoc/parser/ruby'
require 'rdoc/known_classes'
##
@@ -120,7 +121,7 @@ class RDoc::Parser::C < RDoc::Parser
@stats.add_alias as
end
- end
+ end
def do_classes
@content.scan(/(\w+)\s* = \s*rb_define_module\s*\(\s*"(\w+)"\s*\)/mx) do
@@ -155,7 +156,7 @@ class RDoc::Parser::C < RDoc::Parser
\(
\s*(\w+),
\s*"(\w+)",
- \s*(\w+)\s*
+ \s*([\w\*\s\(\)\.\->]+)\s* # for SWIG
\s*\)/mx) do |var_name, in_module, class_name, parent|
handle_class_module(var_name, "class", class_name, parent, in_module)
end
@@ -251,7 +252,7 @@ class RDoc::Parser::C < RDoc::Parser
handle_method("method", "rb_mFileTest", meth_name, meth_body, param_count)
handle_method("singleton_method", "rb_cFile", meth_name, meth_body, param_count)
end
- end
+ end
def find_attr_comment(attr_name)
if @content =~ %r{((?>/\*.*?\*/\s+))
@@ -267,10 +268,10 @@ class RDoc::Parser::C < RDoc::Parser
##
# Find the C code corresponding to a Ruby method
- def find_body(meth_name, meth_obj, body, quiet = false)
+ def find_body(class_name, meth_name, meth_obj, body, quiet = false)
case body
- when %r"((?>/\*.*?\*/\s*))(?:static\s+)?VALUE\s+#{meth_name}
- \s*(\([^)]*\))\s*\{.*?^\}"xm
+ when %r"((?>/\*.*?\*/\s*)*)(?:(?:static|SWIGINTERN)\s+)?(?:intern\s+)?VALUE\s+#{meth_name}
+ \s*(\([^)]*\))([^;]|$)"xm
comment, params = $1, $2
body_text = $&
@@ -279,9 +280,7 @@ class RDoc::Parser::C < RDoc::Parser
# see if we can find the whole body
re = Regexp.escape(body_text) + '[^(]*^\{.*?^\}'
- if Regexp.new(re, Regexp::MULTILINE).match(body)
- body_text = $&
- end
+ body_text = $& if /#{re}/m =~ body
# The comment block may have been overridden with a 'Document-method'
# block. This happens in the interpreter when multiple methods are
@@ -289,7 +288,7 @@ class RDoc::Parser::C < RDoc::Parser
# distinct (for example Kernel.hash and Kernel.object_id share the same
# implementation
- override_comment = find_override_comment(meth_obj.name)
+ override_comment = find_override_comment(class_name, meth_obj.name)
comment = override_comment if override_comment
find_modifiers(comment, meth_obj) if comment
@@ -300,18 +299,18 @@ class RDoc::Parser::C < RDoc::Parser
meth_obj.comment = mangle_comment(comment)
when %r{((?>/\*.*?\*/\s*))^\s*\#\s*define\s+#{meth_name}\s+(\w+)}m
comment = $1
- find_body($2, meth_obj, body, true)
+ find_body(class_name, $2, meth_obj, body, true)
find_modifiers(comment, meth_obj)
meth_obj.comment = mangle_comment(comment) + meth_obj.comment
when %r{^\s*\#\s*define\s+#{meth_name}\s+(\w+)}m
- unless find_body($1, meth_obj, body, true)
+ unless find_body(class_name, $1, meth_obj, body, true)
warn "No definition for #{meth_name}" unless @options.quiet
return false
end
else
# No body, but might still have an override comment
- comment = find_override_comment(meth_obj.name)
+ comment = find_override_comment(class_name, meth_obj.name)
if comment
find_modifiers(comment, meth_obj)
@@ -367,10 +366,10 @@ class RDoc::Parser::C < RDoc::Parser
def find_class_comment(class_name, class_meth)
comment = nil
if @content =~ %r{((?>/\*.*?\*/\s+))
- (static\s+)?void\s+Init_#{class_name}\s*(?:_\(\s*)?\(\s*(?:void\s*)\)}xmi
+ (static\s+)?void\s+Init_#{class_name}\s*(?:_\(\s*)?\(\s*(?:void\s*)\)}xmi then
+ comment = $1
+ elsif @content =~ %r{Document-(?:class|module):\s#{class_name}\s*?(?:<\s+[:,\w]+)?\n((?>.*?\*/))}m
comment = $1
- elsif @content =~ %r{Document-(class|module):\s#{class_name}\s*?\n((?>.*?\*/))}m
- comment = $2
else
if @content =~ /rb_define_(class|module)/m then
class_name = class_name.split("::").last
@@ -424,9 +423,11 @@ class RDoc::Parser::C < RDoc::Parser
end
end
- def find_override_comment(meth_name)
+ def find_override_comment(class_name, meth_name)
name = Regexp.escape(meth_name)
- if @content =~ %r{Document-method:\s#{name}\s*?\n((?>.*?\*/))}m
+ if @content =~ %r{Document-method:\s+#{class_name}(?:\.|::)#{name}\s*?\n((?>.*?\*/))}m then
+ $1
+ elsif @content =~ %r{Document-method:\s#{name}\s*?\n((?>.*?\*/))}m then
$1
end
end
@@ -480,6 +481,10 @@ class RDoc::Parser::C < RDoc::Parser
end
if class_mod == "class" then
+ full_name = enclosure.full_name.to_s + "::#{class_name}"
+ if @content =~ %r{Document-class:\s+#{full_name}\s*<\s+([:,\w]+)} then
+ parent_name = $1
+ end
cm = enclosure.add_class RDoc::NormalClass, class_name, parent_name
@stats.add_class cm
else
@@ -562,18 +567,16 @@ class RDoc::Parser::C < RDoc::Parser
return unless class_name
- class_obj = find_class(var_name, class_name)
+ class_obj = find_class var_name, class_name
- if class_obj
- if meth_name == "initialize"
+ if class_obj then
+ if meth_name == "initialize" then
meth_name = "new"
type = "singleton_method"
end
- meth_obj = RDoc::AnyMethod.new("", meth_name)
- meth_obj.singleton =
- %w{singleton_method module_function}.include?(type)
- @stats.add_method meth_obj
+ meth_obj = RDoc::AnyMethod.new '', meth_name
+ meth_obj.singleton = %w[singleton_method module_function].include? type
p_count = (Integer(param_count) rescue -1)
@@ -585,14 +588,16 @@ class RDoc::Parser::C < RDoc::Parser
meth_obj.params = "(" + (1..p_count).map{|i| "p#{i}"}.join(", ") + ")"
end
- if source_file
+ if source_file then
file_name = File.join(@file_dir, source_file)
body = (@@known_bodies[source_file] ||= File.read(file_name))
else
body = @content
end
- if find_body(meth_body, meth_obj, body) and meth_obj.document_self
- class_obj.add_method(meth_obj)
+
+ if find_body(class_name, meth_body, meth_obj, body) and meth_obj.document_self then
+ class_obj.add_method meth_obj
+ @stats.add_method meth_obj
end
end
end
@@ -628,8 +633,8 @@ class RDoc::Parser::C < RDoc::Parser
end
def remove_private_comments(comment)
- comment.gsub!(/\/?\*--(.*?)\/?\*\+\+/m, '')
- comment.sub!(/\/?\*--.*/m, '')
+ comment.gsub!(/\/?\*--\n(.*?)\/?\*\+\+/m, '')
+ comment.sub!(/\/?\*--\n.*/m, '')
end
##
diff --git a/lib/rdoc/parser/perl.rb b/lib/rdoc/parser/perl.rb
new file mode 100644
index 0000000000..43d1e9ff69
--- /dev/null
+++ b/lib/rdoc/parser/perl.rb
@@ -0,0 +1,165 @@
+require 'rdoc/parser'
+
+##
+#
+# This is an attamept to write a basic parser for Perl's
+# POD (Plain old Documentation) format. Ruby code must
+# co-exist with Perl, and some tasks are easier in Perl
+# than Ruby because of existing libraries.
+#
+# One difficult is that Perl POD has no means of identifying
+# the classes (packages) and methods (subs) with which it
+# is associated, it is more like literate programming in so
+# far as it just happens to be in the same place as the code,
+# but need not be.
+#
+# We would like to support all the markup the POD provides
+# so that it will convert happily to HTML. At the moment
+# I don't think I can do that: time constraints.
+#
+
+class RDoc::Parser::PerlPOD < RDoc::Parser
+
+ parse_files_matching(/.p[lm]$/)
+
+ ##
+ # Prepare to parse a perl file
+
+ def initialize(top_level, file_name, content, options, stats)
+ super
+
+ preprocess = RDoc::Markup::PreProcess.new @file_name, @options.rdoc_include
+
+ preprocess.handle @content do |directive, param|
+ warn "Unrecognized directive '#{directive}' in #{@file_name}"
+ end
+ end
+
+ ##
+ # Extract the Pod(-like) comments from the code.
+ # At its most basic there will ne no need to distinguish
+ # between the different types of header, etc.
+ #
+ # This uses a simple finite state machine, in a very
+ # procedural pattern. I could "replace case with polymorphism"
+ # but I think it would obscure the intent, scatter the
+ # code all over tha place. This machine is necessary
+ # because POD requires that directives be preceded by
+ # blank lines, so reading line by line is necessary,
+ # and preserving state about what is seen is necesary.
+
+ def scan
+
+ @top_level.comment ||= ""
+ state=:code_blank
+ line_number = 0
+ line = nil
+
+ # This started out as a really long nested case statement,
+ # which also led to repetitive code. I'd like to avoid that
+ # so I'm using a "table" instead.
+
+ # Firstly we need some procs to do the transition and processing
+ # work. Because these are procs they are closures, and they can
+ # use variables in the local scope.
+ #
+ # First, the "nothing to see here" stuff.
+ code_noop = lambda do
+ if line =~ /^\s+$/
+ state = :code_blank
+ end
+ end
+
+ pod_noop = lambda do
+ if line =~ /^\s+$/
+ state = :pod_blank
+ end
+ @top_level.comment += filter(line)
+ end
+
+ begin_noop = lambda do
+ if line =~ /^\s+$/
+ state = :begin_blank
+ end
+ @top_level.comment += filter(line)
+ end
+
+ # Now for the blocks that process code and comments...
+
+ transit_to_pod = lambda do
+ case line
+ when /^=(?:pod|head\d+)/
+ state = :pod_no_blank
+ @top_level.comment += filter(line)
+ when /^=over/
+ state = :over_no_blank
+ @top_level.comment += filter(line)
+ when /^=(?:begin|for)/
+ state = :begin_no_blank
+ end
+ end
+
+ process_pod = lambda do
+ case line
+ when /^\s*$/
+ state = :pod_blank
+ @top_level.comment += filter(line)
+ when /^=cut/
+ state = :code_no_blank
+ when /^=end/
+ $stderr.puts "'=end' unexpected at #{line_number} in #{@file_name}"
+ else
+ @top_level.comment += filter(line)
+ end
+ end
+
+
+ process_begin = lambda do
+ case line
+ when /^\s*$/
+ state = :begin_blank
+ @top_level.comment += filter(line)
+ when /^=end/
+ state = :code_no_blank
+ when /^=cut/
+ $stderr.puts "'=cut' unexpected at #{line_number} in #{@file_name}"
+ else
+ @top_level.comment += filter(line)
+ end
+
+ end
+
+
+ transitions = { :code_no_blank => code_noop,
+ :code_blank => transit_to_pod,
+ :pod_no_blank => pod_noop,
+ :pod_blank => process_pod,
+ :begin_no_blank => begin_noop,
+ :begin_blank => process_begin}
+ @content.each_line do |l|
+ line = l
+ line_number += 1
+ transitions[state].call
+ end # each line
+
+ @top_level
+ end
+
+ # Filter the perl markup that does the same as the rdoc
+ # filtering. Only basic for now. Will probably need a
+ # proper parser to cope with C<<...>> etc
+ def filter(comment)
+ return '' if comment =~ /^=pod\s*$/
+ comment.gsub!(/^=pod/, '==')
+ comment.gsub!(/^=head(\d+)/) do
+ "=" * $1.to_i
+ end
+ comment.gsub!(/=item/, '');
+ comment.gsub!(/C<(.*?)>/, '<tt>\1</tt>');
+ comment.gsub!(/I<(.*?)>/, '<i>\1</i>');
+ comment.gsub!(/B<(.*?)>/, '<b>\1</b>');
+ comment
+ end
+
+end
+
diff --git a/lib/rdoc/parser/ruby.rb b/lib/rdoc/parser/ruby.rb
index abbc85bde7..865cb79d39 100644
--- a/lib/rdoc/parser/ruby.rb
+++ b/lib/rdoc/parser/ruby.rb
@@ -134,7 +134,7 @@ module RDoc::RubyToken
TokenDefinitions = [
[:TkCLASS, TkKW, "class", EXPR_CLASS],
- [:TkMODULE, TkKW, "module", EXPR_BEG],
+ [:TkMODULE, TkKW, "module", EXPR_CLASS],
[:TkDEF, TkKW, "def", EXPR_FNAME],
[:TkUNDEF, TkKW, "undef", EXPR_FNAME],
[:TkBEGIN, TkKW, "begin", EXPR_BEG],
@@ -1945,9 +1945,9 @@ class RDoc::Parser::Ruby < RDoc::Parser
case tk
when TkSEMICOLON
break
- when TkLPAREN, TkfLPAREN
+ when TkLPAREN, TkfLPAREN, TkLBRACE, TkLBRACK, TkDO
nest += 1
- when TkRPAREN
+ when TkRPAREN, TkRBRACE, TkRBRACK, TkEND
nest -= 1
when TkCOMMENT
if nest <= 0 && @scanner.lex_state == EXPR_END
@@ -1955,7 +1955,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
break
end
when TkNL
- if (@scanner.lex_state == EXPR_END and nest <= 0) || !@scanner.continue
+ if (nest <= 0) && ((@scanner.lex_state == EXPR_END) || (!@scanner.continue))
unget_tk(tk)
break
end
@@ -2683,8 +2683,8 @@ class RDoc::Parser::Ruby < RDoc::Parser
end
def remove_private_comments(comment)
- comment.gsub!(/^#--.*?^#\+\+/m, '')
- comment.sub!(/^#--.*/m, '')
+ comment.gsub!(/^#--\n.*?^#\+\+/m, '')
+ comment.sub!(/^#--\n.*/m, '')
end
def remove_token_listener(obj)
diff --git a/lib/rdoc/parser/simple.rb b/lib/rdoc/parser/simple.rb
index 6e123a4655..cdfe686718 100644
--- a/lib/rdoc/parser/simple.rb
+++ b/lib/rdoc/parser/simple.rb
@@ -31,7 +31,7 @@ class RDoc::Parser::Simple < RDoc::Parser
end
def remove_private_comments(comment)
- comment.gsub(/^--[^-].*?^\+\+/m, '').sub(/^--.*/m, '')
+ comment.gsub(/^--\n.*?^\+\+/m, '').sub(/^--\n.*/m, '')
end
end
diff --git a/lib/rdoc/rdoc.rb b/lib/rdoc/rdoc.rb
index bc0a32f407..ce1cb1a93f 100644
--- a/lib/rdoc/rdoc.rb
+++ b/lib/rdoc/rdoc.rb
@@ -7,6 +7,7 @@ require 'rdoc/parser/simple'
require 'rdoc/parser/ruby'
require 'rdoc/parser/c'
require 'rdoc/parser/f95'
+require 'rdoc/parser/perl'
require 'rdoc/stats'
require 'rdoc/options'
@@ -189,11 +190,11 @@ module RDoc
def parse_files(options)
@stats = Stats.new options.verbosity
-
+
files = options.files
files = ["."] if files.empty?
- file_list = normalized_file_list(options, files, true)
+ file_list = normalized_file_list(options, files, true, options.exclude)
return [] if file_list.empty?
@@ -288,6 +289,5 @@ module RDoc
end
end
end
-
end
diff --git a/lib/rdoc/ri/cache.rb b/lib/rdoc/ri/cache.rb
index 2e267d95fb..06177a00de 100644
--- a/lib/rdoc/ri/cache.rb
+++ b/lib/rdoc/ri/cache.rb
@@ -14,7 +14,7 @@ class RDoc::RI::ClassEntry
@inferior_classes = []
end
- # We found this class in more tha one place, so add
+ # We found this class in more than one place, so add
# in the name from there.
def add_path(path)
@path_names << path
@@ -37,10 +37,10 @@ class RDoc::RI::ClassEntry
if name =~ /^(.*?)-(c|i).yaml$/
external_name = $1
is_class_method = $2 == "c"
- internal_name = RiWriter.external_to_internal(external_name)
+ internal_name = RDoc::RI::Writer.external_to_internal(external_name)
list = is_class_method ? @class_methods : @instance_methods
path = File.join(dir, name)
- list << MethodEntry.new(path, internal_name, is_class_method, self)
+ list << RDoc::RI::MethodEntry.new(path, internal_name, is_class_method, self)
else
full_name = File.join(dir, name)
if File.directory?(full_name)
@@ -48,7 +48,7 @@ class RDoc::RI::ClassEntry
if inf_class
inf_class.add_path(full_name)
else
- inf_class = ClassEntry.new(full_name, name, self)
+ inf_class = RDoc::RI::ClassEntry.new(full_name, name, self)
@inferior_classes << inf_class
end
inf_class.load_from(full_name)
@@ -168,7 +168,7 @@ class RDoc::RI::MethodEntry
end
##
-# We represent everything know about all 'ri' files accessible to this program
+# We represent everything known about all 'ri' files accessible to this program
class RDoc::RI::Cache
@@ -185,4 +185,3 @@ class RDoc::RI::Cache
end
end
-
diff --git a/lib/rdoc/ri/descriptions.rb b/lib/rdoc/ri/descriptions.rb
index 0d8560323a..467b7de2a9 100644
--- a/lib/rdoc/ri/descriptions.rb
+++ b/lib/rdoc/ri/descriptions.rb
@@ -77,7 +77,9 @@ end
class RDoc::RI::ModuleDescription < RDoc::RI::Description
attr_accessor :class_methods
+ attr_accessor :class_method_extensions
attr_accessor :instance_methods
+ attr_accessor :instance_method_extensions
attr_accessor :attributes
attr_accessor :constants
attr_accessor :includes
@@ -148,6 +150,7 @@ class RDoc::RI::MethodDescription < RDoc::RI::Description
attr_accessor :aliases
attr_accessor :is_alias_for
attr_accessor :params
+ attr_accessor :source_path
end
diff --git a/lib/rdoc/ri/display.rb b/lib/rdoc/ri/display.rb
index 379cef11b3..7b0158c18a 100644
--- a/lib/rdoc/ri/display.rb
+++ b/lib/rdoc/ri/display.rb
@@ -1,5 +1,15 @@
require 'rdoc/ri'
+# readline support might not be present, so be careful
+# when requiring it.
+begin
+ require('readline')
+ require('abbrev')
+ CAN_USE_READLINE = true # HACK use an RDoc namespace constant
+rescue LoadError
+ CAN_USE_READLINE = false
+end
+
##
# This is a kind of 'flag' module. If you want to write your own 'ri' display
# module (perhaps because you're writing an IDE), you write a class which
@@ -41,9 +51,9 @@ class RDoc::RI::DefaultDisplay
# Display information about +klass+. Fetches additional information from
# +ri_reader+ as necessary.
- def display_class_info(klass, ri_reader)
+ def display_class_info(klass)
page do
- superclass = klass.superclass_string
+ superclass = klass.superclass
if superclass
superclass = " < " + superclass
@@ -61,17 +71,11 @@ class RDoc::RI::DefaultDisplay
@formatter.blankline
@formatter.display_heading("Includes:", 2, "")
incs = []
+
klass.includes.each do |inc|
- inc_desc = ri_reader.find_class_by_name(inc.name)
- if inc_desc
- str = inc.name + "("
- str << inc_desc.instance_methods.map{|m| m.name}.join(", ")
- str << ")"
- incs << str
- else
- incs << inc.name
- end
- end
+ incs << inc.name
+ end
+
@formatter.wrap(incs.sort.join(', '))
end
@@ -82,42 +86,19 @@ class RDoc::RI::DefaultDisplay
constants = klass.constants.sort_by { |constant| constant.name }
constants.each do |constant|
+ @formatter.wrap "#{constant.name} = #{constant.value}"
if constant.comment then
- @formatter.wrap "#{constant.name}:"
-
@formatter.indent do
@formatter.display_flow constant.comment
end
else
- @formatter.wrap constant.name
+ @formatter.break_to_newline
end
end
end
- class_data = [
- :class_methods,
- :class_method_extensions,
- :instance_methods,
- :instance_method_extensions,
- ]
-
- class_data.each do |data_type|
- data = klass.send data_type
-
- unless data.empty? then
- @formatter.blankline
-
- heading = data_type.to_s.split('_').join(' ').capitalize << ':'
- @formatter.display_heading heading, 2, ''
-
- data = data.map { |item| item.name }.sort.join ', '
- @formatter.wrap data
- end
- end
-
unless klass.attributes.empty? then
@formatter.blankline
-
@formatter.display_heading 'Attributes:', 2, ''
attributes = klass.attributes.sort_by { |attribute| attribute.name }
@@ -130,11 +111,119 @@ class RDoc::RI::DefaultDisplay
end
else
@formatter.wrap "#{attribute.name} (#{attribute.rw})"
+ @formatter.break_to_newline
+ end
+ end
+ end
+
+ return display_class_method_list(klass)
+ end
+ end
+
+ ##
+ # Given a Hash mapping a class' methods to method types (returned by
+ # display_class_method_list), this method allows the user to
+ # choose one of the methods.
+
+ def get_class_method_choice(method_map)
+ if CAN_USE_READLINE
+ # prepare abbreviations for tab completion
+ abbreviations = method_map.keys.abbrev
+ Readline.completion_proc = proc do |string|
+ abbreviations.values.uniq.grep(/^#{string}/)
+ end
+ end
+
+ @formatter.raw_print_line "\nEnter the method name you want.\n"
+ @formatter.raw_print_line "Class methods can be preceeded by '::' and instance methods by '#'.\n"
+
+ if CAN_USE_READLINE
+ @formatter.raw_print_line "You can use tab to autocomplete.\n"
+ @formatter.raw_print_line "Enter a blank line to exit.\n"
+
+ choice_string = Readline.readline(">> ").strip
+ else
+ @formatter.raw_print_line "Enter a blank line to exit.\n"
+ @formatter.raw_print_line ">> "
+ choice_string = $stdin.gets.strip
+ end
+
+ if choice_string == ''
+ return nil
+ else
+ class_or_instance = method_map[choice_string]
+
+ if class_or_instance
+ # If the user's choice is not preceeded by a '::' or a '#', figure
+ # out whether they want a class or an instance method and decorate
+ # the choice appropriately.
+ if(choice_string =~ /^[a-zA-Z]/)
+ if(class_or_instance == :class)
+ choice_string = "::#{choice_string}"
+ else
+ choice_string = "##{choice_string}"
end
end
+
+ return choice_string
+ else
+ @formatter.raw_print_line "No method matched '#{choice_string}'.\n"
+ return nil
end
end
end
+
+
+ ##
+ # Display methods on +klass+
+ # Returns a hash mapping method name to method contents (HACK?)
+
+ def display_class_method_list(klass)
+ method_map = {}
+
+ class_data = [
+ :class_methods,
+ :class_method_extensions,
+ :instance_methods,
+ :instance_method_extensions,
+ ]
+
+ class_data.each do |data_type|
+ data = klass.send data_type
+
+ unless data.nil? or data.empty? then
+ @formatter.blankline
+
+ heading = data_type.to_s.split('_').join(' ').capitalize << ':'
+ @formatter.display_heading heading, 2, ''
+
+ method_names = []
+ data.each do |item|
+ method_names << item.name
+
+ if(data_type == :class_methods ||
+ data_type == :class_method_extensions) then
+ method_map["::#{item.name}"] = :class
+ method_map[item.name] = :class
+ else
+ #
+ # Since we iterate over instance methods after class methods,
+ # an instance method always will overwrite the unqualified
+ # class method entry for a class method of the same name.
+ #
+ method_map["##{item.name}"] = :instance
+ method_map[item.name] = :instance
+ end
+ end
+ method_names.sort!
+
+ @formatter.wrap method_names.join(', ')
+ end
+ end
+
+ method_map
+ end
+ private :display_class_method_list
##
# Display an Array of RDoc::Markup::Flow objects, +flow+.
@@ -172,10 +261,42 @@ class RDoc::RI::DefaultDisplay
def display_method_list(methods)
page do
@formatter.wrap "More than one method matched your request. You can refine your search by asking for information on one of:"
+ @formatter.blankline
+
+ methods.each do |method|
+ @formatter.raw_print_line "#{method.full_name} [#{method.source_path}]\n"
+ end
+ end
+ end
+
+ ##
+ # Display a list of +methods+ and allow the user to select one of them.
+ def display_method_list_choice(methods)
+ page do
+ @formatter.wrap "More than one method matched your request. Please choose one of the possible matches."
@formatter.blankline
- @formatter.wrap methods.map { |m| m.full_name }.join(", ")
+ methods.each_with_index do |method, index|
+ @formatter.raw_print_line "%3d %s [%s]\n" % [index + 1, method.full_name, method.source_path]
+ end
+
+ @formatter.raw_print_line ">> "
+
+ choice = $stdin.gets.strip!
+
+ if(choice == '')
+ return
+ end
+
+ choice = choice.to_i
+
+ if ((choice == 0) || (choice > methods.size)) then
+ @formatter.raw_print_line "Invalid choice!\n"
+ else
+ method = methods[choice - 1]
+ display_method_info(method)
+ end
end
end
@@ -198,10 +319,8 @@ class RDoc::RI::DefaultDisplay
@formatter.break_to_newline
end
- if method.source_path then
- @formatter.blankline
- @formatter.wrap("Extension from #{method.source_path}")
- end
+ @formatter.blankline
+ @formatter.wrap("From #{method.source_path}")
end
##
@@ -271,4 +390,3 @@ class RDoc::RI::DefaultDisplay
end
end
-
diff --git a/lib/rdoc/ri/driver.rb b/lib/rdoc/ri/driver.rb
index dfc5f2f98a..0c91232b70 100644
--- a/lib/rdoc/ri/driver.rb
+++ b/lib/rdoc/ri/driver.rb
@@ -11,29 +11,33 @@ require 'rdoc/markup/to_flow'
class RDoc::RI::Driver
- class Hash < ::Hash
- def self.convert(hash)
- hash = new.update hash
-
- hash.each do |key, value|
- hash[key] = case value
- when ::Hash then
- convert value
- when Array then
- value = value.map do |v|
- ::Hash === v ? convert(v) : v
- end
- value
- else
- value
- end
- end
-
- hash
- end
+ #
+ # This class offers both Hash and OpenStruct functionality.
+ # We convert from the Core Hash to this before calling any of
+ # the display methods, in order to give the display methods
+ # a cleaner API for accessing the data.
+ #
+ class OpenStructHash < Hash
+ #
+ # This method converts from a Hash to an OpenStructHash.
+ #
+ def self.convert(object)
+ case object
+ when Hash then
+ new_hash = new # Convert Hash -> OpenStructHash
+
+ object.each do |key, value|
+ new_hash[key] = convert(value)
+ end
- def method_missing method, *args
- self[method.to_s]
+ new_hash
+ when Array then
+ object.map do |element|
+ convert(element)
+ end
+ else
+ object
+ end
end
def merge_enums(other)
@@ -57,6 +61,10 @@ class RDoc::RI::Driver
end
end
end
+
+ def method_missing method, *args
+ self[method.to_s]
+ end
end
class Error < RDoc::RI::Error; end
@@ -69,25 +77,31 @@ class RDoc::RI::Driver
attr_accessor :homepath # :nodoc:
- def self.process_args(argv)
+ def self.default_options
options = {}
options[:use_stdout] = !$stdout.tty?
options[:width] = 72
options[:formatter] = RDoc::RI::Formatter.for 'plain'
- options[:list_classes] = false
- options[:list_names] = false
+ options[:interactive] = false
+ options[:use_cache] = true
+
+ # By default all standard paths are used.
+ options[:use_system] = true
+ options[:use_site] = true
+ options[:use_home] = true
+ options[:use_gems] = true
+ options[:extra_doc_dirs] = []
+
+ return options
+ end
- # By default all paths are used. If any of these are true, only those
- # directories are used.
- use_system = false
- use_site = false
- use_home = false
- use_gems = false
- doc_dirs = []
+ def self.process_args(argv)
+ options = default_options
opts = OptionParser.new do |opt|
opt.program_name = File.basename $0
opt.version = RDoc::VERSION
+ opt.release = nil
opt.summary_indent = ' ' * 4
directories = [
@@ -142,86 +156,114 @@ Options may also be set in the 'RI' environment variable.
opt.separator "Options:"
opt.separator nil
- opt.on("--classes", "-c",
- "Display the names of classes and modules we",
- "know about.") do |value|
- options[:list_classes] = value
+ opt.on("--fmt=FORMAT", "--format=FORMAT", "-f",
+ RDoc::RI::Formatter::FORMATTERS.keys,
+ "Format to use when displaying output:",
+ " #{RDoc::RI::Formatter.list}",
+ "Use 'bs' (backspace) with most pager",
+ "programs. To use ANSI, either disable the",
+ "pager or tell the pager to allow control",
+ "characters.") do |value|
+ options[:formatter] = RDoc::RI::Formatter.for value
end
opt.separator nil
opt.on("--doc-dir=DIRNAME", "-d", Array,
- "List of directories to search for",
- "documentation. If not specified, we search",
- "the standard rdoc/ri directories. May be",
- "repeated.") do |value|
+ "List of directories from which to source",
+ "documentation in addition to the standard",
+ "directories. May be repeated.") do |value|
value.each do |dir|
unless File.directory? dir then
raise OptionParser::InvalidArgument, "#{dir} is not a directory"
end
+
+ options[:extra_doc_dirs] << File.expand_path(dir)
end
+ end
+
+ opt.separator nil
- doc_dirs.concat value
+ opt.on("--[no-]use-cache",
+ "Whether or not to use ri's cache.",
+ "True by default.") do |value|
+ options[:use_cache] = value
end
opt.separator nil
- opt.on("--fmt=FORMAT", "--format=FORMAT", "-f",
- RDoc::RI::Formatter::FORMATTERS.keys,
- "Format to use when displaying output:",
- " #{RDoc::RI::Formatter.list}",
- "Use 'bs' (backspace) with most pager",
- "programs. To use ANSI, either disable the",
- "pager or tell the pager to allow control",
- "characters.") do |value|
- options[:formatter] = RDoc::RI::Formatter.for value
+ opt.on("--no-standard-docs",
+ "Do not include documentation from",
+ "the Ruby standard library, site_lib,",
+ "installed gems, or ~/.rdoc.",
+ "Equivalent to specifying",
+ "the options --no-system, --no-site, --no-gems,",
+ "and --no-home") do
+ options[:use_system] = false
+ options[:use_site] = false
+ options[:use_gems] = false
+ options[:use_home] = false
end
opt.separator nil
- unless RDoc::RI::Paths::GEMDIRS.empty? then
- opt.on("--[no-]gems",
- "Include documentation from RubyGems.") do |value|
- use_gems = value
- end
+ opt.on("--[no-]system",
+ "Include documentation from Ruby's standard",
+ "library. Defaults to true.") do |value|
+ options[:use_system] = value
end
opt.separator nil
- opt.on("--[no-]home",
- "Include documentation stored in ~/.rdoc.") do |value|
- use_home = value
+ opt.on("--[no-]site",
+ "Include documentation from libraries",
+ "installed in site_lib.",
+ "Defaults to true.") do |value|
+ options[:use_site] = value
end
opt.separator nil
- opt.on("--[no-]list-names", "-l",
- "List all the names known to RDoc, one per",
- "line.") do |value|
- options[:list_names] = value
+ opt.on("--[no-]gems",
+ "Include documentation from RubyGems.",
+ "Defaults to true.") do |value|
+ options[:use_gems] = value
end
opt.separator nil
- opt.on("--no-pager", "-T",
- "Send output directly to stdout.") do |value|
- options[:use_stdout] = !value
+ opt.on("--[no-]home",
+ "Include documentation stored in ~/.rdoc.",
+ "Defaults to true.") do |value|
+ options[:use_home] = value
end
opt.separator nil
- opt.on("--[no-]site",
- "Include documentation from libraries",
- "installed in site_lib.") do |value|
- use_site = value
+ opt.on("--list-doc-dirs",
+ "List the directories from which ri will",
+ "source documentation on stdout and exit.") do
+ options[:list_doc_dirs] = true
end
opt.separator nil
- opt.on("--[no-]system",
- "Include documentation from Ruby's standard",
- "library.") do |value|
- use_system = value
+ opt.on("--no-pager", "-T",
+ "Send output directly to stdout,",
+ "rather than to a pager.") do
+ options[:use_stdout] = true
+ end
+
+ opt.on("--interactive", "-i",
+ "This makes ri go into interactive mode.",
+ "When ri is in interactive mode it will",
+ "allow the user to disambiguate lists of",
+ "methods in case multiple methods match",
+ "against a method search string. It also",
+ "will allow the user to enter in a method",
+ "name (with auto-completion, if readline",
+ "is supported) when viewing a class.") do
+ options[:interactive] = true
end
opt.separator nil
@@ -238,10 +280,10 @@ Options may also be set in the 'RI' environment variable.
options[:names] = argv
- options[:path] = RDoc::RI::Paths.path(use_system, use_site, use_home,
- use_gems, *doc_dirs)
- options[:raw_path] = RDoc::RI::Paths.raw_path(use_system, use_site,
- use_home, use_gems, *doc_dirs)
+ options[:formatter] ||= RDoc::RI::Formatter.for('plain')
+ options[:use_stdout] ||= !$stdout.tty?
+ options[:use_stdout] ||= options[:interactive]
+ options[:width] ||= 72
options
@@ -258,22 +300,30 @@ Options may also be set in the 'RI' environment variable.
ri.run
end
- def initialize(options={})
- options[:formatter] ||= RDoc::RI::Formatter.for('plain')
- options[:use_stdout] ||= !$stdout.tty?
- options[:width] ||= 72
- @names = options[:names]
+ def initialize(initial_options={})
+ options = self.class.default_options.update(initial_options)
+ @names = options[:names]
@class_cache_name = 'classes'
- @all_dirs = RDoc::RI::Paths.path(true, true, true, true)
+
+ @doc_dirs = RDoc::RI::Paths.path(options[:use_system],
+ options[:use_site],
+ options[:use_home],
+ options[:use_gems],
+ options[:extra_doc_dirs])
+
@homepath = RDoc::RI::Paths.raw_path(false, false, true, false).first
@homepath = @homepath.sub(/\.rdoc/, '.ri')
- @sys_dirs = RDoc::RI::Paths.raw_path(true, false, false, false)
+ @sys_dir = RDoc::RI::Paths.raw_path(true, false, false, false).first
+ @list_doc_dirs = options[:list_doc_dirs]
FileUtils.mkdir_p cache_file_path unless File.directory? cache_file_path
+ @cache_doc_dirs_path = File.join cache_file_path, ".doc_dirs"
+ @use_cache = options[:use_cache]
@class_cache = nil
+ @interactive = options[:interactive]
@display = RDoc::RI::DefaultDisplay.new(options[:formatter],
options[:width],
options[:use_stdout])
@@ -282,30 +332,92 @@ Options may also be set in the 'RI' environment variable.
def class_cache
return @class_cache if @class_cache
- newest = map_dirs('created.rid', :all) do |f|
+ # Get the documentation directories used to make the cache in order to see
+ # whether the cache is valid for the current ri instantiation.
+ if(File.readable?(@cache_doc_dirs_path))
+ cache_doc_dirs = IO.read(@cache_doc_dirs_path).split("\n")
+ else
+ cache_doc_dirs = []
+ end
+
+ newest = map_dirs('created.rid') do |f|
File.mtime f if test ?f, f
end.max
+ # An up to date cache file must have been created more recently than
+ # the last modification of any of the documentation directories. It also
+ # must have been created with the same documentation directories
+ # as those from which ri currently is sourcing documentation.
up_to_date = (File.exist?(class_cache_file_path) and
- newest and newest < File.mtime(class_cache_file_path))
+ newest and newest < File.mtime(class_cache_file_path) and
+ (cache_doc_dirs == @doc_dirs))
+
+ if up_to_date and @use_cache then
+ open class_cache_file_path, 'rb' do |fp|
+ begin
+ @class_cache = Marshal.load fp.read
+ rescue
+ #
+ # This shouldn't be necessary, since the up_to_date logic above
+ # should force the cache to be recreated when a new version of
+ # rdoc is installed. This seems like a worthwhile enhancement
+ # to ri's robustness, however.
+ #
+ $stderr.puts "Error reading the class cache; recreating the class cache!"
+ @class_cache = create_class_cache
+ end
+ end
+ else
+ @class_cache = create_class_cache
+ end
+
+ @class_cache
+ end
- @class_cache = if up_to_date then
- load_cache_for @class_cache_name
- else
- class_cache = RDoc::RI::Driver::Hash.new
+ def create_class_cache
+ class_cache = OpenStructHash.new
- classes = map_dirs('**/cdesc*.yaml', :sys) { |f| Dir[f] }
- populate_class_cache class_cache, classes
+ if(@use_cache)
+ # Dump the documentation directories to a file in the cache, so that
+ # we only will use the cache for future instantiations with identical
+ # documentation directories.
+ File.open @cache_doc_dirs_path, "wb" do |fp|
+ fp << @doc_dirs.join("\n")
+ end
+ end
- classes = map_dirs('**/cdesc*.yaml') { |f| Dir[f] }
- warn "Updating class cache with #{classes.size} classes..."
+ classes = map_dirs('**/cdesc*.yaml') { |f| Dir[f] }
+ warn "Updating class cache with #{classes.size} classes..."
+ populate_class_cache class_cache, classes
- populate_class_cache class_cache, classes, true
- write_cache class_cache, class_cache_file_path
- end
+ write_cache class_cache, class_cache_file_path
- @class_cache = RDoc::RI::Driver::Hash.convert @class_cache
- @class_cache
+ class_cache
+ end
+
+ def populate_class_cache(class_cache, classes, extension = false)
+ classes.each do |cdesc|
+ desc = read_yaml cdesc
+ klassname = desc["full_name"]
+
+ unless class_cache.has_key? klassname then
+ desc["display_name"] = "Class"
+ desc["sources"] = [cdesc]
+ desc["instance_method_extensions"] = []
+ desc["class_method_extensions"] = []
+ class_cache[klassname] = desc
+ else
+ klass = class_cache[klassname]
+
+ if extension then
+ desc["instance_method_extensions"] = desc.delete "instance_methods"
+ desc["class_method_extensions"] = desc.delete "class_methods"
+ end
+
+ klass.merge_enums desc
+ klass["sources"] << cdesc
+ end
+ end
end
def class_cache_file_path
@@ -322,8 +434,11 @@ Options may also be set in the 'RI' environment variable.
def display_class(name)
klass = class_cache[name]
- klass = RDoc::RI::Driver::Hash.convert klass
- @display.display_class_info klass, class_cache
+ @display.display_class_info klass
+ end
+
+ def display_method(method)
+ @display.display_method_info method
end
def get_info_for(arg)
@@ -337,48 +452,74 @@ Options may also be set in the 'RI' environment variable.
cache = nil
if File.exist? path and
- File.mtime(path) >= File.mtime(class_cache_file_path) then
+ File.mtime(path) >= File.mtime(class_cache_file_path) and
+ @use_cache then
open path, 'rb' do |fp|
- cache = Marshal.load fp.read
+ begin
+ cache = Marshal.load fp.read
+ rescue
+ #
+ # The cache somehow is bad. Recreate the cache.
+ #
+ $stderr.puts "Error reading the cache for #{klassname}; recreating the cache!"
+ cache = create_cache_for klassname, path
+ end
end
else
- class_cache = nil
+ cache = create_cache_for klassname, path
+ end
- open class_cache_file_path, 'rb' do |fp|
- class_cache = Marshal.load fp.read
- end
+ cache
+ end
- klass = class_cache[klassname]
- return nil unless klass
-
- method_files = klass["sources"]
- cache = RDoc::RI::Driver::Hash.new
-
- sys_dir = @sys_dirs.first
- method_files.each do |f|
- system_file = f.index(sys_dir) == 0
- Dir[File.join(File.dirname(f), "*")].each do |yaml|
- next unless yaml =~ /yaml$/
- next if yaml =~ /cdesc-[^\/]+yaml$/
- method = read_yaml yaml
- name = method["full_name"]
- ext_path = f
- ext_path = "gem #{$1}" if f =~ %r%gems/[\d.]+/doc/([^/]+)%
- method["source_path"] = ext_path unless system_file
- cache[name] = RDoc::RI::Driver::Hash.convert method
+ def create_cache_for(klassname, path)
+ klass = class_cache[klassname]
+ return nil unless klass
+
+ method_files = klass["sources"]
+ cache = OpenStructHash.new
+
+ method_files.each do |f|
+ system_file = f.index(@sys_dir) == 0
+ Dir[File.join(File.dirname(f), "*")].each do |yaml|
+ next unless yaml =~ /yaml$/
+ next if yaml =~ /cdesc-[^\/]+yaml$/
+
+ method = read_yaml yaml
+
+ if system_file then
+ method["source_path"] = "Ruby #{RDoc::RI::Paths::VERSION}"
+ else
+ if(f =~ %r%gems/[\d.]+/doc/([^/]+)%) then
+ ext_path = "gem #{$1}"
+ else
+ ext_path = f
+ end
+
+ method["source_path"] = ext_path
end
- end
- write_cache cache, path
+ name = method["full_name"]
+ cache[name] = method
+ end
end
- RDoc::RI::Driver::Hash.convert cache
+ write_cache cache, path
end
##
# Finds the next ancestor of +orig_klass+ after +klass+.
def lookup_ancestor(klass, orig_klass)
+ # This is a bit hacky, but ri will go into an infinite
+ # loop otherwise, since Object has an Object ancestor
+ # for some reason. Depending on the documentation state, I've seen
+ # Kernel as an ancestor of Object and not as an ancestor of Object.
+ if ((orig_klass == "Object") &&
+ ((klass == "Kernel") || (klass == "Object")))
+ return nil
+ end
+
cache = class_cache[orig_klass]
return nil unless cache
@@ -386,10 +527,13 @@ Options may also be set in the 'RI' environment variable.
ancestors = [orig_klass]
ancestors.push(*cache.includes.map { |inc| inc['name'] })
ancestors << cache.superclass
+
+ ancestor_index = ancestors.index(klass)
- ancestor = ancestors[ancestors.index(klass) + 1]
-
- return ancestor if ancestor
+ if ancestor_index
+ ancestor = ancestors[ancestors.index(klass) + 1]
+ return ancestor if ancestor
+ end
lookup_ancestor klass, cache.superclass
end
@@ -406,18 +550,8 @@ Options may also be set in the 'RI' environment variable.
method
end
- def map_dirs(file_name, system=false)
- dirs = if system == :all then
- @all_dirs
- else
- if system then
- @sys_dirs
- else
- @all_dirs - @sys_dirs
- end
- end
-
- dirs.map { |dir| yield File.join(dir, file_name) }.flatten.compact
+ def map_dirs(file_name)
+ @doc_dirs.map { |dir| yield File.join(dir, file_name) }.flatten.compact
end
##
@@ -436,83 +570,66 @@ Options may also be set in the 'RI' environment variable.
[klass, meth]
end
- def populate_class_cache(class_cache, classes, extension = false)
- classes.each do |cdesc|
- desc = read_yaml cdesc
- klassname = desc["full_name"]
-
- unless class_cache.has_key? klassname then
- desc["display_name"] = "Class"
- desc["sources"] = [cdesc]
- desc["instance_method_extensions"] = []
- desc["class_method_extensions"] = []
- class_cache[klassname] = desc
- else
- klass = class_cache[klassname]
-
- if extension then
- desc["instance_method_extensions"] = desc.delete "instance_methods"
- desc["class_method_extensions"] = desc.delete "class_methods"
- end
-
- klass = RDoc::RI::Driver::Hash.convert klass
-
- klass.merge_enums desc
- klass["sources"] << cdesc
- end
- end
- end
-
def read_yaml(path)
data = File.read path
+
+ # Necessary to be backward-compatible with documentation generated
+ # by earliar RDoc versions.
data = data.gsub(/ \!ruby\/(object|struct):(RDoc::RI|RI).*/, '')
data = data.gsub(/ \!ruby\/(object|struct):SM::(\S+)/,
' !ruby/\1:RDoc::Markup::\2')
- YAML.load data
+ OpenStructHash.convert(YAML.load(data))
end
def run
- if @names.empty? then
+ if(@list_doc_dirs)
+ puts @doc_dirs.join("\n")
+ elsif @names.empty? then
@display.list_known_classes class_cache.keys.sort
else
@names.each do |name|
- case name
- when /::|\#|\./ then
- if class_cache.key? name then
- display_class name
- else
- klass, = parse_name name
+ if class_cache.key? name then
+ method_map = display_class name
+ if(@interactive)
+ method_name = @display.get_class_method_choice(method_map)
+
+ if(method_name != nil)
+ method = lookup_method "#{name}#{method_name}", name
+ display_method method
+ end
+ end
+ elsif name =~ /::|\#|\./ then
+ klass, = parse_name name
- orig_klass = klass
- orig_name = name
+ orig_klass = klass
+ orig_name = name
- until klass == 'Kernel' do
- method = lookup_method name, klass
+ loop do
+ method = lookup_method name, klass
- break method if method
+ break method if method
- ancestor = lookup_ancestor klass, orig_klass
+ ancestor = lookup_ancestor klass, orig_klass
- break unless ancestor
+ break unless ancestor
- name = name.sub klass, ancestor
- klass = ancestor
- end
+ name = name.sub klass, ancestor
+ klass = ancestor
+ end
- raise NotFoundError, orig_name unless method
+ raise NotFoundError, orig_name unless method
- @display.display_method_info method
- end
+ display_method method
else
- if class_cache.key? name then
- display_class name
- else
- methods = select_methods(/^#{name}/)
+ methods = select_methods(/#{name}/)
- if methods.size == 0
- raise NotFoundError, name
- elsif methods.size == 1
- @display.display_method_info methods.first
+ if methods.size == 0
+ raise NotFoundError, name
+ elsif methods.size == 1
+ display_method methods[0]
+ else
+ if(@interactive)
+ @display.display_method_list_choice methods
else
@display.display_method_list methods
end
@@ -540,12 +657,13 @@ Options may also be set in the 'RI' environment variable.
end
def write_cache(cache, path)
- File.open path, "wb" do |cache_file|
- Marshal.dump cache, cache_file
+ if(@use_cache)
+ File.open path, "wb" do |cache_file|
+ Marshal.dump cache, cache_file
+ end
end
cache
end
end
-
diff --git a/lib/rdoc/ri/formatter.rb b/lib/rdoc/ri/formatter.rb
index 0a0c3f7380..933882abc4 100644
--- a/lib/rdoc/ri/formatter.rb
+++ b/lib/rdoc/ri/formatter.rb
@@ -93,7 +93,7 @@ class RDoc::RI::Formatter
end
def raw_print_line(txt)
- @output.puts txt
+ @output.print txt
end
##
diff --git a/lib/rdoc/ri/paths.rb b/lib/rdoc/ri/paths.rb
index b4b6c64925..2f72b9dfd5 100644
--- a/lib/rdoc/ri/paths.rb
+++ b/lib/rdoc/ri/paths.rb
@@ -26,9 +26,9 @@ module RDoc::RI::Paths
DOC_DIR = "doc/rdoc"
- version = RbConfig::CONFIG['ruby_version']
+ VERSION = RbConfig::CONFIG['ruby_version']
- base = File.join(RbConfig::CONFIG['datadir'], "ri", version)
+ base = File.join(RbConfig::CONFIG['datadir'], "ri", VERSION)
SYSDIR = File.join(base, "system")
SITEDIR = File.join(base, "site")
homedir = ENV['HOME'] || ENV['USERPROFILE'] || ENV['HOMEPATH']
@@ -39,9 +39,6 @@ module RDoc::RI::Paths
HOMEDIR = nil
end
- # This is the search path for 'ri'
- PATH = [ SYSDIR, SITEDIR, HOMEDIR ].find_all {|p| p && File.directory?(p)}
-
begin
require 'rubygems' unless defined?(Gem) and defined?(Gem::Enable) and
Gem::Enable
@@ -67,7 +64,6 @@ module RDoc::RI::Paths
end
GEMDIRS = ri_paths.map { |k,v| v.last }.sort
- GEMDIRS.each { |dir| PATH << dir }
rescue LoadError
GEMDIRS = []
end
@@ -85,9 +81,6 @@ module RDoc::RI::Paths
# found.
def self.raw_path(use_system, use_site, use_home, use_gems, *extra_dirs)
- return PATH unless use_system or use_site or use_home or use_gems or
- not extra_dirs.empty?
-
path = []
path << extra_dirs unless extra_dirs.empty?
path << SYSDIR if use_system
@@ -97,6 +90,4 @@ module RDoc::RI::Paths
return path.flatten.compact
end
-
end
-
diff --git a/lib/rdoc/ri/reader.rb b/lib/rdoc/ri/reader.rb
index 986bb75954..de3c8d9afa 100644
--- a/lib/rdoc/ri/reader.rb
+++ b/lib/rdoc/ri/reader.rb
@@ -45,7 +45,7 @@ class RDoc::RI::Reader
def get_method(method_entry)
path = method_entry.path_name
- File.open(path) { |f| RI::Description.deserialize(f) }
+ File.open(path) { |f| RDoc::RI::Description.deserialize(f) }
end
##
@@ -54,8 +54,8 @@ class RDoc::RI::Reader
def get_class(class_entry)
result = nil
for path in class_entry.path_names
- path = RiWriter.class_desc_path(path, class_entry)
- desc = File.open(path) {|f| RI::Description.deserialize(f) }
+ path = RDoc::RI::Writer.class_desc_path(path, class_entry)
+ desc = File.open(path) {|f| RDoc::RI::Description.deserialize(f) }
if result
result.merge_in(desc)
else
diff --git a/lib/rdoc/ri/util.rb b/lib/rdoc/ri/util.rb
index 34277f2594..4e91eb978d 100644
--- a/lib/rdoc/ri/util.rb
+++ b/lib/rdoc/ri/util.rb
@@ -1,7 +1,5 @@
require 'rdoc/ri'
-class RDoc::RI::Error < RuntimeError; end
-
##
# Break argument into its constituent class or module names, an
# optional method type, and a method name
diff --git a/lib/resolv.rb b/lib/resolv.rb
index d1494b46c9..fc3c78215b 100644
--- a/lib/resolv.rb
+++ b/lib/resolv.rb
@@ -13,24 +13,24 @@ end
# interpreter.
#
# See also resolv-replace.rb to replace the libc resolver with # Resolv.
-#
+#
# Resolv can look up various DNS resources using the DNS module directly.
-#
+#
# Examples:
-#
+#
# p Resolv.getaddress "www.ruby-lang.org"
# p Resolv.getname "210.251.121.214"
-#
+#
# Resolv::DNS.open do |dns|
# ress = dns.getresources "www.ruby-lang.org", Resolv::DNS::Resource::IN::A
# p ress.map { |r| r.address }
# ress = dns.getresources "ruby-lang.org", Resolv::DNS::Resource::IN::MX
# p ress.map { |r| [r.exchange.to_s, r.preference] }
# end
-#
-#
+#
+#
# == Bugs
-#
+#
# * NIS is not supported.
# * /etc/nsswitch.conf is not supported.
@@ -38,14 +38,14 @@ class Resolv
##
# Looks up the first IP address for +name+.
-
+
def self.getaddress(name)
DefaultResolver.getaddress(name)
end
##
# Looks up all IP address for +name+.
-
+
def self.getaddresses(name)
DefaultResolver.getaddresses(name)
end
@@ -87,7 +87,7 @@ class Resolv
##
# Looks up the first IP address for +name+.
-
+
def getaddress(name)
each_address(name) {|address| return address}
raise ResolvError.new("no address for #{name}")
@@ -95,7 +95,7 @@ class Resolv
##
# Looks up all IP address for +name+.
-
+
def getaddresses(name)
ret = []
each_address(name) {|address| ret << address}
@@ -309,7 +309,7 @@ class Resolv
# Creates a new DNS resolver.
#
# +config_info+ can be:
- #
+ #
# nil:: Uses /etc/resolv.conf.
# String:: Path to a file using /etc/resolv.conf's format.
# Hash:: Must contain :nameserver, :search and :ndots keys.
@@ -457,7 +457,7 @@ class Resolv
##
# Looks up all +typeclass+ DNS resources for +name+. See #getresource for
# argument details.
-
+
def getresources(name, typeclass)
ret = []
each_resource(name, typeclass) {|resource| ret << resource}
@@ -467,7 +467,7 @@ class Resolv
##
# Iterates over all +typeclass+ DNS resources for +name+. See
# #getresource for argument details.
-
+
def each_resource(name, typeclass, &proc)
lazy_initialize
requester = make_requester
@@ -569,7 +569,7 @@ class Resolv
h = (RequestID[[host, port]] ||= {})
begin
id = rangerand(0x0000..0xffff)
- end while h[id]
+ end while h[id]
h[id] = true
}
id
@@ -1037,7 +1037,7 @@ class Resolv
# A representation of a DNS name.
class Name
-
+
##
# Creates a new DNS name from +arg+. +arg+ can be:
#
@@ -1460,11 +1460,11 @@ class Resolv
class Query
def encode_rdata(msg) # :nodoc:
- raise EncodeError.new("#{self.class} is query.")
+ raise EncodeError.new("#{self.class} is query.")
end
def self.decode_rdata(msg) # :nodoc:
- raise DecodeError.new("#{self.class} is query.")
+ raise DecodeError.new("#{self.class} is query.")
end
end
@@ -1939,7 +1939,7 @@ class Resolv
def initialize(address)
@address = IPv6.create(address)
end
-
+
##
# The Resolv::IPv6 address for this AAAA.
@@ -1956,7 +1956,7 @@ class Resolv
##
# SRV resource record defined in RFC 2782
- #
+ #
# These records identify the hostname and port that a service is
# available at.
diff --git a/lib/rexml/attlistdecl.rb b/lib/rexml/attlistdecl.rb
index ef4721b5ce..ea5a98b69e 100644
--- a/lib/rexml/attlistdecl.rb
+++ b/lib/rexml/attlistdecl.rb
@@ -3,60 +3,60 @@ require 'rexml/child'
require 'rexml/source'
module REXML
- # This class needs:
- # * Documentation
- # * Work! Not all types of attlists are intelligently parsed, so we just
- # spew back out what we get in. This works, but it would be better if
- # we formatted the output ourselves.
- #
- # AttlistDecls provide *just* enough support to allow namespace
- # declarations. If you need some sort of generalized support, or have an
- # interesting idea about how to map the hideous, terrible design of DTD
- # AttlistDecls onto an intuitive Ruby interface, let me know. I'm desperate
- # for anything to make DTDs more palateable.
- class AttlistDecl < Child
- include Enumerable
+ # This class needs:
+ # * Documentation
+ # * Work! Not all types of attlists are intelligently parsed, so we just
+ # spew back out what we get in. This works, but it would be better if
+ # we formatted the output ourselves.
+ #
+ # AttlistDecls provide *just* enough support to allow namespace
+ # declarations. If you need some sort of generalized support, or have an
+ # interesting idea about how to map the hideous, terrible design of DTD
+ # AttlistDecls onto an intuitive Ruby interface, let me know. I'm desperate
+ # for anything to make DTDs more palateable.
+ class AttlistDecl < Child
+ include Enumerable
- # What is this? Got me.
- attr_reader :element_name
+ # What is this? Got me.
+ attr_reader :element_name
- # Create an AttlistDecl, pulling the information from a Source. Notice
- # that this isn't very convenient; to create an AttlistDecl, you basically
- # have to format it yourself, and then have the initializer parse it.
- # Sorry, but for the forseeable future, DTD support in REXML is pretty
- # weak on convenience. Have I mentioned how much I hate DTDs?
- def initialize(source)
- super()
- if (source.kind_of? Array)
- @element_name, @pairs, @contents = *source
- end
- end
-
- # Access the attlist attribute/value pairs.
- # value = attlist_decl[ attribute_name ]
- def [](key)
- @pairs[key]
- end
+ # Create an AttlistDecl, pulling the information from a Source. Notice
+ # that this isn't very convenient; to create an AttlistDecl, you basically
+ # have to format it yourself, and then have the initializer parse it.
+ # Sorry, but for the forseeable future, DTD support in REXML is pretty
+ # weak on convenience. Have I mentioned how much I hate DTDs?
+ def initialize(source)
+ super()
+ if (source.kind_of? Array)
+ @element_name, @pairs, @contents = *source
+ end
+ end
+
+ # Access the attlist attribute/value pairs.
+ # value = attlist_decl[ attribute_name ]
+ def [](key)
+ @pairs[key]
+ end
- # Whether an attlist declaration includes the given attribute definition
- # if attlist_decl.include? "xmlns:foobar"
- def include?(key)
- @pairs.keys.include? key
- end
+ # Whether an attlist declaration includes the given attribute definition
+ # if attlist_decl.include? "xmlns:foobar"
+ def include?(key)
+ @pairs.keys.include? key
+ end
- # Iterate over the key/value pairs:
- # attlist_decl.each { |attribute_name, attribute_value| ... }
- def each(&block)
- @pairs.each(&block)
- end
+ # Iterate over the key/value pairs:
+ # attlist_decl.each { |attribute_name, attribute_value| ... }
+ def each(&block)
+ @pairs.each(&block)
+ end
- # Write out exactly what we got in.
- def write out, indent=-1
- out << @contents
- end
+ # Write out exactly what we got in.
+ def write out, indent=-1
+ out << @contents
+ end
- def node_type
- :attlistdecl
- end
- end
+ def node_type
+ :attlistdecl
+ end
+ end
end
diff --git a/lib/rexml/attribute.rb b/lib/rexml/attribute.rb
index 17ced44c45..febcc288b1 100644
--- a/lib/rexml/attribute.rb
+++ b/lib/rexml/attribute.rb
@@ -2,24 +2,24 @@ require "rexml/namespace"
require 'rexml/text'
module REXML
- # Defines an Element Attribute; IE, a attribute=value pair, as in:
- # <element attribute="value"/>. Attributes can be in their own
- # namespaces. General users of REXML will not interact with the
- # Attribute class much.
- class Attribute
- include Node
- include Namespace
-
- # The element to which this attribute belongs
- attr_reader :element
- # The normalized value of this attribute. That is, the attribute with
- # entities intact.
- attr_writer :normalized
- PATTERN = /\s*(#{NAME_STR})\s*=\s*(["'])(.*?)\2/um
+ # Defines an Element Attribute; IE, a attribute=value pair, as in:
+ # <element attribute="value"/>. Attributes can be in their own
+ # namespaces. General users of REXML will not interact with the
+ # Attribute class much.
+ class Attribute
+ include Node
+ include Namespace
+
+ # The element to which this attribute belongs
+ attr_reader :element
+ # The normalized value of this attribute. That is, the attribute with
+ # entities intact.
+ attr_writer :normalized
+ PATTERN = /\s*(#{NAME_STR})\s*=\s*(["'])(.*?)\2/um
NEEDS_A_SECOND_CHECK = /(<|&((#{Entity::NAME});|(#0*((?:\d+)|(?:x[a-fA-F0-9]+)));)?)/um
- # Constructor.
+ # Constructor.
# FIXME: The parser doesn't catch illegal characters in attributes
#
# first::
@@ -36,137 +36,137 @@ module REXML
# Ignored unless +first+ is a String; otherwise, may be the Element
# parent of this attribute, or nil.
#
- #
- # Attribute.new( attribute_to_clone )
- # Attribute.new( attribute_to_clone, parent_element )
- # Attribute.new( "attr", "attr_value" )
- # Attribute.new( "attr", "attr_value", parent_element )
- def initialize( first, second=nil, parent=nil )
- @normalized = @unnormalized = @element = nil
- if first.kind_of? Attribute
- self.name = first.expanded_name
- @unnormalized = first.value
- if second.kind_of? Element
- @element = second
- else
- @element = first.element
- end
- elsif first.kind_of? String
- @element = parent
- self.name = first
- @normalized = second.to_s
- else
- raise "illegal argument #{first.class.name} to Attribute constructor"
- end
- end
-
- # Returns the namespace of the attribute.
- #
- # e = Element.new( "elns:myelement" )
- # e.add_attribute( "nsa:a", "aval" )
- # e.add_attribute( "b", "bval" )
- # e.attributes.get_attribute( "a" ).prefix # -> "nsa"
- # e.attributes.get_attribute( "b" ).prefix # -> "elns"
- # a = Attribute.new( "x", "y" )
- # a.prefix # -> ""
- def prefix
- pf = super
- if pf == ""
- pf = @element.prefix if @element
- end
- pf
- end
-
- # Returns the namespace URL, if defined, or nil otherwise
- #
- # e = Element.new("el")
- # e.add_attributes({"xmlns:ns", "http://url"})
- # e.namespace( "ns" ) # -> "http://url"
- def namespace arg=nil
- arg = prefix if arg.nil?
- @element.namespace arg
- end
-
- # Returns true if other is an Attribute and has the same name and value,
- # false otherwise.
- def ==( other )
- other.kind_of?(Attribute) and other.name==name and other.value==value
- end
-
- # Creates (and returns) a hash from both the name and value
- def hash
- name.hash + value.hash
- end
-
- # Returns this attribute out as XML source, expanding the name
- #
- # a = Attribute.new( "x", "y" )
- # a.to_string # -> "x='y'"
- # b = Attribute.new( "ns:x", "y" )
- # b.to_string # -> "ns:x='y'"
- def to_string
- if @element and @element.context and @element.context[:attribute_quote] == :quote
- %Q^#@expanded_name="#{to_s().gsub(/"/, '&quote;')}"^
- else
- "#@expanded_name='#{to_s().gsub(/'/, '&apos;')}'"
- end
- end
+ #
+ # Attribute.new( attribute_to_clone )
+ # Attribute.new( attribute_to_clone, parent_element )
+ # Attribute.new( "attr", "attr_value" )
+ # Attribute.new( "attr", "attr_value", parent_element )
+ def initialize( first, second=nil, parent=nil )
+ @normalized = @unnormalized = @element = nil
+ if first.kind_of? Attribute
+ self.name = first.expanded_name
+ @unnormalized = first.value
+ if second.kind_of? Element
+ @element = second
+ else
+ @element = first.element
+ end
+ elsif first.kind_of? String
+ @element = parent
+ self.name = first
+ @normalized = second.to_s
+ else
+ raise "illegal argument #{first.class.name} to Attribute constructor"
+ end
+ end
+
+ # Returns the namespace of the attribute.
+ #
+ # e = Element.new( "elns:myelement" )
+ # e.add_attribute( "nsa:a", "aval" )
+ # e.add_attribute( "b", "bval" )
+ # e.attributes.get_attribute( "a" ).prefix # -> "nsa"
+ # e.attributes.get_attribute( "b" ).prefix # -> "elns"
+ # a = Attribute.new( "x", "y" )
+ # a.prefix # -> ""
+ def prefix
+ pf = super
+ if pf == ""
+ pf = @element.prefix if @element
+ end
+ pf
+ end
+
+ # Returns the namespace URL, if defined, or nil otherwise
+ #
+ # e = Element.new("el")
+ # e.add_attributes({"xmlns:ns", "http://url"})
+ # e.namespace( "ns" ) # -> "http://url"
+ def namespace arg=nil
+ arg = prefix if arg.nil?
+ @element.namespace arg
+ end
+
+ # Returns true if other is an Attribute and has the same name and value,
+ # false otherwise.
+ def ==( other )
+ other.kind_of?(Attribute) and other.name==name and other.value==value
+ end
+
+ # Creates (and returns) a hash from both the name and value
+ def hash
+ name.hash + value.hash
+ end
+
+ # Returns this attribute out as XML source, expanding the name
+ #
+ # a = Attribute.new( "x", "y" )
+ # a.to_string # -> "x='y'"
+ # b = Attribute.new( "ns:x", "y" )
+ # b.to_string # -> "ns:x='y'"
+ def to_string
+ if @element and @element.context and @element.context[:attribute_quote] == :quote
+ %Q^#@expanded_name="#{to_s().gsub(/"/, '&quote;')}"^
+ else
+ "#@expanded_name='#{to_s().gsub(/'/, '&apos;')}'"
+ end
+ end
def doctype
- if @element
- doc = @element.document
- doctype = doc.doctype if doc
- end
+ if @element
+ doc = @element.document
+ doctype = doc.doctype if doc
+ end
end
- # Returns the attribute value, with entities replaced
- def to_s
- return @normalized if @normalized
+ # Returns the attribute value, with entities replaced
+ def to_s
+ return @normalized if @normalized
- @normalized = Text::normalize( @unnormalized, doctype )
- @unnormalized = nil
+ @normalized = Text::normalize( @unnormalized, doctype )
+ @unnormalized = nil
@normalized
- end
-
- # Returns the UNNORMALIZED value of this attribute. That is, entities
- # have been expanded to their values
- def value
- return @unnormalized if @unnormalized
- @unnormalized = Text::unnormalize( @normalized, doctype )
- @normalized = nil
+ end
+
+ # Returns the UNNORMALIZED value of this attribute. That is, entities
+ # have been expanded to their values
+ def value
+ return @unnormalized if @unnormalized
+ @unnormalized = Text::unnormalize( @normalized, doctype )
+ @normalized = nil
@unnormalized
- end
+ end
- # Returns a copy of this attribute
- def clone
- Attribute.new self
- end
+ # Returns a copy of this attribute
+ def clone
+ Attribute.new self
+ end
- # Sets the element of which this object is an attribute. Normally, this
- # is not directly called.
- #
- # Returns this attribute
- def element=( element )
- @element = element
+ # Sets the element of which this object is an attribute. Normally, this
+ # is not directly called.
+ #
+ # Returns this attribute
+ def element=( element )
+ @element = element
if @normalized
Text.check( @normalized, NEEDS_A_SECOND_CHECK, doctype )
end
- self
- end
+ self
+ end
- # Removes this Attribute from the tree, and returns true if successfull
- #
- # This method is usually not called directly.
- def remove
- @element.attributes.delete self.name unless @element.nil?
- end
+ # Removes this Attribute from the tree, and returns true if successfull
+ #
+ # This method is usually not called directly.
+ def remove
+ @element.attributes.delete self.name unless @element.nil?
+ end
- # Writes this attribute (EG, puts 'key="value"' to the output)
- def write( output, indent=-1 )
- output << to_string
- end
+ # Writes this attribute (EG, puts 'key="value"' to the output)
+ def write( output, indent=-1 )
+ output << to_string
+ end
def node_type
:attribute
@@ -183,6 +183,6 @@ module REXML
path += "/@#{self.expanded_name}"
return path
end
- end
+ end
end
#vim:ts=2 sw=2 noexpandtab:
diff --git a/lib/rexml/cdata.rb b/lib/rexml/cdata.rb
index 856b9ef8b2..123a7c3d82 100644
--- a/lib/rexml/cdata.rb
+++ b/lib/rexml/cdata.rb
@@ -1,39 +1,39 @@
require "rexml/text"
module REXML
- class CData < Text
- START = '<![CDATA['
- STOP = ']]>'
- ILLEGAL = /(\]\]>)/
+ class CData < Text
+ START = '<![CDATA['
+ STOP = ']]>'
+ ILLEGAL = /(\]\]>)/
- # Constructor. CData is data between <![CDATA[ ... ]]>
- #
- # _Examples_
- # CData.new( source )
- # CData.new( "Here is some CDATA" )
- # CData.new( "Some unprocessed data", respect_whitespace_TF, parent_element )
- def initialize( first, whitespace=true, parent=nil )
- super( first, whitespace, parent, false, true, ILLEGAL )
- end
+ # Constructor. CData is data between <![CDATA[ ... ]]>
+ #
+ # _Examples_
+ # CData.new( source )
+ # CData.new( "Here is some CDATA" )
+ # CData.new( "Some unprocessed data", respect_whitespace_TF, parent_element )
+ def initialize( first, whitespace=true, parent=nil )
+ super( first, whitespace, parent, false, true, ILLEGAL )
+ end
- # Make a copy of this object
- #
- # _Examples_
- # c = CData.new( "Some text" )
- # d = c.clone
- # d.to_s # -> "Some text"
- def clone
- CData.new self
- end
+ # Make a copy of this object
+ #
+ # _Examples_
+ # c = CData.new( "Some text" )
+ # d = c.clone
+ # d.to_s # -> "Some text"
+ def clone
+ CData.new self
+ end
- # Returns the content of this CData object
- #
- # _Examples_
- # c = CData.new( "Some text" )
- # c.to_s # -> "Some text"
- def to_s
- @string
- end
+ # Returns the content of this CData object
+ #
+ # _Examples_
+ # c = CData.new( "Some text" )
+ # c.to_s # -> "Some text"
+ def to_s
+ @string
+ end
def value
@string
@@ -42,26 +42,26 @@ module REXML
# == DEPRECATED
# See the rexml/formatters package
#
- # Generates XML output of this object
- #
- # output::
- # Where to write the string. Defaults to $stdout
- # indent::
+ # Generates XML output of this object
+ #
+ # output::
+ # Where to write the string. Defaults to $stdout
+ # indent::
# The amount to indent this node by
- # transitive::
+ # transitive::
# Ignored
- # ie_hack::
+ # ie_hack::
# Ignored
- #
- # _Examples_
- # c = CData.new( " Some text " )
- # c.write( $stdout ) #-> <![CDATA[ Some text ]]>
- def write( output=$stdout, indent=-1, transitive=false, ie_hack=false )
+ #
+ # _Examples_
+ # c = CData.new( " Some text " )
+ # c.write( $stdout ) #-> <![CDATA[ Some text ]]>
+ def write( output=$stdout, indent=-1, transitive=false, ie_hack=false )
Kernel.warn( "#{self.class.name}.write is deprecated" )
- indent( output, indent )
- output << START
- output << @string
- output << STOP
- end
- end
+ indent( output, indent )
+ output << START
+ output << @string
+ output << STOP
+ end
+ end
end
diff --git a/lib/rexml/child.rb b/lib/rexml/child.rb
index 6d3c9df5e6..033057da55 100644
--- a/lib/rexml/child.rb
+++ b/lib/rexml/child.rb
@@ -1,96 +1,96 @@
require "rexml/node"
module REXML
- ##
- # A Child object is something contained by a parent, and this class
- # contains methods to support that. Most user code will not use this
- # class directly.
- class Child
- include Node
- attr_reader :parent # The Parent of this object
+ ##
+ # A Child object is something contained by a parent, and this class
+ # contains methods to support that. Most user code will not use this
+ # class directly.
+ class Child
+ include Node
+ attr_reader :parent # The Parent of this object
- # Constructor. Any inheritors of this class should call super to make
- # sure this method is called.
- # parent::
- # if supplied, the parent of this child will be set to the
- # supplied value, and self will be added to the parent
- def initialize( parent = nil )
- @parent = nil
- # Declare @parent, but don't define it. The next line sets the
- # parent.
- parent.add( self ) if parent
- end
+ # Constructor. Any inheritors of this class should call super to make
+ # sure this method is called.
+ # parent::
+ # if supplied, the parent of this child will be set to the
+ # supplied value, and self will be added to the parent
+ def initialize( parent = nil )
+ @parent = nil
+ # Declare @parent, but don't define it. The next line sets the
+ # parent.
+ parent.add( self ) if parent
+ end
- # Replaces this object with another object. Basically, calls
- # Parent.replace_child
- #
- # Returns:: self
- def replace_with( child )
- @parent.replace_child( self, child )
- self
- end
+ # Replaces this object with another object. Basically, calls
+ # Parent.replace_child
+ #
+ # Returns:: self
+ def replace_with( child )
+ @parent.replace_child( self, child )
+ self
+ end
- # Removes this child from the parent.
- #
- # Returns:: self
- def remove
- unless @parent.nil?
- @parent.delete self
- end
- self
- end
+ # Removes this child from the parent.
+ #
+ # Returns:: self
+ def remove
+ unless @parent.nil?
+ @parent.delete self
+ end
+ self
+ end
- # Sets the parent of this child to the supplied argument.
- #
- # other::
- # Must be a Parent object. If this object is the same object as the
- # existing parent of this child, no action is taken. Otherwise, this
- # child is removed from the current parent (if one exists), and is added
- # to the new parent.
- # Returns:: The parent added
- def parent=( other )
- return @parent if @parent == other
- @parent.delete self if defined? @parent and @parent
- @parent = other
- end
+ # Sets the parent of this child to the supplied argument.
+ #
+ # other::
+ # Must be a Parent object. If this object is the same object as the
+ # existing parent of this child, no action is taken. Otherwise, this
+ # child is removed from the current parent (if one exists), and is added
+ # to the new parent.
+ # Returns:: The parent added
+ def parent=( other )
+ return @parent if @parent == other
+ @parent.delete self if defined? @parent and @parent
+ @parent = other
+ end
- alias :next_sibling :next_sibling_node
- alias :previous_sibling :previous_sibling_node
+ alias :next_sibling :next_sibling_node
+ alias :previous_sibling :previous_sibling_node
- # Sets the next sibling of this child. This can be used to insert a child
- # after some other child.
- # a = Element.new("a")
- # b = a.add_element("b")
- # c = Element.new("c")
- # b.next_sibling = c
- # # => <a><b/><c/></a>
- def next_sibling=( other )
- parent.insert_after self, other
- end
+ # Sets the next sibling of this child. This can be used to insert a child
+ # after some other child.
+ # a = Element.new("a")
+ # b = a.add_element("b")
+ # c = Element.new("c")
+ # b.next_sibling = c
+ # # => <a><b/><c/></a>
+ def next_sibling=( other )
+ parent.insert_after self, other
+ end
- # Sets the previous sibling of this child. This can be used to insert a
- # child before some other child.
- # a = Element.new("a")
- # b = a.add_element("b")
- # c = Element.new("c")
- # b.previous_sibling = c
- # # => <a><b/><c/></a>
- def previous_sibling=(other)
- parent.insert_before self, other
- end
+ # Sets the previous sibling of this child. This can be used to insert a
+ # child before some other child.
+ # a = Element.new("a")
+ # b = a.add_element("b")
+ # c = Element.new("c")
+ # b.previous_sibling = c
+ # # => <a><b/><c/></a>
+ def previous_sibling=(other)
+ parent.insert_before self, other
+ end
- # Returns:: the document this child belongs to, or nil if this child
- # belongs to no document
- def document
- return parent.document unless parent.nil?
- nil
- end
+ # Returns:: the document this child belongs to, or nil if this child
+ # belongs to no document
+ def document
+ return parent.document unless parent.nil?
+ nil
+ end
- # This doesn't yet handle encodings
- def bytes
- encoding = document.encoding
+ # This doesn't yet handle encodings
+ def bytes
+ encoding = document.encoding
- to_s
- end
- end
+ to_s
+ end
+ end
end
diff --git a/lib/rexml/comment.rb b/lib/rexml/comment.rb
index 2b9b4b89c9..d5be89b652 100644
--- a/lib/rexml/comment.rb
+++ b/lib/rexml/comment.rb
@@ -1,80 +1,80 @@
require "rexml/child"
module REXML
- ##
- # Represents an XML comment; that is, text between \<!-- ... -->
- class Comment < Child
- include Comparable
- START = "<!--"
- STOP = "-->"
+ ##
+ # Represents an XML comment; that is, text between \<!-- ... -->
+ class Comment < Child
+ include Comparable
+ START = "<!--"
+ STOP = "-->"
- # The content text
+ # The content text
- attr_accessor :string
+ attr_accessor :string
- ##
- # Constructor. The first argument can be one of three types:
- # @param first If String, the contents of this comment are set to the
- # argument. If Comment, the argument is duplicated. If
- # Source, the argument is scanned for a comment.
- # @param second If the first argument is a Source, this argument
- # should be nil, not supplied, or a Parent to be set as the parent
- # of this object
- def initialize( first, second = nil )
- #puts "IN COMMENT CONSTRUCTOR; SECOND IS #{second.type}"
- super(second)
- if first.kind_of? String
- @string = first
- elsif first.kind_of? Comment
- @string = first.string
- end
- end
+ ##
+ # Constructor. The first argument can be one of three types:
+ # @param first If String, the contents of this comment are set to the
+ # argument. If Comment, the argument is duplicated. If
+ # Source, the argument is scanned for a comment.
+ # @param second If the first argument is a Source, this argument
+ # should be nil, not supplied, or a Parent to be set as the parent
+ # of this object
+ def initialize( first, second = nil )
+ #puts "IN COMMENT CONSTRUCTOR; SECOND IS #{second.type}"
+ super(second)
+ if first.kind_of? String
+ @string = first
+ elsif first.kind_of? Comment
+ @string = first.string
+ end
+ end
- def clone
- Comment.new self
- end
+ def clone
+ Comment.new self
+ end
# == DEPRECATED
# See REXML::Formatters
#
- # output::
- # Where to write the string
- # indent::
- # An integer. If -1, no indenting will be used; otherwise, the
- # indentation will be this number of spaces, and children will be
- # indented an additional amount.
- # transitive::
- # Ignored by this class. The contents of comments are never modified.
- # ie_hack::
- # Needed for conformity to the child API, but not used by this class.
- def write( output, indent=-1, transitive=false, ie_hack=false )
+ # output::
+ # Where to write the string
+ # indent::
+ # An integer. If -1, no indenting will be used; otherwise, the
+ # indentation will be this number of spaces, and children will be
+ # indented an additional amount.
+ # transitive::
+ # Ignored by this class. The contents of comments are never modified.
+ # ie_hack::
+ # Needed for conformity to the child API, but not used by this class.
+ def write( output, indent=-1, transitive=false, ie_hack=false )
Kernel.warn("Comment.write is deprecated. See REXML::Formatters")
- indent( output, indent )
- output << START
- output << @string
- output << STOP
- end
+ indent( output, indent )
+ output << START
+ output << @string
+ output << STOP
+ end
- alias :to_s :string
+ alias :to_s :string
- ##
- # Compares this Comment to another; the contents of the comment are used
- # in the comparison.
- def <=>(other)
- other.to_s <=> @string
- end
+ ##
+ # Compares this Comment to another; the contents of the comment are used
+ # in the comparison.
+ def <=>(other)
+ other.to_s <=> @string
+ end
- ##
- # Compares this Comment to another; the contents of the comment are used
- # in the comparison.
- def ==( other )
- other.kind_of? Comment and
- (other <=> self) == 0
- end
+ ##
+ # Compares this Comment to another; the contents of the comment are used
+ # in the comparison.
+ def ==( other )
+ other.kind_of? Comment and
+ (other <=> self) == 0
+ end
def node_type
:comment
end
- end
+ end
end
#vim:ts=2 sw=2 noexpandtab:
diff --git a/lib/rexml/document.rb b/lib/rexml/document.rb
index 97a73e94a0..28c3a781db 100644
--- a/lib/rexml/document.rb
+++ b/lib/rexml/document.rb
@@ -16,59 +16,59 @@ module REXML
# Document has a single child that can be accessed by root().
# Note that if you want to have an XML declaration written for a document
# you create, you must add one; REXML documents do not write a default
- # declaration for you. See |DECLARATION| and |write|.
- class Document < Element
- # A convenient default XML declaration. If you want an XML declaration,
- # the easiest way to add one is mydoc << Document::DECLARATION
+ # declaration for you. See |DECLARATION| and |write|.
+ class Document < Element
+ # A convenient default XML declaration. If you want an XML declaration,
+ # the easiest way to add one is mydoc << Document::DECLARATION
# +DEPRECATED+
# Use: mydoc << XMLDecl.default
- DECLARATION = XMLDecl.default
-
- # Constructor
- # @param source if supplied, must be a Document, String, or IO.
- # Documents have their context and Element attributes cloned.
- # Strings are expected to be valid XML documents. IOs are expected
- # to be sources of valid XML documents.
- # @param context if supplied, contains the context of the document;
- # this should be a Hash.
- def initialize( source = nil, context = {} )
+ DECLARATION = XMLDecl.default
+
+ # Constructor
+ # @param source if supplied, must be a Document, String, or IO.
+ # Documents have their context and Element attributes cloned.
+ # Strings are expected to be valid XML documents. IOs are expected
+ # to be sources of valid XML documents.
+ # @param context if supplied, contains the context of the document;
+ # this should be a Hash.
+ def initialize( source = nil, context = {} )
@entity_expansion_count = 0
- super()
- @context = context
- return if source.nil?
- if source.kind_of? Document
- @context = source.context
- super source
- else
- build( source )
- end
- end
+ super()
+ @context = context
+ return if source.nil?
+ if source.kind_of? Document
+ @context = source.context
+ super source
+ else
+ build( source )
+ end
+ end
def node_type
:document
end
- # Should be obvious
- def clone
- Document.new self
- end
+ # Should be obvious
+ def clone
+ Document.new self
+ end
- # According to the XML spec, a root node has no expanded name
- def expanded_name
- ''
- #d = doc_type
- #d ? d.name : "UNDEFINED"
- end
+ # According to the XML spec, a root node has no expanded name
+ def expanded_name
+ ''
+ #d = doc_type
+ #d ? d.name : "UNDEFINED"
+ end
- alias :name :expanded_name
+ alias :name :expanded_name
- # We override this, because XMLDecls and DocTypes must go at the start
- # of the document
- def add( child )
- if child.kind_of? XMLDecl
- @children.unshift child
+ # We override this, because XMLDecls and DocTypes must go at the start
+ # of the document
+ def add( child )
+ if child.kind_of? XMLDecl
+ @children.unshift child
child.parent = self
- elsif child.kind_of? DocType
+ elsif child.kind_of? DocType
# Find first Element or DocType node and insert the decl right
# before it. If there is no such node, just insert the child at the
# end. If there is a child and it is an DocType, then replace it.
@@ -86,60 +86,60 @@ module REXML
else # Insert at end of list
@children[insert_before_index] = child
end
- child.parent = self
- else
- rv = super
- raise "attempted adding second root element to document" if @elements.size > 1
- rv
- end
- end
- alias :<< :add
-
- def add_element(arg=nil, arg2=nil)
- rv = super
- raise "attempted adding second root element to document" if @elements.size > 1
- rv
- end
-
- # @return the root Element of the document, or nil if this document
- # has no children.
- def root
+ child.parent = self
+ else
+ rv = super
+ raise "attempted adding second root element to document" if @elements.size > 1
+ rv
+ end
+ end
+ alias :<< :add
+
+ def add_element(arg=nil, arg2=nil)
+ rv = super
+ raise "attempted adding second root element to document" if @elements.size > 1
+ rv
+ end
+
+ # @return the root Element of the document, or nil if this document
+ # has no children.
+ def root
elements[1]
#self
#@children.find { |item| item.kind_of? Element }
- end
-
- # @return the DocType child of the document, if one exists,
- # and nil otherwise.
- def doctype
- @children.find { |item| item.kind_of? DocType }
- end
-
- # @return the XMLDecl of this document; if no XMLDecl has been
- # set, the default declaration is returned.
- def xml_decl
- rv = @children[0]
+ end
+
+ # @return the DocType child of the document, if one exists,
+ # and nil otherwise.
+ def doctype
+ @children.find { |item| item.kind_of? DocType }
+ end
+
+ # @return the XMLDecl of this document; if no XMLDecl has been
+ # set, the default declaration is returned.
+ def xml_decl
+ rv = @children[0]
return rv if rv.kind_of? XMLDecl
rv = @children.unshift(XMLDecl.default)[0]
- end
-
- # @return the XMLDecl version of this document as a String.
- # If no XMLDecl has been set, returns the default version.
- def version
- xml_decl().version
- end
-
- # @return the XMLDecl encoding of this document as a String.
- # If no XMLDecl has been set, returns the default encoding.
- def encoding
- xml_decl().encoding
- end
-
- # @return the XMLDecl standalone value of this document as a String.
- # If no XMLDecl has been set, returns the default setting.
- def stand_alone?
- xml_decl().stand_alone?
- end
+ end
+
+ # @return the XMLDecl version of this document as a String.
+ # If no XMLDecl has been set, returns the default version.
+ def version
+ xml_decl().version
+ end
+
+ # @return the XMLDecl encoding of this document as a String.
+ # If no XMLDecl has been set, returns the default encoding.
+ def encoding
+ xml_decl().encoding
+ end
+
+ # @return the XMLDecl standalone value of this document as a String.
+ # If no XMLDecl has been set, returns the default setting.
+ def stand_alone?
+ xml_decl().stand_alone?
+ end
# Write the XML tree out, optionally with indent. This writes out the
# entire XML document, including XML declarations, doctype declarations,
@@ -194,21 +194,21 @@ module REXML
REXML::Formatters::Default.new( ie_hack )
end
formatter.write( self, output )
- end
+ end
-
- def Document::parse_stream( source, listener )
- Parsers::StreamParser.new( source, listener ).parse
- end
+
+ def Document::parse_stream( source, listener )
+ Parsers::StreamParser.new( source, listener ).parse
+ end
@@entity_expansion_limit = 10_000
- # Set the entity expansion limit. By defualt the limit is set to 10000.
+ # Set the entity expansion limit. By default the limit is set to 10000.
def Document::entity_expansion_limit=( val )
@@entity_expansion_limit = val
end
- # Get the entity expansion limit. By defualt the limit is set to 10000.
+ # Get the entity expansion limit. By default the limit is set to 10000.
def Document::entity_expansion_limit
return @@entity_expansion_limit
end
@@ -222,9 +222,9 @@ module REXML
end
end
- private
- def build( source )
+ private
+ def build( source )
Parsers::TreeParser.new( source, self ).parse
- end
- end
+ end
+ end
end
diff --git a/lib/rexml/dtd/attlistdecl.rb b/lib/rexml/dtd/attlistdecl.rb
index e176bb0749..25955ee274 100644
--- a/lib/rexml/dtd/attlistdecl.rb
+++ b/lib/rexml/dtd/attlistdecl.rb
@@ -1,10 +1,10 @@
require "rexml/child"
module REXML
- module DTD
- class AttlistDecl < Child
- START = "<!ATTLIST"
- START_RE = /^\s*#{START}/um
- PATTERN_RE = /\s*(#{START}.*?>)/um
- end
- end
+ module DTD
+ class AttlistDecl < Child
+ START = "<!ATTLIST"
+ START_RE = /^\s*#{START}/um
+ PATTERN_RE = /\s*(#{START}.*?>)/um
+ end
+ end
end
diff --git a/lib/rexml/dtd/dtd.rb b/lib/rexml/dtd/dtd.rb
index 4f735d4812..966e39ea57 100644
--- a/lib/rexml/dtd/dtd.rb
+++ b/lib/rexml/dtd/dtd.rb
@@ -6,46 +6,46 @@ require "rexml/dtd/attlistdecl"
require "rexml/parent"
module REXML
- module DTD
- class Parser
- def Parser.parse( input )
- case input
- when String
- parse_helper input
- when File
- parse_helper input.read
- end
- end
+ module DTD
+ class Parser
+ def Parser.parse( input )
+ case input
+ when String
+ parse_helper input
+ when File
+ parse_helper input.read
+ end
+ end
- # Takes a String and parses it out
- def Parser.parse_helper( input )
- contents = Parent.new
- while input.size > 0
- case input
- when ElementDecl.PATTERN_RE
- match = $&
- source = $'
- contents << ElementDecl.new( match )
- when AttlistDecl.PATTERN_RE
- matchdata = $~
- source = $'
- contents << AttlistDecl.new( matchdata )
- when EntityDecl.PATTERN_RE
- matchdata = $~
- source = $'
- contents << EntityDecl.new( matchdata )
- when Comment.PATTERN_RE
- matchdata = $~
- source = $'
- contents << Comment.new( matchdata )
- when NotationDecl.PATTERN_RE
- matchdata = $~
- source = $'
- contents << NotationDecl.new( matchdata )
- end
- end
- contents
- end
- end
- end
+ # Takes a String and parses it out
+ def Parser.parse_helper( input )
+ contents = Parent.new
+ while input.size > 0
+ case input
+ when ElementDecl.PATTERN_RE
+ match = $&
+ source = $'
+ contents << ElementDecl.new( match )
+ when AttlistDecl.PATTERN_RE
+ matchdata = $~
+ source = $'
+ contents << AttlistDecl.new( matchdata )
+ when EntityDecl.PATTERN_RE
+ matchdata = $~
+ source = $'
+ contents << EntityDecl.new( matchdata )
+ when Comment.PATTERN_RE
+ matchdata = $~
+ source = $'
+ contents << Comment.new( matchdata )
+ when NotationDecl.PATTERN_RE
+ matchdata = $~
+ source = $'
+ contents << NotationDecl.new( matchdata )
+ end
+ end
+ contents
+ end
+ end
+ end
end
diff --git a/lib/rexml/dtd/elementdecl.rb b/lib/rexml/dtd/elementdecl.rb
index c4e620f389..a0bf641300 100644
--- a/lib/rexml/dtd/elementdecl.rb
+++ b/lib/rexml/dtd/elementdecl.rb
@@ -1,17 +1,17 @@
require "rexml/child"
module REXML
- module DTD
- class ElementDecl < Child
- START = "<!ELEMENT"
- START_RE = /^\s*#{START}/um
- PATTERN_RE = /^\s*(#{START}.*?)>/um
- PATTERN_RE = /^\s*#{START}\s+((?:[:\w_][-\.\w_]*:)?[-!\*\.\w_]*)(.*?)>/
- #\s*((((["']).*?\5)|[^\/'">]*)*?)(\/)?>/um, true)
+ module DTD
+ class ElementDecl < Child
+ START = "<!ELEMENT"
+ START_RE = /^\s*#{START}/um
+ PATTERN_RE = /^\s*(#{START}.*?)>/um
+ PATTERN_RE = /^\s*#{START}\s+((?:[:\w_][-\.\w_]*:)?[-!\*\.\w_]*)(.*?)>/
+ #\s*((((["']).*?\5)|[^\/'">]*)*?)(\/)?>/um, true)
- def initialize match
- @name = match[1]
- @rest = match[2]
- end
- end
- end
+ def initialize match
+ @name = match[1]
+ @rest = match[2]
+ end
+ end
+ end
end
diff --git a/lib/rexml/dtd/entitydecl.rb b/lib/rexml/dtd/entitydecl.rb
index a5f1520f2b..0adda6f7b9 100644
--- a/lib/rexml/dtd/entitydecl.rb
+++ b/lib/rexml/dtd/entitydecl.rb
@@ -1,56 +1,56 @@
require "rexml/child"
module REXML
- module DTD
- class EntityDecl < Child
- START = "<!ENTITY"
- START_RE = /^\s*#{START}/um
- PUBLIC = /^\s*#{START}\s+(?:%\s+)?(\w+)\s+PUBLIC\s+((["']).*?\3)\s+((["']).*?\5)\s*>/um
- SYSTEM = /^\s*#{START}\s+(?:%\s+)?(\w+)\s+SYSTEM\s+((["']).*?\3)(?:\s+NDATA\s+\w+)?\s*>/um
- PLAIN = /^\s*#{START}\s+(\w+)\s+((["']).*?\3)\s*>/um
- PERCENT = /^\s*#{START}\s+%\s+(\w+)\s+((["']).*?\3)\s*>/um
- # <!ENTITY name SYSTEM "...">
- # <!ENTITY name "...">
- def initialize src
- super()
- md = nil
- if src.match( PUBLIC )
- md = src.match( PUBLIC, true )
- @middle = "PUBLIC"
- @content = "#{md[2]} #{md[4]}"
- elsif src.match( SYSTEM )
- md = src.match( SYSTEM, true )
- @middle = "SYSTEM"
- @content = md[2]
- elsif src.match( PLAIN )
- md = src.match( PLAIN, true )
- @middle = ""
- @content = md[2]
- elsif src.match( PERCENT )
- md = src.match( PERCENT, true )
- @middle = ""
- @content = md[2]
- end
- raise ParseException.new("failed Entity match", src) if md.nil?
- @name = md[1]
- end
+ module DTD
+ class EntityDecl < Child
+ START = "<!ENTITY"
+ START_RE = /^\s*#{START}/um
+ PUBLIC = /^\s*#{START}\s+(?:%\s+)?(\w+)\s+PUBLIC\s+((["']).*?\3)\s+((["']).*?\5)\s*>/um
+ SYSTEM = /^\s*#{START}\s+(?:%\s+)?(\w+)\s+SYSTEM\s+((["']).*?\3)(?:\s+NDATA\s+\w+)?\s*>/um
+ PLAIN = /^\s*#{START}\s+(\w+)\s+((["']).*?\3)\s*>/um
+ PERCENT = /^\s*#{START}\s+%\s+(\w+)\s+((["']).*?\3)\s*>/um
+ # <!ENTITY name SYSTEM "...">
+ # <!ENTITY name "...">
+ def initialize src
+ super()
+ md = nil
+ if src.match( PUBLIC )
+ md = src.match( PUBLIC, true )
+ @middle = "PUBLIC"
+ @content = "#{md[2]} #{md[4]}"
+ elsif src.match( SYSTEM )
+ md = src.match( SYSTEM, true )
+ @middle = "SYSTEM"
+ @content = md[2]
+ elsif src.match( PLAIN )
+ md = src.match( PLAIN, true )
+ @middle = ""
+ @content = md[2]
+ elsif src.match( PERCENT )
+ md = src.match( PERCENT, true )
+ @middle = ""
+ @content = md[2]
+ end
+ raise ParseException.new("failed Entity match", src) if md.nil?
+ @name = md[1]
+ end
- def to_s
- rv = "<!ENTITY #@name "
- rv << "#@middle " if @middle.size > 0
- rv << @content
- rv
- end
+ def to_s
+ rv = "<!ENTITY #@name "
+ rv << "#@middle " if @middle.size > 0
+ rv << @content
+ rv
+ end
- def write( output, indent )
+ def write( output, indent )
indent( output, indent )
- output << to_s
- end
+ output << to_s
+ end
- def EntityDecl.parse_source source, listener
- md = source.match( PATTERN_RE, true )
- thing = md[0].squeeze(" \t\n\r")
- listener.send inspect.downcase, thing
- end
- end
- end
+ def EntityDecl.parse_source source, listener
+ md = source.match( PATTERN_RE, true )
+ thing = md[0].squeeze(" \t\n\r")
+ listener.send inspect.downcase, thing
+ end
+ end
+ end
end
diff --git a/lib/rexml/dtd/notationdecl.rb b/lib/rexml/dtd/notationdecl.rb
index a47ff8f24b..eae71f2e52 100644
--- a/lib/rexml/dtd/notationdecl.rb
+++ b/lib/rexml/dtd/notationdecl.rb
@@ -1,39 +1,39 @@
require "rexml/child"
module REXML
- module DTD
- class NotationDecl < Child
- START = "<!NOTATION"
- START_RE = /^\s*#{START}/um
- PUBLIC = /^\s*#{START}\s+(\w[\w-]*)\s+(PUBLIC)\s+((["']).*?\4)\s*>/um
- SYSTEM = /^\s*#{START}\s+(\w[\w-]*)\s+(SYSTEM)\s+((["']).*?\4)\s*>/um
- def initialize src
- super()
- if src.match( PUBLIC )
- md = src.match( PUBLIC, true )
- elsif src.match( SYSTEM )
- md = src.match( SYSTEM, true )
- else
- raise ParseException.new( "error parsing notation: no matching pattern", src )
- end
- @name = md[1]
- @middle = md[2]
- @rest = md[3]
- end
+ module DTD
+ class NotationDecl < Child
+ START = "<!NOTATION"
+ START_RE = /^\s*#{START}/um
+ PUBLIC = /^\s*#{START}\s+(\w[\w-]*)\s+(PUBLIC)\s+((["']).*?\4)\s*>/um
+ SYSTEM = /^\s*#{START}\s+(\w[\w-]*)\s+(SYSTEM)\s+((["']).*?\4)\s*>/um
+ def initialize src
+ super()
+ if src.match( PUBLIC )
+ md = src.match( PUBLIC, true )
+ elsif src.match( SYSTEM )
+ md = src.match( SYSTEM, true )
+ else
+ raise ParseException.new( "error parsing notation: no matching pattern", src )
+ end
+ @name = md[1]
+ @middle = md[2]
+ @rest = md[3]
+ end
- def to_s
- "<!NOTATION #@name #@middle #@rest>"
- end
+ def to_s
+ "<!NOTATION #@name #@middle #@rest>"
+ end
- def write( output, indent )
+ def write( output, indent )
indent( output, indent )
- output << to_s
- end
+ output << to_s
+ end
- def NotationDecl.parse_source source, listener
- md = source.match( PATTERN_RE, true )
- thing = md[0].squeeze(" \t\n\r")
- listener.send inspect.downcase, thing
- end
- end
- end
+ def NotationDecl.parse_source source, listener
+ md = source.match( PATTERN_RE, true )
+ thing = md[0].squeeze(" \t\n\r")
+ listener.send inspect.downcase, thing
+ end
+ end
+ end
end
diff --git a/lib/rexml/encodings/CP-1252.rb b/lib/rexml/encodings/CP-1252.rb
index 8675f9ff98..2ef6a1a291 100644
--- a/lib/rexml/encodings/CP-1252.rb
+++ b/lib/rexml/encodings/CP-1252.rb
@@ -3,12 +3,12 @@
#
module REXML
module Encoding
- register( "CP-1252" ) do |o|
- class << o
- alias encode encode_cp1252
- alias decode decode_cp1252
- end
- end
+ register( "CP-1252" ) do |o|
+ class << o
+ alias encode encode_cp1252
+ alias decode decode_cp1252
+ end
+ end
# Convert from UTF-8
def encode_cp1252(content)
diff --git a/lib/rexml/encodings/ISO-8859-15.rb b/lib/rexml/encodings/ISO-8859-15.rb
index 8dea0d38a4..953267250e 100644
--- a/lib/rexml/encodings/ISO-8859-15.rb
+++ b/lib/rexml/encodings/ISO-8859-15.rb
@@ -3,10 +3,10 @@
#
module REXML
module Encoding
- register("ISO-8859-15") do |o|
- alias encode to_iso_8859_15
+ register("ISO-8859-15") do |o|
+ alias encode to_iso_8859_15
alias decode from_iso_8859_15
- end
+ end
# Convert from UTF-8
def to_iso_8859_15(content)
diff --git a/lib/rexml/entity.rb b/lib/rexml/entity.rb
index dc2249f106..d2f27ecd44 100644
--- a/lib/rexml/entity.rb
+++ b/lib/rexml/entity.rb
@@ -3,164 +3,164 @@ require 'rexml/source'
require 'rexml/xmltokens'
module REXML
- # God, I hate DTDs. I really do. Why this idiot standard still
- # plagues us is beyond me.
- class Entity < Child
- include XMLTokens
- PUBIDCHAR = "\x20\x0D\x0Aa-zA-Z0-9\\-()+,./:=?;!*@$_%#"
- SYSTEMLITERAL = %Q{((?:"[^"]*")|(?:'[^']*'))}
- PUBIDLITERAL = %Q{("[#{PUBIDCHAR}']*"|'[#{PUBIDCHAR}]*')}
- EXTERNALID = "(?:(?:(SYSTEM)\\s+#{SYSTEMLITERAL})|(?:(PUBLIC)\\s+#{PUBIDLITERAL}\\s+#{SYSTEMLITERAL}))"
- NDATADECL = "\\s+NDATA\\s+#{NAME}"
- PEREFERENCE = "%#{NAME};"
- ENTITYVALUE = %Q{((?:"(?:[^%&"]|#{PEREFERENCE}|#{REFERENCE})*")|(?:'([^%&']|#{PEREFERENCE}|#{REFERENCE})*'))}
- PEDEF = "(?:#{ENTITYVALUE}|#{EXTERNALID})"
- ENTITYDEF = "(?:#{ENTITYVALUE}|(?:#{EXTERNALID}(#{NDATADECL})?))"
- PEDECL = "<!ENTITY\\s+(%)\\s+#{NAME}\\s+#{PEDEF}\\s*>"
- GEDECL = "<!ENTITY\\s+#{NAME}\\s+#{ENTITYDEF}\\s*>"
- ENTITYDECL = /\s*(?:#{GEDECL})|(?:#{PEDECL})/um
+ # God, I hate DTDs. I really do. Why this idiot standard still
+ # plagues us is beyond me.
+ class Entity < Child
+ include XMLTokens
+ PUBIDCHAR = "\x20\x0D\x0Aa-zA-Z0-9\\-()+,./:=?;!*@$_%#"
+ SYSTEMLITERAL = %Q{((?:"[^"]*")|(?:'[^']*'))}
+ PUBIDLITERAL = %Q{("[#{PUBIDCHAR}']*"|'[#{PUBIDCHAR}]*')}
+ EXTERNALID = "(?:(?:(SYSTEM)\\s+#{SYSTEMLITERAL})|(?:(PUBLIC)\\s+#{PUBIDLITERAL}\\s+#{SYSTEMLITERAL}))"
+ NDATADECL = "\\s+NDATA\\s+#{NAME}"
+ PEREFERENCE = "%#{NAME};"
+ ENTITYVALUE = %Q{((?:"(?:[^%&"]|#{PEREFERENCE}|#{REFERENCE})*")|(?:'([^%&']|#{PEREFERENCE}|#{REFERENCE})*'))}
+ PEDEF = "(?:#{ENTITYVALUE}|#{EXTERNALID})"
+ ENTITYDEF = "(?:#{ENTITYVALUE}|(?:#{EXTERNALID}(#{NDATADECL})?))"
+ PEDECL = "<!ENTITY\\s+(%)\\s+#{NAME}\\s+#{PEDEF}\\s*>"
+ GEDECL = "<!ENTITY\\s+#{NAME}\\s+#{ENTITYDEF}\\s*>"
+ ENTITYDECL = /\s*(?:#{GEDECL})|(?:#{PEDECL})/um
- attr_reader :name, :external, :ref, :ndata, :pubid
+ attr_reader :name, :external, :ref, :ndata, :pubid
- # Create a new entity. Simple entities can be constructed by passing a
- # name, value to the constructor; this creates a generic, plain entity
- # reference. For anything more complicated, you have to pass a Source to
- # the constructor with the entity definiton, or use the accessor methods.
- # +WARNING+: There is no validation of entity state except when the entity
- # is read from a stream. If you start poking around with the accessors,
- # you can easily create a non-conformant Entity. The best thing to do is
- # dump the stupid DTDs and use XMLSchema instead.
- #
- # e = Entity.new( 'amp', '&' )
- def initialize stream, value=nil, parent=nil, reference=false
- super(parent)
- @ndata = @pubid = @value = @external = nil
- if stream.kind_of? Array
- @name = stream[1]
- if stream[-1] == '%'
- @reference = true
- stream.pop
- else
- @reference = false
- end
- if stream[2] =~ /SYSTEM|PUBLIC/
- @external = stream[2]
- if @external == 'SYSTEM'
- @ref = stream[3]
- @ndata = stream[4] if stream.size == 5
- else
- @pubid = stream[3]
- @ref = stream[4]
- end
- else
- @value = stream[2]
- end
- else
- @reference = reference
- @external = nil
- @name = stream
- @value = value
- end
- end
+ # Create a new entity. Simple entities can be constructed by passing a
+ # name, value to the constructor; this creates a generic, plain entity
+ # reference. For anything more complicated, you have to pass a Source to
+ # the constructor with the entity definiton, or use the accessor methods.
+ # +WARNING+: There is no validation of entity state except when the entity
+ # is read from a stream. If you start poking around with the accessors,
+ # you can easily create a non-conformant Entity. The best thing to do is
+ # dump the stupid DTDs and use XMLSchema instead.
+ #
+ # e = Entity.new( 'amp', '&' )
+ def initialize stream, value=nil, parent=nil, reference=false
+ super(parent)
+ @ndata = @pubid = @value = @external = nil
+ if stream.kind_of? Array
+ @name = stream[1]
+ if stream[-1] == '%'
+ @reference = true
+ stream.pop
+ else
+ @reference = false
+ end
+ if stream[2] =~ /SYSTEM|PUBLIC/
+ @external = stream[2]
+ if @external == 'SYSTEM'
+ @ref = stream[3]
+ @ndata = stream[4] if stream.size == 5
+ else
+ @pubid = stream[3]
+ @ref = stream[4]
+ end
+ else
+ @value = stream[2]
+ end
+ else
+ @reference = reference
+ @external = nil
+ @name = stream
+ @value = value
+ end
+ end
- # Evaluates whether the given string matchs an entity definition,
- # returning true if so, and false otherwise.
- def Entity::matches? string
- (ENTITYDECL =~ string) == 0
- end
+ # Evaluates whether the given string matchs an entity definition,
+ # returning true if so, and false otherwise.
+ def Entity::matches? string
+ (ENTITYDECL =~ string) == 0
+ end
- # Evaluates to the unnormalized value of this entity; that is, replacing
- # all entities -- both %ent; and &ent; entities. This differs from
- # +value()+ in that +value+ only replaces %ent; entities.
- def unnormalized
- document.record_entity_expansion
- v = value()
- return nil if v.nil?
- @unnormalized = Text::unnormalize(v, parent)
- @unnormalized
- end
+ # Evaluates to the unnormalized value of this entity; that is, replacing
+ # all entities -- both %ent; and &ent; entities. This differs from
+ # +value()+ in that +value+ only replaces %ent; entities.
+ def unnormalized
+ document.record_entity_expansion unless document.nil?
+ v = value()
+ return nil if v.nil?
+ @unnormalized = Text::unnormalize(v, parent)
+ @unnormalized
+ end
- #once :unnormalized
+ #once :unnormalized
- # Returns the value of this entity unprocessed -- raw. This is the
- # normalized value; that is, with all %ent; and &ent; entities intact
- def normalized
- @value
- end
+ # Returns the value of this entity unprocessed -- raw. This is the
+ # normalized value; that is, with all %ent; and &ent; entities intact
+ def normalized
+ @value
+ end
- # Write out a fully formed, correct entity definition (assuming the Entity
- # object itself is valid.)
+ # Write out a fully formed, correct entity definition (assuming the Entity
+ # object itself is valid.)
#
# out::
# An object implementing <TT>&lt;&lt;<TT> to which the entity will be
# output
# indent::
# *DEPRECATED* and ignored
- def write out, indent=-1
- out << '<!ENTITY '
- out << '% ' if @reference
- out << @name
- out << ' '
- if @external
- out << @external << ' '
- if @pubid
- q = @pubid.include?('"')?"'":'"'
- out << q << @pubid << q << ' '
- end
- q = @ref.include?('"')?"'":'"'
- out << q << @ref << q
- out << ' NDATA ' << @ndata if @ndata
- else
- q = @value.include?('"')?"'":'"'
- out << q << @value << q
- end
- out << '>'
- end
+ def write out, indent=-1
+ out << '<!ENTITY '
+ out << '% ' if @reference
+ out << @name
+ out << ' '
+ if @external
+ out << @external << ' '
+ if @pubid
+ q = @pubid.include?('"')?"'":'"'
+ out << q << @pubid << q << ' '
+ end
+ q = @ref.include?('"')?"'":'"'
+ out << q << @ref << q
+ out << ' NDATA ' << @ndata if @ndata
+ else
+ q = @value.include?('"')?"'":'"'
+ out << q << @value << q
+ end
+ out << '>'
+ end
- # Returns this entity as a string. See write().
- def to_s
- rv = ''
- write rv
- rv
- end
+ # Returns this entity as a string. See write().
+ def to_s
+ rv = ''
+ write rv
+ rv
+ end
- PEREFERENCE_RE = /#{PEREFERENCE}/um
- # Returns the value of this entity. At the moment, only internal entities
- # are processed. If the value contains internal references (IE,
- # %blah;), those are replaced with their values. IE, if the doctype
- # contains:
- # <!ENTITY % foo "bar">
- # <!ENTITY yada "nanoo %foo; nanoo>
- # then:
- # doctype.entity('yada').value #-> "nanoo bar nanoo"
- def value
- if @value
- matches = @value.scan(PEREFERENCE_RE)
- rv = @value.clone
- if @parent
- matches.each do |entity_reference|
- entity_value = @parent.entity( entity_reference[0] )
- rv.gsub!( /%#{entity_reference.join};/um, entity_value )
- end
- end
- return rv
- end
- nil
- end
- end
+ PEREFERENCE_RE = /#{PEREFERENCE}/um
+ # Returns the value of this entity. At the moment, only internal entities
+ # are processed. If the value contains internal references (IE,
+ # %blah;), those are replaced with their values. IE, if the doctype
+ # contains:
+ # <!ENTITY % foo "bar">
+ # <!ENTITY yada "nanoo %foo; nanoo>
+ # then:
+ # doctype.entity('yada').value #-> "nanoo bar nanoo"
+ def value
+ if @value
+ matches = @value.scan(PEREFERENCE_RE)
+ rv = @value.clone
+ if @parent
+ matches.each do |entity_reference|
+ entity_value = @parent.entity( entity_reference[0] )
+ rv.gsub!( /%#{entity_reference.join};/um, entity_value )
+ end
+ end
+ return rv
+ end
+ nil
+ end
+ end
- # This is a set of entity constants -- the ones defined in the XML
- # specification. These are +gt+, +lt+, +amp+, +quot+ and +apos+.
- module EntityConst
- # +>+
- GT = Entity.new( 'gt', '>' )
- # +<+
- LT = Entity.new( 'lt', '<' )
- # +&+
- AMP = Entity.new( 'amp', '&' )
- # +"+
- QUOT = Entity.new( 'quot', '"' )
- # +'+
- APOS = Entity.new( 'apos', "'" )
- end
+ # This is a set of entity constants -- the ones defined in the XML
+ # specification. These are +gt+, +lt+, +amp+, +quot+ and +apos+.
+ module EntityConst
+ # +>+
+ GT = Entity.new( 'gt', '>' )
+ # +<+
+ LT = Entity.new( 'lt', '<' )
+ # +&+
+ AMP = Entity.new( 'amp', '&' )
+ # +"+
+ QUOT = Entity.new( 'quot', '"' )
+ # +'+
+ APOS = Entity.new( 'apos', "'" )
+ end
end
diff --git a/lib/rexml/formatters/pretty.rb b/lib/rexml/formatters/pretty.rb
index 296e607687..84c442e8bb 100644
--- a/lib/rexml/formatters/pretty.rb
+++ b/lib/rexml/formatters/pretty.rb
@@ -129,6 +129,7 @@ module REXML
# Recursively wrap string at width.
return string if string.length <= width
place = string.rindex(' ', width) # Position in string with last ' ' before cutoff
+ return string if place.nil?
return string[0,place] + "\n" + wrap(string[place+1..-1], width)
end
diff --git a/lib/rexml/instruction.rb b/lib/rexml/instruction.rb
index c16b894b4a..50bf95d17a 100644
--- a/lib/rexml/instruction.rb
+++ b/lib/rexml/instruction.rb
@@ -2,62 +2,62 @@ require "rexml/child"
require "rexml/source"
module REXML
- # Represents an XML Instruction; IE, <? ... ?>
- # TODO: Add parent arg (3rd arg) to constructor
- class Instruction < Child
- START = '<\?'
- STOP = '\?>'
+ # Represents an XML Instruction; IE, <? ... ?>
+ # TODO: Add parent arg (3rd arg) to constructor
+ class Instruction < Child
+ START = '<\?'
+ STOP = '\?>'
- # target is the "name" of the Instruction; IE, the "tag" in <?tag ...?>
- # content is everything else.
- attr_accessor :target, :content
+ # target is the "name" of the Instruction; IE, the "tag" in <?tag ...?>
+ # content is everything else.
+ attr_accessor :target, :content
- # Constructs a new Instruction
- # @param target can be one of a number of things. If String, then
- # the target of this instruction is set to this. If an Instruction,
- # then the Instruction is shallowly cloned (target and content are
- # copied). If a Source, then the source is scanned and parsed for
- # an Instruction declaration.
- # @param content Must be either a String, or a Parent. Can only
- # be a Parent if the target argument is a Source. Otherwise, this
- # String is set as the content of this instruction.
- def initialize(target, content=nil)
- if target.kind_of? String
- super()
- @target = target
- @content = content
- elsif target.kind_of? Instruction
- super(content)
- @target = target.target
- @content = target.content
- end
- @content.strip! if @content
- end
+ # Constructs a new Instruction
+ # @param target can be one of a number of things. If String, then
+ # the target of this instruction is set to this. If an Instruction,
+ # then the Instruction is shallowly cloned (target and content are
+ # copied). If a Source, then the source is scanned and parsed for
+ # an Instruction declaration.
+ # @param content Must be either a String, or a Parent. Can only
+ # be a Parent if the target argument is a Source. Otherwise, this
+ # String is set as the content of this instruction.
+ def initialize(target, content=nil)
+ if target.kind_of? String
+ super()
+ @target = target
+ @content = content
+ elsif target.kind_of? Instruction
+ super(content)
+ @target = target.target
+ @content = target.content
+ end
+ @content.strip! if @content
+ end
- def clone
- Instruction.new self
- end
-
+ def clone
+ Instruction.new self
+ end
+
# == DEPRECATED
# See the rexml/formatters package
#
- def write writer, indent=-1, transitive=false, ie_hack=false
+ def write writer, indent=-1, transitive=false, ie_hack=false
Kernel.warn( "#{self.class.name}.write is deprecated" )
- indent(writer, indent)
- writer << START.sub(/\\/u, '')
- writer << @target
- writer << ' '
- writer << @content
- writer << STOP.sub(/\\/u, '')
- end
+ indent(writer, indent)
+ writer << START.sub(/\\/u, '')
+ writer << @target
+ writer << ' '
+ writer << @content
+ writer << STOP.sub(/\\/u, '')
+ end
- # @return true if other is an Instruction, and the content and target
- # of the other matches the target and content of this object.
- def ==( other )
- other.kind_of? Instruction and
- other.target == @target and
- other.content == @content
- end
+ # @return true if other is an Instruction, and the content and target
+ # of the other matches the target and content of this object.
+ def ==( other )
+ other.kind_of? Instruction and
+ other.target == @target and
+ other.content == @content
+ end
def node_type
:processing_instruction
@@ -66,5 +66,5 @@ module REXML
def inspect
"<?p-i #{target} ...?>"
end
- end
+ end
end
diff --git a/lib/rexml/light/node.rb b/lib/rexml/light/node.rb
index 943ec5f1a0..9c90148c05 100644
--- a/lib/rexml/light/node.rb
+++ b/lib/rexml/light/node.rb
@@ -2,195 +2,195 @@ require 'rexml/xmltokens'
require 'rexml/light/node'
# [ :element, parent, name, attributes, children* ]
- # a = Node.new
- # a << "B" # => <a>B</a>
- # a.b # => <a>B<b/></a>
- # a.b[1] # => <a>B<b/><b/><a>
- # a.b[1]["x"] = "y" # => <a>B<b/><b x="y"/></a>
- # a.b[0].c # => <a>B<b><c/></b><b x="y"/></a>
- # a.b.c << "D" # => <a>B<b><c>D</c></b><b x="y"/></a>
+ # a = Node.new
+ # a << "B" # => <a>B</a>
+ # a.b # => <a>B<b/></a>
+ # a.b[1] # => <a>B<b/><b/><a>
+ # a.b[1]["x"] = "y" # => <a>B<b/><b x="y"/></a>
+ # a.b[0].c # => <a>B<b><c/></b><b x="y"/></a>
+ # a.b.c << "D" # => <a>B<b><c>D</c></b><b x="y"/></a>
module REXML
- module Light
- # Represents a tagged XML element. Elements are characterized by
- # having children, attributes, and names, and can themselves be
- # children.
- class Node
- NAMESPLIT = /^(?:(#{XMLTokens::NCNAME_STR}):)?(#{XMLTokens::NCNAME_STR})/u
- PARENTS = [ :element, :document, :doctype ]
- # Create a new element.
- def initialize node=nil
- @node = node
- if node.kind_of? String
- node = [ :text, node ]
- elsif node.nil?
- node = [ :document, nil, nil ]
- elsif node[0] == :start_element
- node[0] = :element
- elsif node[0] == :start_doctype
- node[0] = :doctype
- elsif node[0] == :start_document
- node[0] = :document
- end
- end
-
- def size
- if PARENTS.include? @node[0]
- @node[-1].size
- else
- 0
- end
- end
-
- def each( &block )
- size.times { |x| yield( at(x+4) ) }
- end
-
- def name
- at(2)
- end
-
- def name=( name_str, ns=nil )
- pfx = ''
- pfx = "#{prefix(ns)}:" if ns
- _old_put(2, "#{pfx}#{name_str}")
- end
-
- def parent=( node )
- _old_put(1,node)
- end
-
- def local_name
- namesplit
- @name
- end
-
- def local_name=( name_str )
- _old_put( 1, "#@prefix:#{name_str}" )
- end
-
- def prefix( namespace=nil )
- prefix_of( self, namespace )
- end
-
- def namespace( prefix=prefix() )
- namespace_of( self, prefix )
- end
-
- def namespace=( namespace )
- @prefix = prefix( namespace )
- pfx = ''
- pfx = "#@prefix:" if @prefix.size > 0
- _old_put(1, "#{pfx}#@name")
- end
-
- def []( reference, ns=nil )
- if reference.kind_of? String
- pfx = ''
- pfx = "#{prefix(ns)}:" if ns
- at(3)["#{pfx}#{reference}"]
- elsif reference.kind_of? Range
- _old_get( Range.new(4+reference.begin, reference.end, reference.exclude_end?) )
- else
- _old_get( 4+reference )
- end
- end
-
- def =~( path )
- XPath.match( self, path )
- end
-
- # Doesn't handle namespaces yet
- def []=( reference, ns, value=nil )
- if reference.kind_of? String
- value = ns unless value
- at( 3 )[reference] = value
- elsif reference.kind_of? Range
- _old_put( Range.new(3+reference.begin, reference.end, reference.exclude_end?), ns )
- else
- if value
- _old_put( 4+reference, ns, value )
- else
- _old_put( 4+reference, ns )
- end
- end
- end
-
- # Append a child to this element, optionally under a provided namespace.
- # The namespace argument is ignored if the element argument is an Element
- # object. Otherwise, the element argument is a string, the namespace (if
- # provided) is the namespace the element is created in.
- def << element
- if node_type() == :text
- at(-1) << element
- else
- newnode = Node.new( element )
- newnode.parent = self
- self.push( newnode )
- end
- at(-1)
- end
-
- def node_type
- _old_get(0)
- end
-
- def text=( foo )
- replace = at(4).kind_of?(String)? 1 : 0
- self._old_put(4,replace, normalizefoo)
- end
-
- def root
- context = self
- context = context.at(1) while context.at(1)
- end
-
- def has_name?( name, namespace = '' )
- at(3) == name and namespace() == namespace
- end
-
- def children
- self
- end
-
- def parent
- at(1)
- end
-
- def to_s
-
- end
-
- private
-
- def namesplit
- return if @name.defined?
- at(2) =~ NAMESPLIT
- @prefix = '' || $1
- @name = $2
- end
-
- def namespace_of( node, prefix=nil )
- if not prefix
- name = at(2)
- name =~ NAMESPLIT
- prefix = $1
- end
- to_find = 'xmlns'
- to_find = "xmlns:#{prefix}" if not prefix.nil?
- ns = at(3)[ to_find ]
- ns ? ns : namespace_of( @node[0], prefix )
- end
-
- def prefix_of( node, namespace=nil )
- if not namespace
- name = node.name
- name =~ NAMESPLIT
- $1
- else
- ns = at(3).find { |k,v| v == namespace }
- ns ? ns : prefix_of( node.parent, namespace )
- end
- end
- end
- end
+ module Light
+ # Represents a tagged XML element. Elements are characterized by
+ # having children, attributes, and names, and can themselves be
+ # children.
+ class Node
+ NAMESPLIT = /^(?:(#{XMLTokens::NCNAME_STR}):)?(#{XMLTokens::NCNAME_STR})/u
+ PARENTS = [ :element, :document, :doctype ]
+ # Create a new element.
+ def initialize node=nil
+ @node = node
+ if node.kind_of? String
+ node = [ :text, node ]
+ elsif node.nil?
+ node = [ :document, nil, nil ]
+ elsif node[0] == :start_element
+ node[0] = :element
+ elsif node[0] == :start_doctype
+ node[0] = :doctype
+ elsif node[0] == :start_document
+ node[0] = :document
+ end
+ end
+
+ def size
+ if PARENTS.include? @node[0]
+ @node[-1].size
+ else
+ 0
+ end
+ end
+
+ def each( &block )
+ size.times { |x| yield( at(x+4) ) }
+ end
+
+ def name
+ at(2)
+ end
+
+ def name=( name_str, ns=nil )
+ pfx = ''
+ pfx = "#{prefix(ns)}:" if ns
+ _old_put(2, "#{pfx}#{name_str}")
+ end
+
+ def parent=( node )
+ _old_put(1,node)
+ end
+
+ def local_name
+ namesplit
+ @name
+ end
+
+ def local_name=( name_str )
+ _old_put( 1, "#@prefix:#{name_str}" )
+ end
+
+ def prefix( namespace=nil )
+ prefix_of( self, namespace )
+ end
+
+ def namespace( prefix=prefix() )
+ namespace_of( self, prefix )
+ end
+
+ def namespace=( namespace )
+ @prefix = prefix( namespace )
+ pfx = ''
+ pfx = "#@prefix:" if @prefix.size > 0
+ _old_put(1, "#{pfx}#@name")
+ end
+
+ def []( reference, ns=nil )
+ if reference.kind_of? String
+ pfx = ''
+ pfx = "#{prefix(ns)}:" if ns
+ at(3)["#{pfx}#{reference}"]
+ elsif reference.kind_of? Range
+ _old_get( Range.new(4+reference.begin, reference.end, reference.exclude_end?) )
+ else
+ _old_get( 4+reference )
+ end
+ end
+
+ def =~( path )
+ XPath.match( self, path )
+ end
+
+ # Doesn't handle namespaces yet
+ def []=( reference, ns, value=nil )
+ if reference.kind_of? String
+ value = ns unless value
+ at( 3 )[reference] = value
+ elsif reference.kind_of? Range
+ _old_put( Range.new(3+reference.begin, reference.end, reference.exclude_end?), ns )
+ else
+ if value
+ _old_put( 4+reference, ns, value )
+ else
+ _old_put( 4+reference, ns )
+ end
+ end
+ end
+
+ # Append a child to this element, optionally under a provided namespace.
+ # The namespace argument is ignored if the element argument is an Element
+ # object. Otherwise, the element argument is a string, the namespace (if
+ # provided) is the namespace the element is created in.
+ def << element
+ if node_type() == :text
+ at(-1) << element
+ else
+ newnode = Node.new( element )
+ newnode.parent = self
+ self.push( newnode )
+ end
+ at(-1)
+ end
+
+ def node_type
+ _old_get(0)
+ end
+
+ def text=( foo )
+ replace = at(4).kind_of?(String)? 1 : 0
+ self._old_put(4,replace, normalizefoo)
+ end
+
+ def root
+ context = self
+ context = context.at(1) while context.at(1)
+ end
+
+ def has_name?( name, namespace = '' )
+ at(3) == name and namespace() == namespace
+ end
+
+ def children
+ self
+ end
+
+ def parent
+ at(1)
+ end
+
+ def to_s
+
+ end
+
+ private
+
+ def namesplit
+ return if @name.defined?
+ at(2) =~ NAMESPLIT
+ @prefix = '' || $1
+ @name = $2
+ end
+
+ def namespace_of( node, prefix=nil )
+ if not prefix
+ name = at(2)
+ name =~ NAMESPLIT
+ prefix = $1
+ end
+ to_find = 'xmlns'
+ to_find = "xmlns:#{prefix}" if not prefix.nil?
+ ns = at(3)[ to_find ]
+ ns ? ns : namespace_of( @node[0], prefix )
+ end
+
+ def prefix_of( node, namespace=nil )
+ if not namespace
+ name = node.name
+ name =~ NAMESPLIT
+ $1
+ else
+ ns = at(3).find { |k,v| v == namespace }
+ ns ? ns : prefix_of( node.parent, namespace )
+ end
+ end
+ end
+ end
end
diff --git a/lib/rexml/namespace.rb b/lib/rexml/namespace.rb
index 3e8790580b..8d43fc85ad 100644
--- a/lib/rexml/namespace.rb
+++ b/lib/rexml/namespace.rb
@@ -1,47 +1,47 @@
require 'rexml/xmltokens'
module REXML
- # Adds named attributes to an object.
- module Namespace
- # The name of the object, valid if set
- attr_reader :name, :expanded_name
- # The expanded name of the object, valid if name is set
- attr_accessor :prefix
- include XMLTokens
- NAMESPLIT = /^(?:(#{NCNAME_STR}):)?(#{NCNAME_STR})/u
+ # Adds named attributes to an object.
+ module Namespace
+ # The name of the object, valid if set
+ attr_reader :name, :expanded_name
+ # The expanded name of the object, valid if name is set
+ attr_accessor :prefix
+ include XMLTokens
+ NAMESPLIT = /^(?:(#{NCNAME_STR}):)?(#{NCNAME_STR})/u
- # Sets the name and the expanded name
- def name=( name )
- @expanded_name = name
- name =~ NAMESPLIT
- if $1
- @prefix = $1
- else
- @prefix = ""
- @namespace = ""
- end
- @name = $2
- end
+ # Sets the name and the expanded name
+ def name=( name )
+ @expanded_name = name
+ name =~ NAMESPLIT
+ if $1
+ @prefix = $1
+ else
+ @prefix = ""
+ @namespace = ""
+ end
+ @name = $2
+ end
- # Compares names optionally WITH namespaces
- def has_name?( other, ns=nil )
- if ns
- return (namespace() == ns and name() == other)
- elsif other.include? ":"
- return fully_expanded_name == other
- else
- return name == other
- end
- end
+ # Compares names optionally WITH namespaces
+ def has_name?( other, ns=nil )
+ if ns
+ return (namespace() == ns and name() == other)
+ elsif other.include? ":"
+ return fully_expanded_name == other
+ else
+ return name == other
+ end
+ end
- alias :local_name :name
+ alias :local_name :name
- # Fully expand the name, even if the prefix wasn't specified in the
- # source file.
- def fully_expanded_name
- ns = prefix
- return "#{ns}:#@name" if ns.size > 0
- return @name
- end
- end
+ # Fully expand the name, even if the prefix wasn't specified in the
+ # source file.
+ def fully_expanded_name
+ ns = prefix
+ return "#{ns}:#@name" if ns.size > 0
+ return @name
+ end
+ end
end
diff --git a/lib/rexml/node.rb b/lib/rexml/node.rb
index d5e8456e53..eb39141944 100644
--- a/lib/rexml/node.rb
+++ b/lib/rexml/node.rb
@@ -3,27 +3,27 @@ require "rexml/formatters/pretty"
require "rexml/formatters/default"
module REXML
- # Represents a node in the tree. Nodes are never encountered except as
- # superclasses of other objects. Nodes have siblings.
- module Node
- # @return the next sibling (nil if unset)
- def next_sibling_node
- return nil if @parent.nil?
- @parent[ @parent.index(self) + 1 ]
- end
+ # Represents a node in the tree. Nodes are never encountered except as
+ # superclasses of other objects. Nodes have siblings.
+ module Node
+ # @return the next sibling (nil if unset)
+ def next_sibling_node
+ return nil if @parent.nil?
+ @parent[ @parent.index(self) + 1 ]
+ end
- # @return the previous sibling (nil if unset)
- def previous_sibling_node
- return nil if @parent.nil?
- ind = @parent.index(self)
- return nil if ind == 0
- @parent[ ind - 1 ]
- end
+ # @return the previous sibling (nil if unset)
+ def previous_sibling_node
+ return nil if @parent.nil?
+ ind = @parent.index(self)
+ return nil if ind == 0
+ @parent[ ind - 1 ]
+ end
# indent::
# *DEPRECATED* This parameter is now ignored. See the formatters in the
# REXML::Formatters package for changing the output style.
- def to_s indent=nil
+ def to_s indent=nil
unless indent.nil?
Kernel.warn( "#{self.class.name}.to_s(indent) parameter is deprecated" )
f = REXML::Formatters::Pretty.new( indent )
@@ -33,33 +33,33 @@ module REXML
f.write( self, rv = "" )
end
return rv
- end
+ end
- def indent to, ind
+ def indent to, ind
if @parent and @parent.context and not @parent.context[:indentstyle].nil? then
indentstyle = @parent.context[:indentstyle]
else
indentstyle = ' '
end
to << indentstyle*ind unless ind<1
- end
+ end
- def parent?
- false;
- end
+ def parent?
+ false;
+ end
- # Visit all subnodes of +self+ recursively
- def each_recursive(&block) # :yields: node
- self.elements.each {|node|
- block.call(node)
- node.each_recursive(&block)
- }
- end
+ # Visit all subnodes of +self+ recursively
+ def each_recursive(&block) # :yields: node
+ self.elements.each {|node|
+ block.call(node)
+ node.each_recursive(&block)
+ }
+ end
- # Find (and return) first subnode (recursively) for which the block
+ # Find (and return) first subnode (recursively) for which the block
# evaluates to true. Returns +nil+ if none was found.
- def find_first_recursive(&block) # :yields: node
+ def find_first_recursive(&block) # :yields: node
each_recursive {|node|
return node if block.call(node)
}
@@ -71,5 +71,5 @@ module REXML
def index_in_parent
parent.index(self)+1
end
- end
+ end
end
diff --git a/lib/rexml/output.rb b/lib/rexml/output.rb
index be4d23d42d..997f2b117d 100644
--- a/lib/rexml/output.rb
+++ b/lib/rexml/output.rb
@@ -1,24 +1,24 @@
require 'rexml/encoding'
module REXML
- class Output
- include Encoding
+ class Output
+ include Encoding
attr_reader :encoding
- def initialize real_IO, encd="iso-8859-1"
- @output = real_IO
- self.encoding = encd
+ def initialize real_IO, encd="iso-8859-1"
+ @output = real_IO
+ self.encoding = encd
- @to_utf = encd == UTF_8 ? false : true
- end
+ @to_utf = encd == UTF_8 ? false : true
+ end
- def <<( content )
- @output << (@to_utf ? self.encode(content) : content)
- end
+ def <<( content )
+ @output << (@to_utf ? self.encode(content) : content)
+ end
def to_s
"Output[#{encoding}]"
end
- end
+ end
end
diff --git a/lib/rexml/parsers/lightparser.rb b/lib/rexml/parsers/lightparser.rb
index 0f35034993..ca9692c449 100644
--- a/lib/rexml/parsers/lightparser.rb
+++ b/lib/rexml/parsers/lightparser.rb
@@ -3,12 +3,12 @@ require 'rexml/parsers/baseparser'
require 'rexml/light/node'
module REXML
- module Parsers
- class LightParser
- def initialize stream
- @stream = stream
- @parser = REXML::Parsers::BaseParser.new( stream )
- end
+ module Parsers
+ class LightParser
+ def initialize stream
+ @stream = stream
+ @parser = REXML::Parsers::BaseParser.new( stream )
+ end
def add_listener( listener )
@parser.add_listener( listener )
@@ -19,42 +19,40 @@ module REXML
@parser.stream = @stream
end
- def parse
- root = context = [ :document ]
- while true
- event = @parser.pull
- case event[0]
- when :end_document
- break
- when :end_doctype
- context = context[1]
- when :start_element, :start_doctype
- new_node = event
- context << new_node
- new_node[1,0] = [context]
- context = new_node
- when :end_element, :end_doctype
- context = context[1]
- else
- new_node = event
- context << new_node
- new_node[1,0] = [context]
- end
- end
- root
- end
- end
+ def parse
+ root = context = [ :document ]
+ while true
+ event = @parser.pull
+ case event[0]
+ when :end_document
+ break
+ when :start_element, :start_doctype
+ new_node = event
+ context << new_node
+ new_node[1,0] = [context]
+ context = new_node
+ when :end_element, :end_doctype
+ context = context[1]
+ else
+ new_node = event
+ context << new_node
+ new_node[1,0] = [context]
+ end
+ end
+ root
+ end
+ end
- # An element is an array. The array contains:
- # 0 The parent element
- # 1 The tag name
- # 2 A hash of attributes
- # 3..-1 The child elements
- # An element is an array of size > 3
- # Text is a String
- # PIs are [ :processing_instruction, target, data ]
- # Comments are [ :comment, data ]
- # DocTypes are DocType structs
- # The root is an array with XMLDecls, Text, DocType, Array, Text
- end
+ # An element is an array. The array contains:
+ # 0 The parent element
+ # 1 The tag name
+ # 2 A hash of attributes
+ # 3..-1 The child elements
+ # An element is an array of size > 3
+ # Text is a String
+ # PIs are [ :processing_instruction, target, data ]
+ # Comments are [ :comment, data ]
+ # DocTypes are DocType structs
+ # The root is an array with XMLDecls, Text, DocType, Array, Text
+ end
end
diff --git a/lib/rexml/parsers/sax2parser.rb b/lib/rexml/parsers/sax2parser.rb
index cafc39375d..72131401c3 100644
--- a/lib/rexml/parsers/sax2parser.rb
+++ b/lib/rexml/parsers/sax2parser.rb
@@ -4,158 +4,158 @@ require 'rexml/namespace'
require 'rexml/text'
module REXML
- module Parsers
+ module Parsers
# SAX2Parser
- class SAX2Parser
- def initialize source
- @parser = BaseParser.new(source)
- @listeners = []
- @procs = []
- @namespace_stack = []
- @has_listeners = false
- @tag_stack = []
+ class SAX2Parser
+ def initialize source
+ @parser = BaseParser.new(source)
+ @listeners = []
+ @procs = []
+ @namespace_stack = []
+ @has_listeners = false
+ @tag_stack = []
@entities = {}
- end
+ end
def source
@parser.source
end
-
+
def add_listener( listener )
@parser.add_listener( listener )
end
- # Listen arguments:
- #
- # Symbol, Array, Block
- # Listen to Symbol events on Array elements
- # Symbol, Block
- # Listen to Symbol events
- # Array, Listener
- # Listen to all events on Array elements
- # Array, Block
- # Listen to :start_element events on Array elements
- # Listener
- # Listen to All events
- #
- # Symbol can be one of: :start_element, :end_element,
- # :start_prefix_mapping, :end_prefix_mapping, :characters,
- # :processing_instruction, :doctype, :attlistdecl, :elementdecl,
- # :entitydecl, :notationdecl, :cdata, :xmldecl, :comment
+ # Listen arguments:
+ #
+ # Symbol, Array, Block
+ # Listen to Symbol events on Array elements
+ # Symbol, Block
+ # Listen to Symbol events
+ # Array, Listener
+ # Listen to all events on Array elements
+ # Array, Block
+ # Listen to :start_element events on Array elements
+ # Listener
+ # Listen to All events
+ #
+ # Symbol can be one of: :start_element, :end_element,
+ # :start_prefix_mapping, :end_prefix_mapping, :characters,
+ # :processing_instruction, :doctype, :attlistdecl, :elementdecl,
+ # :entitydecl, :notationdecl, :cdata, :xmldecl, :comment
#
# There is an additional symbol that can be listened for: :progress.
# This will be called for every event generated, passing in the current
# stream position.
- #
- # Array contains regular expressions or strings which will be matched
- # against fully qualified element names.
- #
- # Listener must implement the methods in SAX2Listener
- #
- # Block will be passed the same arguments as a SAX2Listener method would
- # be, where the method name is the same as the matched Symbol.
- # See the SAX2Listener for more information.
- def listen( *args, &blok )
- if args[0].kind_of? Symbol
- if args.size == 2
- args[1].each { |match| @procs << [args[0], match, blok] }
- else
- add( [args[0], nil, blok] )
- end
- elsif args[0].kind_of? Array
- if args.size == 2
- args[0].each { |match| add( [nil, match, args[1]] ) }
- else
- args[0].each { |match| add( [ :start_element, match, blok ] ) }
- end
- else
- add([nil, nil, args[0]])
- end
- end
-
- def deafen( listener=nil, &blok )
- if listener
- @listeners.delete_if {|item| item[-1] == listener }
- @has_listeners = false if @listeners.size == 0
- else
- @procs.delete_if {|item| item[-1] == blok }
- end
- end
-
- def parse
- @procs.each { |sym,match,block| block.call if sym == :start_document }
- @listeners.each { |sym,match,block|
- block.start_document if sym == :start_document or sym.nil?
- }
- root = context = []
- while true
- event = @parser.pull
- case event[0]
- when :end_document
- handle( :end_document )
- break
+ #
+ # Array contains regular expressions or strings which will be matched
+ # against fully qualified element names.
+ #
+ # Listener must implement the methods in SAX2Listener
+ #
+ # Block will be passed the same arguments as a SAX2Listener method would
+ # be, where the method name is the same as the matched Symbol.
+ # See the SAX2Listener for more information.
+ def listen( *args, &blok )
+ if args[0].kind_of? Symbol
+ if args.size == 2
+ args[1].each { |match| @procs << [args[0], match, blok] }
+ else
+ add( [args[0], nil, blok] )
+ end
+ elsif args[0].kind_of? Array
+ if args.size == 2
+ args[0].each { |match| add( [nil, match, args[1]] ) }
+ else
+ args[0].each { |match| add( [ :start_element, match, blok ] ) }
+ end
+ else
+ add([nil, nil, args[0]])
+ end
+ end
+
+ def deafen( listener=nil, &blok )
+ if listener
+ @listeners.delete_if {|item| item[-1] == listener }
+ @has_listeners = false if @listeners.size == 0
+ else
+ @procs.delete_if {|item| item[-1] == blok }
+ end
+ end
+
+ def parse
+ @procs.each { |sym,match,block| block.call if sym == :start_document }
+ @listeners.each { |sym,match,block|
+ block.start_document if sym == :start_document or sym.nil?
+ }
+ root = context = []
+ while true
+ event = @parser.pull
+ case event[0]
+ when :end_document
+ handle( :end_document )
+ break
when :start_doctype
handle( :doctype, *event[1..-1])
- when :end_doctype
- context = context[1]
- when :start_element
- @tag_stack.push(event[1])
- # find the observers for namespaces
- procs = get_procs( :start_prefix_mapping, event[1] )
- listeners = get_listeners( :start_prefix_mapping, event[1] )
- if procs or listeners
- # break out the namespace declarations
- # The attributes live in event[2]
- event[2].each {|n, v| event[2][n] = @parser.normalize(v)}
- nsdecl = event[2].find_all { |n, value| n =~ /^xmlns(:|$)/ }
- nsdecl.collect! { |n, value| [ n[6..-1], value ] }
- @namespace_stack.push({})
- nsdecl.each do |n,v|
- @namespace_stack[-1][n] = v
- # notify observers of namespaces
- procs.each { |ob| ob.call( n, v ) } if procs
- listeners.each { |ob| ob.start_prefix_mapping(n, v) } if listeners
- end
- end
- event[1] =~ Namespace::NAMESPLIT
- prefix = $1
- local = $2
- uri = get_namespace(prefix)
- # find the observers for start_element
- procs = get_procs( :start_element, event[1] )
- listeners = get_listeners( :start_element, event[1] )
- # notify observers
- procs.each { |ob| ob.call( uri, local, event[1], event[2] ) } if procs
- listeners.each { |ob|
- ob.start_element( uri, local, event[1], event[2] )
- } if listeners
- when :end_element
- @tag_stack.pop
- event[1] =~ Namespace::NAMESPLIT
- prefix = $1
- local = $2
- uri = get_namespace(prefix)
- # find the observers for start_element
- procs = get_procs( :end_element, event[1] )
- listeners = get_listeners( :end_element, event[1] )
- # notify observers
- procs.each { |ob| ob.call( uri, local, event[1] ) } if procs
- listeners.each { |ob|
- ob.end_element( uri, local, event[1] )
- } if listeners
+ when :end_doctype
+ context = context[1]
+ when :start_element
+ @tag_stack.push(event[1])
+ # find the observers for namespaces
+ procs = get_procs( :start_prefix_mapping, event[1] )
+ listeners = get_listeners( :start_prefix_mapping, event[1] )
+ if procs or listeners
+ # break out the namespace declarations
+ # The attributes live in event[2]
+ event[2].each {|n, v| event[2][n] = @parser.normalize(v)}
+ nsdecl = event[2].find_all { |n, value| n =~ /^xmlns(:|$)/ }
+ nsdecl.collect! { |n, value| [ n[6..-1], value ] }
+ @namespace_stack.push({})
+ nsdecl.each do |n,v|
+ @namespace_stack[-1][n] = v
+ # notify observers of namespaces
+ procs.each { |ob| ob.call( n, v ) } if procs
+ listeners.each { |ob| ob.start_prefix_mapping(n, v) } if listeners
+ end
+ end
+ event[1] =~ Namespace::NAMESPLIT
+ prefix = $1
+ local = $2
+ uri = get_namespace(prefix)
+ # find the observers for start_element
+ procs = get_procs( :start_element, event[1] )
+ listeners = get_listeners( :start_element, event[1] )
+ # notify observers
+ procs.each { |ob| ob.call( uri, local, event[1], event[2] ) } if procs
+ listeners.each { |ob|
+ ob.start_element( uri, local, event[1], event[2] )
+ } if listeners
+ when :end_element
+ @tag_stack.pop
+ event[1] =~ Namespace::NAMESPLIT
+ prefix = $1
+ local = $2
+ uri = get_namespace(prefix)
+ # find the observers for start_element
+ procs = get_procs( :end_element, event[1] )
+ listeners = get_listeners( :end_element, event[1] )
+ # notify observers
+ procs.each { |ob| ob.call( uri, local, event[1] ) } if procs
+ listeners.each { |ob|
+ ob.end_element( uri, local, event[1] )
+ } if listeners
- namespace_mapping = @namespace_stack.pop
- # find the observers for namespaces
- procs = get_procs( :end_prefix_mapping, event[1] )
- listeners = get_listeners( :end_prefix_mapping, event[1] )
- if procs or listeners
- namespace_mapping.each do |ns_prefix, ns_uri|
- # notify observers of namespaces
- procs.each { |ob| ob.call( ns_prefix ) } if procs
- listeners.each { |ob| ob.end_prefix_mapping(ns_prefix) } if listeners
- end
- end
- when :text
+ namespace_mapping = @namespace_stack.pop
+ # find the observers for namespaces
+ procs = get_procs( :end_prefix_mapping, event[1] )
+ listeners = get_listeners( :end_prefix_mapping, event[1] )
+ if procs or listeners
+ namespace_mapping.each do |ns_prefix, ns_uri|
+ # notify observers of namespaces
+ procs.each { |ob| ob.call( ns_prefix ) } if procs
+ listeners.each { |ob| ob.end_prefix_mapping(ns_prefix) } if listeners
+ end
+ end
+ when :text
#normalized = @parser.normalize( event[1] )
#handle( :characters, normalized )
copy = event[1].clone
@@ -177,71 +177,71 @@ module REXML
handle( :characters, copy )
when :entitydecl
@entities[ event[1] ] = event[2] if event.size == 3
- handle( *event )
- when :processing_instruction, :comment, :attlistdecl,
- :elementdecl, :cdata, :notationdecl, :xmldecl
- handle( *event )
- end
+ handle( *event )
+ when :processing_instruction, :comment, :attlistdecl,
+ :elementdecl, :cdata, :notationdecl, :xmldecl
+ handle( *event )
+ end
handle( :progress, @parser.position )
- end
- end
+ end
+ end
- private
- def handle( symbol, *arguments )
- tag = @tag_stack[-1]
- procs = get_procs( symbol, tag )
- listeners = get_listeners( symbol, tag )
- # notify observers
- procs.each { |ob| ob.call( *arguments ) } if procs
- listeners.each { |l|
- l.send( symbol.to_s, *arguments )
- } if listeners
- end
+ private
+ def handle( symbol, *arguments )
+ tag = @tag_stack[-1]
+ procs = get_procs( symbol, tag )
+ listeners = get_listeners( symbol, tag )
+ # notify observers
+ procs.each { |ob| ob.call( *arguments ) } if procs
+ listeners.each { |l|
+ l.send( symbol.to_s, *arguments )
+ } if listeners
+ end
- # The following methods are duplicates, but it is faster than using
- # a helper
- def get_procs( symbol, name )
- return nil if @procs.size == 0
- @procs.find_all do |sym, match, block|
+ # The following methods are duplicates, but it is faster than using
+ # a helper
+ def get_procs( symbol, name )
+ return nil if @procs.size == 0
+ @procs.find_all do |sym, match, block|
#puts sym.inspect+"=="+symbol.inspect+ "\t"+match.inspect+"=="+name.inspect+ "\t"+( (sym.nil? or symbol == sym) and ((name.nil? and match.nil?) or match.nil? or ( (name == match) or (match.kind_of? Regexp and name =~ match)))).to_s
- (
- (sym.nil? or symbol == sym) and
- ((name.nil? and match.nil?) or match.nil? or (
- (name == match) or
- (match.kind_of? Regexp and name =~ match)
- )
- )
- )
- end.collect{|x| x[-1]}
- end
- def get_listeners( symbol, name )
- return nil if @listeners.size == 0
- @listeners.find_all do |sym, match, block|
- (
- (sym.nil? or symbol == sym) and
- ((name.nil? and match.nil?) or match.nil? or (
- (name == match) or
- (match.kind_of? Regexp and name =~ match)
- )
- )
- )
- end.collect{|x| x[-1]}
- end
+ (
+ (sym.nil? or symbol == sym) and
+ ((name.nil? and match.nil?) or match.nil? or (
+ (name == match) or
+ (match.kind_of? Regexp and name =~ match)
+ )
+ )
+ )
+ end.collect{|x| x[-1]}
+ end
+ def get_listeners( symbol, name )
+ return nil if @listeners.size == 0
+ @listeners.find_all do |sym, match, block|
+ (
+ (sym.nil? or symbol == sym) and
+ ((name.nil? and match.nil?) or match.nil? or (
+ (name == match) or
+ (match.kind_of? Regexp and name =~ match)
+ )
+ )
+ )
+ end.collect{|x| x[-1]}
+ end
- def add( pair )
- if pair[-1].respond_to? :call
- @procs << pair unless @procs.include? pair
- else
- @listeners << pair unless @listeners.include? pair
- @has_listeners = true
- end
- end
+ def add( pair )
+ if pair[-1].respond_to? :call
+ @procs << pair unless @procs.include? pair
+ else
+ @listeners << pair unless @listeners.include? pair
+ @has_listeners = true
+ end
+ end
- def get_namespace( prefix )
+ def get_namespace( prefix )
uris = (@namespace_stack.find_all { |ns| not ns[prefix].nil? }) ||
- (@namespace_stack.find { |ns| not ns[nil].nil? })
- uris[-1][prefix] unless uris.nil? or 0 == uris.size
- end
- end
- end
+ (@namespace_stack.find { |ns| not ns[nil].nil? })
+ uris[-1][prefix] unless uris.nil? or 0 == uris.size
+ end
+ end
+ end
end
diff --git a/lib/rexml/parsers/ultralightparser.rb b/lib/rexml/parsers/ultralightparser.rb
index adc4af18e2..96c55d837e 100644
--- a/lib/rexml/parsers/ultralightparser.rb
+++ b/lib/rexml/parsers/ultralightparser.rb
@@ -2,12 +2,12 @@ require 'rexml/parsers/streamparser'
require 'rexml/parsers/baseparser'
module REXML
- module Parsers
- class UltraLightParser
- def initialize stream
- @stream = stream
- @parser = REXML::Parsers::BaseParser.new( stream )
- end
+ module Parsers
+ class UltraLightParser
+ def initialize stream
+ @stream = stream
+ @parser = REXML::Parsers::BaseParser.new( stream )
+ end
def add_listener( listener )
@parser.add_listener( listener )
@@ -18,39 +18,39 @@ module REXML
@parser.stream = @stream
end
- def parse
- root = context = []
- while true
- event = @parser.pull
- case event[0]
- when :end_document
- break
- when :end_doctype
- context = context[1]
- when :start_element, :doctype
- context << event
- event[1,0] = [context]
- context = event
- when :end_element
- context = context[1]
- else
- context << event
- end
- end
- root
- end
- end
+ def parse
+ root = context = []
+ while true
+ event = @parser.pull
+ case event[0]
+ when :end_document
+ break
+ when :end_doctype
+ context = context[1]
+ when :start_element, :doctype
+ context << event
+ event[1,0] = [context]
+ context = event
+ when :end_element
+ context = context[1]
+ else
+ context << event
+ end
+ end
+ root
+ end
+ end
- # An element is an array. The array contains:
- # 0 The parent element
- # 1 The tag name
- # 2 A hash of attributes
- # 3..-1 The child elements
- # An element is an array of size > 3
- # Text is a String
- # PIs are [ :processing_instruction, target, data ]
- # Comments are [ :comment, data ]
- # DocTypes are DocType structs
- # The root is an array with XMLDecls, Text, DocType, Array, Text
- end
+ # An element is an array. The array contains:
+ # 0 The parent element
+ # 1 The tag name
+ # 2 A hash of attributes
+ # 3..-1 The child elements
+ # An element is an array of size > 3
+ # Text is a String
+ # PIs are [ :processing_instruction, target, data ]
+ # Comments are [ :comment, data ]
+ # DocTypes are DocType structs
+ # The root is an array with XMLDecls, Text, DocType, Array, Text
+ end
end
diff --git a/lib/rexml/parsers/xpathparser.rb b/lib/rexml/parsers/xpathparser.rb
index 152198856d..49450b4aef 100644
--- a/lib/rexml/parsers/xpathparser.rb
+++ b/lib/rexml/parsers/xpathparser.rb
@@ -39,10 +39,10 @@ module REXML
case op
when :node
when :attribute
- string << "/" if string.size > 0
- string << "@"
+ string << "/" if string.size > 0
+ string << "@"
when :child
- string << "/" if string.size > 0
+ string << "/" if string.size > 0
when :descendant_or_self
string << "/"
when :self
@@ -51,8 +51,8 @@ module REXML
string << ".."
when :any
string << "*"
- when :text
- string << "text()"
+ when :text
+ string << "text()"
when :following, :following_sibling,
:ancestor, :ancestor_or_self, :descendant,
:namespace, :preceding, :preceding_sibling
@@ -70,13 +70,13 @@ module REXML
string << ']'
when :document
document = true
- when :function
- string << path.shift
- string << "( "
- string << predicate_to_string( path.shift[0] ) {|x| abbreviate( x )}
- string << " )"
- when :literal
- string << %Q{ "#{path.shift}" }
+ when :function
+ string << path.shift
+ string << "( "
+ string << predicate_to_string( path.shift[0] ) {|x| abbreviate( x )}
+ string << " )"
+ when :literal
+ string << %Q{ "#{path.shift}" }
else
string << "/" unless string.size == 0
string << "UNKNOWN("
@@ -84,7 +84,7 @@ module REXML
string << ")"
end
end
- string = "/"+string if document
+ string = "/"+string if document
return string
end
@@ -653,39 +653,39 @@ module REXML
def parse_args( string )
arguments = []
ind = 0
- inquot = false
- inapos = false
+ inquot = false
+ inapos = false
depth = 1
begin
case string[ind]
when ?"
- inquot = !inquot unless inapos
+ inquot = !inquot unless inapos
when ?'
- inapos = !inapos unless inquot
+ inapos = !inapos unless inquot
else
- unless inquot or inapos
- case string[ind]
- when ?(
- depth += 1
+ unless inquot or inapos
+ case string[ind]
+ when ?(
+ depth += 1
if depth == 1
- string = string[1..-1]
- ind -= 1
+ string = string[1..-1]
+ ind -= 1
+ end
+ when ?)
+ depth -= 1
+ if depth == 0
+ s = string[0,ind].strip
+ arguments << s unless s == ""
+ string = string[ind+1..-1]
end
- when ?)
- depth -= 1
- if depth == 0
- s = string[0,ind].strip
- arguments << s unless s == ""
- string = string[ind+1..-1]
- end
- when ?,
- if depth == 1
- s = string[0,ind].strip
- arguments << s unless s == ""
- string = string[ind+1..-1]
- ind = -1
- end
- end
+ when ?,
+ if depth == 1
+ s = string[0,ind].strip
+ arguments << s unless s == ""
+ string = string[ind+1..-1]
+ ind = -1
+ end
+ end
end
end
ind += 1
diff --git a/lib/rexml/quickpath.rb b/lib/rexml/quickpath.rb
index cdf4c53017..fd2ebdd0ca 100644
--- a/lib/rexml/quickpath.rb
+++ b/lib/rexml/quickpath.rb
@@ -2,262 +2,262 @@ require 'rexml/functions'
require 'rexml/xmltokens'
module REXML
- class QuickPath
- include Functions
- include XMLTokens
+ class QuickPath
+ include Functions
+ include XMLTokens
- EMPTY_HASH = {}
+ EMPTY_HASH = {}
- def QuickPath::first element, path, namespaces=EMPTY_HASH
- match(element, path, namespaces)[0]
- end
+ def QuickPath::first element, path, namespaces=EMPTY_HASH
+ match(element, path, namespaces)[0]
+ end
- def QuickPath::each element, path, namespaces=EMPTY_HASH, &block
- path = "*" unless path
- match(element, path, namespaces).each( &block )
- end
+ def QuickPath::each element, path, namespaces=EMPTY_HASH, &block
+ path = "*" unless path
+ match(element, path, namespaces).each( &block )
+ end
- def QuickPath::match element, path, namespaces=EMPTY_HASH
- raise "nil is not a valid xpath" unless path
- results = nil
- Functions::namespace_context = namespaces
- case path
- when /^\/([^\/]|$)/u
- # match on root
- path = path[1..-1]
- return [element.root.parent] if path == ''
- results = filter([element.root], path)
- when /^[-\w]*::/u
- results = filter([element], path)
- when /^\*/u
- results = filter(element.to_a, path)
- when /^[\[!\w:]/u
- # match on child
- matches = []
- children = element.to_a
- results = filter(children, path)
- else
- results = filter([element], path)
- end
- return results
- end
+ def QuickPath::match element, path, namespaces=EMPTY_HASH
+ raise "nil is not a valid xpath" unless path
+ results = nil
+ Functions::namespace_context = namespaces
+ case path
+ when /^\/([^\/]|$)/u
+ # match on root
+ path = path[1..-1]
+ return [element.root.parent] if path == ''
+ results = filter([element.root], path)
+ when /^[-\w]*::/u
+ results = filter([element], path)
+ when /^\*/u
+ results = filter(element.to_a, path)
+ when /^[\[!\w:]/u
+ # match on child
+ matches = []
+ children = element.to_a
+ results = filter(children, path)
+ else
+ results = filter([element], path)
+ end
+ return results
+ end
- # Given an array of nodes it filters the array based on the path. The
- # result is that when this method returns, the array will contain elements
- # which match the path
- def QuickPath::filter elements, path
- return elements if path.nil? or path == '' or elements.size == 0
- case path
- when /^\/\//u # Descendant
- return axe( elements, "descendant-or-self", $' )
- when /^\/?\b(\w[-\w]*)\b::/u # Axe
- axe_name = $1
- rest = $'
- return axe( elements, $1, $' )
- when /^\/(?=\b([:!\w][-\.\w]*:)?[-!\*\.\w]*\b([^:(]|$)|\*)/u # Child
- rest = $'
- results = []
- elements.each do |element|
- results |= filter( element.to_a, rest )
- end
- return results
- when /^\/?(\w[-\w]*)\(/u # / Function
- return function( elements, $1, $' )
- when Namespace::NAMESPLIT # Element name
- name = $2
- ns = $1
- rest = $'
- elements.delete_if do |element|
- !(element.kind_of? Element and
- (element.expanded_name == name or
- (element.name == name and
- element.namespace == Functions.namespace_context[ns])))
- end
- return filter( elements, rest )
- when /^\/\[/u
- matches = []
- elements.each do |element|
- matches |= predicate( element.to_a, path[1..-1] ) if element.kind_of? Element
- end
- return matches
- when /^\[/u # Predicate
- return predicate( elements, path )
- when /^\/?\.\.\./u # Ancestor
- return axe( elements, "ancestor", $' )
- when /^\/?\.\./u # Parent
- return filter( elements.collect{|e|e.parent}, $' )
- when /^\/?\./u # Self
- return filter( elements, $' )
- when /^\*/u # Any
- results = []
- elements.each do |element|
- results |= filter( [element], $' ) if element.kind_of? Element
- #if element.kind_of? Element
- # children = element.to_a
- # children.delete_if { |child| !child.kind_of?(Element) }
- # results |= filter( children, $' )
- #end
- end
- return results
- end
- return []
- end
+ # Given an array of nodes it filters the array based on the path. The
+ # result is that when this method returns, the array will contain elements
+ # which match the path
+ def QuickPath::filter elements, path
+ return elements if path.nil? or path == '' or elements.size == 0
+ case path
+ when /^\/\//u # Descendant
+ return axe( elements, "descendant-or-self", $' )
+ when /^\/?\b(\w[-\w]*)\b::/u # Axe
+ axe_name = $1
+ rest = $'
+ return axe( elements, $1, $' )
+ when /^\/(?=\b([:!\w][-\.\w]*:)?[-!\*\.\w]*\b([^:(]|$)|\*)/u # Child
+ rest = $'
+ results = []
+ elements.each do |element|
+ results |= filter( element.to_a, rest )
+ end
+ return results
+ when /^\/?(\w[-\w]*)\(/u # / Function
+ return function( elements, $1, $' )
+ when Namespace::NAMESPLIT # Element name
+ name = $2
+ ns = $1
+ rest = $'
+ elements.delete_if do |element|
+ !(element.kind_of? Element and
+ (element.expanded_name == name or
+ (element.name == name and
+ element.namespace == Functions.namespace_context[ns])))
+ end
+ return filter( elements, rest )
+ when /^\/\[/u
+ matches = []
+ elements.each do |element|
+ matches |= predicate( element.to_a, path[1..-1] ) if element.kind_of? Element
+ end
+ return matches
+ when /^\[/u # Predicate
+ return predicate( elements, path )
+ when /^\/?\.\.\./u # Ancestor
+ return axe( elements, "ancestor", $' )
+ when /^\/?\.\./u # Parent
+ return filter( elements.collect{|e|e.parent}, $' )
+ when /^\/?\./u # Self
+ return filter( elements, $' )
+ when /^\*/u # Any
+ results = []
+ elements.each do |element|
+ results |= filter( [element], $' ) if element.kind_of? Element
+ #if element.kind_of? Element
+ # children = element.to_a
+ # children.delete_if { |child| !child.kind_of?(Element) }
+ # results |= filter( children, $' )
+ #end
+ end
+ return results
+ end
+ return []
+ end
- def QuickPath::axe( elements, axe_name, rest )
- matches = []
- matches = filter( elements.dup, rest ) if axe_name =~ /-or-self$/u
- case axe_name
- when /^descendant/u
- elements.each do |element|
- matches |= filter( element.to_a, "descendant-or-self::#{rest}" ) if element.kind_of? Element
- end
- when /^ancestor/u
- elements.each do |element|
- while element.parent
- matches << element.parent
- element = element.parent
- end
- end
- matches = filter( matches, rest )
- when "self"
- matches = filter( elements, rest )
- when "child"
- elements.each do |element|
- matches |= filter( element.to_a, rest ) if element.kind_of? Element
- end
- when "attribute"
- elements.each do |element|
- matches << element.attributes[ rest ] if element.kind_of? Element
- end
- when "parent"
- matches = filter(elements.collect{|element| element.parent}.uniq, rest)
- when "following-sibling"
- matches = filter(elements.collect{|element| element.next_sibling}.uniq,
- rest)
- when "previous-sibling"
- matches = filter(elements.collect{|element|
- element.previous_sibling}.uniq, rest )
- end
- return matches.uniq
- end
+ def QuickPath::axe( elements, axe_name, rest )
+ matches = []
+ matches = filter( elements.dup, rest ) if axe_name =~ /-or-self$/u
+ case axe_name
+ when /^descendant/u
+ elements.each do |element|
+ matches |= filter( element.to_a, "descendant-or-self::#{rest}" ) if element.kind_of? Element
+ end
+ when /^ancestor/u
+ elements.each do |element|
+ while element.parent
+ matches << element.parent
+ element = element.parent
+ end
+ end
+ matches = filter( matches, rest )
+ when "self"
+ matches = filter( elements, rest )
+ when "child"
+ elements.each do |element|
+ matches |= filter( element.to_a, rest ) if element.kind_of? Element
+ end
+ when "attribute"
+ elements.each do |element|
+ matches << element.attributes[ rest ] if element.kind_of? Element
+ end
+ when "parent"
+ matches = filter(elements.collect{|element| element.parent}.uniq, rest)
+ when "following-sibling"
+ matches = filter(elements.collect{|element| element.next_sibling}.uniq,
+ rest)
+ when "previous-sibling"
+ matches = filter(elements.collect{|element|
+ element.previous_sibling}.uniq, rest )
+ end
+ return matches.uniq
+ end
- # A predicate filters a node-set with respect to an axis to produce a
- # new node-set. For each node in the node-set to be filtered, the
- # PredicateExpr is evaluated with that node as the context node, with
- # the number of nodes in the node-set as the context size, and with the
- # proximity position of the node in the node-set with respect to the
- # axis as the context position; if PredicateExpr evaluates to true for
- # that node, the node is included in the new node-set; otherwise, it is
- # not included.
- #
- # A PredicateExpr is evaluated by evaluating the Expr and converting
- # the result to a boolean. If the result is a number, the result will
- # be converted to true if the number is equal to the context position
- # and will be converted to false otherwise; if the result is not a
- # number, then the result will be converted as if by a call to the
- # boolean function. Thus a location path para[3] is equivalent to
- # para[position()=3].
- def QuickPath::predicate( elements, path )
- ind = 1
- bcount = 1
- while bcount > 0
- bcount += 1 if path[ind] == ?[
- bcount -= 1 if path[ind] == ?]
- ind += 1
- end
- ind -= 1
- predicate = path[1..ind-1]
- rest = path[ind+1..-1]
+ # A predicate filters a node-set with respect to an axis to produce a
+ # new node-set. For each node in the node-set to be filtered, the
+ # PredicateExpr is evaluated with that node as the context node, with
+ # the number of nodes in the node-set as the context size, and with the
+ # proximity position of the node in the node-set with respect to the
+ # axis as the context position; if PredicateExpr evaluates to true for
+ # that node, the node is included in the new node-set; otherwise, it is
+ # not included.
+ #
+ # A PredicateExpr is evaluated by evaluating the Expr and converting
+ # the result to a boolean. If the result is a number, the result will
+ # be converted to true if the number is equal to the context position
+ # and will be converted to false otherwise; if the result is not a
+ # number, then the result will be converted as if by a call to the
+ # boolean function. Thus a location path para[3] is equivalent to
+ # para[position()=3].
+ def QuickPath::predicate( elements, path )
+ ind = 1
+ bcount = 1
+ while bcount > 0
+ bcount += 1 if path[ind] == ?[
+ bcount -= 1 if path[ind] == ?]
+ ind += 1
+ end
+ ind -= 1
+ predicate = path[1..ind-1]
+ rest = path[ind+1..-1]
- # have to change 'a [=<>] b [=<>] c' into 'a [=<>] b and b [=<>] c'
- predicate.gsub!( /([^\s(and)(or)<>=]+)\s*([<>=])\s*([^\s(and)(or)<>=]+)\s*([<>=])\s*([^\s(and)(or)<>=]+)/u,
- '\1 \2 \3 and \3 \4 \5' )
- # Let's do some Ruby trickery to avoid some work:
- predicate.gsub!( /&/u, "&&" )
- predicate.gsub!( /=/u, "==" )
- predicate.gsub!( /@(\w[-\w.]*)/u, 'attribute("\1")' )
- predicate.gsub!( /\bmod\b/u, "%" )
- predicate.gsub!( /\b(\w[-\w.]*\()/u ) {
- fname = $1
- fname.gsub( /-/u, "_" )
- }
-
- Functions.pair = [ 0, elements.size ]
- results = []
- elements.each do |element|
- Functions.pair[0] += 1
- Functions.node = element
- res = eval( predicate )
- case res
- when true
- results << element
- when Fixnum
- results << element if Functions.pair[0] == res
- when String
- results << element
- end
- end
- return filter( results, rest )
- end
+ # have to change 'a [=<>] b [=<>] c' into 'a [=<>] b and b [=<>] c'
+ predicate.gsub!( /([^\s(and)(or)<>=]+)\s*([<>=])\s*([^\s(and)(or)<>=]+)\s*([<>=])\s*([^\s(and)(or)<>=]+)/u,
+ '\1 \2 \3 and \3 \4 \5' )
+ # Let's do some Ruby trickery to avoid some work:
+ predicate.gsub!( /&/u, "&&" )
+ predicate.gsub!( /=/u, "==" )
+ predicate.gsub!( /@(\w[-\w.]*)/u, 'attribute("\1")' )
+ predicate.gsub!( /\bmod\b/u, "%" )
+ predicate.gsub!( /\b(\w[-\w.]*\()/u ) {
+ fname = $1
+ fname.gsub( /-/u, "_" )
+ }
+
+ Functions.pair = [ 0, elements.size ]
+ results = []
+ elements.each do |element|
+ Functions.pair[0] += 1
+ Functions.node = element
+ res = eval( predicate )
+ case res
+ when true
+ results << element
+ when Fixnum
+ results << element if Functions.pair[0] == res
+ when String
+ results << element
+ end
+ end
+ return filter( results, rest )
+ end
- def QuickPath::attribute( name )
- return Functions.node.attributes[name] if Functions.node.kind_of? Element
- end
+ def QuickPath::attribute( name )
+ return Functions.node.attributes[name] if Functions.node.kind_of? Element
+ end
- def QuickPath::name()
- return Functions.node.name if Functions.node.kind_of? Element
- end
+ def QuickPath::name()
+ return Functions.node.name if Functions.node.kind_of? Element
+ end
- def QuickPath::method_missing( id, *args )
- begin
- Functions.send( id.id2name, *args )
- rescue Exception
- raise "METHOD: #{id.id2name}(#{args.join ', '})\n#{$!.message}"
- end
- end
+ def QuickPath::method_missing( id, *args )
+ begin
+ Functions.send( id.id2name, *args )
+ rescue Exception
+ raise "METHOD: #{id.id2name}(#{args.join ', '})\n#{$!.message}"
+ end
+ end
- def QuickPath::function( elements, fname, rest )
- args = parse_args( elements, rest )
- Functions.pair = [0, elements.size]
- results = []
- elements.each do |element|
- Functions.pair[0] += 1
- Functions.node = element
- res = Functions.send( fname, *args )
- case res
- when true
- results << element
- when Fixnum
- results << element if Functions.pair[0] == res
- end
- end
- return results
- end
+ def QuickPath::function( elements, fname, rest )
+ args = parse_args( elements, rest )
+ Functions.pair = [0, elements.size]
+ results = []
+ elements.each do |element|
+ Functions.pair[0] += 1
+ Functions.node = element
+ res = Functions.send( fname, *args )
+ case res
+ when true
+ results << element
+ when Fixnum
+ results << element if Functions.pair[0] == res
+ end
+ end
+ return results
+ end
- def QuickPath::parse_args( element, string )
- # /.*?(?:\)|,)/
- arguments = []
- buffer = ""
- while string and string != ""
- c = string[0]
- string.sub!(/^./u, "")
- case c
- when ?,
- # if depth = 1, then we start a new argument
- arguments << evaluate( buffer )
- #arguments << evaluate( string[0..count] )
- when ?(
- # start a new method call
- function( element, buffer, string )
- buffer = ""
- when ?)
- # close the method call and return arguments
- return arguments
- else
- buffer << c
- end
- end
- ""
- end
- end
+ def QuickPath::parse_args( element, string )
+ # /.*?(?:\)|,)/
+ arguments = []
+ buffer = ""
+ while string and string != ""
+ c = string[0]
+ string.sub!(/^./u, "")
+ case c
+ when ?,
+ # if depth = 1, then we start a new argument
+ arguments << evaluate( buffer )
+ #arguments << evaluate( string[0..count] )
+ when ?(
+ # start a new method call
+ function( element, buffer, string )
+ buffer = ""
+ when ?)
+ # close the method call and return arguments
+ return arguments
+ else
+ buffer << c
+ end
+ end
+ ""
+ end
+ end
end
diff --git a/lib/rexml/sax2listener.rb b/lib/rexml/sax2listener.rb
index 8db1389d06..9545b08a93 100644
--- a/lib/rexml/sax2listener.rb
+++ b/lib/rexml/sax2listener.rb
@@ -1,97 +1,97 @@
module REXML
- # A template for stream parser listeners.
- # Note that the declarations (attlistdecl, elementdecl, etc) are trivially
- # processed; REXML doesn't yet handle doctype entity declarations, so you
- # have to parse them out yourself.
- # === Missing methods from SAX2
- # ignorable_whitespace
- # === Methods extending SAX2
- # +WARNING+
- # These methods are certainly going to change, until DTDs are fully
- # supported. Be aware of this.
- # start_document
- # end_document
- # doctype
- # elementdecl
- # attlistdecl
- # entitydecl
- # notationdecl
- # cdata
- # xmldecl
- # comment
- module SAX2Listener
- def start_document
- end
- def end_document
- end
- def start_prefix_mapping prefix, uri
- end
- def end_prefix_mapping prefix
- end
- def start_element uri, localname, qname, attributes
- end
- def end_element uri, localname, qname
- end
- def characters text
- end
- def processing_instruction target, data
- end
- # Handles a doctype declaration. Any attributes of the doctype which are
- # not supplied will be nil. # EG, <!DOCTYPE me PUBLIC "foo" "bar">
- # @p name the name of the doctype; EG, "me"
- # @p pub_sys "PUBLIC", "SYSTEM", or nil. EG, "PUBLIC"
- # @p long_name the supplied long name, or nil. EG, "foo"
- # @p uri the uri of the doctype, or nil. EG, "bar"
- def doctype name, pub_sys, long_name, uri
- end
- # If a doctype includes an ATTLIST declaration, it will cause this
- # method to be called. The content is the declaration itself, unparsed.
- # EG, <!ATTLIST el attr CDATA #REQUIRED> will come to this method as "el
- # attr CDATA #REQUIRED". This is the same for all of the .*decl
- # methods.
- def attlistdecl(element, pairs, contents)
- end
- # <!ELEMENT ...>
- def elementdecl content
- end
- # <!ENTITY ...>
- # The argument passed to this method is an array of the entity
- # declaration. It can be in a number of formats, but in general it
- # returns (example, result):
- # <!ENTITY % YN '"Yes"'>
- # ["%", "YN", "'\"Yes\"'", "\""]
- # <!ENTITY % YN 'Yes'>
- # ["%", "YN", "'Yes'", "s"]
- # <!ENTITY WhatHeSaid "He said %YN;">
- # ["WhatHeSaid", "\"He said %YN;\"", "YN"]
- # <!ENTITY open-hatch SYSTEM "http://www.textuality.com/boilerplate/OpenHatch.xml">
- # ["open-hatch", "SYSTEM", "\"http://www.textuality.com/boilerplate/OpenHatch.xml\""]
- # <!ENTITY open-hatch PUBLIC "-//Textuality//TEXT Standard open-hatch boilerplate//EN" "http://www.textuality.com/boilerplate/OpenHatch.xml">
- # ["open-hatch", "PUBLIC", "\"-//Textuality//TEXT Standard open-hatch boilerplate//EN\"", "\"http://www.textuality.com/boilerplate/OpenHatch.xml\""]
- # <!ENTITY hatch-pic SYSTEM "../grafix/OpenHatch.gif" NDATA gif>
- # ["hatch-pic", "SYSTEM", "\"../grafix/OpenHatch.gif\"", "\n\t\t\t\t\t\t\tNDATA gif", "gif"]
- def entitydecl name, decl
- end
- # <!NOTATION ...>
- def notationdecl content
- end
- # Called when <![CDATA[ ... ]]> is encountered in a document.
- # @p content "..."
- def cdata content
- end
- # Called when an XML PI is encountered in the document.
- # EG: <?xml version="1.0" encoding="utf"?>
- # @p version the version attribute value. EG, "1.0"
- # @p encoding the encoding attribute value, or nil. EG, "utf"
- # @p standalone the standalone attribute value, or nil. EG, nil
+ # A template for stream parser listeners.
+ # Note that the declarations (attlistdecl, elementdecl, etc) are trivially
+ # processed; REXML doesn't yet handle doctype entity declarations, so you
+ # have to parse them out yourself.
+ # === Missing methods from SAX2
+ # ignorable_whitespace
+ # === Methods extending SAX2
+ # +WARNING+
+ # These methods are certainly going to change, until DTDs are fully
+ # supported. Be aware of this.
+ # start_document
+ # end_document
+ # doctype
+ # elementdecl
+ # attlistdecl
+ # entitydecl
+ # notationdecl
+ # cdata
+ # xmldecl
+ # comment
+ module SAX2Listener
+ def start_document
+ end
+ def end_document
+ end
+ def start_prefix_mapping prefix, uri
+ end
+ def end_prefix_mapping prefix
+ end
+ def start_element uri, localname, qname, attributes
+ end
+ def end_element uri, localname, qname
+ end
+ def characters text
+ end
+ def processing_instruction target, data
+ end
+ # Handles a doctype declaration. Any attributes of the doctype which are
+ # not supplied will be nil. # EG, <!DOCTYPE me PUBLIC "foo" "bar">
+ # @p name the name of the doctype; EG, "me"
+ # @p pub_sys "PUBLIC", "SYSTEM", or nil. EG, "PUBLIC"
+ # @p long_name the supplied long name, or nil. EG, "foo"
+ # @p uri the uri of the doctype, or nil. EG, "bar"
+ def doctype name, pub_sys, long_name, uri
+ end
+ # If a doctype includes an ATTLIST declaration, it will cause this
+ # method to be called. The content is the declaration itself, unparsed.
+ # EG, <!ATTLIST el attr CDATA #REQUIRED> will come to this method as "el
+ # attr CDATA #REQUIRED". This is the same for all of the .*decl
+ # methods.
+ def attlistdecl(element, pairs, contents)
+ end
+ # <!ELEMENT ...>
+ def elementdecl content
+ end
+ # <!ENTITY ...>
+ # The argument passed to this method is an array of the entity
+ # declaration. It can be in a number of formats, but in general it
+ # returns (example, result):
+ # <!ENTITY % YN '"Yes"'>
+ # ["%", "YN", "'\"Yes\"'", "\""]
+ # <!ENTITY % YN 'Yes'>
+ # ["%", "YN", "'Yes'", "s"]
+ # <!ENTITY WhatHeSaid "He said %YN;">
+ # ["WhatHeSaid", "\"He said %YN;\"", "YN"]
+ # <!ENTITY open-hatch SYSTEM "http://www.textuality.com/boilerplate/OpenHatch.xml">
+ # ["open-hatch", "SYSTEM", "\"http://www.textuality.com/boilerplate/OpenHatch.xml\""]
+ # <!ENTITY open-hatch PUBLIC "-//Textuality//TEXT Standard open-hatch boilerplate//EN" "http://www.textuality.com/boilerplate/OpenHatch.xml">
+ # ["open-hatch", "PUBLIC", "\"-//Textuality//TEXT Standard open-hatch boilerplate//EN\"", "\"http://www.textuality.com/boilerplate/OpenHatch.xml\""]
+ # <!ENTITY hatch-pic SYSTEM "../grafix/OpenHatch.gif" NDATA gif>
+ # ["hatch-pic", "SYSTEM", "\"../grafix/OpenHatch.gif\"", "\n\t\t\t\t\t\t\tNDATA gif", "gif"]
+ def entitydecl name, decl
+ end
+ # <!NOTATION ...>
+ def notationdecl content
+ end
+ # Called when <![CDATA[ ... ]]> is encountered in a document.
+ # @p content "..."
+ def cdata content
+ end
+ # Called when an XML PI is encountered in the document.
+ # EG: <?xml version="1.0" encoding="utf"?>
+ # @p version the version attribute value. EG, "1.0"
+ # @p encoding the encoding attribute value, or nil. EG, "utf"
+ # @p standalone the standalone attribute value, or nil. EG, nil
# @p spaced the declaration is followed by a line break
- def xmldecl version, encoding, standalone
- end
- # Called when a comment is encountered.
- # @p comment The content of the comment
- def comment comment
- end
+ def xmldecl version, encoding, standalone
+ end
+ # Called when a comment is encountered.
+ # @p comment The content of the comment
+ def comment comment
+ end
def progress position
end
- end
+ end
end
diff --git a/lib/rexml/streamlistener.rb b/lib/rexml/streamlistener.rb
index 6f401125b5..3a4ef9f769 100644
--- a/lib/rexml/streamlistener.rb
+++ b/lib/rexml/streamlistener.rb
@@ -1,92 +1,92 @@
module REXML
- # A template for stream parser listeners.
- # Note that the declarations (attlistdecl, elementdecl, etc) are trivially
- # processed; REXML doesn't yet handle doctype entity declarations, so you
- # have to parse them out yourself.
- module StreamListener
- # Called when a tag is encountered.
- # @p name the tag name
- # @p attrs an array of arrays of attribute/value pairs, suitable for
- # use with assoc or rassoc. IE, <tag attr1="value1" attr2="value2">
- # will result in
- # tag_start( "tag", # [["attr1","value1"],["attr2","value2"]])
- def tag_start name, attrs
- end
- # Called when the end tag is reached. In the case of <tag/>, tag_end
- # will be called immidiately after tag_start
- # @p the name of the tag
- def tag_end name
- end
- # Called when text is encountered in the document
- # @p text the text content.
- def text text
- end
- # Called when an instruction is encountered. EG: <?xsl sheet='foo'?>
- # @p name the instruction name; in the example, "xsl"
- # @p instruction the rest of the instruction. In the example,
- # "sheet='foo'"
- def instruction name, instruction
- end
- # Called when a comment is encountered.
- # @p comment The content of the comment
- def comment comment
- end
- # Handles a doctype declaration. Any attributes of the doctype which are
- # not supplied will be nil. # EG, <!DOCTYPE me PUBLIC "foo" "bar">
- # @p name the name of the doctype; EG, "me"
- # @p pub_sys "PUBLIC", "SYSTEM", or nil. EG, "PUBLIC"
- # @p long_name the supplied long name, or nil. EG, "foo"
- # @p uri the uri of the doctype, or nil. EG, "bar"
- def doctype name, pub_sys, long_name, uri
- end
- # Called when the doctype is done
- def doctype_end
- end
- # If a doctype includes an ATTLIST declaration, it will cause this
- # method to be called. The content is the declaration itself, unparsed.
- # EG, <!ATTLIST el attr CDATA #REQUIRED> will come to this method as "el
- # attr CDATA #REQUIRED". This is the same for all of the .*decl
- # methods.
- def attlistdecl element_name, attributes, raw_content
- end
- # <!ELEMENT ...>
- def elementdecl content
- end
- # <!ENTITY ...>
- # The argument passed to this method is an array of the entity
- # declaration. It can be in a number of formats, but in general it
- # returns (example, result):
- # <!ENTITY % YN '"Yes"'>
- # ["%", "YN", "'\"Yes\"'", "\""]
- # <!ENTITY % YN 'Yes'>
- # ["%", "YN", "'Yes'", "s"]
- # <!ENTITY WhatHeSaid "He said %YN;">
- # ["WhatHeSaid", "\"He said %YN;\"", "YN"]
- # <!ENTITY open-hatch SYSTEM "http://www.textuality.com/boilerplate/OpenHatch.xml">
- # ["open-hatch", "SYSTEM", "\"http://www.textuality.com/boilerplate/OpenHatch.xml\""]
- # <!ENTITY open-hatch PUBLIC "-//Textuality//TEXT Standard open-hatch boilerplate//EN" "http://www.textuality.com/boilerplate/OpenHatch.xml">
- # ["open-hatch", "PUBLIC", "\"-//Textuality//TEXT Standard open-hatch boilerplate//EN\"", "\"http://www.textuality.com/boilerplate/OpenHatch.xml\""]
- # <!ENTITY hatch-pic SYSTEM "../grafix/OpenHatch.gif" NDATA gif>
- # ["hatch-pic", "SYSTEM", "\"../grafix/OpenHatch.gif\"", "\n\t\t\t\t\t\t\tNDATA gif", "gif"]
- def entitydecl content
- end
- # <!NOTATION ...>
- def notationdecl content
- end
- # Called when %foo; is encountered in a doctype declaration.
- # @p content "foo"
- def entity content
- end
- # Called when <![CDATA[ ... ]]> is encountered in a document.
- # @p content "..."
- def cdata content
- end
- # Called when an XML PI is encountered in the document.
- # EG: <?xml version="1.0" encoding="utf"?>
- # @p version the version attribute value. EG, "1.0"
- # @p encoding the encoding attribute value, or nil. EG, "utf"
- # @p standalone the standalone attribute value, or nil. EG, nil
- def xmldecl version, encoding, standalone
- end
- end
+ # A template for stream parser listeners.
+ # Note that the declarations (attlistdecl, elementdecl, etc) are trivially
+ # processed; REXML doesn't yet handle doctype entity declarations, so you
+ # have to parse them out yourself.
+ module StreamListener
+ # Called when a tag is encountered.
+ # @p name the tag name
+ # @p attrs an array of arrays of attribute/value pairs, suitable for
+ # use with assoc or rassoc. IE, <tag attr1="value1" attr2="value2">
+ # will result in
+ # tag_start( "tag", # [["attr1","value1"],["attr2","value2"]])
+ def tag_start name, attrs
+ end
+ # Called when the end tag is reached. In the case of <tag/>, tag_end
+ # will be called immidiately after tag_start
+ # @p the name of the tag
+ def tag_end name
+ end
+ # Called when text is encountered in the document
+ # @p text the text content.
+ def text text
+ end
+ # Called when an instruction is encountered. EG: <?xsl sheet='foo'?>
+ # @p name the instruction name; in the example, "xsl"
+ # @p instruction the rest of the instruction. In the example,
+ # "sheet='foo'"
+ def instruction name, instruction
+ end
+ # Called when a comment is encountered.
+ # @p comment The content of the comment
+ def comment comment
+ end
+ # Handles a doctype declaration. Any attributes of the doctype which are
+ # not supplied will be nil. # EG, <!DOCTYPE me PUBLIC "foo" "bar">
+ # @p name the name of the doctype; EG, "me"
+ # @p pub_sys "PUBLIC", "SYSTEM", or nil. EG, "PUBLIC"
+ # @p long_name the supplied long name, or nil. EG, "foo"
+ # @p uri the uri of the doctype, or nil. EG, "bar"
+ def doctype name, pub_sys, long_name, uri
+ end
+ # Called when the doctype is done
+ def doctype_end
+ end
+ # If a doctype includes an ATTLIST declaration, it will cause this
+ # method to be called. The content is the declaration itself, unparsed.
+ # EG, <!ATTLIST el attr CDATA #REQUIRED> will come to this method as "el
+ # attr CDATA #REQUIRED". This is the same for all of the .*decl
+ # methods.
+ def attlistdecl element_name, attributes, raw_content
+ end
+ # <!ELEMENT ...>
+ def elementdecl content
+ end
+ # <!ENTITY ...>
+ # The argument passed to this method is an array of the entity
+ # declaration. It can be in a number of formats, but in general it
+ # returns (example, result):
+ # <!ENTITY % YN '"Yes"'>
+ # ["%", "YN", "'\"Yes\"'", "\""]
+ # <!ENTITY % YN 'Yes'>
+ # ["%", "YN", "'Yes'", "s"]
+ # <!ENTITY WhatHeSaid "He said %YN;">
+ # ["WhatHeSaid", "\"He said %YN;\"", "YN"]
+ # <!ENTITY open-hatch SYSTEM "http://www.textuality.com/boilerplate/OpenHatch.xml">
+ # ["open-hatch", "SYSTEM", "\"http://www.textuality.com/boilerplate/OpenHatch.xml\""]
+ # <!ENTITY open-hatch PUBLIC "-//Textuality//TEXT Standard open-hatch boilerplate//EN" "http://www.textuality.com/boilerplate/OpenHatch.xml">
+ # ["open-hatch", "PUBLIC", "\"-//Textuality//TEXT Standard open-hatch boilerplate//EN\"", "\"http://www.textuality.com/boilerplate/OpenHatch.xml\""]
+ # <!ENTITY hatch-pic SYSTEM "../grafix/OpenHatch.gif" NDATA gif>
+ # ["hatch-pic", "SYSTEM", "\"../grafix/OpenHatch.gif\"", "\n\t\t\t\t\t\t\tNDATA gif", "gif"]
+ def entitydecl content
+ end
+ # <!NOTATION ...>
+ def notationdecl content
+ end
+ # Called when %foo; is encountered in a doctype declaration.
+ # @p content "foo"
+ def entity content
+ end
+ # Called when <![CDATA[ ... ]]> is encountered in a document.
+ # @p content "..."
+ def cdata content
+ end
+ # Called when an XML PI is encountered in the document.
+ # EG: <?xml version="1.0" encoding="utf"?>
+ # @p version the version attribute value. EG, "1.0"
+ # @p encoding the encoding attribute value, or nil. EG, "utf"
+ # @p standalone the standalone attribute value, or nil. EG, nil
+ def xmldecl version, encoding, standalone
+ end
+ end
end
diff --git a/lib/rexml/xmldecl.rb b/lib/rexml/xmldecl.rb
index 427eb78cf8..361e4b7106 100644
--- a/lib/rexml/xmldecl.rb
+++ b/lib/rexml/xmldecl.rb
@@ -2,40 +2,40 @@ require 'rexml/encoding'
require 'rexml/source'
module REXML
- # NEEDS DOCUMENTATION
- class XMLDecl < Child
- include Encoding
+ # NEEDS DOCUMENTATION
+ class XMLDecl < Child
+ include Encoding
- DEFAULT_VERSION = "1.0";
- DEFAULT_ENCODING = "UTF-8";
- DEFAULT_STANDALONE = "no";
- START = '<\?xml';
- STOP = '\?>';
+ DEFAULT_VERSION = "1.0";
+ DEFAULT_ENCODING = "UTF-8";
+ DEFAULT_STANDALONE = "no";
+ START = '<\?xml';
+ STOP = '\?>';
- attr_accessor :version, :standalone
+ attr_accessor :version, :standalone
attr_reader :writeencoding, :writethis
- def initialize(version=DEFAULT_VERSION, encoding=nil, standalone=nil)
+ def initialize(version=DEFAULT_VERSION, encoding=nil, standalone=nil)
@writethis = true
@writeencoding = !encoding.nil?
- if version.kind_of? XMLDecl
- super()
- @version = version.version
- self.encoding = version.encoding
+ if version.kind_of? XMLDecl
+ super()
+ @version = version.version
+ self.encoding = version.encoding
@writeencoding = version.writeencoding
- @standalone = version.standalone
- else
- super()
- @version = version
- self.encoding = encoding
- @standalone = standalone
- end
- @version = DEFAULT_VERSION if @version.nil?
- end
-
- def clone
- XMLDecl.new(self)
- end
+ @standalone = version.standalone
+ else
+ super()
+ @version = version
+ self.encoding = encoding
+ @standalone = standalone
+ end
+ @version = DEFAULT_VERSION if @version.nil?
+ end
+
+ def clone
+ XMLDecl.new(self)
+ end
# indent::
# Ignored. There must be no whitespace before an XML declaration
@@ -43,35 +43,35 @@ module REXML
# Ignored
# ie_hack::
# Ignored
- def write(writer, indent=-1, transitive=false, ie_hack=false)
+ def write(writer, indent=-1, transitive=false, ie_hack=false)
return nil unless @writethis or writer.kind_of? Output
- writer << START.sub(/\\/u, '')
+ writer << START.sub(/\\/u, '')
if writer.kind_of? Output
writer << " #{content writer.encoding}"
else
writer << " #{content encoding}"
end
- writer << STOP.sub(/\\/u, '')
- end
-
- def ==( other )
- other.kind_of?(XMLDecl) and
- other.version == @version and
- other.encoding == self.encoding and
- other.standalone == @standalone
- end
-
- def xmldecl version, encoding, standalone
- @version = version
- self.encoding = encoding
- @standalone = standalone
- end
-
- def node_type
- :xmldecl
- end
-
- alias :stand_alone? :standalone
+ writer << STOP.sub(/\\/u, '')
+ end
+
+ def ==( other )
+ other.kind_of?(XMLDecl) and
+ other.version == @version and
+ other.encoding == self.encoding and
+ other.standalone == @standalone
+ end
+
+ def xmldecl version, encoding, standalone
+ @version = version
+ self.encoding = encoding
+ @standalone = standalone
+ end
+
+ def node_type
+ :xmldecl
+ end
+
+ alias :stand_alone? :standalone
alias :old_enc= :encoding=
def encoding=( enc )
@@ -108,12 +108,12 @@ module REXML
START.sub(/\\/u, '') + " ... " + STOP.sub(/\\/u, '')
end
- private
- def content(enc)
- rv = "version='#@version'"
- rv << " encoding='#{enc}'" if @writeencoding || enc !~ /utf-8/i
- rv << " standalone='#@standalone'" if @standalone
- rv
- end
- end
+ private
+ def content(enc)
+ rv = "version='#@version'"
+ rv << " encoding='#{enc}'" if @writeencoding || enc !~ /utf-8/i
+ rv << " standalone='#@standalone'" if @standalone
+ rv
+ end
+ end
end
diff --git a/lib/rexml/xmltokens.rb b/lib/rexml/xmltokens.rb
index 6bbe5b07d5..83efeb0e44 100644
--- a/lib/rexml/xmltokens.rb
+++ b/lib/rexml/xmltokens.rb
@@ -1,18 +1,18 @@
module REXML
- # Defines a number of tokens used for parsing XML. Not for general
- # consumption.
- module XMLTokens
- NCNAME_STR= '[\w:][\-\w\d.]*'
- NAME_STR= "(?:#{NCNAME_STR}:)?#{NCNAME_STR}"
+ # Defines a number of tokens used for parsing XML. Not for general
+ # consumption.
+ module XMLTokens
+ NCNAME_STR= '[\w:][\-\w\d.]*'
+ NAME_STR= "(?:#{NCNAME_STR}:)?#{NCNAME_STR}"
- NAMECHAR = '[\-\w\d\.:]'
- NAME = "([\\w:]#{NAMECHAR}*)"
- NMTOKEN = "(?:#{NAMECHAR})+"
- NMTOKENS = "#{NMTOKEN}(\\s+#{NMTOKEN})*"
- REFERENCE = "(?:&#{NAME};|&#\\d+;|&#x[0-9a-fA-F]+;)"
+ NAMECHAR = '[\-\w\d\.:]'
+ NAME = "([\\w:]#{NAMECHAR}*)"
+ NMTOKEN = "(?:#{NAMECHAR})+"
+ NMTOKENS = "#{NMTOKEN}(\\s+#{NMTOKEN})*"
+ REFERENCE = "(?:&#{NAME};|&#\\d+;|&#x[0-9a-fA-F]+;)"
- #REFERENCE = "(?:#{ENTITYREF}|#{CHARREF})"
- #ENTITYREF = "&#{NAME};"
- #CHARREF = "&#\\d+;|&#x[0-9a-fA-F]+;"
- end
+ #REFERENCE = "(?:#{ENTITYREF}|#{CHARREF})"
+ #ENTITYREF = "&#{NAME};"
+ #CHARREF = "&#\\d+;|&#x[0-9a-fA-F]+;"
+ end
end
diff --git a/lib/rexml/xpath.rb b/lib/rexml/xpath.rb
index e8813efd3e..7c5c258ad9 100644
--- a/lib/rexml/xpath.rb
+++ b/lib/rexml/xpath.rb
@@ -2,65 +2,65 @@ require 'rexml/functions'
require 'rexml/xpath_parser'
module REXML
- # Wrapper class. Use this class to access the XPath functions.
- class XPath
- include Functions
- EMPTY_HASH = {}
+ # Wrapper class. Use this class to access the XPath functions.
+ class XPath
+ include Functions
+ EMPTY_HASH = {}
- # Finds and returns the first node that matches the supplied xpath.
- # element::
- # The context element
- # path::
- # The xpath to search for. If not supplied or nil, returns the first
- # node matching '*'.
- # namespaces::
- # If supplied, a Hash which defines a namespace mapping.
- #
- # XPath.first( node )
- # XPath.first( doc, "//b"} )
- # XPath.first( node, "a/x:b", { "x"=>"http://doofus" } )
+ # Finds and returns the first node that matches the supplied xpath.
+ # element::
+ # The context element
+ # path::
+ # The xpath to search for. If not supplied or nil, returns the first
+ # node matching '*'.
+ # namespaces::
+ # If supplied, a Hash which defines a namespace mapping.
+ #
+ # XPath.first( node )
+ # XPath.first( doc, "//b"} )
+ # XPath.first( node, "a/x:b", { "x"=>"http://doofus" } )
def XPath::first element, path=nil, namespaces=nil, variables={}
raise "The namespaces argument, if supplied, must be a hash object." unless namespaces.nil? or namespaces.kind_of?(Hash)
raise "The variables argument, if supplied, must be a hash object." unless variables.kind_of?(Hash)
- parser = XPathParser.new
- parser.namespaces = namespaces
- parser.variables = variables
- path = "*" unless path
- element = [element] unless element.kind_of? Array
- parser.parse(path, element).flatten[0]
- end
+ parser = XPathParser.new
+ parser.namespaces = namespaces
+ parser.variables = variables
+ path = "*" unless path
+ element = [element] unless element.kind_of? Array
+ parser.parse(path, element).flatten[0]
+ end
- # Iterates over nodes that match the given path, calling the supplied
- # block with the match.
- # element::
- # The context element
- # path::
- # The xpath to search for. If not supplied or nil, defaults to '*'
- # namespaces::
- # If supplied, a Hash which defines a namespace mapping
- #
- # XPath.each( node ) { |el| ... }
- # XPath.each( node, '/*[@attr='v']' ) { |el| ... }
- # XPath.each( node, 'ancestor::x' ) { |el| ... }
- def XPath::each element, path=nil, namespaces=nil, variables={}, &block
+ # Iterates over nodes that match the given path, calling the supplied
+ # block with the match.
+ # element::
+ # The context element
+ # path::
+ # The xpath to search for. If not supplied or nil, defaults to '*'
+ # namespaces::
+ # If supplied, a Hash which defines a namespace mapping
+ #
+ # XPath.each( node ) { |el| ... }
+ # XPath.each( node, '/*[@attr='v']' ) { |el| ... }
+ # XPath.each( node, 'ancestor::x' ) { |el| ... }
+ def XPath::each element, path=nil, namespaces=nil, variables={}, &block
raise "The namespaces argument, if supplied, must be a hash object." unless namespaces.nil? or namespaces.kind_of?(Hash)
raise "The variables argument, if supplied, must be a hash object." unless variables.kind_of?(Hash)
- parser = XPathParser.new
- parser.namespaces = namespaces
- parser.variables = variables
- path = "*" unless path
- element = [element] unless element.kind_of? Array
- parser.parse(path, element).each( &block )
- end
+ parser = XPathParser.new
+ parser.namespaces = namespaces
+ parser.variables = variables
+ path = "*" unless path
+ element = [element] unless element.kind_of? Array
+ parser.parse(path, element).each( &block )
+ end
- # Returns an array of nodes matching a given XPath.
- def XPath::match element, path=nil, namespaces=nil, variables={}
- parser = XPathParser.new
- parser.namespaces = namespaces
- parser.variables = variables
- path = "*" unless path
- element = [element] unless element.kind_of? Array
- parser.parse(path,element)
- end
- end
+ # Returns an array of nodes matching a given XPath.
+ def XPath::match element, path=nil, namespaces=nil, variables={}
+ parser = XPathParser.new
+ parser.namespaces = namespaces
+ parser.variables = variables
+ path = "*" unless path
+ element = [element] unless element.kind_of? Array
+ parser.parse(path,element)
+ end
+ end
end
diff --git a/lib/rexml/xpath_parser.rb b/lib/rexml/xpath_parser.rb
index 4275c2db0e..ead5adaf7f 100644
--- a/lib/rexml/xpath_parser.rb
+++ b/lib/rexml/xpath_parser.rb
@@ -419,10 +419,10 @@ module REXML
return @variables[ var_name ]
# :and, :or, :eq, :neq, :lt, :lteq, :gt, :gteq
- # TODO: Special case for :or and :and -- not evaluate the right
- # operand if the left alone determines result (i.e. is true for
- # :or and false for :and).
- when :eq, :neq, :lt, :lteq, :gt, :gteq, :and, :or
+ # TODO: Special case for :or and :and -- not evaluate the right
+ # operand if the left alone determines result (i.e. is true for
+ # :or and false for :and).
+ when :eq, :neq, :lt, :lteq, :gt, :gteq, :or
left = expr( path_stack.shift, nodeset.dup, context )
#puts "LEFT => #{left.inspect} (#{left.class.name})"
right = expr( path_stack.shift, nodeset.dup, context )
@@ -675,7 +675,7 @@ module REXML
def equality_relational_compare( set1, op, set2 )
#puts "EQ_REL_COMP(#{set1.inspect} #{op.inspect} #{set2.inspect})"
if set1.kind_of? Array and set2.kind_of? Array
- #puts "#{set1.size} & #{set2.size}"
+ #puts "#{set1.size} & #{set2.size}"
if set1.size == 1 and set2.size == 1
set1 = set1[0]
set2 = set2[0]
@@ -696,7 +696,7 @@ module REXML
return res
end
end
- #puts "EQ_REL_COMP: #{set1.inspect} (#{set1.class.name}), #{op}, #{set2.inspect} (#{set2.class.name})"
+ #puts "EQ_REL_COMP: #{set1.inspect} (#{set1.class.name}), #{op}, #{set2.inspect} (#{set2.class.name})"
#puts "COMPARING VALUES"
# If one is nodeset and other is number, compare number to each item
# in nodeset s.t. number op number(string(item))
@@ -705,7 +705,7 @@ module REXML
# If one is nodeset and other is boolean, compare boolean to each item
# in nodeset s.t. boolean op boolean(item)
if set1.kind_of? Array or set2.kind_of? Array
- #puts "ISA ARRAY"
+ #puts "ISA ARRAY"
if set1.kind_of? Array
a = set1
b = set2
@@ -724,7 +724,7 @@ module REXML
#puts "B = #{b.inspect}"
return a.collect {|v| compare( Functions::number(v), op, b )}
else
- #puts "Functions::string( #{b}(#{b.class.name}) ) = #{Functions::string(b)}"
+ #puts "Functions::string( #{b}(#{b.class.name}) ) = #{Functions::string(b)}"
b = Functions::string( b )
return a.collect { |v| compare( Functions::string(v), op, b ) }
end
diff --git a/lib/rss/converter.rb b/lib/rss/converter.rb
index 415a319188..745d6de965 100644
--- a/lib/rss/converter.rb
+++ b/lib/rss/converter.rb
@@ -7,6 +7,10 @@ module RSS
include Utils
def initialize(to_enc, from_enc=nil)
+ if "".respond_to?(:encode)
+ @to_encoding = to_enc
+ return
+ end
normalized_to_enc = to_enc.downcase.gsub(/-/, '_')
from_enc ||= 'utf-8'
normalized_from_enc = from_enc.downcase.gsub(/-/, '_')
@@ -23,7 +27,11 @@ module RSS
end
def convert(value)
- value
+ if value.is_a?(String) and value.respond_to?(:encode)
+ value.encode(@to_encoding)
+ else
+ value
+ end
end
def def_convert(depth=0)
diff --git a/lib/rubygems.rb b/lib/rubygems.rb
index fde91bfd4b..9913b59ce1 100644
--- a/lib/rubygems.rb
+++ b/lib/rubygems.rb
@@ -43,12 +43,14 @@ module Kernel
#
# GEM_SKIP=libA:libB ruby -I../libA -I../libB ./mycode.rb
- def gem(gem_name, *version_requirements)
+ def gem(gem_name, *version_requirements) # :doc:
skip_list = (ENV['GEM_SKIP'] || "").split(/:/)
raise Gem::LoadError, "skipping #{gem_name}" if skip_list.include? gem_name
Gem.activate(gem_name, *version_requirements)
end
+ private :gem
+
end
##
@@ -104,6 +106,11 @@ module Gem
@ruby = nil
@sources = []
+ @post_install_hooks ||= []
+ @post_uninstall_hooks ||= []
+ @pre_uninstall_hooks ||= []
+ @pre_install_hooks ||= []
+
##
# Activates an installed gem matching +gem+. The gem must satisfy
# +version_requirements+.
@@ -244,7 +251,10 @@ module Gem
def self.clear_paths
@gem_home = nil
@gem_path = nil
+ @user_home = nil
+
@@source_index = nil
+
MUTEX.synchronize do
@searcher = nil
end
@@ -261,9 +271,7 @@ module Gem
# The standard configuration object for gems.
def self.configuration
- return @configuration if @configuration
- require 'rubygems/config_file'
- @configuration = Gem::ConfigFile.new []
+ @configuration ||= Gem::ConfigFile.new []
end
##
@@ -288,6 +296,7 @@ module Gem
# A Zlib::Deflate.deflate wrapper
def self.deflate(data)
+ require 'zlib'
Zlib::Deflate.deflate data
end
@@ -296,7 +305,7 @@ module Gem
def self.dir
@gem_home ||= nil
- set_home(ENV['GEM_HOME'] || default_dir) unless @gem_home
+ set_home(ENV['GEM_HOME'] || Gem.configuration.home || default_dir) unless @gem_home
@gem_home
end
@@ -337,6 +346,22 @@ module Gem
end
##
+ # Returns a list of paths matching +file+ that can be used by a gem to pick
+ # up features from other gems. For example:
+ #
+ # Gem.find_files('rdoc/discover').each do |path| load path end
+ #
+ # find_files does not search $LOAD_PATH for files, only gems.
+
+ def self.find_files(path)
+ specs = searcher.find_all path
+
+ specs.map do |spec|
+ searcher.matching_files spec, path
+ end.flatten
+ end
+
+ ##
# Finds the user's home directory.
#--
# Some comments from the ruby-talk list regarding finding the home
@@ -353,7 +378,7 @@ module Gem
end
if ENV['HOMEDRIVE'] && ENV['HOMEPATH'] then
- return "#{ENV['HOMEDRIVE']}:#{ENV['HOMEPATH']}"
+ return "#{ENV['HOMEDRIVE']}#{ENV['HOMEPATH']}"
end
begin
@@ -373,6 +398,8 @@ module Gem
# Zlib::GzipReader wrapper that unzips +data+.
def self.gunzip(data)
+ require 'stringio'
+ require 'zlib'
data = StringIO.new data
Zlib::GzipReader.new(data).read
@@ -382,6 +409,8 @@ module Gem
# Zlib::GzipWriter wrapper that zips +data+.
def self.gzip(data)
+ require 'stringio'
+ require 'zlib'
zipped = StringIO.new
Zlib::GzipWriter.wrap zipped do |io| io.write data end
@@ -393,6 +422,7 @@ module Gem
# A Zlib::Inflate#inflate wrapper
def self.inflate(data)
+ require 'zlib'
Zlib::Inflate.inflate data
end
@@ -457,22 +487,20 @@ module Gem
# The file name and line number of the caller of the caller of this method.
def self.location_of_caller
- file, lineno = caller[1].split(':')
- lineno = lineno.to_i
+ caller[1] =~ /(.*?):(\d+)$/i
+ file = $1
+ lineno = $2.to_i
+
[file, lineno]
end
- private_class_method :location_of_caller
-
##
# manage_gems is useless and deprecated. Don't call it anymore.
- #--
- # TODO warn w/ RubyGems 1.2.x release.
- def self.manage_gems
- #file, lineno = location_of_caller
+ def self.manage_gems # :nodoc:
+ file, lineno = location_of_caller
- #warn "#{file}:#{lineno}:Warning: Gem#manage_gems is deprecated and will be removed on or after September 2008."
+ warn "#{file}:#{lineno}:Warning: Gem::manage_gems is deprecated and will be removed on or after March 2009."
end
##
@@ -489,11 +517,7 @@ module Gem
@gem_path ||= nil
unless @gem_path then
- paths = if ENV['GEM_PATH'] then
- [ENV['GEM_PATH']]
- else
- [default_path]
- end
+ paths = [ENV['GEM_PATH'] || Gem.configuration.path || default_path]
if defined?(APPLE_GEM_HOME) and not ENV['GEM_PATH'] then
paths << APPLE_GEM_HOME
@@ -524,6 +548,40 @@ module Gem
end
##
+ # Adds a post-install hook that will be passed an Gem::Installer instance
+ # when Gem::Installer#install is called
+
+ def self.post_install(&hook)
+ @post_install_hooks << hook
+ end
+
+ ##
+ # Adds a post-uninstall hook that will be passed a Gem::Uninstaller instance
+ # and the spec that was uninstalled when Gem::Uninstaller#uninstall is
+ # called
+
+ def self.post_uninstall(&hook)
+ @post_uninstall_hooks << hook
+ end
+
+ ##
+ # Adds a pre-install hook that will be passed an Gem::Installer instance
+ # when Gem::Installer#install is called
+
+ def self.pre_install(&hook)
+ @pre_install_hooks << hook
+ end
+
+ ##
+ # Adds a pre-uninstall hook that will be passed an Gem::Uninstaller instance
+ # and the spec that will be uninstalled when Gem::Uninstaller#uninstall is
+ # called
+
+ def self.pre_uninstall(&hook)
+ @pre_uninstall_hooks << hook
+ end
+
+ ##
# The directory prefix this RubyGems was installed at.
def self.prefix
@@ -600,6 +658,9 @@ module Gem
@ruby = File.join(ConfigMap[:bindir],
ConfigMap[:ruby_install_name])
@ruby << ConfigMap[:EXEEXT]
+
+ # escape string in case path to ruby executable contain spaces.
+ @ruby.sub!(/.*\s.*/m, '"\&"')
end
@ruby
@@ -655,7 +716,16 @@ module Gem
end
@gem_path.uniq!
- @gem_path.each do |gp| ensure_gem_subdirectories(gp) end
+ @gem_path.each do |path|
+ if 0 == File.expand_path(path).index(Gem.user_home)
+ next unless File.directory? Gem.user_home
+ unless win_platform? then
+ # only create by matching user
+ next if Etc.getpwuid.uid != File::Stat.new(Gem.user_home).uid
+ end
+ end
+ ensure_gem_subdirectories path
+ end
end
private_class_method :set_paths
@@ -686,6 +756,14 @@ module Gem
end
##
+ # Need to be able to set the sources without calling
+ # Gem.sources.replace since that would cause an infinite loop.
+
+ def self.sources=(new_sources)
+ @sources = new_sources
+ end
+
+ ##
# Glob pattern for require-able path suffixes.
def self.suffix_pattern
@@ -731,6 +809,27 @@ module Gem
attr_reader :loaded_specs
+ ##
+ # The list of hooks to be run before Gem::Install#install does any work
+
+ attr_reader :post_install_hooks
+
+ ##
+ # The list of hooks to be run before Gem::Uninstall#uninstall does any
+ # work
+
+ attr_reader :post_uninstall_hooks
+
+ ##
+ # The list of hooks to be run after Gem::Install#install is finished
+
+ attr_reader :pre_install_hooks
+
+ ##
+ # The list of hooks to be run after Gem::Uninstall#uninstall is finished
+
+ attr_reader :pre_uninstall_hooks
+
# :stopdoc:
alias cache source_index # an alias for the old name
@@ -781,7 +880,10 @@ if defined?(RUBY_ENGINE) then
end
end
+require 'rubygems/config_file'
+
if RUBY_VERSION < '1.9' then
require 'rubygems/custom_require'
end
+Gem.clear_paths
diff --git a/lib/rubygems/commands/check_command.rb b/lib/rubygems/commands/check_command.rb
index ca5e14b12d..17c2c8f9c7 100644
--- a/lib/rubygems/commands/check_command.rb
+++ b/lib/rubygems/commands/check_command.rb
@@ -31,7 +31,8 @@ class Gem::Commands::CheckCommand < Gem::Command
def execute
if options[:test]
version = options[:version] || Gem::Requirement.default
- gem_spec = Gem::SourceIndex.from_installed_gems.search(get_one_gem_name, version).first
+ dep = Gem::Dependency.new get_one_gem_name, version
+ gem_spec = Gem::SourceIndex.from_installed_gems.search(dep).first
Gem::Validator.new.unit_test(gem_spec)
end
diff --git a/lib/rubygems/commands/contents_command.rb b/lib/rubygems/commands/contents_command.rb
index 5060403fd8..bc75fb5c03 100644
--- a/lib/rubygems/commands/contents_command.rb
+++ b/lib/rubygems/commands/contents_command.rb
@@ -51,7 +51,7 @@ class Gem::Commands::ContentsCommand < Gem::Command
si = Gem::SourceIndex.from_gems_in(*s)
- gem_spec = si.search(/\A#{gem}\z/, version).last
+ gem_spec = si.find_name(gem, version).last
unless gem_spec then
say "Unable to find gem '#{gem}' in #{path_kind}"
diff --git a/lib/rubygems/commands/environment_command.rb b/lib/rubygems/commands/environment_command.rb
index a67c00bfd6..e672da54f0 100644
--- a/lib/rubygems/commands/environment_command.rb
+++ b/lib/rubygems/commands/environment_command.rb
@@ -18,6 +18,46 @@ class Gem::Commands::EnvironmentCommand < Gem::Command
return args.gsub(/^\s+/, '')
end
+ def description # :nodoc:
+ <<-EOF
+The RubyGems environment can be controlled through command line arguments,
+gemrc files, environment variables and built-in defaults.
+
+Command line argument defaults and some RubyGems defaults can be set in
+~/.gemrc file for individual users and a /etc/gemrc for all users. A gemrc
+is a YAML file with the following YAML keys:
+
+ :sources: A YAML array of remote gem repositories to install gems from
+ :verbose: Verbosity of the gem command. false, true, and :really are the
+ levels
+ :update_sources: Enable/disable automatic updating of repository metadata
+ :backtrace: Print backtrace when RubyGems encounters an error
+ :bulk_threshold: Switch to a bulk update when this many sources are out of
+ date (legacy setting)
+ :gempath: The paths in which to look for gems
+ gem_command: A string containing arguments for the specified gem command
+
+Example:
+
+ :verbose: false
+ install: --no-wrappers
+ update: --no-wrappers
+
+RubyGems' default local repository can be overriden with the GEM_PATH and
+GEM_HOME environment variables. GEM_HOME sets the default repository to
+install into. GEM_PATH allows multiple local repositories to be searched for
+gems.
+
+If you are behind a proxy server, RubyGems uses the HTTP_PROXY,
+HTTP_PROXY_USER and HTTP_PROXY_PASS environment variables to discover the
+proxy server.
+
+If you are packaging RubyGems all of RubyGems' defaults are in
+lib/rubygems/defaults.rb. You may override these in
+lib/rubygems/defaults/operating_system.rb
+ EOF
+ end
+
def usage # :nodoc:
"#{program_name} [arg]"
end
diff --git a/lib/rubygems/commands/help_command.rb b/lib/rubygems/commands/help_command.rb
index 05ea3f7a71..0c4a4ec16f 100644
--- a/lib/rubygems/commands/help_command.rb
+++ b/lib/rubygems/commands/help_command.rb
@@ -20,9 +20,9 @@ Some examples of 'gem' usage.
gem install --remote rake --test --rdoc --ri
* Install 'rake', but only version 0.3.1, even if dependencies
- are not met, and into a specific directory:
+ are not met, and into a user-specific directory:
- gem install rake --version 0.3.1 --force --install-dir $HOME/.gems
+ gem install rake --version 0.3.1 --force --user-install
* List local gems whose name begins with 'D':
diff --git a/lib/rubygems/commands/install_command.rb b/lib/rubygems/commands/install_command.rb
index 923d578a15..1a6eb68a8b 100644
--- a/lib/rubygems/commands/install_command.rb
+++ b/lib/rubygems/commands/install_command.rb
@@ -38,6 +38,19 @@ class Gem::Commands::InstallCommand < Gem::Command
"--no-test --install-dir #{Gem.dir}"
end
+ def description # :nodoc:
+ <<-EOF
+The install command installs local or remote gem into a gem repository.
+
+For gems with executables ruby installs a wrapper file into the executable
+directory by deault. This can be overridden with the --no-wrappers option.
+The wrapper allows you to choose among alternate gem versions using _version_.
+
+For example `rake _0.7.3_ --version` will run rake version 0.7.3 if a newer
+version is also installed.
+ EOF
+ end
+
def usage # :nodoc:
"#{program_name} GEMNAME [GEMNAME ...] [options] -- --build-flags"
end
@@ -106,6 +119,8 @@ class Gem::Commands::InstallCommand < Gem::Command
installed_gems.each do |gem|
Gem::DocManager.new(gem, options[:rdoc_args]).generate_ri
end
+
+ Gem::DocManager.update_ri_cache
end
if options[:generate_rdoc] then
diff --git a/lib/rubygems/commands/lock_command.rb b/lib/rubygems/commands/lock_command.rb
index 6be2774e92..5a43978dd9 100644
--- a/lib/rubygems/commands/lock_command.rb
+++ b/lib/rubygems/commands/lock_command.rb
@@ -58,15 +58,15 @@ lock it down to the exact version.
end
def complain(message)
- if options.strict then
- raise message
+ if options[:strict] then
+ raise Gem::Exception, message
else
say "# #{message}"
end
end
def execute
- say 'require "rubygems"'
+ say "require 'rubygems'"
locked = {}
@@ -77,15 +77,20 @@ lock it down to the exact version.
spec = Gem::SourceIndex.load_specification spec_path(full_name)
+ if spec.nil? then
+ complain "Could not find gem #{full_name}, try using the full name"
+ next
+ end
+
say "gem '#{spec.name}', '= #{spec.version}'" unless locked[spec.name]
locked[spec.name] = true
spec.runtime_dependencies.each do |dep|
next if locked[dep.name]
- candidates = Gem.source_index.search dep.name, dep.requirement_list
+ candidates = Gem.source_index.search dep
if candidates.empty? then
- complain "Unable to satisfy '#{dep}' from currently installed gems."
+ complain "Unable to satisfy '#{dep}' from currently installed gems"
else
pending << candidates.last.full_name
end
@@ -94,7 +99,11 @@ lock it down to the exact version.
end
def spec_path(gem_full_name)
- File.join Gem.path, "specifications", "#{gem_full_name }.gemspec"
+ gemspecs = Gem.path.map do |path|
+ File.join path, "specifications", "#{gem_full_name}.gemspec"
+ end
+
+ gemspecs.find { |gemspec| File.exist? gemspec }
end
end
diff --git a/lib/rubygems/commands/outdated_command.rb b/lib/rubygems/commands/outdated_command.rb
index 1cd1087dd1..9e054f988c 100644
--- a/lib/rubygems/commands/outdated_command.rb
+++ b/lib/rubygems/commands/outdated_command.rb
@@ -19,7 +19,7 @@ class Gem::Commands::OutdatedCommand < Gem::Command
locals = Gem::SourceIndex.from_installed_gems
locals.outdated.sort.each do |name|
- local = locals.search(/^#{name}$/).last
+ local = locals.find_name(name).last
dep = Gem::Dependency.new local.name, ">= #{local.version}"
remotes = Gem::SpecFetcher.fetcher.fetch dep
diff --git a/lib/rubygems/commands/pristine_command.rb b/lib/rubygems/commands/pristine_command.rb
index 3e55a1bb30..d47fe54edd 100644
--- a/lib/rubygems/commands/pristine_command.rb
+++ b/lib/rubygems/commands/pristine_command.rb
@@ -57,7 +57,7 @@ revert the gem.
end
else
gem_name = get_one_gem_name
- Gem::SourceIndex.from_installed_gems.search(gem_name,
+ Gem::SourceIndex.from_installed_gems.find_name(gem_name,
options[:version])
end
diff --git a/lib/rubygems/commands/query_command.rb b/lib/rubygems/commands/query_command.rb
index f4d6120bcd..29fe8acb79 100644
--- a/lib/rubygems/commands/query_command.rb
+++ b/lib/rubygems/commands/query_command.rb
@@ -59,7 +59,7 @@ class Gem::Commands::QueryCommand < Gem::Command
if name.source.empty? then
alert_error "You must specify a gem name"
exit_code |= 4
- elsif installed? name.source, options[:version] then
+ elsif installed? name, options[:version] then
say "true"
else
say "false"
@@ -69,12 +69,16 @@ class Gem::Commands::QueryCommand < Gem::Command
raise Gem::SystemExitException, exit_code
end
+ dep = Gem::Dependency.new name, Gem::Requirement.default
+
if local? then
- say
- say "*** LOCAL GEMS ***"
- say
+ if ui.outs.tty? or both? then
+ say
+ say "*** LOCAL GEMS ***"
+ say
+ end
- specs = Gem.source_index.search name
+ specs = Gem.source_index.search dep
spec_tuples = specs.map do |spec|
[[spec.name, spec.version, spec.original_platform, spec], :local]
@@ -84,13 +88,14 @@ class Gem::Commands::QueryCommand < Gem::Command
end
if remote? then
- say
- say "*** REMOTE GEMS ***"
- say
+ if ui.outs.tty? or both? then
+ say
+ say "*** REMOTE GEMS ***"
+ say
+ end
all = options[:all]
- dep = Gem::Dependency.new name, Gem::Requirement.default
begin
fetcher = Gem::SpecFetcher.fetcher
spec_tuples = fetcher.find_matching dep, all, false
diff --git a/lib/rubygems/commands/rdoc_command.rb b/lib/rubygems/commands/rdoc_command.rb
index f2e677c115..82180d485c 100644
--- a/lib/rubygems/commands/rdoc_command.rb
+++ b/lib/rubygems/commands/rdoc_command.rb
@@ -59,11 +59,15 @@ module Gem
if specs.empty?
fail "Failed to find gem #{gem_name} to generate RDoc for #{options[:version]}"
end
+
if options[:include_ri]
specs.each do |spec|
Gem::DocManager.new(spec).generate_ri
end
+
+ Gem::DocManager.update_ri_cache
end
+
if options[:include_rdoc]
specs.each do |spec|
Gem::DocManager.new(spec).generate_rdoc
@@ -73,6 +77,6 @@ module Gem
true
end
end
-
+
end
end
diff --git a/lib/rubygems/commands/specification_command.rb b/lib/rubygems/commands/specification_command.rb
index 689f2560c9..5aaf6d1797 100644
--- a/lib/rubygems/commands/specification_command.rb
+++ b/lib/rubygems/commands/specification_command.rb
@@ -40,6 +40,7 @@ class Gem::Commands::SpecificationCommand < Gem::Command
def execute
specs = []
gem = get_one_gem_name
+ dep = Gem::Dependency.new gem, options[:version]
if local? then
if File.exist? gem then
@@ -47,12 +48,11 @@ class Gem::Commands::SpecificationCommand < Gem::Command
end
if specs.empty? then
- specs.push(*Gem.source_index.search(/\A#{gem}\z/, options[:version]))
+ specs.push(*Gem.source_index.search(dep))
end
end
if remote? then
- dep = Gem::Dependency.new gem, options[:version]
found = Gem::SpecFetcher.fetcher.fetch dep
specs.push(*found.map { |spec,| spec })
diff --git a/lib/rubygems/commands/unpack_command.rb b/lib/rubygems/commands/unpack_command.rb
index d187f8a9ea..ab2494b0da 100644
--- a/lib/rubygems/commands/unpack_command.rb
+++ b/lib/rubygems/commands/unpack_command.rb
@@ -43,7 +43,7 @@ class Gem::Commands::UnpackCommand < Gem::Command
basename = File.basename(path).sub(/\.gem$/, '')
target_dir = File.expand_path File.join(options[:target], basename)
FileUtils.mkdir_p target_dir
- Gem::Installer.new(path).unpack target_dir
+ Gem::Installer.new(path, :unpack => true).unpack target_dir
say "Unpacked gem: '#{target_dir}'"
else
alert_error "Gem '#{gemname}' not installed."
@@ -68,7 +68,7 @@ class Gem::Commands::UnpackCommand < Gem::Command
def get_path(gemname, version_req)
return gemname if gemname =~ /\.gem$/i
- specs = Gem::source_index.search(/\A#{gemname}\z/, version_req)
+ specs = Gem::source_index.find_name gemname, version_req
selected = specs.sort_by { |s| s.version }.last
diff --git a/lib/rubygems/commands/update_command.rb b/lib/rubygems/commands/update_command.rb
index 78baa8ba56..28d3a5d382 100644
--- a/lib/rubygems/commands/update_command.rb
+++ b/lib/rubygems/commands/update_command.rb
@@ -45,6 +45,8 @@ class Gem::Commands::UpdateCommand < Gem::Command
end
def execute
+ hig = {}
+
if options[:system] then
say "Updating RubyGems"
@@ -52,16 +54,21 @@ class Gem::Commands::UpdateCommand < Gem::Command
fail "No gem names are allowed with the --system option"
end
- options[:args] = ["rubygems-update"]
+ rubygems_update = Gem::Specification.new
+ rubygems_update.name = 'rubygems-update'
+ rubygems_update.version = Gem::Version.new Gem::RubyGemsVersion
+ hig['rubygems-update'] = rubygems_update
+
+ options[:user_install] = false
else
say "Updating installed gems"
- end
- hig = {} # highest installed gems
+ hig = {} # highest installed gems
- Gem.source_index.each do |name, spec|
- if hig[spec.name].nil? or hig[spec.name].version < spec.version then
- hig[spec.name] = spec
+ Gem.source_index.each do |name, spec|
+ if hig[spec.name].nil? or hig[spec.name].version < spec.version then
+ hig[spec.name] = spec
+ end
end
end
@@ -84,14 +91,14 @@ class Gem::Commands::UpdateCommand < Gem::Command
end
if gems_to_update.include? "rubygems-update" then
- latest_ruby_gem = remote_gemspecs.select do |s|
- s.name == 'rubygems-update'
- end
+ Gem.source_index.refresh!
+
+ update_gems = Gem.source_index.search 'rubygems-update'
- latest_ruby_gem = latest_ruby_gem.sort_by { |s| s.version }.last
+ latest_update_gem = update_gems.sort_by { |s| s.version }.last
- say "Updating version of RubyGems to #{latest_ruby_gem.version}"
- installed = do_rubygems_update latest_ruby_gem.version
+ say "Updating RubyGems to #{latest_update_gem.version}"
+ installed = do_rubygems_update latest_update_gem.version
say "RubyGems system software updated" if installed
else
@@ -103,6 +110,9 @@ class Gem::Commands::UpdateCommand < Gem::Command
end
end
+ ##
+ # Update the RubyGems software to +version+.
+
def do_rubygems_update(version)
args = []
args.push '--prefix', Gem.prefix unless Gem.prefix.nil?
@@ -112,8 +122,6 @@ class Gem::Commands::UpdateCommand < Gem::Command
update_dir = File.join Gem.dir, 'gems', "rubygems-update-#{version}"
- success = false
-
Dir.chdir update_dir do
say "Installing RubyGems #{version}"
setup_cmd = "#{Gem.ruby} setup.rb #{args.join ' '}"
diff --git a/lib/rubygems/commands/which_command.rb b/lib/rubygems/commands/which_command.rb
index b42244ce7d..2267e44b11 100644
--- a/lib/rubygems/commands/which_command.rb
+++ b/lib/rubygems/commands/which_command.rb
@@ -3,10 +3,10 @@ require 'rubygems/gem_path_searcher'
class Gem::Commands::WhichCommand < Gem::Command
- EXT = %w[.rb .rbw .so .dll] # HACK
+ EXT = %w[.rb .rbw .so .dll .bundle] # HACK
def initialize
- super 'which', 'Find the location of a library',
+ super 'which', 'Find the location of a library file you can require',
:search_gems_first => false, :show_all => false
add_option '-a', '--[no-]all', 'show all matching files' do |show_all, options|
@@ -52,7 +52,7 @@ class Gem::Commands::WhichCommand < Gem::Command
paths = find_paths arg, dirs
if paths.empty? then
- say "Can't find #{arg}"
+ say "Can't find ruby library file or shared library #{arg}"
else
say paths
end
@@ -84,3 +84,4 @@ class Gem::Commands::WhichCommand < Gem::Command
end
end
+
diff --git a/lib/rubygems/config_file.rb b/lib/rubygems/config_file.rb
index c093c31a1b..276a5c151d 100644
--- a/lib/rubygems/config_file.rb
+++ b/lib/rubygems/config_file.rb
@@ -49,6 +49,11 @@ class Gem::ConfigFile
# List of arguments supplied to the config file object.
attr_reader :args
+ # Where to look for gems
+ attr_accessor :path
+
+ attr_accessor :home
+
# True if we print backtraces on errors.
attr_writer :backtrace
@@ -123,9 +128,11 @@ class Gem::ConfigFile
@backtrace = @hash[:backtrace] if @hash.key? :backtrace
@benchmark = @hash[:benchmark] if @hash.key? :benchmark
@bulk_threshold = @hash[:bulk_threshold] if @hash.key? :bulk_threshold
- Gem.sources.replace @hash[:sources] if @hash.key? :sources
+ Gem.sources = @hash[:sources] if @hash.key? :sources
@verbose = @hash[:verbose] if @hash.key? :verbose
@update_sources = @hash[:update_sources] if @hash.key? :update_sources
+ @path = @hash[:gempath] if @hash.key? :gempath
+ @home = @hash[:gemhome] if @hash.key? :gemhome
handle_arguments arg_list
end
diff --git a/lib/rubygems/custom_require.rb b/lib/rubygems/custom_require.rb
index 90e6b53959..78c7872b6f 100755
--- a/lib/rubygems/custom_require.rb
+++ b/lib/rubygems/custom_require.rb
@@ -7,11 +7,15 @@
require 'rubygems'
module Kernel
- alias gem_original_require require # :nodoc:
- #
- # We replace Ruby's require with our own, which is capable of
- # loading gems on demand.
+ ##
+ # The Kernel#require from before RubyGems was loaded.
+
+ alias gem_original_require require
+
+ ##
+ # When RubyGems is required, Kernel#require is replaced with our own which
+ # is capable of loading gems on demand.
#
# When you call <tt>require 'x'</tt>, this is what happens:
# * If the file can be loaded from the existing Ruby loadpath, it
@@ -22,8 +26,8 @@ module Kernel
#
# The normal <tt>require</tt> functionality of returning false if
# that file has already been loaded is preserved.
- #
- def require(path) # :nodoc:
+
+ def require(path) # :doc:
gem_original_require path
rescue LoadError => load_error
if load_error.message =~ /#{Regexp.escape path}\z/ and
@@ -34,5 +38,9 @@ module Kernel
raise load_error
end
end
-end # module Kernel
+
+ private :require
+ private :gem_original_require
+
+end
diff --git a/lib/rubygems/defaults.rb b/lib/rubygems/defaults.rb
index 8bb9776575..7884fad83d 100644
--- a/lib/rubygems/defaults.rb
+++ b/lib/rubygems/defaults.rb
@@ -1,36 +1,60 @@
module Gem
- # An Array of the default sources that come with RubyGems.
+ @post_install_hooks ||= []
+ @post_uninstall_hooks ||= []
+ @pre_uninstall_hooks ||= []
+ @pre_install_hooks ||= []
+
+ ##
+ # An Array of the default sources that come with RubyGems
+
def self.default_sources
%w[http://gems.rubyforge.org/]
end
+ ##
# Default home directory path to be used if an alternate value is not
- # specified in the environment.
+ # specified in the environment
+
def self.default_dir
if defined? RUBY_FRAMEWORK_VERSION then
File.join File.dirname(ConfigMap[:sitedir]), 'Gems',
ConfigMap[:ruby_version]
- elsif defined? RUBY_ENGINE then
- File.join ConfigMap[:libdir], RUBY_ENGINE, 'gems',
- ConfigMap[:ruby_version]
+ elsif RUBY_VERSION > '1.9' then
+ File.join(ConfigMap[:libdir], ConfigMap[:ruby_install_name], 'gems',
+ ConfigMap[:ruby_version])
else
- File.join ConfigMap[:libdir], 'ruby', 'gems', ConfigMap[:ruby_version]
+ File.join(ConfigMap[:libdir], ruby_engine, 'gems',
+ ConfigMap[:ruby_version])
end
end
- # Default gem load path.
+ ##
+ # Path for gems in the user's home directory
+
+ def self.user_dir
+ File.join(Gem.user_home, '.gem', ruby_engine,
+ ConfigMap[:ruby_version])
+ end
+
+ ##
+ # Default gem load path
+
def self.default_path
- [File.join(ENV['HOME'], '.gem'), default_dir]
+ [user_dir, default_dir]
end
- # Deduce Ruby's --program-prefix and --program-suffix from its install name.
+ ##
+ # Deduce Ruby's --program-prefix and --program-suffix from its install name
+
def self.default_exec_format
baseruby = ConfigMap[:BASERUBY] || 'ruby'
ConfigMap[:RUBY_INSTALL_NAME].sub(baseruby, '%s') rescue '%s'
end
+ ##
# The default directory for binaries
+
def self.default_bindir
if defined? RUBY_FRAMEWORK_VERSION then # mac framework support
'/usr/bin'
@@ -39,15 +63,30 @@ module Gem
end
end
- # The default system-wide source info cache directory.
+ ##
+ # The default system-wide source info cache directory
+
def self.default_system_source_cache_dir
File.join Gem.dir, 'source_cache'
end
- # The default user-specific source info cache directory.
+ ##
+ # The default user-specific source info cache directory
+
def self.default_user_source_cache_dir
File.join Gem.user_home, '.gem', 'source_cache'
end
+ ##
+ # A wrapper around RUBY_ENGINE const that may not be defined
+
+ def self.ruby_engine
+ if defined? RUBY_ENGINE then
+ RUBY_ENGINE
+ else
+ 'ruby'
+ end
+ end
+
end
diff --git a/lib/rubygems/dependency_installer.rb b/lib/rubygems/dependency_installer.rb
index 8406844e79..9ae2659536 100644
--- a/lib/rubygems/dependency_installer.rb
+++ b/lib/rubygems/dependency_installer.rb
@@ -38,9 +38,17 @@ class Gem::DependencyInstaller
# :ignore_dependencies:: Don't install any dependencies.
# :install_dir:: See Gem::Installer#install.
# :security_policy:: See Gem::Installer::new and Gem::Security.
+ # :user_install:: See Gem::Installer.new
# :wrappers:: See Gem::Installer::new
def initialize(options = {})
+ if options[:install_dir] then
+ spec_dir = options[:install_dir], 'specifications'
+ @source_index = Gem::SourceIndex.from_gems_in spec_dir
+ else
+ @source_index = Gem.source_index
+ end
+
options = DEFAULT_OPTIONS.merge options
@bin_dir = options[:bin_dir]
@@ -51,19 +59,13 @@ class Gem::DependencyInstaller
@format_executable = options[:format_executable]
@ignore_dependencies = options[:ignore_dependencies]
@security_policy = options[:security_policy]
+ @user_install = options[:user_install]
@wrappers = options[:wrappers]
@installed_gems = []
@install_dir = options[:install_dir] || Gem.dir
@cache_dir = options[:cache_dir] || @install_dir
-
- if options[:install_dir] then
- spec_dir = File.join @install_dir, 'specifications'
- @source_index = Gem::SourceIndex.from_gems_in spec_dir
- else
- @source_index = Gem.source_index
- end
end
##
@@ -232,15 +234,17 @@ class Gem::DependencyInstaller
end
inst = Gem::Installer.new local_gem_path,
- :env_shebang => @env_shebang,
- :force => @force,
- :format_executable => @format_executable,
+ :bin_dir => @bin_dir,
+ :development => @development,
+ :env_shebang => @env_shebang,
+ :force => @force,
+ :format_executable => @format_executable,
:ignore_dependencies => @ignore_dependencies,
- :install_dir => @install_dir,
- :security_policy => @security_policy,
- :wrappers => @wrappers,
- :bin_dir => @bin_dir,
- :development => @development
+ :install_dir => @install_dir,
+ :security_policy => @security_policy,
+ :source_index => @source_index,
+ :user_install => @user_install,
+ :wrappers => @wrappers
spec = inst.install
diff --git a/lib/rubygems/doc_manager.rb b/lib/rubygems/doc_manager.rb
index 88d7964d85..00ef4c51e3 100644
--- a/lib/rubygems/doc_manager.rb
+++ b/lib/rubygems/doc_manager.rb
@@ -5,132 +5,194 @@
#++
require 'fileutils'
+require 'rubygems'
-module Gem
+##
+# The documentation manager generates RDoc and RI for RubyGems.
- class DocManager
+class Gem::DocManager
- include UserInteraction
+ include Gem::UserInteraction
- # Create a document manager for the given gem spec.
- #
- # spec:: The Gem::Specification object representing the gem.
- # rdoc_args:: Optional arguments for RDoc (template etc.) as a String.
- #
- def initialize(spec, rdoc_args="")
- @spec = spec
- @doc_dir = File.join(spec.installation_path, "doc", spec.full_name)
- @rdoc_args = rdoc_args.nil? ? [] : rdoc_args.split
+ @configured_args = []
+
+ def self.configured_args
+ @configured_args ||= []
+ end
+
+ def self.configured_args=(args)
+ case args
+ when Array
+ @configured_args = args
+ when String
+ @configured_args = args.split
end
+ end
+
+ ##
+ # Load RDoc from a gem if it is available, otherwise from Ruby's stdlib
- # Is the RDoc documentation installed?
- def rdoc_installed?
- return File.exist?(File.join(@doc_dir, "rdoc"))
+ def self.load_rdoc
+ begin
+ gem 'rdoc'
+ rescue Gem::LoadError
+ # use built-in RDoc
end
- # Generate the RI documents for this gem spec.
- #
- # Note that if both RI and RDoc documents are generated from the
- # same process, the RI docs should be done first (a likely bug in
- # RDoc will cause RI docs generation to fail if run after RDoc).
- def generate_ri
- if @spec.has_rdoc then
- load_rdoc
- install_ri # RDoc bug, ri goes first
- end
+ begin
+ require 'rdoc/rdoc'
+ rescue LoadError => e
+ raise Gem::DocumentError,
+ "ERROR: RDoc documentation generator not installed!"
+ end
+ end
+
+ ##
+ # Updates the RI cache for RDoc 2 if it is installed
+
+ def self.update_ri_cache
+ load_rdoc rescue return
+
+ return unless defined? RDoc::VERSION # RDoc 1 does not have VERSION
- FileUtils.mkdir_p @doc_dir unless File.exist?(@doc_dir)
+ require 'rdoc/ri/driver'
+
+ options = {
+ :use_cache => true,
+ :use_system => true,
+ :use_site => true,
+ :use_home => true,
+ :use_gems => true,
+ :formatter => RDoc::RI::Formatter,
+ }
+
+ driver = RDoc::RI::Driver.new(options).class_cache
+ end
+
+ ##
+ # Create a document manager for +spec+. +rdoc_args+ contains arguments for
+ # RDoc (template etc.) as a String.
+
+ def initialize(spec, rdoc_args="")
+ @spec = spec
+ @doc_dir = File.join(spec.installation_path, "doc", spec.full_name)
+ @rdoc_args = rdoc_args.nil? ? [] : rdoc_args.split
+ end
+
+ ##
+ # Is the RDoc documentation installed?
+
+ def rdoc_installed?
+ File.exist?(File.join(@doc_dir, "rdoc"))
+ end
+
+ ##
+ # Generate the RI documents for this gem spec.
+ #
+ # Note that if both RI and RDoc documents are generated from the same
+ # process, the RI docs should be done first (a likely bug in RDoc will cause
+ # RI docs generation to fail if run after RDoc).
+
+ def generate_ri
+ if @spec.has_rdoc then
+ setup_rdoc
+ install_ri # RDoc bug, ri goes first
end
- # Generate the RDoc documents for this gem spec.
- #
- # Note that if both RI and RDoc documents are generated from the
- # same process, the RI docs should be done first (a likely bug in
- # RDoc will cause RI docs generation to fail if run after RDoc).
- def generate_rdoc
- if @spec.has_rdoc then
- load_rdoc
- install_rdoc
- end
+ FileUtils.mkdir_p @doc_dir unless File.exist?(@doc_dir)
+ end
- FileUtils.mkdir_p @doc_dir unless File.exist?(@doc_dir)
+ ##
+ # Generate the RDoc documents for this gem spec.
+ #
+ # Note that if both RI and RDoc documents are generated from the same
+ # process, the RI docs should be done first (a likely bug in RDoc will cause
+ # RI docs generation to fail if run after RDoc).
+
+ def generate_rdoc
+ if @spec.has_rdoc then
+ setup_rdoc
+ install_rdoc
end
- # Load the RDoc documentation generator library.
- def load_rdoc
- if File.exist?(@doc_dir) && !File.writable?(@doc_dir) then
- raise Gem::FilePermissionError.new(@doc_dir)
- end
+ FileUtils.mkdir_p @doc_dir unless File.exist?(@doc_dir)
+ end
- FileUtils.mkdir_p @doc_dir unless File.exist?(@doc_dir)
+ ##
+ # Generate and install RDoc into the documentation directory
- begin
- gem 'rdoc'
- rescue Gem::LoadError
- # use built-in RDoc
- end
+ def install_rdoc
+ rdoc_dir = File.join @doc_dir, 'rdoc'
- begin
- require 'rdoc/rdoc'
- rescue LoadError => e
- raise Gem::DocumentError,
- "ERROR: RDoc documentation generator not installed!"
- end
- end
+ FileUtils.rm_rf rdoc_dir
- def install_rdoc
- rdoc_dir = File.join @doc_dir, 'rdoc'
+ say "Installing RDoc documentation for #{@spec.full_name}..."
+ run_rdoc '--op', rdoc_dir
+ end
- FileUtils.rm_rf rdoc_dir
+ ##
+ # Generate and install RI into the documentation directory
- say "Installing RDoc documentation for #{@spec.full_name}..."
- run_rdoc '--op', rdoc_dir
- end
+ def install_ri
+ ri_dir = File.join @doc_dir, 'ri'
- def install_ri
- ri_dir = File.join @doc_dir, 'ri'
+ FileUtils.rm_rf ri_dir
- FileUtils.rm_rf ri_dir
+ say "Installing ri documentation for #{@spec.full_name}..."
+ run_rdoc '--ri', '--op', ri_dir
+ end
- say "Installing ri documentation for #{@spec.full_name}..."
- run_rdoc '--ri', '--op', ri_dir
+ ##
+ # Run RDoc with +args+, which is an ARGV style argument list
+
+ def run_rdoc(*args)
+ args << @spec.rdoc_options
+ args << self.class.configured_args
+ args << '--quiet'
+ args << @spec.require_paths.clone
+ args << @spec.extra_rdoc_files
+ args = args.flatten.map do |arg| arg.to_s end
+
+ r = RDoc::RDoc.new
+
+ old_pwd = Dir.pwd
+ Dir.chdir(@spec.full_gem_path)
+ begin
+ r.document args
+ rescue Errno::EACCES => e
+ dirname = File.dirname e.message.split("-")[1].strip
+ raise Gem::FilePermissionError.new(dirname)
+ rescue RuntimeError => ex
+ alert_error "While generating documentation for #{@spec.full_name}"
+ ui.errs.puts "... MESSAGE: #{ex}"
+ ui.errs.puts "... RDOC args: #{args.join(' ')}"
+ ui.errs.puts "\t#{ex.backtrace.join "\n\t"}" if
+ Gem.configuration.backtrace
+ ui.errs.puts "(continuing with the rest of the installation)"
+ ensure
+ Dir.chdir(old_pwd)
end
+ end
- def run_rdoc(*args)
- args << @spec.rdoc_options
- args << DocManager.configured_args
- args << '--quiet'
- args << @spec.require_paths.clone
- args << @spec.extra_rdoc_files
- args = args.flatten.map do |arg| arg.to_s end
-
- r = RDoc::RDoc.new
-
- old_pwd = Dir.pwd
- Dir.chdir(@spec.full_gem_path)
- begin
- r.document args
- rescue Errno::EACCES => e
- dirname = File.dirname e.message.split("-")[1].strip
- raise Gem::FilePermissionError.new(dirname)
- rescue RuntimeError => ex
- alert_error "While generating documentation for #{@spec.full_name}"
- ui.errs.puts "... MESSAGE: #{ex}"
- ui.errs.puts "... RDOC args: #{args.join(' ')}"
- ui.errs.puts "\t#{ex.backtrace.join "\n\t"}" if
- Gem.configuration.backtrace
- ui.errs.puts "(continuing with the rest of the installation)"
- ensure
- Dir.chdir(old_pwd)
- end
+ def setup_rdoc
+ if File.exist?(@doc_dir) && !File.writable?(@doc_dir) then
+ raise Gem::FilePermissionError.new(@doc_dir)
end
- def uninstall_doc
- raise Gem::FilePermissionError.new(@spec.installation_path) unless
- File.writable? @spec.installation_path
+ FileUtils.mkdir_p @doc_dir unless File.exist?(@doc_dir)
- original_name = [
- @spec.name, @spec.version, @spec.original_platform].join '-'
+ self.class.load_rdoc
+ end
+
+ ##
+ # Remove RDoc and RI documentation
+
+ def uninstall_doc
+ raise Gem::FilePermissionError.new(@spec.installation_path) unless
+ File.writable? @spec.installation_path
+
+ original_name = [
+ @spec.name, @spec.version, @spec.original_platform].join '-'
doc_dir = File.join @spec.installation_path, 'doc', @spec.full_name
unless File.directory? doc_dir then
@@ -146,22 +208,7 @@ module Gem
end
FileUtils.rm_rf ri_dir
- end
-
- class << self
- def configured_args
- @configured_args ||= []
- end
-
- def configured_args=(args)
- case args
- when Array
- @configured_args = args
- when String
- @configured_args = args.split
- end
- end
- end
-
end
+
end
+
diff --git a/lib/rubygems/gem_path_searcher.rb b/lib/rubygems/gem_path_searcher.rb
index dadad66289..e2b8543bb0 100644
--- a/lib/rubygems/gem_path_searcher.rb
+++ b/lib/rubygems/gem_path_searcher.rb
@@ -6,15 +6,15 @@
require 'rubygems'
-#
+##
# GemPathSearcher has the capability to find loadable files inside
# gems. It generates data up front to speed up searches later.
-#
+
class Gem::GemPathSearcher
- #
+ ##
# Initialise the data we need to make searches later.
- #
+
def initialize
# We want a record of all the installed gemspecs, in the order
# we wish to examine them.
@@ -27,7 +27,7 @@ class Gem::GemPathSearcher
end
end
- #
+ ##
# Look in all the installed gems until a matching _path_ is found.
# Return the _gemspec_ of the gem where it was found. If no match
# is found, return nil.
@@ -46,36 +46,52 @@ class Gem::GemPathSearcher
# others), which may or may not already be attached to _file_.
# This method doesn't care about the full filename that matches;
# only that there is a match.
- #
+
def find(path)
- @gemspecs.each do |spec|
- return spec if matching_file(spec, path)
+ @gemspecs.find do |spec| matching_file? spec, path end
+ end
+
+ ##
+ # Works like #find, but finds all gemspecs matching +path+.
+
+ def find_all(path)
+ @gemspecs.select do |spec|
+ matching_file? spec, path
end
- nil
end
- private
+ ##
+ # Attempts to find a matching path using the require_paths of the given
+ # +spec+.
- # Attempts to find a matching path using the require_paths of the
- # given _spec_.
- #
- # Some of the intermediate results are cached in @lib_dirs for
- # speed.
- def matching_file(spec, path) # :doc:
+ def matching_file?(spec, path)
+ !matching_files(spec, path).empty?
+ end
+
+ ##
+ # Returns files matching +path+ in +spec+.
+ #--
+ # Some of the intermediate results are cached in @lib_dirs for speed.
+
+ def matching_files(spec, path)
glob = File.join @lib_dirs[spec.object_id], "#{path}#{Gem.suffix_pattern}"
- return true unless Dir[glob].select { |f| File.file?(f.untaint) }.empty?
+ Dir[glob].select { |f| File.file? f.untaint }
end
- # Return a list of all installed gemspecs, sorted by alphabetical
- # order and in reverse version order.
+ ##
+ # Return a list of all installed gemspecs, sorted by alphabetical order and
+ # in reverse version order.
+
def init_gemspecs
Gem.source_index.map { |_, spec| spec }.sort { |a,b|
(a.name <=> b.name).nonzero? || (b.version <=> a.version)
}
end
+ ##
# Returns library directories glob for a gemspec. For example,
# '/usr/local/lib/ruby/gems/1.8/gems/foobar-1.0/{lib,ext}'
+
def lib_dirs_for(spec)
"#{spec.full_gem_path}/{#{spec.require_paths.join(',')}}"
end
diff --git a/lib/rubygems/installer.rb b/lib/rubygems/installer.rb
index 5e2e8e0f42..d719580a0a 100644
--- a/lib/rubygems/installer.rb
+++ b/lib/rubygems/installer.rb
@@ -20,6 +20,7 @@ require 'rubygems/require_paths_builder'
# filesystem including unpacking the gem into its gem dir, installing the
# gemspec in the specifications dir, storing the cached gem in the cache dir,
# and installing either wrappers or symlinks for executables.
+
class Gem::Installer
##
@@ -31,8 +32,36 @@ class Gem::Installer
include Gem::RequirePathsBuilder
+ ##
+ # The directory a gem's executables will be installed into
+
+ attr_reader :bin_dir
+
+ ##
+ # The gem repository the gem will be installed into
+
+ attr_reader :gem_home
+
+ ##
+ # The Gem::Specification for the gem being installed
+
+ attr_reader :spec
+
+ @home_install_warning = false
+ @path_warning = false
+
class << self
+ ##
+ # True if we've warned about ~/.gems install
+
+ attr_accessor :home_install_warning
+
+ ##
+ # True if we've warned about PATH not including Gem.bindir
+
+ attr_accessor :path_warning
+
attr_writer :exec_format
# Defaults to use Ruby's program prefix and suffix.
@@ -61,11 +90,12 @@ class Gem::Installer
@gem = gem
options = {
- :force => false,
- :install_dir => Gem.dir,
- :exec_format => false,
- :env_shebang => false,
- :bin_dir => nil
+ :bin_dir => nil,
+ :env_shebang => false,
+ :exec_format => false,
+ :force => false,
+ :install_dir => Gem.dir,
+ :source_index => Gem.source_index,
}.merge options
@env_shebang = options[:env_shebang]
@@ -78,6 +108,7 @@ class Gem::Installer
@wrappers = options[:wrappers]
@bin_dir = options[:bin_dir]
@development = options[:development]
+ @source_index = options[:source_index]
begin
@format = Gem::Format.from_file_by_path @gem, @security_policy
@@ -85,30 +116,41 @@ class Gem::Installer
raise Gem::InstallError, "invalid gem format for #{@gem}"
end
+ begin
+ FileUtils.mkdir_p @gem_home
+ rescue Errno::EACCESS, Errno::ENOTDIR
+ # We'll divert to ~/.gems below
+ end
+
if not File.writable? @gem_home or
# TODO: Shouldn't have to test for existence of bindir; tests need it.
- (@gem_home.to_s == Gem.dir and File.exist? Gem.bindir and
- not File.writable? Gem.bindir)
- if options[:user_install] == false # You explicitly don't want to use ~
+ (@gem_home.to_s == Gem.dir and File.exist? Gem.bindir and
+ not File.writable? Gem.bindir) then
+ if options[:user_install] == false then # You don't want to use ~
raise Gem::FilePermissionError, @gem_home
- elsif options[:user_install].nil?
- say "Warning: falling back to user-level install since #{@gem_home} and #{@bin_dir} aren't both writable."
+ elsif options[:user_install].nil? then
+ unless self.class.home_install_warning then
+ alert_warning "Installing to ~/.gem since #{@gem_home} and\n\t #{Gem.bindir} aren't both writable."
+ self.class.home_install_warning = true
+ end
end
options[:user_install] = true
end
- if options[:user_install]
- @gem_home = File.join(ENV['HOME'], '.gem')
+ if options[:user_install] and not options[:unpack] then
+ @gem_home = Gem.user_dir
- user_bin_dir = File.join(@gem_home, 'gems', 'bin')
- if !ENV['PATH'].split(':').include?(user_bin_dir)
- say "You don't have #{user_bin_dir} in your PATH."
- say "You won't be able to run gem-installed executables until you add it."
+ user_bin_dir = File.join(@gem_home, 'bin')
+ unless ENV['PATH'].split(File::PATH_SEPARATOR).include? user_bin_dir then
+ unless self.class.path_warning then
+ alert_warning "You don't have #{user_bin_dir} in your PATH,\n\t gem executables will not run."
+ self.class.path_warning = true
+ end
end
-
- Dir.mkdir @gem_home if ! File.directory? @gem_home
+
+ FileUtils.mkdir_p @gem_home unless File.directory? @gem_home
# If it's still not writable, you've got issues.
- raise Gem::FilePermissionError, @gem_home if ! File.writable? @gem_home
+ raise Gem::FilePermissionError, @gem_home unless File.writable? @gem_home
end
@spec = @format.spec
@@ -157,6 +199,10 @@ class Gem::Installer
end
end
+ Gem.pre_install_hooks.each do |hook|
+ hook.call self
+ end
+
FileUtils.mkdir_p @gem_home unless File.directory? @gem_home
Gem.ensure_gem_subdirectories @gem_home
@@ -181,7 +227,11 @@ class Gem::Installer
@spec.loaded_from = File.join(@gem_home, 'specifications',
"#{@spec.full_name}.gemspec")
- Gem.source_index.add_spec @spec
+ @source_index.add_spec @spec
+
+ Gem.post_install_hooks.each do |hook|
+ hook.call self
+ end
return @spec
rescue Zlib::GzipFile::Error
@@ -204,10 +254,10 @@ class Gem::Installer
end
##
- # True if the gems in Gem.source_index satisfy +dependency+.
+ # True if the gems in the source_index satisfy +dependency+.
def installation_satisfies_dependency?(dependency)
- Gem.source_index.find_name(dependency.name, dependency.version_requirements).size > 0
+ @source_index.find_name(dependency.name, dependency.version_requirements).size > 0
end
##
diff --git a/lib/rubygems/local_remote_options.rb b/lib/rubygems/local_remote_options.rb
index 799b9d5893..d77d600ec6 100644
--- a/lib/rubygems/local_remote_options.rb
+++ b/lib/rubygems/local_remote_options.rb
@@ -110,6 +110,13 @@ module Gem::LocalRemoteOptions
end
##
+ # Is fetching of local and remote information enabled?
+
+ def both?
+ options[:domain] == :both
+ end
+
+ ##
# Is local fetching enabled?
def local?
diff --git a/lib/rubygems/package/tar_reader.rb b/lib/rubygems/package/tar_reader.rb
index 8359399207..4aa9c26cc9 100644
--- a/lib/rubygems/package/tar_reader.rb
+++ b/lib/rubygems/package/tar_reader.rb
@@ -46,17 +46,17 @@ class Gem::Package::TarReader
yield entry
skip = (512 - (size % 512)) % 512
+ pending = size - entry.bytes_read
- if @io.respond_to? :seek then
+ begin
# avoid reading...
- @io.seek(size - entry.bytes_read, IO::SEEK_CUR)
- else
- pending = size - entry.bytes_read
-
+ @io.seek pending, IO::SEEK_CUR
+ pending = 0
+ rescue Errno::EINVAL, NameError
while pending > 0 do
- bread = @io.read([pending, 4096].min).size
+ bytes_read = @io.read([pending, 4096].min).size
raise UnexpectedEOF if @io.eof?
- pending -= bread
+ pending -= bytes_read
end
end
diff --git a/lib/rubygems/platform.rb b/lib/rubygems/platform.rb
index 5e932cd592..3e5b5cde66 100644
--- a/lib/rubygems/platform.rb
+++ b/lib/rubygems/platform.rb
@@ -13,23 +13,6 @@ class Gem::Platform
attr_accessor :version
- DEPRECATED_CONSTS = [
- :DARWIN,
- :LINUX_586,
- :MSWIN32,
- :PPC_DARWIN,
- :WIN32,
- :X86_LINUX
- ]
-
- def self.const_missing(name) # TODO remove six months from 2007/12
- if DEPRECATED_CONSTS.include? name then
- raise NameError, "#{name} has been removed, use CURRENT instead"
- else
- super
- end
- end
-
def self.local
arch = Gem::ConfigMap[:arch]
arch = "#{arch}_60" if arch =~ /mswin32$/
@@ -73,7 +56,7 @@ class Gem::Platform
else cpu
end
- if arch.length == 2 and arch.last =~ /^\d+$/ then # for command-line
+ if arch.length == 2 and arch.last =~ /^\d+(\.\d+)?$/ then # for command-line
@os, @version = arch
return
end
diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb
index 3c747f1d65..1570740163 100644
--- a/lib/rubygems/remote_fetcher.rb
+++ b/lib/rubygems/remote_fetcher.rb
@@ -78,7 +78,7 @@ class Gem::RemoteFetcher
if File.writable?(install_dir)
cache_dir = File.join install_dir, 'cache'
else
- cache_dir = File.join(ENV['HOME'], '.gem', 'cache')
+ cache_dir = File.join(Gem.user_dir, 'cache')
end
gem_file_name = "#{spec.full_name}.gem"
@@ -93,7 +93,7 @@ class Gem::RemoteFetcher
scheme = nil if scheme =~ /^[a-z]$/i
case scheme
- when 'http' then
+ when 'http', 'https' then
unless File.exist? local_gem_path then
begin
say "Downloading gem #{gem_file_name}" if
@@ -139,8 +139,8 @@ class Gem::RemoteFetcher
# Downloads +uri+ and returns it as a String.
def fetch_path(uri, mtime = nil, head = false)
- data = open_uri_or_path(uri, mtime, head)
- data = Gem.gunzip data if uri.to_s =~ /gz$/ and not head
+ data = open_uri_or_path uri, mtime, head
+ data = Gem.gunzip data if data and not head and uri.to_s =~ /gz$/
data
rescue FetchError
raise
@@ -216,8 +216,9 @@ class Gem::RemoteFetcher
connection = @connections[connection_id]
if uri.scheme == 'https' and not connection.started? then
- http_obj.use_ssl = true
- http_obj.verify_mode = OpenSSL::SSL::VERIFY_NONE
+ require 'net/https'
+ connection.use_ssl = true
+ connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
connection.start unless connection.started?
@@ -241,9 +242,10 @@ class Gem::RemoteFetcher
response = request uri, fetch_type, last_modified
case response
- when Net::HTTPOK then
+ when Net::HTTPOK, Net::HTTPNotModified then
head ? response : response.body
- when Net::HTTPRedirection then
+ when Net::HTTPMovedPermanently, Net::HTTPFound, Net::HTTPSeeOther,
+ Net::HTTPTemporaryRedirect then
raise FetchError.new('too many redirects', uri) if depth > 10
open_uri_or_path(response['Location'], last_modified, head, depth + 1)
@@ -274,6 +276,7 @@ class Gem::RemoteFetcher
request.add_field 'Keep-Alive', '30'
if last_modified then
+ last_modified = last_modified.utc
request.add_field 'If-Modified-Since', last_modified.rfc2822
end
@@ -282,9 +285,6 @@ class Gem::RemoteFetcher
retried = false
bad_response = false
- # HACK work around EOFError bug in Net::HTTP
- # NOTE Errno::ECONNABORTED raised a lot on Windows, and make impossible
- # to install gems.
begin
@requests[connection.object_id] += 1
response = connection.request request
@@ -297,6 +297,9 @@ class Gem::RemoteFetcher
bad_response = true
retry
+ # HACK work around EOFError bug in Net::HTTP
+ # NOTE Errno::ECONNABORTED raised a lot on Windows, and make impossible
+ # to install gems.
rescue EOFError, Errno::ECONNABORTED, Errno::ECONNRESET
requests = @requests[connection.object_id]
say "connection reset after #{requests} requests, retrying" if
diff --git a/lib/rubygems/rubygems_version.rb b/lib/rubygems/rubygems_version.rb
index d393e57a09..d7b5622d97 100644
--- a/lib/rubygems/rubygems_version.rb
+++ b/lib/rubygems/rubygems_version.rb
@@ -2,5 +2,5 @@
# This file is auto-generated by build scripts.
# See: rake update_version
module Gem
- RubyGemsVersion = '1.2.0.1824'
+ RubyGemsVersion = '1.3.1'
end
diff --git a/lib/rubygems/source_index.rb b/lib/rubygems/source_index.rb
index 1eefd8c149..8a8db2ef0d 100644
--- a/lib/rubygems/source_index.rb
+++ b/lib/rubygems/source_index.rb
@@ -7,7 +7,9 @@
require 'rubygems'
require 'rubygems/user_interaction'
require 'rubygems/specification'
-require 'rubygems/spec_fetcher'
+module Gem
+ autoload(:SpecFetcher, 'rubygems/spec_fetcher')
+end
##
# The SourceIndex object indexes all the gems available from a
@@ -80,8 +82,14 @@ class Gem::SourceIndex
def load_specification(file_name)
begin
- spec_code = File.read(file_name).untaint
+ spec_code = if RUBY_VERSION < '1.9' then
+ File.read file_name
+ else
+ File.read file_name, :encoding => 'UTF-8'
+ end.untaint
+
gemspec = eval spec_code, binding, file_name
+
if gemspec.is_a?(Gem::Specification)
gemspec.loaded_from = file_name
return gemspec
@@ -93,7 +101,7 @@ class Gem::SourceIndex
alert_warning e
alert_warning spec_code
rescue Exception => e
- alert_warning(e.inspect.to_s + "\n" + spec_code)
+ alert_warning "#{e.inspect}\n#{spec_code}"
alert_warning "Invalid .gemspec format in '#{file_name}'"
end
return nil
@@ -230,7 +238,8 @@ class Gem::SourceIndex
# Find a gem by an exact match on the short name.
def find_name(gem_name, version_requirement = Gem::Requirement.default)
- search(/^#{gem_name}$/, version_requirement)
+ dep = Gem::Dependency.new(/^#{gem_name}$/, version_requirement)
+ search dep
end
##
@@ -246,7 +255,12 @@ class Gem::SourceIndex
version_requirement = nil
only_platform = false
- case gem_pattern # TODO warn after 2008/03, remove three months after
+ # TODO - Remove support and warning for legacy arguments after 2008/11
+ unless Gem::Dependency === gem_pattern
+ warn "#{Gem.location_of_caller.join ':'}:Warning: Gem::SourceIndex#search support for #{gem_pattern.class} patterns is deprecated"
+ end
+
+ case gem_pattern
when Regexp then
version_requirement = platform_only || Gem::Requirement.default
when Gem::Dependency then
@@ -270,7 +284,7 @@ class Gem::SourceIndex
specs = @gems.values.select do |spec|
spec.name =~ gem_pattern and
- version_requirement.satisfied_by? spec.version
+ version_requirement.satisfied_by? spec.version
end
if only_platform then
@@ -539,7 +553,7 @@ module Gem
# objects to load properly.
Cache = SourceIndex
- # :starddoc:
+ # :startdoc:
end
diff --git a/lib/rubygems/source_info_cache.rb b/lib/rubygems/source_info_cache.rb
index ec6928c00d..fdb30ad8d3 100644
--- a/lib/rubygems/source_info_cache.rb
+++ b/lib/rubygems/source_info_cache.rb
@@ -284,6 +284,10 @@ class Gem::SourceInfoCache
cache_data.map do |source_uri, sic_entry|
next unless Gem.sources.include? source_uri
+ # TODO - Remove this gunk after 2008/11
+ unless pattern.kind_of?(Gem::Dependency)
+ pattern = Gem::Dependency.new(pattern, Gem::Requirement.default)
+ end
sic_entry.source_index.search pattern, platform_only
end.flatten.compact
end
@@ -300,6 +304,11 @@ class Gem::SourceInfoCache
cache_data.map do |source_uri, sic_entry|
next unless Gem.sources.include? source_uri
+ # TODO - Remove this gunk after 2008/11
+ unless pattern.kind_of?(Gem::Dependency)
+ pattern = Gem::Dependency.new(pattern, Gem::Requirement.default)
+ end
+
sic_entry.source_index.search(pattern, only_platform).each do |spec|
results << [spec, source_uri]
end
diff --git a/lib/rubygems/spec_fetcher.rb b/lib/rubygems/spec_fetcher.rb
index 66b4ee36c7..a1fc82ed4f 100644
--- a/lib/rubygems/spec_fetcher.rb
+++ b/lib/rubygems/spec_fetcher.rb
@@ -167,7 +167,7 @@ class Gem::SpecFetcher
if all and @specs.include? source_uri then
list[source_uri] = @specs[source_uri]
- elsif @latest_specs.include? source_uri then
+ elsif not all and @latest_specs.include? source_uri then
list[source_uri] = @latest_specs[source_uri]
else
specs = load_specs source_uri, file
@@ -182,6 +182,10 @@ class Gem::SpecFetcher
list
end
+ ##
+ # Loads specs in +file+, fetching from +source_uri+ if the on-disk cache is
+ # out of date.
+
def load_specs(source_uri, file)
file_name = "#{file}.#{Gem.marshal_version}"
spec_path = source_uri + "#{file_name}.gz"
@@ -192,7 +196,7 @@ class Gem::SpecFetcher
if File.exist? local_file then
spec_dump = @fetcher.fetch_path spec_path, File.mtime(local_file)
- if spec_dump.empty? then
+ if spec_dump.nil? then
spec_dump = Gem.read_binary local_file
else
loaded = true
diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb
index f3f38e5033..2e6cdc1b04 100644
--- a/lib/rubygems/specification.rb
+++ b/lib/rubygems/specification.rb
@@ -24,6 +24,7 @@ class Date; end # for ruby_code if date.rb wasn't required
module Gem
+ ##
# == Gem::Specification
#
# The Specification class contains the metadata for a Gem. Typically
@@ -38,7 +39,7 @@ module Gem
#
# There are many <em>gemspec attributes</em>, and the best place to learn
# about them in the "Gemspec Reference" linked from the RubyGems wiki.
- #
+
class Specification
##
@@ -46,8 +47,6 @@ module Gem
attr_accessor :original_platform # :nodoc:
- # ------------------------- Specification version constants.
-
##
# The the version number of a specification that does not specify one
# (i.e. RubyGems 0.7 or earlier).
@@ -88,77 +87,98 @@ module Gem
TODAY = now - ((now.to_i + now.gmt_offset) % 86400)
# :startdoc:
- # ------------------------- Class variables.
-
+ ##
# List of Specification instances.
+
@@list = []
+ ##
# Optional block used to gather newly defined instances.
+
@@gather = nil
+ ##
# List of attribute names: [:name, :version, ...]
@@required_attributes = []
- # List of _all_ attributes and default values: [[:name, nil], [:bindir, 'bin'], ...]
+ ##
+ # List of _all_ attributes and default values:
+ #
+ # [[:name, nil],
+ # [:bindir, 'bin'],
+ # ...]
+
@@attributes = []
@@nil_attributes = []
@@non_nil_attributes = [:@original_platform]
+ ##
# List of array attributes
+
@@array_attributes = []
+ ##
# Map of attribute names to default values.
+
@@default_value = {}
- # ------------------------- Convenience class methods.
+ ##
+ # Names of all specification attributes
def self.attribute_names
@@attributes.map { |name, default| name }
end
+ ##
+ # Default values for specification attributes
+
def self.attribute_defaults
@@attributes.dup
end
+ ##
+ # The default value for specification attribute +name+
+
def self.default_value(name)
@@default_value[name]
end
+ ##
+ # Required specification attributes
+
def self.required_attributes
@@required_attributes.dup
end
+ ##
+ # Is +name+ a required attribute?
+
def self.required_attribute?(name)
@@required_attributes.include? name.to_sym
end
+ ##
+ # Specification attributes that are arrays (appendable and so-forth)
+
def self.array_attributes
@@array_attributes.dup
end
- # ------------------------- Infrastructure class methods.
+ ##
+ # A list of Specification instances that have been defined in this Ruby
+ # instance.
- # A list of Specification instances that have been defined in this Ruby instance.
def self.list
@@list
end
- # Used to specify the name and default value of a specification
- # attribute. The side effects are:
- # * the name and default value are added to the @@attributes list
- # and @@default_value map
- # * a standard _writer_ method (<tt>attribute=</tt>) is created
- # * a non-standard _reader method (<tt>attribute</tt>) is created
- #
- # The reader method behaves like this:
- # def attribute
- # @attribute ||= (copy of default value)
- # end
- #
- # This allows lazy initialization of attributes to their default
- # values.
+ ##
+ # Specifies the +name+ and +default+ for a specification attribute, and
+ # creates a reader and writer method like Module#attr_accessor.
#
+ # The reader method returns the default if the value hasn't been set.
+
def self.attribute(name, default=nil)
ivar_name = "@#{name}".intern
if default.nil? then
@@ -172,8 +192,10 @@ module Gem
attr_accessor(name)
end
- # Same as :attribute, but ensures that values assigned to the
- # attribute are array values by applying :to_a to the value.
+ ##
+ # Same as :attribute, but ensures that values assigned to the attribute
+ # are array values by applying :to_a to the value.
+
def self.array_attribute(name)
@@non_nil_attributes << ["@#{name}".intern, []]
@@ -192,51 +214,60 @@ module Gem
module_eval code, __FILE__, __LINE__ - 9
end
+ ##
# Same as attribute above, but also records this attribute as mandatory.
+
def self.required_attribute(*args)
@@required_attributes << args.first
attribute(*args)
end
- # Sometimes we don't want the world to use a setter method for a particular attribute.
+ ##
+ # Sometimes we don't want the world to use a setter method for a
+ # particular attribute.
+ #
# +read_only+ makes it private so we can still use it internally.
+
def self.read_only(*names)
names.each do |name|
private "#{name}="
end
end
- # Shortcut for creating several attributes at once (each with a default value of
- # +nil+).
+ # Shortcut for creating several attributes at once (each with a default
+ # value of +nil+).
+
def self.attributes(*args)
args.each do |arg|
attribute(arg, nil)
end
end
- # Some attributes require special behaviour when they are accessed. This allows for
- # that.
+ ##
+ # Some attributes require special behaviour when they are accessed. This
+ # allows for that.
+
def self.overwrite_accessor(name, &block)
remove_method name
define_method(name, &block)
end
- # Defines a _singular_ version of an existing _plural_ attribute
- # (i.e. one whose value is expected to be an array). This means
- # just creating a helper method that takes a single value and
- # appends it to the array. These are created for convenience, so
- # that in a spec, one can write
+ ##
+ # Defines a _singular_ version of an existing _plural_ attribute (i.e. one
+ # whose value is expected to be an array). This means just creating a
+ # helper method that takes a single value and appends it to the array.
+ # These are created for convenience, so that in a spec, one can write
#
# s.require_path = 'mylib'
#
- # instead of
+ # instead of:
#
# s.require_paths = ['mylib']
#
- # That above convenience is available courtesy of
+ # That above convenience is available courtesy of:
#
# attribute_alias_singular :require_path, :require_paths
- #
+
def self.attribute_alias_singular(singular, plural)
define_method("#{singular}=") { |val|
send("#{plural}=", [val])
@@ -320,189 +351,45 @@ module Gem
spec
end
- # REQUIRED gemspec attributes ------------------------------------
-
- required_attribute :rubygems_version, Gem::RubyGemsVersion
- required_attribute :specification_version, CURRENT_SPECIFICATION_VERSION
- required_attribute :name
- required_attribute :version
- required_attribute :date, TODAY
- required_attribute :summary
- required_attribute :require_paths, ['lib']
-
- # OPTIONAL gemspec attributes ------------------------------------
-
- attributes :email, :homepage, :rubyforge_project, :description
- attributes :autorequire, :default_executable
-
- attribute :bindir, 'bin'
- attribute :has_rdoc, false
- attribute :required_ruby_version, Gem::Requirement.default
- attribute :required_rubygems_version, Gem::Requirement.default
- attribute :platform, Gem::Platform::RUBY
-
- attribute :signing_key, nil
- attribute :cert_chain, []
- attribute :post_install_message, nil
-
- array_attribute :authors
- array_attribute :files
- array_attribute :test_files
- array_attribute :rdoc_options
- array_attribute :extra_rdoc_files
- array_attribute :executables
-
- # Array of extensions to build. See Gem::Installer#build_extensions for
- # valid values.
-
- array_attribute :extensions
- array_attribute :requirements
- array_attribute :dependencies
-
- read_only :dependencies
+ ##
+ # List of depedencies that will automatically be activated at runtime.
def runtime_dependencies
dependencies.select { |d| d.type == :runtime || d.type == nil }
end
+ ##
+ # List of dependencies that are used for development
+
def development_dependencies
dependencies.select { |d| d.type == :development }
end
- # ALIASED gemspec attributes -------------------------------------
-
- attribute_alias_singular :executable, :executables
- attribute_alias_singular :author, :authors
- attribute_alias_singular :require_path, :require_paths
- attribute_alias_singular :test_file, :test_files
-
- # DEPRECATED gemspec attributes ----------------------------------
-
- def test_suite_file
+ def test_suite_file # :nodoc:
warn 'test_suite_file deprecated, use test_files'
test_files.first
end
- def test_suite_file=(val)
+ def test_suite_file=(val) # :nodoc:
warn 'test_suite_file= deprecated, use test_files='
@test_files = [] unless defined? @test_files
@test_files << val
end
+ ##
# true when this gemspec has been loaded from a specifications directory.
# This attribute is not persisted.
- attr_writer :loaded
+ attr_accessor :loaded
+ ##
# Path this gemspec was loaded from. This attribute is not persisted.
- attr_accessor :loaded_from
-
- # Special accessor behaviours (overwriting default) --------------
-
- overwrite_accessor :version= do |version|
- @version = Version.create(version)
- end
-
- overwrite_accessor :platform do
- @new_platform
- end
-
- overwrite_accessor :platform= do |platform|
- if @original_platform.nil? or
- @original_platform == Gem::Platform::RUBY then
- @original_platform = platform
- end
-
- case platform
- when Gem::Platform::CURRENT then
- @new_platform = Gem::Platform.local
- @original_platform = @new_platform.to_s
-
- when Gem::Platform then
- @new_platform = platform
-
- # legacy constants
- when nil, Gem::Platform::RUBY then
- @new_platform = Gem::Platform::RUBY
- when 'mswin32' then # was Gem::Platform::WIN32
- @new_platform = Gem::Platform.new 'x86-mswin32'
- when 'i586-linux' then # was Gem::Platform::LINUX_586
- @new_platform = Gem::Platform.new 'x86-linux'
- when 'powerpc-darwin' then # was Gem::Platform::DARWIN
- @new_platform = Gem::Platform.new 'ppc-darwin'
- else
- @new_platform = Gem::Platform.new platform
- end
-
- @platform = @new_platform.to_s
-
- @new_platform
- end
-
- overwrite_accessor :required_ruby_version= do |value|
- @required_ruby_version = Gem::Requirement.create(value)
- end
-
- overwrite_accessor :required_rubygems_version= do |value|
- @required_rubygems_version = Gem::Requirement.create(value)
- end
-
- overwrite_accessor :date= do |date|
- # We want to end up with a Time object with one-day resolution.
- # This is the cleanest, most-readable, faster-than-using-Date
- # way to do it.
- case date
- when String then
- @date = if /\A(\d{4})-(\d{2})-(\d{2})\Z/ =~ date then
- Time.local($1.to_i, $2.to_i, $3.to_i)
- else
- require 'time'
- Time.parse date
- end
- when Time then
- @date = Time.local(date.year, date.month, date.day)
- when Date then
- @date = Time.local(date.year, date.month, date.day)
- else
- @date = TODAY
- end
- end
- overwrite_accessor :date do
- self.date = nil if @date.nil? # HACK Sets the default value for date
- @date
- end
-
- overwrite_accessor :summary= do |str|
- @summary = if str then
- str.strip.
- gsub(/(\w-)\n[ \t]*(\w)/, '\1\2').
- gsub(/\n[ \t]*/, " ")
- end
- end
-
- overwrite_accessor :description= do |str|
- @description = if str then
- str.strip.
- gsub(/(\w-)\n[ \t]*(\w)/, '\1\2').
- gsub(/\n[ \t]*/, " ")
- end
- end
+ attr_accessor :loaded_from
- overwrite_accessor :default_executable do
- begin
- if defined?(@default_executable) and @default_executable
- result = @default_executable
- elsif @executables and @executables.size == 1
- result = Array(@executables).first
- else
- result = nil
- end
- result
- rescue
- nil
- end
- end
+ ##
+ # Returns an array with bindir attached to each executable in the
+ # executables list
def add_bindir(executables)
return nil if executables.nil?
@@ -516,17 +403,9 @@ module Gem
return nil
end
- overwrite_accessor :files do
- result = []
- result.push(*@files) if defined?(@files)
- result.push(*@test_files) if defined?(@test_files)
- result.push(*(add_bindir(@executables)))
- result.push(*@extra_rdoc_files) if defined?(@extra_rdoc_files)
- result.push(*@extensions) if defined?(@extensions)
- result.uniq.compact
- end
-
+ ##
# Files in the Gem under one of the require_paths
+
def lib_files
@files.select do |file|
require_paths.any? do |path|
@@ -535,34 +414,25 @@ module Gem
end
end
- overwrite_accessor :test_files do
- # Handle the possibility that we have @test_suite_file but not
- # @test_files. This will happen when an old gem is loaded via
- # YAML.
- if defined? @test_suite_file then
- @test_files = [@test_suite_file].flatten
- @test_suite_file = nil
- end
- if defined?(@test_files) and @test_files then
- @test_files
- else
- @test_files = []
- end
+ ##
+ # True if this gem was loaded from disk
+
+ alias :loaded? :loaded
+
+ ##
+ # True if this gem has files in test_files
+
+ def has_unit_tests?
+ not test_files.empty?
end
- # Predicates -----------------------------------------------------
-
- def loaded?; @loaded ? true : false ; end
- def has_rdoc?; has_rdoc ? true : false ; end
- def has_unit_tests?; not test_files.empty?; end
- alias has_test_suite? has_unit_tests? # (deprecated)
-
- # Constructors ---------------------------------------------------
+ alias has_test_suite? has_unit_tests? # :nodoc: deprecated
+ ##
# Specification constructor. Assigns the default values to the
# attributes, adds this spec to the list of loaded specs (see
# Specification.list), and yields itself for further initialization.
- #
+
def initialize
@new_platform = nil
assign_defaults
@@ -575,11 +445,13 @@ module Gem
@@gather.call(self) if @@gather
end
- # Each attribute has a default value (possibly nil). Here, we
- # initialize all attributes to their default value. This is
- # done through the accessor methods, so special behaviours will
- # be honored. Furthermore, we take a _copy_ of the default so
- # each specification instance has its own empty arrays, etc.
+ ##
+ # Each attribute has a default value (possibly nil). Here, we initialize
+ # all attributes to their default value. This is done through the
+ # accessor methods, so special behaviours will be honored. Furthermore,
+ # we take a _copy_ of the default so each specification instance has its
+ # own empty arrays, etc.
+
def assign_defaults
@@nil_attributes.each do |name|
instance_variable_set name, nil
@@ -598,13 +470,14 @@ module Gem
instance_variable_set :@new_platform, Gem::Platform::RUBY
end
- # Special loader for YAML files. When a Specification object is
- # loaded from a YAML file, it bypasses the normal Ruby object
- # initialization routine (#initialize). This method makes up for
- # that and deals with gems of different ages.
+ ##
+ # Special loader for YAML files. When a Specification object is loaded
+ # from a YAML file, it bypasses the normal Ruby object initialization
+ # routine (#initialize). This method makes up for that and deals with
+ # gems of different ages.
#
# 'input' can be anything that YAML.load() accepts: String or IO.
- #
+
def self.from_yaml(input)
input = normalize_yaml_input input
spec = YAML.load input
@@ -627,6 +500,9 @@ module Gem
spec
end
+ ##
+ # Loads ruby format gemspec from +filename+
+
def self.load(filename)
gemspec = nil
fail "NESTED Specification.load calls not allowed!" if @@gather
@@ -638,22 +514,25 @@ module Gem
@@gather = nil
end
- # Make sure the yaml specification is properly formatted with dashes.
+ ##
+ # Make sure the YAML specification is properly formatted with dashes
+
def self.normalize_yaml_input(input)
result = input.respond_to?(:read) ? input.read : input
result = "--- " + result unless result =~ /^--- /
result
end
- # Instance methods -----------------------------------------------
-
- # Sets the rubygems_version to Gem::RubyGemsVersion.
- #
+ ##
+ # Sets the rubygems_version to the current RubyGems version
+
def mark_version
@rubygems_version = RubyGemsVersion
end
- # Ignore unknown attributes if the
+ ##
+ # Ignore unknown attributes while loading
+
def method_missing(sym, *a, &b) # :nodoc:
if @specification_version > CURRENT_SPECIFICATION_VERSION and
sym.to_s =~ /=$/ then
@@ -663,35 +542,39 @@ module Gem
end
end
- # Adds a development dependency to this Gem. For example,
- #
- # spec.add_development_dependency('jabber4r', '> 0.1', '<= 0.5')
+ ##
+ # Adds a development dependency named +gem+ with +requirements+ to this
+ # Gem. For example:
#
- # Development dependencies aren't installed by default, and
- # aren't activated when a gem is required.
+ # spec.add_development_dependency 'jabber4r', '> 0.1', '<= 0.5'
#
- # gem:: [String or Gem::Dependency] The Gem name/dependency.
- # requirements:: [default=">= 0"] The version requirements.
+ # Development dependencies aren't installed by default and aren't
+ # activated when a gem is required.
+
def add_development_dependency(gem, *requirements)
add_dependency_with_type(gem, :development, *requirements)
end
- # Adds a runtime dependency to this Gem. For example,
- #
- # spec.add_runtime_dependency('jabber4r', '> 0.1', '<= 0.5')
+ ##
+ # Adds a runtime dependency named +gem+ with +requirements+ to this Gem.
+ # For example:
#
- # gem:: [String or Gem::Dependency] The Gem name/dependency.
- # requirements:: [default=">= 0"] The version requirements.
+ # spec.add_runtime_dependency 'jabber4r', '> 0.1', '<= 0.5'
+
def add_runtime_dependency(gem, *requirements)
add_dependency_with_type(gem, :runtime, *requirements)
end
+ ##
+ # Adds a runtime dependency
+
alias add_dependency add_runtime_dependency
+ ##
# Returns the full name (name-version) of this Gem. Platform information
- # is included (name-version-platform) if it is specified (and not the
- # default Ruby platform).
- #
+ # is included (name-version-platform) if it is specified and not the
+ # default Ruby platform.
+
def full_name
if platform == Gem::Platform::RUBY or platform.nil? then
"#{@name}-#{@version}"
@@ -700,9 +583,10 @@ module Gem
end
end
+ ##
# Returns the full name (name-version) of this gemspec using the original
- # platform.
- #
+ # platform. For use with legacy gems.
+
def original_name # :nodoc:
if platform == Gem::Platform::RUBY or platform.nil? then
"#{@name}-#{@version}"
@@ -736,18 +620,16 @@ module Gem
File.expand_path path
end
- # Checks if this Specification meets the requirement of the supplied
- # dependency.
- #
- # dependency:: [Gem::Dependency] the dependency to check
- # return:: [Boolean] true if dependency is met, otherwise false
- #
+ ##
+ # Checks if this specification meets the requirement of +dependency+.
+
def satisfies_requirement?(dependency)
return @name == dependency.name &&
dependency.version_requirements.satisfied_by?(@version)
end
- # Comparison methods ---------------------------------------------
+ ##
+ # Returns an object you can use to sort specifications in #sort_by.
def sort_obj
[@name, @version.to_ints, @new_platform == Gem::Platform::RUBY ? -1 : 1]
@@ -757,19 +639,25 @@ module Gem
sort_obj <=> other.sort_obj
end
+ ##
# Tests specs for equality (across all attributes).
+
def ==(other) # :nodoc:
self.class === other && same_attributes?(other)
end
alias eql? == # :nodoc:
+ ##
+ # True if this gem has the same attributes as +other+.
+
def same_attributes?(other)
@@attributes.each do |name, default|
return false unless self.send(name) == other.send(name)
end
true
end
+
private :same_attributes?
def hash # :nodoc:
@@ -779,8 +667,6 @@ module Gem
}
end
- # Export methods (YAML and Ruby code) ----------------------------
-
def to_yaml(opts = {}) # :nodoc:
mark_version
@@ -825,6 +711,8 @@ module Gem
def to_ruby
mark_version
result = []
+ result << "# -*- encoding: utf-8 -*-"
+ result << nil
result << "Gem::Specification.new do |s|"
result << " s.name = #{ruby_code name}"
@@ -861,7 +749,7 @@ module Gem
result << " s.specification_version = #{specification_version}"
result << nil
- result << " if current_version >= 3 then"
+ result << " if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then"
unless dependencies.empty? then
dependencies.each do |dep|
@@ -895,16 +783,15 @@ module Gem
result.join "\n"
end
- # Validation and normalization methods ---------------------------
-
- # Checks that the specification contains all required fields, and
- # does a very basic sanity check.
+ ##
+ # Checks that the specification contains all required fields, and does a
+ # very basic sanity check.
#
- # Raises InvalidSpecificationException if the spec does not pass
- # the checks..
+ # Raises InvalidSpecificationException if the spec does not pass the
+ # checks..
+
def validate
extend Gem::UserInteraction
-
normalize
if rubygems_version != RubyGemsVersion then
@@ -959,13 +846,14 @@ module Gem
true
end
+ ##
# Normalize the list of files so that:
# * All file lists have redundancies removed.
- # * Files referenced in the extra_rdoc_files are included in the
- # package file list.
+ # * Files referenced in the extra_rdoc_files are included in the package
+ # file list.
#
- # Also, the summary and description are converted to a normal
- # format.
+ # Also, the summary and description are converted to a normal format.
+
def normalize
if defined?(@extra_rdoc_files) and @extra_rdoc_files then
@extra_rdoc_files.uniq!
@@ -975,15 +863,12 @@ module Gem
@files.uniq! if @files
end
- # Dependency methods ---------------------------------------------
-
- # Return a list of all gems that have a dependency on this
- # gemspec. The list is structured with entries that conform to:
+ ##
+ # Return a list of all gems that have a dependency on this gemspec. The
+ # list is structured with entries that conform to:
#
# [depending_gem, dependency, [list_of_gems_that_satisfy_dependency]]
- #
- # return:: [Array] [[dependent_gem, dependency, [list_of_satisfiers]]]
- #
+
def dependent_gems
out = []
Gem.source_index.each do |name,gem|
@@ -1004,8 +889,6 @@ module Gem
"#<Gem::Specification name=#{@name} version=#{@version}>"
end
- private
-
def add_dependency_with_type(dependency, type, *requirements)
requirements = if requirements.empty? then
Gem::Requirement.default
@@ -1022,6 +905,8 @@ module Gem
dependencies << dependency
end
+ private :add_dependency_with_type
+
def find_all_satisfiers(dep)
Gem.source_index.each do |name,gem|
if(gem.satisfies_requirement?(dep)) then
@@ -1030,8 +915,12 @@ module Gem
end
end
- # Return a string containing a Ruby code representation of the
- # given object.
+ private :find_all_satisfiers
+
+ ##
+ # Return a string containing a Ruby code representation of the given
+ # object.
+
def ruby_code(obj)
case obj
when String then '%q{' + obj + '}'
@@ -1046,6 +935,326 @@ module Gem
else raise Exception, "ruby_code case not handled: #{obj.class}"
end
end
+
+ private :ruby_code
+
+ # :section: Required gemspec attributes
+
+ ##
+ # The version of RubyGems used to create this gem
+
+ required_attribute :rubygems_version, Gem::RubyGemsVersion
+
+ ##
+ # The Gem::Specification version of this gemspec
+
+ required_attribute :specification_version, CURRENT_SPECIFICATION_VERSION
+
+ ##
+ # This gem's name
+
+ required_attribute :name
+
+ ##
+ # This gem's version
+
+ required_attribute :version
+
+ ##
+ # The date this gem was created
+
+ required_attribute :date, TODAY
+
+ ##
+ # A short summary of this gem's description. Displayed in `gem list -d`.
+
+ required_attribute :summary
+
+ ##
+ # Paths in the gem to add to $LOAD_PATH when this gem is activated
+
+ required_attribute :require_paths, ['lib']
+
+ # :section: Optional gemspec attributes
+
+ ##
+ # A contact email for this gem
+
+ attribute :email
+
+ ##
+ # The URL of this gem's home page
+
+ attribute :homepage
+
+ ##
+ # The rubyforge project this gem lives under. i.e. RubyGems'
+ # rubyforge_project is "rubygems".
+
+ attribute :rubyforge_project
+
+ ##
+ # A long description of this gem
+
+ attribute :description
+
+ ##
+ # Autorequire was used by old RubyGems to automatically require a file.
+ # It no longer is supported.
+
+ attribute :autorequire
+
+ ##
+ # The default executable for this gem.
+
+ attribute :default_executable
+
+ ##
+ # The path in the gem for executable scripts
+
+ attribute :bindir, 'bin'
+
+ ##
+ # True if this gem is RDoc-compliant
+
+ attribute :has_rdoc, false
+
+ ##
+ # True if this gem supports RDoc
+
+ alias :has_rdoc? :has_rdoc
+
+ ##
+ # The ruby of version required by this gem
+
+ attribute :required_ruby_version, Gem::Requirement.default
+
+ ##
+ # The RubyGems version required by this gem
+
+ attribute :required_rubygems_version, Gem::Requirement.default
+
+ ##
+ # The platform this gem runs on. See Gem::Platform for details.
+
+ attribute :platform, Gem::Platform::RUBY
+
+ ##
+ # The key used to sign this gem. See Gem::Security for details.
+
+ attribute :signing_key, nil
+
+ ##
+ # The certificate chain used to sign this gem. See Gem::Security for
+ # details.
+
+ attribute :cert_chain, []
+
+ ##
+ # A message that gets displayed after the gem is installed
+
+ attribute :post_install_message, nil
+
+ ##
+ # The list of authors who wrote this gem
+
+ array_attribute :authors
+
+ ##
+ # Files included in this gem
+
+ array_attribute :files
+
+ ##
+ # Test files included in this gem
+
+ array_attribute :test_files
+
+ ##
+ # An ARGV-style array of options to RDoc
+
+ array_attribute :rdoc_options
+
+ ##
+ # Extra files to add to RDoc
+
+ array_attribute :extra_rdoc_files
+
+ ##
+ # Executables included in the gem
+
+ array_attribute :executables
+
+ ##
+ # Extensions to build when installing the gem. See
+ # Gem::Installer#build_extensions for valid values.
+
+ array_attribute :extensions
+
+ ##
+ # An array or things required by this gem. Not used by anything
+ # presently.
+
+ array_attribute :requirements
+
+ ##
+ # A list of Gem::Dependency objects this gem depends on. Only appendable.
+
+ array_attribute :dependencies
+
+ read_only :dependencies
+
+ # :section: Aliased gemspec attributes
+
+ ##
+ # Singular accessor for executables
+
+ attribute_alias_singular :executable, :executables
+
+ ##
+ # Singular accessor for authors
+
+ attribute_alias_singular :author, :authors
+
+ ##
+ # Singular accessor for require_paths
+
+ attribute_alias_singular :require_path, :require_paths
+
+ ##
+ # Singular accessor for test_files
+
+ attribute_alias_singular :test_file, :test_files
+
+ overwrite_accessor :version= do |version|
+ @version = Version.create(version)
+ end
+
+ overwrite_accessor :platform do
+ @new_platform
+ end
+
+ overwrite_accessor :platform= do |platform|
+ if @original_platform.nil? or
+ @original_platform == Gem::Platform::RUBY then
+ @original_platform = platform
+ end
+
+ case platform
+ when Gem::Platform::CURRENT then
+ @new_platform = Gem::Platform.local
+ @original_platform = @new_platform.to_s
+
+ when Gem::Platform then
+ @new_platform = platform
+
+ # legacy constants
+ when nil, Gem::Platform::RUBY then
+ @new_platform = Gem::Platform::RUBY
+ when 'mswin32' then # was Gem::Platform::WIN32
+ @new_platform = Gem::Platform.new 'x86-mswin32'
+ when 'i586-linux' then # was Gem::Platform::LINUX_586
+ @new_platform = Gem::Platform.new 'x86-linux'
+ when 'powerpc-darwin' then # was Gem::Platform::DARWIN
+ @new_platform = Gem::Platform.new 'ppc-darwin'
+ else
+ @new_platform = Gem::Platform.new platform
+ end
+
+ @platform = @new_platform.to_s
+
+ @new_platform
+ end
+
+ overwrite_accessor :required_ruby_version= do |value|
+ @required_ruby_version = Gem::Requirement.create(value)
+ end
+
+ overwrite_accessor :required_rubygems_version= do |value|
+ @required_rubygems_version = Gem::Requirement.create(value)
+ end
+
+ overwrite_accessor :date= do |date|
+ # We want to end up with a Time object with one-day resolution.
+ # This is the cleanest, most-readable, faster-than-using-Date
+ # way to do it.
+ case date
+ when String then
+ @date = if /\A(\d{4})-(\d{2})-(\d{2})\Z/ =~ date then
+ Time.local($1.to_i, $2.to_i, $3.to_i)
+ else
+ require 'time'
+ Time.parse date
+ end
+ when Time then
+ @date = Time.local(date.year, date.month, date.day)
+ when Date then
+ @date = Time.local(date.year, date.month, date.day)
+ else
+ @date = TODAY
+ end
+ end
+
+ overwrite_accessor :date do
+ self.date = nil if @date.nil? # HACK Sets the default value for date
+ @date
+ end
+
+ overwrite_accessor :summary= do |str|
+ @summary = if str then
+ str.strip.
+ gsub(/(\w-)\n[ \t]*(\w)/, '\1\2').
+ gsub(/\n[ \t]*/, " ")
+ end
+ end
+
+ overwrite_accessor :description= do |str|
+ @description = if str then
+ str.strip.
+ gsub(/(\w-)\n[ \t]*(\w)/, '\1\2').
+ gsub(/\n[ \t]*/, " ")
+ end
+ end
+
+ overwrite_accessor :default_executable do
+ begin
+ if defined?(@default_executable) and @default_executable
+ result = @default_executable
+ elsif @executables and @executables.size == 1
+ result = Array(@executables).first
+ else
+ result = nil
+ end
+ result
+ rescue
+ nil
+ end
+ end
+
+ overwrite_accessor :test_files do
+ # Handle the possibility that we have @test_suite_file but not
+ # @test_files. This will happen when an old gem is loaded via
+ # YAML.
+ if defined? @test_suite_file then
+ @test_files = [@test_suite_file].flatten
+ @test_suite_file = nil
+ end
+ if defined?(@test_files) and @test_files then
+ @test_files
+ else
+ @test_files = []
+ end
+ end
+
+ overwrite_accessor :files do
+ result = []
+ result.push(*@files) if defined?(@files)
+ result.push(*@test_files) if defined?(@test_files)
+ result.push(*(add_bindir(@executables)))
+ result.push(*@extra_rdoc_files) if defined?(@extra_rdoc_files)
+ result.push(*@extensions) if defined?(@extensions)
+ result.uniq.compact
+ end
end
diff --git a/lib/rubygems/test_utilities.rb b/lib/rubygems/test_utilities.rb
index e8709b9be3..8b23d3236e 100644
--- a/lib/rubygems/test_utilities.rb
+++ b/lib/rubygems/test_utilities.rb
@@ -34,16 +34,20 @@ class Gem::FakeFetcher
path = path.to_s
@paths << path
raise ArgumentError, 'need full URI' unless path =~ %r'^http://'
- data = @data[path]
- if data.nil? then
- raise Gem::RemoteFetcher::FetchError.new('no data', path)
+ unless @data.key? path then
+ raise Gem::RemoteFetcher::FetchError.new("no data for #{path}", path)
end
+ data = @data[path]
+
if data.respond_to?(:call) then
data.call
else
- data = Gem.gunzip data if path.to_s =~ /gz$/ unless data.empty?
+ if path.to_s =~ /gz$/ and not data.nil? and not data.empty? then
+ data = Gem.gunzip data
+ end
+
data
end
end
@@ -51,13 +55,15 @@ class Gem::FakeFetcher
def fetch_size(path)
path = path.to_s
@paths << path
+
raise ArgumentError, 'need full URI' unless path =~ %r'^http://'
- data = @data[path]
- if data.nil? then
- raise Gem::RemoteFetcher::FetchError.new("no data for #{path}", nil)
+ unless @data.key? path then
+ raise Gem::RemoteFetcher::FetchError.new("no data for #{path}", path)
end
+ data = @data[path]
+
data.respond_to?(:call) ? data.call : data.length
end
diff --git a/lib/rubygems/timer.rb b/lib/rubygems/timer.rb
index 06250f26b5..06250f26b5 100755..100644
--- a/lib/rubygems/timer.rb
+++ b/lib/rubygems/timer.rb
diff --git a/lib/rubygems/uninstaller.rb b/lib/rubygems/uninstaller.rb
index 2ad961972b..5f19da5e82 100644
--- a/lib/rubygems/uninstaller.rb
+++ b/lib/rubygems/uninstaller.rb
@@ -18,9 +18,23 @@ class Gem::Uninstaller
include Gem::UserInteraction
##
- # Constructs an Uninstaller instance
- #
- # gem:: [String] The Gem name to uninstall
+ # The directory a gem's executables will be installed into
+
+ attr_reader :bin_dir
+
+ ##
+ # The gem repository the gem will be installed into
+
+ attr_reader :gem_home
+
+ ##
+ # The Gem::Specification for the gem being uninstalled, only set during
+ # #uninstall_gem
+
+ attr_reader :spec
+
+ ##
+ # Constructs an uninstaller that will uninstall +gem+
def initialize(gem, options = {})
@gem = gem
@@ -31,42 +45,63 @@ class Gem::Uninstaller
@force_all = options[:all]
@force_ignore = options[:ignore]
@bin_dir = options[:bin_dir]
+
+ spec_dir = File.join @gem_home, 'specifications'
+ @source_index = Gem::SourceIndex.from_gems_in spec_dir
end
##
- # Performs the uninstall of the Gem. This removes the spec, the
- # Gem directory, and the cached .gem file,
+ # Performs the uninstall of the gem. This removes the spec, the Gem
+ # directory, and the cached .gem file.
def uninstall
- list = Gem.source_index.search(/^#{@gem}$/, @version)
+ list = @source_index.find_name @gem, @version
if list.empty? then
raise Gem::InstallError, "Unknown gem #{@gem} #{@version}"
- elsif list.size > 1 && @force_all
- remove_all(list.dup)
- remove_executables(list.last)
- elsif list.size > 1
- say
+
+ elsif list.size > 1 and @force_all then
+ remove_all list.dup
+
+ elsif list.size > 1 then
gem_names = list.collect {|gem| gem.full_name} + ["All versions"]
- gem_name, index =
- choose_from_list("Select gem to uninstall:", gem_names)
- if index == list.size
- remove_all(list.dup)
- remove_executables(list.last)
- elsif index >= 0 && index < list.size
- to_remove = list[index]
- remove(to_remove, list)
- remove_executables(to_remove)
+
+ say
+ gem_name, index = choose_from_list "Select gem to uninstall:", gem_names
+
+ if index == list.size then
+ remove_all list.dup
+ elsif index >= 0 && index < list.size then
+ uninstall_gem list[index], list.dup
else
say "Error: must enter a number [1-#{list.size+1}]"
end
else
- remove(list[0], list.dup)
- remove_executables(list.last)
+ uninstall_gem list.first, list.dup
end
end
##
+ # Uninstalls gem +spec+
+
+ def uninstall_gem(spec, specs)
+ @spec = spec
+
+ Gem.pre_uninstall_hooks.each do |hook|
+ hook.call self
+ end
+
+ specs.each { |s| remove_executables s }
+ remove spec, specs
+
+ Gem.post_uninstall_hooks.each do |hook|
+ hook.call self
+ end
+
+ @spec = nil
+ end
+
+ ##
# Removes installed executables and batch files (windows only) for
# +gemspec+.
@@ -76,7 +111,7 @@ class Gem::Uninstaller
if gemspec.executables.size > 0 then
bindir = @bin_dir ? @bin_dir : (Gem.bindir @gem_home)
- list = Gem.source_index.search(gemspec.name).delete_if { |spec|
+ list = @source_index.find_name(gemspec.name).delete_if { |spec|
spec.version == gemspec.version
}
@@ -118,7 +153,7 @@ class Gem::Uninstaller
# NOTE: removes uninstalled gems from +list+.
def remove_all(list)
- list.dup.each { |spec| remove spec, list }
+ list.dup.each { |spec| uninstall_gem spec, list }
end
##
@@ -185,8 +220,7 @@ class Gem::Uninstaller
def dependencies_ok?(spec)
return true if @force_ignore
- source_index = Gem::SourceIndex.from_installed_gems
- deplist = Gem::DependencyList.from_source_index source_index
+ deplist = Gem::DependencyList.from_source_index @source_index
deplist.ok_to_remove?(spec.full_name) || ask_if_ok(spec)
end
diff --git a/lib/rubygems/validator.rb b/lib/rubygems/validator.rb
index 8aaaa5a413..4595ad9a40 100755..100644
--- a/lib/rubygems/validator.rb
+++ b/lib/rubygems/validator.rb
@@ -10,118 +10,130 @@ require 'rubygems/digest/md5'
require 'rubygems/format'
require 'rubygems/installer'
-module Gem
+##
+# Validator performs various gem file and gem database validation
+
+class Gem::Validator
+
+ include Gem::UserInteraction
##
- # Validator performs various gem file and gem database validation
- class Validator
- include UserInteraction
-
- ##
- # Given a gem file's contents, validates against its own MD5 checksum
- # gem_data:: [String] Contents of the gem file
- def verify_gem(gem_data)
- raise VerificationError, 'empty gem file' if gem_data.size == 0
-
- unless gem_data =~ /MD5SUM/ then
- return # Don't worry about it...this sucks. Need to fix MD5 stuff for
- # new format
- # FIXME
- end
+ # Given a gem file's contents, validates against its own MD5 checksum
+ # gem_data:: [String] Contents of the gem file
- sum_data = gem_data.gsub(/MD5SUM = "([a-z0-9]+)"/,
- "MD5SUM = \"#{"F" * 32}\"")
+ def verify_gem(gem_data)
+ raise Gem::VerificationError, 'empty gem file' if gem_data.size == 0
- unless Gem::MD5.hexdigest(sum_data) == $1.to_s then
- raise VerificationError, 'invalid checksum for gem file'
- end
+ unless gem_data =~ /MD5SUM/ then
+ return # Don't worry about it...this sucks. Need to fix MD5 stuff for
+ # new format
+ # FIXME
end
- ##
- # Given the path to a gem file, validates against its own MD5 checksum
- #
- # gem_path:: [String] Path to gem file
- def verify_gem_file(gem_path)
- open gem_path, Gem.binary_mode do |file|
- gem_data = file.read
- verify_gem gem_data
- end
- rescue Errno::ENOENT
- raise Gem::VerificationError.new("missing gem file #{gem_path}")
+ sum_data = gem_data.gsub(/MD5SUM = "([a-z0-9]+)"/,
+ "MD5SUM = \"#{"F" * 32}\"")
+
+ unless Gem::MD5.hexdigest(sum_data) == $1.to_s then
+ raise Gem::VerificationError, 'invalid checksum for gem file'
end
+ end
- private
- def find_files_for_gem(gem_directory)
- installed_files = []
- Find.find(gem_directory) {|file_name|
- fn = file_name.slice((gem_directory.size)..(file_name.size-1)).sub(/^\//, "")
- if(!(fn =~ /CVS/ || File.directory?(fn) || fn == "")) then
- installed_files << fn
- end
-
- }
- installed_files
+ ##
+ # Given the path to a gem file, validates against its own MD5 checksum
+ #
+ # gem_path:: [String] Path to gem file
+
+ def verify_gem_file(gem_path)
+ open gem_path, Gem.binary_mode do |file|
+ gem_data = file.read
+ verify_gem gem_data
end
-
-
- public
- ErrorData = Struct.new(:path, :problem)
-
- ##
- # Checks the gem directory for the following potential
- # inconsistencies/problems:
- # * Checksum gem itself
- # * For each file in each gem, check consistency of installed versions
- # * Check for files that aren't part of the gem but are in the gems directory
- # * 1 cache - 1 spec - 1 directory.
- #
- # returns a hash of ErrorData objects, keyed on the problem gem's name.
- def alien
- errors = {}
- Gem::SourceIndex.from_installed_gems.each do |gem_name, gem_spec|
- errors[gem_name] ||= []
- gem_path = File.join(Gem.dir, "cache", gem_spec.full_name) + ".gem"
- spec_path = File.join(Gem.dir, "specifications", gem_spec.full_name) + ".gemspec"
- gem_directory = File.join(Gem.dir, "gems", gem_spec.full_name)
- installed_files = find_files_for_gem(gem_directory)
-
- if(!File.exist?(spec_path)) then
- errors[gem_name] << ErrorData.new(spec_path, "Spec file doesn't exist for installed gem")
- end
-
- begin
- verify_gem_file(gem_path)
- open gem_path, Gem.binary_mode do |file|
- format = Gem::Format.from_file_by_path(gem_path)
- format.file_entries.each do |entry, data|
- # Found this file. Delete it from list
- installed_files.delete remove_leading_dot_dir(entry['path'])
-
- next unless data # HACK `gem check -a mkrf`
-
- open File.join(gem_directory, entry['path']), Gem.binary_mode do |f|
- unless Gem::MD5.hexdigest(f.read).to_s ==
- Gem::MD5.hexdigest(data).to_s then
- errors[gem_name] << ErrorData.new(entry['path'], "installed file doesn't match original from gem")
- end
+ rescue Errno::ENOENT
+ raise Gem::VerificationError, "missing gem file #{gem_path}"
+ end
+
+ private
+
+ def find_files_for_gem(gem_directory)
+ installed_files = []
+ Find.find(gem_directory) {|file_name|
+ fn = file_name.slice((gem_directory.size)..(file_name.size-1)).sub(/^\//, "")
+ if(!(fn =~ /CVS/ || File.directory?(fn) || fn == "")) then
+ installed_files << fn
+ end
+
+ }
+ installed_files
+ end
+
+ public
+
+ ErrorData = Struct.new :path, :problem
+
+ ##
+ # Checks the gem directory for the following potential
+ # inconsistencies/problems:
+ #
+ # * Checksum gem itself
+ # * For each file in each gem, check consistency of installed versions
+ # * Check for files that aren't part of the gem but are in the gems directory
+ # * 1 cache - 1 spec - 1 directory.
+ #
+ # returns a hash of ErrorData objects, keyed on the problem gem's name.
+
+ def alien
+ errors = {}
+
+ Gem::SourceIndex.from_installed_gems.each do |gem_name, gem_spec|
+ errors[gem_name] ||= []
+
+ gem_path = File.join(Gem.dir, "cache", gem_spec.full_name) + ".gem"
+ spec_path = File.join(Gem.dir, "specifications", gem_spec.full_name) + ".gemspec"
+ gem_directory = File.join(Gem.dir, "gems", gem_spec.full_name)
+
+ installed_files = find_files_for_gem(gem_directory)
+
+ unless File.exist? spec_path then
+ errors[gem_name] << ErrorData.new(spec_path, "Spec file doesn't exist for installed gem")
+ end
+
+ begin
+ verify_gem_file(gem_path)
+
+ open gem_path, Gem.binary_mode do |file|
+ format = Gem::Format.from_file_by_path(gem_path)
+ format.file_entries.each do |entry, data|
+ # Found this file. Delete it from list
+ installed_files.delete remove_leading_dot_dir(entry['path'])
+
+ next unless data # HACK `gem check -a mkrf`
+
+ open File.join(gem_directory, entry['path']), Gem.binary_mode do |f|
+ unless Gem::MD5.hexdigest(f.read).to_s ==
+ Gem::MD5.hexdigest(data).to_s then
+ errors[gem_name] << ErrorData.new(entry['path'], "installed file doesn't match original from gem")
end
end
end
- rescue VerificationError => e
- errors[gem_name] << ErrorData.new(gem_path, e.message)
- end
- # Clean out directories that weren't explicitly included in the gemspec
- # FIXME: This still allows arbitrary incorrect directories.
- installed_files.delete_if {|potential_directory|
- File.directory?(File.join(gem_directory, potential_directory))
- }
- if(installed_files.size > 0) then
- errors[gem_name] << ErrorData.new(gem_path, "Unmanaged files in gem: #{installed_files.inspect}")
end
+ rescue Gem::VerificationError => e
+ errors[gem_name] << ErrorData.new(gem_path, e.message)
+ end
+
+ # Clean out directories that weren't explicitly included in the gemspec
+ # FIXME: This still allows arbitrary incorrect directories.
+ installed_files.delete_if {|potential_directory|
+ File.directory?(File.join(gem_directory, potential_directory))
+ }
+ if(installed_files.size > 0) then
+ errors[gem_name] << ErrorData.new(gem_path, "Unmanaged files in gem: #{installed_files.inspect}")
end
- errors
end
+ errors
+ end
+
+ if RUBY_VERSION < '1.9' then
class TestRunner
def initialize(suite, ui)
@suite = suite
@@ -147,40 +159,50 @@ module Gem
end
autoload :TestRunner, 'test/unit/ui/testrunnerutilities'
-
- ##
- # Runs unit tests for a given gem specification
- def unit_test(gem_spec)
- start_dir = Dir.pwd
- Dir.chdir(gem_spec.full_gem_path)
- $: << File.join(Gem.dir, "gems", gem_spec.full_name)
- # XXX: why do we need this gem_spec when we've already got 'spec'?
- test_files = gem_spec.test_files
- if test_files.empty?
- say "There are no unit tests to run for #{gem_spec.full_name}"
- require 'test/unit/ui/console/testrunner'
- return Test::Unit::TestResult.new
- end
- gem gem_spec.name, "= #{gem_spec.version.version}"
- test_files.each do |f| require f end
+ end
+
+ ##
+ # Runs unit tests for a given gem specification
+
+ def unit_test(gem_spec)
+ start_dir = Dir.pwd
+ Dir.chdir(gem_spec.full_gem_path)
+ $: << File.join(Gem.dir, "gems", gem_spec.full_name)
+ # XXX: why do we need this gem_spec when we've already got 'spec'?
+ test_files = gem_spec.test_files
+
+ if test_files.empty? then
+ say "There are no unit tests to run for #{gem_spec.full_name}"
+ return nil
+ end
+
+ gem gem_spec.name, "= #{gem_spec.version.version}"
+
+ test_files.each do |f| require f end
+
+ if RUBY_VERSION < '1.9' then
suite = Test::Unit::TestSuite.new("#{gem_spec.name}-#{gem_spec.version}")
+
ObjectSpace.each_object(Class) do |klass|
suite << klass.suite if (klass < Test::Unit::TestCase)
end
- result = TestRunner.run(suite, ui())
- unless result.passed?
- alert_error(result.to_s)
- #unless ask_yes_no(result.to_s + "...keep Gem?", true) then
- #Gem::Uninstaller.new(gem_spec.name, gem_spec.version.version).uninstall
- #end
- end
- result
- ensure
- Dir.chdir(start_dir)
- end
- def remove_leading_dot_dir(path)
- path.sub(/^\.\//, "")
+ result = TestRunner.run suite, ui
+
+ alert_error result.to_s unless result.passed?
+ else
+ result = MiniTest::Unit.new
+ result.run
end
+
+ result
+ ensure
+ Dir.chdir(start_dir)
+ end
+
+ def remove_leading_dot_dir(path)
+ path.sub(/^\.\//, "")
end
+
end
+
diff --git a/lib/sync.rb b/lib/sync.rb
index 22f160f290..f4dea76d1f 100644
--- a/lib/sync.rb
+++ b/lib/sync.rb
@@ -126,9 +126,9 @@ module Sync_m
# locking methods.
def sync_try_lock(mode = EX)
- return unlock if sync_mode == UN
+ return unlock if mode == UN
@sync_mutex.synchronize do
- ret = sync_try_lock_sub(sync_mode)
+ ret = sync_try_lock_sub(mode)
end
ret
end
diff --git a/lib/tempfile.rb b/lib/tempfile.rb
index 5eb294e390..601bb8d2f8 100644
--- a/lib/tempfile.rb
+++ b/lib/tempfile.rb
@@ -29,7 +29,12 @@ class Tempfile < DelegateClass(File)
# Dir::tmpdir provided by 'tmpdir.rb'.
# When $SAFE > 0 and the given tmpdir is tainted, it uses
# /tmp. (Note that ENV values are tainted by default)
- def initialize(basename, tmpdir=Dir::tmpdir)
+ def initialize(basename, *rest)
+ # I wish keyword argument settled soon.
+ if opts = Hash.try_convert(rest[-1])
+ rest.pop
+ end
+ tmpdir = rest[0] || Dir::tmpdir
if $SAFE > 0 and tmpdir.tainted?
tmpdir = '/tmp'
end
@@ -56,7 +61,12 @@ class Tempfile < DelegateClass(File)
@clean_proc = Tempfile.callback(@data)
ObjectSpace.define_finalizer(self, @clean_proc)
- @tmpfile = File.open(tmpname, File::RDWR|File::CREAT|File::EXCL, 0600)
+ if opts.nil?
+ opts = []
+ else
+ opts = [opts]
+ end
+ @tmpfile = File.open(tmpname, File::RDWR|File::CREAT|File::EXCL, 0600, *opts)
@tmpname = tmpname
@@cleanlist << @tmpname
@data[1] = @tmpfile
@@ -187,8 +197,6 @@ class Tempfile < DelegateClass(File)
ensure
tempfile.close
end
-
- nil
else
tempfile
end
diff --git a/lib/test/unit.rb b/lib/test/unit.rb
index b71f644566..3ddeb51643 100644
--- a/lib/test/unit.rb
+++ b/lib/test/unit.rb
@@ -1,280 +1,175 @@
-require 'test/unit/testcase'
-require 'test/unit/autorunner'
+# test/unit compatibility layer using minitest.
-module Test # :nodoc:
- #
- # = Test::Unit - Ruby Unit Testing Framework
- #
- # == Introduction
- #
- # Unit testing is making waves all over the place, largely due to the
- # fact that it is a core practice of XP. While XP is great, unit testing
- # has been around for a long time and has always been a good idea. One
- # of the keys to good unit testing, though, is not just writing tests,
- # but having tests. What's the difference? Well, if you just _write_ a
- # test and throw it away, you have no guarantee that something won't
- # change later which breaks your code. If, on the other hand, you _have_
- # tests (obviously you have to write them first), and run them as often
- # as possible, you slowly build up a wall of things that cannot break
- # without you immediately knowing about it. This is when unit testing
- # hits its peak usefulness.
- #
- # Enter Test::Unit, a framework for unit testing in Ruby, helping you to
- # design, debug and evaluate your code by making it easy to write and
- # have tests for it.
- #
- #
- # == Notes
- #
- # Test::Unit has grown out of and superceded Lapidary.
- #
- #
- # == Feedback
- #
- # I like (and do my best to practice) XP, so I value early releases,
- # user feedback, and clean, simple, expressive code. There is always
- # room for improvement in everything I do, and Test::Unit is no
- # exception. Please, let me know what you think of Test::Unit as it
- # stands, and what you'd like to see expanded/changed/improved/etc. If
- # you find a bug, let me know ASAP; one good way to let me know what the
- # bug is is to submit a new test that catches it :-) Also, I'd love to
- # hear about any successes you have with Test::Unit, and any
- # documentation you might add will be greatly appreciated. My contact
- # info is below.
- #
- #
- # == Contact Information
- #
- # A lot of discussion happens about Ruby in general on the ruby-talk
- # mailing list (http://www.ruby-lang.org/en/ml.html), and you can ask
- # any questions you might have there. I monitor the list, as do many
- # other helpful Rubyists, and you're sure to get a quick answer. Of
- # course, you're also welcome to email me (Nathaniel Talbott) directly
- # at mailto:testunit@talbott.ws, and I'll do my best to help you out.
- #
- #
- # == Credits
- #
- # I'd like to thank...
- #
- # Matz, for a great language!
- #
- # Masaki Suketa, for his work on RubyUnit, which filled a vital need in
- # the Ruby world for a very long time. I'm also grateful for his help in
- # polishing Test::Unit and getting the RubyUnit compatibility layer
- # right. His graciousness in allowing Test::Unit to supercede RubyUnit
- # continues to be a challenge to me to be more willing to defer my own
- # rights.
- #
- # Ken McKinlay, for his interest and work on unit testing, and for his
- # willingness to dialog about it. He was also a great help in pointing
- # out some of the holes in the RubyUnit compatibility layer.
- #
- # Dave Thomas, for the original idea that led to the extremely simple
- # "require 'test/unit'", plus his code to improve it even more by
- # allowing the selection of tests from the command-line. Also, without
- # RDoc, the documentation for Test::Unit would stink a lot more than it
- # does now.
- #
- # Everyone who's helped out with bug reports, feature ideas,
- # encouragement to continue, etc. It's a real privilege to be a part of
- # the Ruby community.
- #
- # The guys at RoleModel Software, for putting up with me repeating, "But
- # this would be so much easier in Ruby!" whenever we're coding in Java.
- #
- # My Creator, for giving me life, and giving it more abundantly.
- #
- #
- # == License
- #
- # Test::Unit is copyright (c) 2000-2003 Nathaniel Talbott. It is free
- # software, and is distributed under the Ruby license. See the COPYING
- # file in the standard Ruby distribution for details.
- #
- #
- # == Warranty
- #
- # This software is provided "as is" and without any express or
- # implied warranties, including, without limitation, the implied
- # warranties of merchantibility and fitness for a particular
- # purpose.
- #
- #
- # == Author
- #
- # Nathaniel Talbott.
- # Copyright (c) 2000-2003, Nathaniel Talbott
- #
- # ----
- #
- # = Usage
- #
- # The general idea behind unit testing is that you write a _test_
- # _method_ that makes certain _assertions_ about your code, working
- # against a _test_ _fixture_. A bunch of these _test_ _methods_ are
- # bundled up into a _test_ _suite_ and can be run any time the
- # developer wants. The results of a run are gathered in a _test_
- # _result_ and displayed to the user through some UI. So, lets break
- # this down and see how Test::Unit provides each of these necessary
- # pieces.
- #
- #
- # == Assertions
- #
- # These are the heart of the framework. Think of an assertion as a
- # statement of expected outcome, i.e. "I assert that x should be equal
- # to y". If, when the assertion is executed, it turns out to be
- # correct, nothing happens, and life is good. If, on the other hand,
- # your assertion turns out to be false, an error is propagated with
- # pertinent information so that you can go back and make your
- # assertion succeed, and, once again, life is good. For an explanation
- # of the current assertions, see Test::Unit::Assertions.
- #
- #
- # == Test Method & Test Fixture
- #
- # Obviously, these assertions have to be called within a context that
- # knows about them and can do something meaningful with their
- # pass/fail value. Also, it's handy to collect a bunch of related
- # tests, each test represented by a method, into a common test class
- # that knows how to run them. The tests will be in a separate class
- # from the code they're testing for a couple of reasons. First of all,
- # it allows your code to stay uncluttered with test code, making it
- # easier to maintain. Second, it allows the tests to be stripped out
- # for deployment, since they're really there for you, the developer,
- # and your users don't need them. Third, and most importantly, it
- # allows you to set up a common test fixture for your tests to run
- # against.
- #
- # What's a test fixture? Well, tests do not live in a vacuum; rather,
- # they're run against the code they are testing. Often, a collection
- # of tests will run against a common set of data, also called a
- # fixture. If they're all bundled into the same test class, they can
- # all share the setting up and tearing down of that data, eliminating
- # unnecessary duplication and making it much easier to add related
- # tests.
- #
- # Test::Unit::TestCase wraps up a collection of test methods together
- # and allows you to easily set up and tear down the same test fixture
- # for each test. This is done by overriding #setup and/or #teardown,
- # which will be called before and after each test method that is
- # run. The TestCase also knows how to collect the results of your
- # assertions into a Test::Unit::TestResult, which can then be reported
- # back to you... but I'm getting ahead of myself. To write a test,
- # follow these steps:
- #
- # * Make sure Test::Unit is in your library path.
- # * require 'test/unit' in your test script.
- # * Create a class that subclasses Test::Unit::TestCase.
- # * Add a method that begins with "test" to your class.
- # * Make assertions in your test method.
- # * Optionally define #setup and/or #teardown to set up and/or tear
- # down your common test fixture.
- # * You can now run your test as you would any other Ruby
- # script... try it and see!
- #
- # A really simple test might look like this (#setup and #teardown are
- # commented out to indicate that they are completely optional):
- #
- # require 'test/unit'
- #
- # class TC_MyTest < Test::Unit::TestCase
- # # def setup
- # # end
- #
- # # def teardown
- # # end
- #
- # def test_fail
- # assert(false, 'Assertion was false.')
- # end
- # end
- #
- #
- # == Test Runners
- #
- # So, now you have this great test class, but you still need a way to
- # run it and view any failures that occur during the run. This is
- # where Test::Unit::UI::Console::TestRunner (and others, such as
- # Test::Unit::UI::GTK::TestRunner) comes into play. The console test
- # runner is automatically invoked for you if you require 'test/unit'
- # and simply run the file. To use another runner, or to manually
- # invoke a runner, simply call its run class method and pass in an
- # object that responds to the suite message with a
- # Test::Unit::TestSuite. This can be as simple as passing in your
- # TestCase class (which has a class suite method). It might look
- # something like this:
- #
- # require 'test/unit/ui/console/testrunner'
- # Test::Unit::UI::Console::TestRunner.run(TC_MyTest)
- #
- #
- # == Test Suite
- #
- # As more and more unit tests accumulate for a given project, it
- # becomes a real drag running them one at a time, and it also
- # introduces the potential to overlook a failing test because you
- # forget to run it. Suddenly it becomes very handy that the
- # TestRunners can take any object that returns a Test::Unit::TestSuite
- # in response to a suite method. The TestSuite can, in turn, contain
- # other TestSuites or individual tests (typically created by a
- # TestCase). In other words, you can easily wrap up a group of
- # TestCases and TestSuites like this:
- #
- # require 'test/unit/testsuite'
- # require 'tc_myfirsttests'
- # require 'tc_moretestsbyme'
- # require 'ts_anothersetoftests'
- #
- # class TS_MyTests
- # def self.suite
- # suite = Test::Unit::TestSuite.new
- # suite << TC_MyFirstTests.suite
- # suite << TC_MoreTestsByMe.suite
- # suite << TS_AnotherSetOfTests.suite
- # return suite
- # end
- # end
- # Test::Unit::UI::Console::TestRunner.run(TS_MyTests)
- #
- # Now, this is a bit cumbersome, so Test::Unit does a little bit more
- # for you, by wrapping these up automatically when you require
- # 'test/unit'. What does this mean? It means you could write the above
- # test case like this instead:
- #
- # require 'test/unit'
- # require 'tc_myfirsttests'
- # require 'tc_moretestsbyme'
- # require 'ts_anothersetoftests'
- #
- # Test::Unit is smart enough to find all the test cases existing in
- # the ObjectSpace and wrap them up into a suite for you. It then runs
- # the dynamic suite using the console TestRunner.
- #
- #
- # == Questions?
- #
- # I'd really like to get feedback from all levels of Ruby
- # practitioners about typos, grammatical errors, unclear statements,
- # missing points, etc., in this document (or any other).
- #
+require 'minitest/unit'
+require 'pp'
+module Test
module Unit
- # If set to false Test::Unit will not automatically run at exit.
- def self.run=(flag)
- @run = flag
+ TEST_UNIT_IMPLEMENTATION = 'test/unit compatibility layer using minitest'
+
+ def self.setup_argv(original_argv=ARGV)
+ minitest_argv = []
+ files = []
+ reject = []
+ original_argv = original_argv.dup
+ while arg = original_argv.shift
+ case arg
+ when '-v'
+ minitest_argv << arg
+ when /\A(-n)(.+)?/, /\A(--name)=?\b(.+)?/
+ minitest_argv << $1
+ minitest_argv << ($2 || original_argv.shift)
+ when /\A-x(.+)?/
+ reject << ($1 || original_argv.shift)
+ else
+ files << arg
+ end
+ end
+
+ if block_given?
+ files = yield files
+ end
+
+ files.map! {|f|
+ if File.directory? f
+ Dir["#{f}/**/test_*.rb"]
+ elsif File.file? f
+ f
+ else
+ raise ArgumentError, "file not found: #{f}"
+ end
+ }
+ files.flatten!
+
+ reject_pat = Regexp.union(reject.map {|r| /#{r}/ })
+ files.reject! {|f| reject_pat =~ f }
+
+ files.each {|f|
+ d = File.dirname(File.expand_path(f))
+ unless $:.include? d
+ $: << d
+ end
+ begin
+ require f
+ rescue LoadError
+ puts "#{f}: #{$!}"
+ end
+ }
+
+ ARGV.replace minitest_argv
end
- # Automatically run tests at exit?
- def self.run?
- @run ||= false
+ module Assertions
+ include MiniTest::Assertions
+
+ def mu_pp(obj)
+ obj.pretty_inspect.chomp
+ end
+
+ def assert_raise(*args, &b)
+ assert_raises(*args, &b)
+ end
+
+ def assert_nothing_raised(*args)
+ if Module === args.last
+ msg = nil
+ else
+ msg = args.pop
+ end
+ begin
+ yield
+ rescue Exception => e
+ if ((args.empty? && !e.instance_of?(MiniTest::Assertion)) ||
+ args.any? {|a| a.instance_of?(Module) ? e.is_a?(a) : e.class == a })
+ msg = message(msg) { "Exception raised:\n<#{mu_pp(e)}>" }
+ raise MiniTest::Assertion, msg.call, e.backtrace
+ else
+ raise
+ end
+ end
+ nil
+ end
+
+ def assert_nothing_thrown(msg=nil)
+ begin
+ yield
+ rescue ArgumentError => error
+ raise error if /\Auncaught throw (.+)\z/m !~ error.message
+ msg = message(msg) { "<#{$1}> was thrown when nothing was expected" }
+ flunk(msg)
+ end
+ assert(true, "Expected nothing to be thrown")
+ end
+
+ def assert_equal(exp, act, msg = nil)
+ msg = message(msg) {
+ exp_str = mu_pp(exp)
+ act_str = mu_pp(act)
+ exp_comment = ''
+ act_comment = ''
+ if exp_str == act_str
+ if exp.is_a?(String) && act.is_a?(String)
+ exp_comment = " (#{exp.encoding})"
+ act_comment = " (#{act.encoding})"
+ elsif exp.is_a?(Time) && act.is_a?(Time)
+ exp_comment = " (nsec=#{exp.nsec})"
+ act_comment = " (nsec=#{act.nsec})"
+ end
+ elsif !Encoding.compatible?(exp_str, act_str)
+ if exp.is_a?(String) && act.is_a?(String)
+ exp_str = exp.dump
+ act_str = act.dump
+ exp_comment = " (#{exp.encoding})"
+ act_comment = " (#{act.encoding})"
+ else
+ exp_str = exp_str.dump
+ act_str = act_str.dump
+ end
+ end
+ "<#{exp_str}>#{exp_comment} expected but was\n<#{act_str}>#{act_comment}"
+ }
+ assert(exp == act, msg)
+ end
+
+ def assert_not_nil(exp, msg=nil)
+ msg = message(msg) { "<#{mu_pp(exp)}> expected to not be nil" }
+ assert(!exp.nil?, msg)
+ end
+
+ def assert_not_equal(exp, act, msg=nil)
+ msg = message(msg) { "<#{mu_pp(exp)}> expected to be != to\n<#{mu_pp(act)}>" }
+ assert(exp != act, msg)
+ end
+
+ def assert_no_match(regexp, string, msg=nil)
+ assert_instance_of(Regexp, regexp, "The first argument to assert_no_match should be a Regexp.")
+ msg = message(msg) { "<#{mu_pp(regexp)}> expected to not match\n<#{mu_pp(string)}>" }
+ assert(regexp !~ string, msg)
+ end
+
+ def assert_not_same(expected, actual, message="")
+ msg = message(msg) { build_message(message, <<EOT, expected, expected.__id__, actual, actual.__id__) }
+<?>
+with id <?> expected to not be equal\\? to
+<?>
+with id <?>.
+EOT
+ assert(!actual.equal?(expected), msg)
+ end
+
+ def build_message(head, template=nil, *arguments)
+ template &&= template.chomp
+ template.gsub(/\?/) { mu_pp(arguments.shift) }
+ end
end
- end
-end
-at_exit do
- unless $! || Test::Unit.run?
- exit Test::Unit::AutoRunner.run
+ class TestCase < MiniTest::Unit::TestCase
+ include Assertions
+ def self.test_order
+ :sorted
+ end
+ end
end
end
+
+MiniTest::Unit.autorun
diff --git a/lib/test/unit/assertionfailederror.rb b/lib/test/unit/assertionfailederror.rb
deleted file mode 100644
index a21e4b5870..0000000000
--- a/lib/test/unit/assertionfailederror.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-#--
-#
-# Author:: Nathaniel Talbott.
-# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
-# License:: Ruby license.
-
-module Test
- module Unit
-
- # Thrown by Test::Unit::Assertions when an assertion fails.
- class AssertionFailedError < StandardError
- end
- end
-end
diff --git a/lib/test/unit/assertions.rb b/lib/test/unit/assertions.rb
deleted file mode 100644
index d9c9e096ba..0000000000
--- a/lib/test/unit/assertions.rb
+++ /dev/null
@@ -1,622 +0,0 @@
-# Author:: Nathaniel Talbott.
-# Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
-# License:: Ruby license.
-
-require 'test/unit/assertionfailederror'
-require 'test/unit/util/backtracefilter'
-
-module Test # :nodoc:
- module Unit # :nodoc:
-
- ##
- # Test::Unit::Assertions contains the standard Test::Unit assertions.
- # Assertions is included in Test::Unit::TestCase.
- #
- # To include it in your own code and use its functionality, you simply
- # need to rescue Test::Unit::AssertionFailedError. Additionally you may
- # override add_assertion to get notified whenever an assertion is made.
- #
- # Notes:
- # * The message to each assertion, if given, will be propagated with the
- # failure.
- # * It is easy to add your own assertions based on assert_block().
- #
- # = Example Custom Assertion
- #
- # def deny(boolean, message = nil)
- # message = build_message message, '<?> is not false or nil.', boolean
- # assert_block message do
- # not boolean
- # end
- # end
-
- module Assertions
-
- ##
- # The assertion upon which all other assertions are based. Passes if the
- # block yields true.
- #
- # Example:
- # assert_block "Couldn't do the thing" do
- # do_the_thing
- # end
-
- public
- def assert_block(message="assert_block failed.") # :yields:
- _wrap_assertion do
- if (! yield)
- raise AssertionFailedError.new(message.to_s)
- end
- end
- end
-
- ##
- # Asserts that +boolean+ is not false or nil.
- #
- # Example:
- # assert [1, 2].include?(5)
-
- public
- def assert(boolean, message=nil)
- _wrap_assertion do
- assert_block("assert should not be called with a block.") { !block_given? }
- assert_block(build_message(message, "<?> is not true.", boolean)) { boolean }
- end
- end
-
- ##
- # Passes if +expected+ == +actual.
- #
- # Note that the ordering of arguments is important, since a helpful
- # error message is generated when this one fails that tells you the
- # values of expected and actual.
- #
- # Example:
- # assert_equal 'MY STRING', 'my string'.upcase
-
- public
- def assert_equal(expected, actual, message=nil)
- full_message = build_message(message, <<EOT, expected, actual)
-<?> expected but was
-<?>.
-EOT
- assert_block(full_message) { expected == actual }
- end
-
- private
- def _check_exception_class(args) # :nodoc:
- args.partition do |klass|
- next if klass.instance_of?(Module)
- assert(Exception >= klass, "Should expect a class of exception, #{klass}")
- true
- end
- end
-
- private
- def _expected_exception?(actual_exception, exceptions, modules) # :nodoc:
- exceptions.include?(actual_exception.class) or
- modules.any? {|mod| actual_exception.is_a?(mod)}
- end
-
- ##
- # Passes if the block raises one of the given exceptions.
- #
- # Example:
- # assert_raise RuntimeError, LoadError do
- # raise 'Boom!!!'
- # end
-
- public
- def assert_raise(*args)
- _wrap_assertion do
- if Module === args.last
- message = ""
- else
- message = args.pop
- end
- exceptions, modules = _check_exception_class(args)
- expected = args.size == 1 ? args.first : args
- actual_exception = nil
- full_message = build_message(message, "<?> exception expected but none was thrown.", expected)
- assert_block(full_message) do
- begin
- yield
- rescue Exception => actual_exception
- break
- end
- false
- end
- full_message = build_message(message, "<?> exception expected but was\n?", expected, actual_exception)
- assert_block(full_message) {_expected_exception?(actual_exception, exceptions, modules)}
- actual_exception
- end
- end
-
- ##
- # Alias of assert_raise.
- #
- # Will be deprecated in 1.9, and removed in 2.0.
-
- public
- def assert_raises(*args, &block)
- assert_raise(*args, &block)
- end
-
- ##
- # Passes if +object+ .instance_of? +klass+
- #
- # Example:
- # assert_instance_of String, 'foo'
-
- public
- def assert_instance_of(klass, object, message="")
- _wrap_assertion do
- assert_equal(Class, klass.class, "assert_instance_of takes a Class as its first argument")
- full_message = build_message(message, <<EOT, object, klass, object.class)
-<?> expected to be an instance of
-<?> but was
-<?>.
-EOT
- assert_block(full_message){object.instance_of?(klass)}
- end
- end
-
- ##
- # Passes if +object+ is nil.
- #
- # Example:
- # assert_nil [1, 2].uniq!
-
- public
- def assert_nil(object, message="")
- assert_equal(nil, object, message)
- end
-
- ##
- # Passes if +object+ .kind_of? +klass+
- #
- # Example:
- # assert_kind_of Object, 'foo'
-
- public
- def assert_kind_of(klass, object, message="")
- _wrap_assertion do
- assert(klass.kind_of?(Module), "The first parameter to assert_kind_of should be a kind_of Module.")
- full_message = build_message(message, "<?>\nexpected to be kind_of\\?\n<?> but was\n<?>.", object, klass, object.class)
- assert_block(full_message){object.kind_of?(klass)}
- end
- end
-
- ##
- # Passes if +object+ .respond_to? +method+
- #
- # Example:
- # assert_respond_to 'bugbear', :slice
-
- public
- def assert_respond_to(object, method, message="")
- _wrap_assertion do
- full_message = build_message(nil, "<?>\ngiven as the method name argument to #assert_respond_to must be a Symbol or #respond_to\\?(:to_str).", method)
-
- assert_block(full_message) do
- method.kind_of?(Symbol) || method.respond_to?(:to_str)
- end
- full_message = build_message(message, <<EOT, object, object.class, method)
-<?>
-of type <?>
-expected to respond_to\\?<?>.
-EOT
- assert_block(full_message) { object.respond_to?(method) }
- end
- end
-
- ##
- # Passes if +string+ =~ +pattern+.
- #
- # Example:
- # assert_match(/\d+/, 'five, 6, seven')
-
- public
- def assert_match(pattern, string, message="")
- _wrap_assertion do
- pattern = case(pattern)
- when String
- Regexp.new(Regexp.escape(pattern))
- else
- pattern
- end
- full_message = build_message(message, "<?> expected to be =~\n<?>.", string, pattern)
- assert_block(full_message) { string =~ pattern }
- end
- end
-
- ##
- # Passes if +actual+ .equal? +expected+ (i.e. they are the same
- # instance).
- #
- # Example:
- # o = Object.new
- # assert_same o, o
-
- public
- def assert_same(expected, actual, message="")
- full_message = build_message(message, <<EOT, expected, expected.__id__, actual, actual.__id__)
-<?>
-with id <?> expected to be equal\\? to
-<?>
-with id <?>.
-EOT
- assert_block(full_message) { actual.equal?(expected) }
- end
-
- ##
- # Compares the +object1+ with +object2+ using +operator+.
- #
- # Passes if object1.__send__(operator, object2) is true.
- #
- # Example:
- # assert_operator 5, :>=, 4
-
- public
- def assert_operator(object1, operator, object2, message="")
- _wrap_assertion do
- full_message = build_message(nil, "<?>\ngiven as the operator for #assert_operator must be a Symbol or #respond_to\\?(:to_str).", operator)
- assert_block(full_message){operator.kind_of?(Symbol) || operator.respond_to?(:to_str)}
- full_message = build_message(message, <<EOT, object1, AssertionMessage.literal(operator), object2)
-<?> expected to be
-?
-<?>.
-EOT
- assert_block(full_message) { object1.__send__(operator, object2) }
- end
- end
-
- ##
- # Passes if block does not raise an exception.
- #
- # Example:
- # assert_nothing_raised do
- # [1, 2].uniq
- # end
-
- public
- def assert_nothing_raised(*args)
- _wrap_assertion do
- if Module === args.last
- message = ""
- else
- message = args.pop
- end
- exceptions, modules = _check_exception_class(args)
- begin
- yield
- rescue Exception => e
- if ((args.empty? && !e.instance_of?(AssertionFailedError)) ||
- _expected_exception?(e, exceptions, modules))
- assert_block(build_message(message, "Exception raised:\n?", e)){false}
- else
- raise
- end
- end
- nil
- end
- end
-
- ##
- # Flunk always fails.
- #
- # Example:
- # flunk 'Not done testing yet.'
-
- public
- def flunk(message="Flunked")
- assert_block(build_message(message)){false}
- end
-
- ##
- # Passes if ! +actual+ .equal? +expected+
- #
- # Example:
- # assert_not_same Object.new, Object.new
-
- public
- def assert_not_same(expected, actual, message="")
- full_message = build_message(message, <<EOT, expected, expected.__id__, actual, actual.__id__)
-<?>
-with id <?> expected to not be equal\\? to
-<?>
-with id <?>.
-EOT
- assert_block(full_message) { !actual.equal?(expected) }
- end
-
- ##
- # Passes if +expected+ != +actual+
- #
- # Example:
- # assert_not_equal 'some string', 5
-
- public
- def assert_not_equal(expected, actual, message="")
- full_message = build_message(message, "<?> expected to be != to\n<?>.", expected, actual)
- assert_block(full_message) { expected != actual }
- end
-
- ##
- # Passes if ! +object+ .nil?
- #
- # Example:
- # assert_not_nil '1 two 3'.sub!(/two/, '2')
-
- public
- def assert_not_nil(object, message="")
- full_message = build_message(message, "<?> expected to not be nil.", object)
- assert_block(full_message){!object.nil?}
- end
-
- ##
- # Passes if +regexp+ !~ +string+
- #
- # Example:
- # assert_no_match(/two/, 'one 2 three')
-
- public
- def assert_no_match(regexp, string, message="")
- _wrap_assertion do
- assert_instance_of(Regexp, regexp, "The first argument to assert_no_match should be a Regexp.")
- full_message = build_message(message, "<?> expected to not match\n<?>.", regexp, string)
- assert_block(full_message) { regexp !~ string }
- end
- end
-
- UncaughtThrow = {
- ArgumentError => /^uncaught throw (.+)$/,
- } #`
-
- ##
- # Passes if the block throws +expected_object+
- #
- # Example:
- # assert_throws :done do
- # throw :done
- # end
-
- public
- def assert_throws(expected_object, message="", &proc)
- _wrap_assertion do
- assert_block("Should have passed a block to assert_throws."){block_given?}
- caught = true
- begin
- catch(expected_object) do
- proc.call
- caught = false
- end
- full_message = build_message(message, "<?> should have been thrown.", expected_object)
- assert_block(full_message){caught}
- rescue ArgumentError => error
- if UncaughtThrow[error.class] !~ error.message
- raise error
- end
- full_message = build_message(message, "<?> expected to be thrown but\n<#$1> was thrown.", expected_object)
- flunk(full_message)
- end
- end
- end
-
- ##
- # Passes if block does not throw anything.
- #
- # Example:
- # assert_nothing_thrown do
- # [1, 2].uniq
- # end
-
- public
- def assert_nothing_thrown(message="", &proc)
- _wrap_assertion do
- assert(block_given?, "Should have passed a block to assert_nothing_thrown")
- begin
- proc.call
- rescue ArgumentError => error
- if UncaughtThrow[error.class] !~ error.message
- raise error
- end
- full_message = build_message(message, "<#$1> was thrown when nothing was expected")
- flunk(full_message)
- end
- assert(true, "Expected nothing to be thrown")
- end
- end
-
- ##
- # Passes if +expected_float+ and +actual_float+ are equal
- # within +delta+ tolerance.
- #
- # Example:
- # assert_in_delta 0.05, (50000.0 / 10**6), 0.00001
-
- public
- def assert_in_delta(expected_float, actual_float, delta, message="")
- _wrap_assertion do
- {expected_float => "first float", actual_float => "second float", delta => "delta"}.each do |float, name|
- assert_respond_to(float, :to_f, "The arguments must respond to to_f; the #{name} did not")
- end
- assert_operator(delta, :>=, 0.0, "The delta should not be negative")
- full_message = build_message(message, <<EOT, expected_float, actual_float, delta)
-<?> and
-<?> expected to be within
-<?> of each other.
-EOT
- assert_block(full_message) { (expected_float.to_f - actual_float.to_f).abs <= delta.to_f }
- end
- end
-
- ##
- # Passes if the method send returns a true value.
- #
- # +send_array+ is composed of:
- # * A receiver
- # * A method
- # * Arguments to the method
- #
- # Example:
- # assert_send [[1, 2], :include?, 4]
-
- public
- def assert_send(send_array, message="")
- _wrap_assertion do
- assert_instance_of(Array, send_array, "assert_send requires an array of send information")
- assert(send_array.size >= 2, "assert_send requires at least a receiver and a message name")
- full_message = build_message(message, <<EOT, send_array[0], AssertionMessage.literal(send_array[1].to_s), send_array[2..-1])
-<?> expected to respond to
-<?(?)> with a true value.
-EOT
- assert_block(full_message) { send_array[0].__send__(send_array[1], *send_array[2..-1]) }
- end
- end
-
- ##
- # Builds a failure message. +head+ is added before the +template+ and
- # +arguments+ replaces the '?'s positionally in the template.
-
- public
- def build_message(head, template=nil, *arguments) # :nodoc:
- template &&= template.chomp
- return AssertionMessage.new(head, template, arguments)
- end
-
- private
- def _wrap_assertion # :nodoc:
- @_assertion_wrapped ||= false
- unless (@_assertion_wrapped)
- @_assertion_wrapped = true
- begin
- add_assertion
- return yield
- ensure
- @_assertion_wrapped = false
- end
- else
- return yield
- end
- end
-
- ##
- # Called whenever an assertion is made. Define this in classes that
- # include Test::Unit::Assertions to record assertion counts.
-
- private
- def add_assertion
- end
-
- ##
- # Select whether or not to use the pretty-printer. If this option is set
- # to false before any assertions are made, pp.rb will not be required.
-
- public
- def self.use_pp=(value)
- AssertionMessage.use_pp = value
- end
-
- # :stopdoc:
-
- class AssertionMessage
- @use_pp = true
- class << self
- attr_accessor :use_pp
- end
-
- class Literal
- def initialize(value)
- @value = value
- end
-
- def inspect
- @value.to_s
- end
- end
-
- class Template
- def self.create(string)
- parts = (string ? string.scan(/(?=[^\\])\?|(?:\\\?|[^\?])+/m) : [])
- self.new(parts)
- end
-
- attr_reader :count
-
- def initialize(parts)
- @parts = parts
- @count = parts.find_all{|e| e == '?'}.size
- end
-
- def result(parameters)
- raise "The number of parameters does not match the number of substitutions." if(parameters.size != count)
- params = parameters.dup
- @parts.collect{|e| e == '?' ? params.shift : e.gsub(/\\\?/m, '?')}.join('')
- end
- end
-
- def self.literal(value)
- Literal.new(value)
- end
-
- include Util::BacktraceFilter
-
- def initialize(head, template_string, parameters)
- @head = head
- @template_string = template_string
- @parameters = parameters
- end
-
- def convert(object)
- case object
- when Exception
- <<EOM.chop
-Class: <#{convert(object.class)}>
-Message: <#{convert(object.message)}>
----Backtrace---
-#{filter_backtrace(object.backtrace).join("\n")}
----------------
-EOM
- else
- if(self.class.use_pp)
- begin
- require 'pp'
- rescue LoadError
- self.class.use_pp = false
- return object.inspect
- end unless(defined?(PP))
- PP.pp(object, '').chomp
- else
- object.inspect
- end
- end
- end
-
- def template
- @template ||= Template.create(@template_string)
- end
-
- def add_period(string)
- (string =~ /\.\Z/ ? string : string + '.')
- end
-
- def to_s
- message_parts = []
- if (@head)
- head = @head.to_s
- unless(head.empty?)
- message_parts << add_period(head)
- end
- end
- tail = template.result(@parameters.collect{|e| convert(e)})
- message_parts << tail unless(tail.empty?)
- message_parts.join("\n")
- end
- end
-
- # :startdoc:
-
- end
- end
-end
diff --git a/lib/test/unit/autorunner.rb b/lib/test/unit/autorunner.rb
deleted file mode 100644
index c252e2e7cb..0000000000
--- a/lib/test/unit/autorunner.rb
+++ /dev/null
@@ -1,217 +0,0 @@
-require 'test/unit'
-require 'test/unit/ui/testrunnerutilities'
-require 'optparse'
-
-module Test
- module Unit
- class AutoRunner
- def self.run(force_standalone=false, default_dir=nil, argv=ARGV, &block)
- r = new(force_standalone || standalone?, &block)
- r.base = default_dir
- r.process_args(argv)
- r.run
- end
-
- def self.standalone?
- return false unless("-e" == $0)
- TestCase::DECENDANT_CLASSES.empty?
- end
-
- RUNNERS = {
- :console => proc do |r|
- require 'test/unit/ui/console/testrunner'
- Test::Unit::UI::Console::TestRunner
- end,
- :gtk => proc do |r|
- require 'test/unit/ui/gtk/testrunner'
- Test::Unit::UI::GTK::TestRunner
- end,
- :gtk2 => proc do |r|
- require 'test/unit/ui/gtk2/testrunner'
- Test::Unit::UI::GTK2::TestRunner
- end,
- :fox => proc do |r|
- require 'test/unit/ui/fox/testrunner'
- Test::Unit::UI::Fox::TestRunner
- end,
- :tk => proc do |r|
- require 'test/unit/ui/tk/testrunner'
- Test::Unit::UI::Tk::TestRunner
- end,
- }
-
- OUTPUT_LEVELS = [
- [:silent, UI::SILENT],
- [:progress, UI::PROGRESS_ONLY],
- [:normal, UI::NORMAL],
- [:verbose, UI::VERBOSE],
- ]
-
- COLLECTORS = {
- :objectspace => proc do |r|
- require 'test/unit/collector/objectspace'
- c = Collector::ObjectSpace.new
- c.filter = r.filters
- c.collect($0.sub(/\.rb\Z/, ''))
- end,
- :dir => proc do |r|
- require 'test/unit/collector/dir'
- c = Collector::Dir.new
- c.filter = r.filters
- c.pattern.concat(r.pattern) if(r.pattern)
- c.exclude.concat(r.exclude) if(r.exclude)
- c.base = r.base
- $:.push(r.base) if r.base
- c.collect(*(r.to_run.empty? ? ['.'] : r.to_run))
- end,
- }
-
- attr_reader :suite
- attr_accessor :output_level, :filters, :to_run, :pattern, :exclude, :base, :workdir
- attr_writer :runner, :collector
-
- def initialize(standalone)
- Unit.run = true
- @standalone = standalone
- @runner = RUNNERS[:console]
- @collector = COLLECTORS[(standalone ? :dir : :objectspace)]
- @filters = []
- @to_run = []
- @output_level = UI::NORMAL
- @workdir = false
- yield(self) if(block_given?)
- end
-
- def process_args(args = ARGV)
- begin
- options.order!(args) {|arg| @to_run << arg}
- rescue OptionParser::ParseError => e
- puts e
- puts options
- $! = nil
- abort
- else
- @filters << proc{false} unless(@filters.empty?)
- end
- not @to_run.empty?
- end
-
- def options
- @options ||= OptionParser.new do |o|
- o.banner = "Test::Unit automatic runner."
- o.banner << "\nUsage: #{$0} [options] [-- untouched arguments]"
-
- o.on
- o.on('-r', '--runner=RUNNER', RUNNERS,
- "Use the given RUNNER.",
- "(" + keyword_display(RUNNERS) + ")") do |r|
- @runner = r
- end
-
- if(@standalone)
- o.on('-b', '--basedir=DIR', "Base directory of test suites.") do |b|
- @base = b
- end
-
- o.on('-w', '--workdir=DIR', "Working directory to run tests.") do |w|
- @workdir = w
- end
-
- o.on('-a', '--add=TORUN', Array,
- "Add TORUN to the list of things to run;",
- "can be a file or a directory.") do |a|
- @to_run.concat(a)
- end
-
- @pattern = []
- o.on('-p', '--pattern=PATTERN', Regexp,
- "Match files to collect against PATTERN.") do |e|
- @pattern << e
- end
-
- @exclude = []
- o.on('-x', '--exclude=PATTERN', Regexp,
- "Ignore files to collect against PATTERN.") do |e|
- @exclude << e
- end
- end
-
- o.on('-n', '--name=NAME', String,
- "Runs tests matching NAME.",
- "(patterns may be used).") do |n|
- n = (%r{\A/(.*)/\Z} =~ n ? Regexp.new($1) : n)
- case n
- when Regexp
- @filters << proc{|t| n =~ t.method_name ? true : nil}
- else
- @filters << proc{|t| n == t.method_name ? true : nil}
- end
- end
-
- o.on('-t', '--testcase=TESTCASE', String,
- "Runs tests in TestCases matching TESTCASE.",
- "(patterns may be used).") do |n|
- n = (%r{\A/(.*)/\Z} =~ n ? Regexp.new($1) : n)
- case n
- when Regexp
- @filters << proc{|t| n =~ t.class.name ? true : nil}
- else
- @filters << proc{|t| n == t.class.name ? true : nil}
- end
- end
-
- o.on('-I', "--load-path=DIR[#{File::PATH_SEPARATOR}DIR...]",
- "Appends directory list to $LOAD_PATH.") do |dirs|
- $LOAD_PATH.concat(dirs.split(File::PATH_SEPARATOR))
- end
-
- o.on('-v', '--verbose=[LEVEL]', OUTPUT_LEVELS,
- "Set the output level (default is verbose).",
- "(" + keyword_display(OUTPUT_LEVELS) + ")") do |l|
- @output_level = l || UI::VERBOSE
- end
-
- o.on('--',
- "Stop processing options so that the",
- "remaining options will be passed to the",
- "test."){o.terminate}
-
- o.on('-h', '--help', 'Display this help.'){puts o; exit}
-
- o.on_tail
- o.on_tail('Deprecated options:')
-
- o.on_tail('--console', 'Console runner (use --runner).') do
- warn("Deprecated option (--console).")
- @runner = RUNNERS[:console]
- end
-
- o.on_tail('--gtk', 'GTK runner (use --runner).') do
- warn("Deprecated option (--gtk).")
- @runner = RUNNERS[:gtk]
- end
-
- o.on_tail('--fox', 'Fox runner (use --runner).') do
- warn("Deprecated option (--fox).")
- @runner = RUNNERS[:fox]
- end
-
- o.on_tail
- end
- end
-
- def keyword_display(array)
- list = array.collect {|e, *| e.to_s}
- Array === array or list.sort!
- list.collect {|e| e.sub(/^(.)([A-Za-z]+)(?=\w*$)/, '\\1[\\2]')}.join(", ")
- end
-
- def run
- @suite = @collector[self]
- result = @runner[self] or return false
- Dir.chdir(@workdir) if @workdir
- result.run(@suite, @output_level).passed?
- end
- end
- end
-end
diff --git a/lib/test/unit/collector.rb b/lib/test/unit/collector.rb
deleted file mode 100644
index 9e9e654147..0000000000
--- a/lib/test/unit/collector.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-module Test
- module Unit
- module Collector
- def initialize
- @filters = []
- end
-
- def filter=(filters)
- @filters = case(filters)
- when Proc
- [filters]
- when Array
- filters
- end
- end
-
- def add_suite(destination, suite)
- to_delete = suite.tests.find_all{|t| !include?(t)}
- to_delete.each{|t| suite.delete(t)}
- destination << suite unless(suite.size == 0)
- end
-
- def include?(test)
- return true if(@filters.empty?)
- @filters.each do |filter|
- result = filter[test]
- if(result.nil?)
- next
- elsif(!result)
- return false
- else
- return true
- end
- end
- true
- end
-
- def sort(suites)
- suites.sort_by{|s| s.name}
- end
- end
- end
-end
diff --git a/lib/test/unit/collector/dir.rb b/lib/test/unit/collector/dir.rb
deleted file mode 100644
index 9c311b72ce..0000000000
--- a/lib/test/unit/collector/dir.rb
+++ /dev/null
@@ -1,113 +0,0 @@
-require 'test/unit/testsuite'
-require 'test/unit/collector'
-
-module Test
- module Unit
- module Collector
- class Dir
- include Collector
-
- attr_reader :pattern, :exclude
- attr_accessor :base
-
- def initialize(dir=::Dir, file=::File, object_space=nil, req=nil)
- super()
- @dir = dir
- @file = file
- @object_space = object_space
- @req = req
- @pattern = [/\btest_.*\.rb\Z/m]
- @exclude = []
- end
-
- def collect(*from)
- basedir = @base
- $:.push(basedir) if basedir
- if(from.empty?)
- recursive_collect('.', find_test_cases)
- elsif(from.size == 1)
- recursive_collect(from.first, find_test_cases)
- else
- suites = []
- from.each do |f|
- suite = recursive_collect(f, find_test_cases)
- suites << suite unless(suite.tests.empty?)
- end
- suite = TestSuite.new("[#{from.join(', ')}]")
- sort(suites).each{|s| suite << s}
- suite
- end
- ensure
- $:.delete_at($:.rindex(basedir)) if basedir
- end
-
- def find_test_cases(ignore=[])
- cases = []
- if @object_space
- @object_space.each_object(Class) do |c|
- cases << c if(c < TestCase && !ignore.include?(c))
- end
- else
- TestCase::DECENDANT_CLASSES.each do |c|
- cases << c if !ignore.include?(c)
- end
- end
- ignore.concat(cases)
- cases
- end
-
- def recursive_collect(name, already_gathered)
- sub_suites = []
- path = realdir(name)
- if @file.directory?(path)
- dir_name = name unless name == '.'
- @dir.entries(path).each do |e|
- next if(e == '.' || e == '..')
- e_name = dir_name ? @file.join(dir_name, e) : e
- if @file.directory?(realdir(e_name))
- next if /\A(?:CVS|\.svn)\z/ =~ e
- sub_suite = recursive_collect(e_name, already_gathered)
- sub_suites << sub_suite unless(sub_suite.empty?)
- else
- next if /~\z/ =~ e_name or /\A\.\#/ =~ e
- if @pattern and !@pattern.empty?
- next unless @pattern.any? {|pat| pat =~ e_name}
- end
- if @exclude and !@exclude.empty?
- next if @exclude.any? {|pat| pat =~ e_name}
- end
- collect_file(e_name, sub_suites, already_gathered)
- end
- end
- else
- collect_file(name, sub_suites, already_gathered)
- end
- suite = TestSuite.new(@file.basename(name))
- sort(sub_suites).each{|s| suite << s}
- suite
- end
-
- def collect_file(name, suites, already_gathered)
- dir = @file.dirname(@file.expand_path(name, @base))
- $:.unshift(dir)
- if(@req)
- @req.require(name)
- else
- require(name)
- end
- find_test_cases(already_gathered).each{|t| add_suite(suites, t.suite)}
- ensure
- $:.delete_at($:.index(dir)) if dir
- end
-
- def realdir(path)
- if @base
- @file.join(@base, path)
- else
- path
- end
- end
- end
- end
- end
-end
diff --git a/lib/test/unit/collector/objectspace.rb b/lib/test/unit/collector/objectspace.rb
deleted file mode 100644
index 4a768c721e..0000000000
--- a/lib/test/unit/collector/objectspace.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# Author:: Nathaniel Talbott.
-# Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
-# License:: Ruby license.
-
-require 'test/unit/collector'
-
-module Test
- module Unit
- module Collector
- class ObjectSpace
- include Test::Unit::Collector
-
- NAME = 'collected from the subclasses of TestCase'
-
- def initialize(source=nil)
- super()
- @source = source
- end
-
- def collect(name=NAME)
- suite = TestSuite.new(name)
- sub_suites = []
- if @source
- @source.each_object(Class) do |klass|
- if(Test::Unit::TestCase > klass)
- add_suite(sub_suites, klass.suite)
- end
- end
- else
- TestCase::DECENDANT_CLASSES.each do |klass|
- add_suite(sub_suites, klass.suite)
- end
- end
- sort(sub_suites).each{|s| suite << s}
- suite
- end
- end
- end
- end
-end
diff --git a/lib/test/unit/error.rb b/lib/test/unit/error.rb
deleted file mode 100644
index 43a813f7d1..0000000000
--- a/lib/test/unit/error.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-#--
-#
-# Author:: Nathaniel Talbott.
-# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
-# License:: Ruby license.
-
-require 'test/unit/util/backtracefilter'
-
-module Test
- module Unit
-
- # Encapsulates an error in a test. Created by
- # Test::Unit::TestCase when it rescues an exception thrown
- # during the processing of a test.
- class Error
- include Util::BacktraceFilter
-
- attr_reader(:test_name, :exception)
-
- SINGLE_CHARACTER = 'E'
-
- # Creates a new Error with the given test_name and
- # exception.
- def initialize(test_name, exception)
- @test_name = test_name
- @exception = exception
- end
-
- # Returns a single character representation of an error.
- def single_character_display
- SINGLE_CHARACTER
- end
-
- # Returns the message associated with the error.
- def message
- "#{@exception.class.name}: #{@exception.message}"
- end
-
- # Returns a brief version of the error description.
- def short_display
- "#@test_name: #{message.split("\n")[0]}"
- end
-
- # Returns a verbose version of the error description.
- def long_display
- backtrace = filter_backtrace(@exception.backtrace).join("\n ")
- "Error:\n#@test_name:\n#{message}\n #{backtrace}"
- end
-
- # Overridden to return long_display.
- def to_s
- long_display
- end
- end
- end
-end
diff --git a/lib/test/unit/failure.rb b/lib/test/unit/failure.rb
deleted file mode 100644
index 832c99857c..0000000000
--- a/lib/test/unit/failure.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-#--
-#
-# Author:: Nathaniel Talbott.
-# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
-# License:: Ruby license.
-
-module Test
- module Unit
-
- # Encapsulates a test failure. Created by Test::Unit::TestCase
- # when an assertion fails.
- class Failure
- attr_reader :test_name, :location, :message
-
- SINGLE_CHARACTER = 'F'
-
- # Creates a new Failure with the given location and
- # message.
- def initialize(test_name, location, message)
- @test_name = test_name
- @location = location
- @message = message
- end
-
- # Returns a single character representation of a failure.
- def single_character_display
- SINGLE_CHARACTER
- end
-
- # Returns a brief version of the error description.
- def short_display
- "#@test_name: #{@message.split("\n")[0]}"
- end
-
- # Returns a verbose version of the error description.
- def long_display
- location_display = if(location.size == 1)
- location[0].sub(/\A(.+:\d+).*/, ' [\\1]')
- else
- "\n [#{location.join("\n ")}]"
- end
- "Failure:\n#@test_name#{location_display}:\n#@message"
- end
-
- # Overridden to return long_display.
- def to_s
- long_display
- end
- end
- end
-end
diff --git a/lib/test/unit/testcase.rb b/lib/test/unit/testcase.rb
deleted file mode 100644
index 3cf80d2256..0000000000
--- a/lib/test/unit/testcase.rb
+++ /dev/null
@@ -1,163 +0,0 @@
-#--
-#
-# Author:: Nathaniel Talbott.
-# Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
-# License:: Ruby license.
-
-require 'test/unit/assertions'
-require 'test/unit/failure'
-require 'test/unit/error'
-require 'test/unit/testsuite'
-require 'test/unit/assertionfailederror'
-require 'test/unit/util/backtracefilter'
-
-module Test
- module Unit
-
- # Ties everything together. If you subclass and add your own
- # test methods, it takes care of making them into tests and
- # wrapping those tests into a suite. It also does the
- # nitty-gritty of actually running an individual test and
- # collecting its results into a Test::Unit::TestResult object.
- class TestCase
- include Assertions
- include Util::BacktraceFilter
-
- attr_reader :method_name
-
- STARTED = name + "::STARTED"
- FINISHED = name + "::FINISHED"
-
- ##
- # These exceptions are not caught by #run.
-
- PASSTHROUGH_EXCEPTIONS = [NoMemoryError, SignalException, Interrupt,
- SystemExit]
-
- DECENDANT_CLASSES = []
- def self.inherited(decendant)
- DECENDANT_CLASSES << decendant
- end
-
- # Creates a new instance of the fixture for running the
- # test represented by test_method_name.
- def initialize(test_method_name)
- unless(respond_to?(test_method_name) && method(test_method_name).arity == 0)
- throw :invalid_test
- end
- @method_name = test_method_name
- @test_passed = true
- end
-
- # Rolls up all of the test* methods in the fixture into
- # one suite, creating a new instance of the fixture for
- # each method.
- def self.suite
- method_names = public_instance_methods(true).map { |m| m.to_s }
- tests = method_names.delete_if {|method_name| method_name !~ /^test./}
- suite = TestSuite.new(name)
- tests.sort.each do
- |test|
- catch(:invalid_test) do
- suite << new(test)
- end
- end
- if (suite.empty?)
- catch(:invalid_test) do
- suite << new(:default_test)
- end
- end
- return suite
- end
-
- # Runs the individual test method represented by this
- # instance of the fixture, collecting statistics, failures
- # and errors in result.
- def run(result)
- yield(STARTED, name)
- @_result = result
- begin
- setup
- __send__(@method_name)
- rescue AssertionFailedError => e
- add_failure(e.message, e.backtrace)
- rescue Exception
- raise if PASSTHROUGH_EXCEPTIONS.include? $!.class
- add_error($!)
- ensure
- begin
- teardown
- rescue AssertionFailedError => e
- add_failure(e.message, e.backtrace)
- rescue Exception
- raise if PASSTHROUGH_EXCEPTIONS.include? $!.class
- add_error($!)
- end
- end
- result.add_run
- yield(FINISHED, name)
- end
-
- # Called before every test method runs. Can be used
- # to set up fixture information.
- def setup
- end
-
- # Called after every test method runs. Can be used to tear
- # down fixture information.
- def teardown
- end
-
- def default_test
- flunk("No tests were specified")
- end
-
- # Returns whether this individual test passed or
- # not. Primarily for use in teardown so that artifacts
- # can be left behind if the test fails.
- def passed?
- return @test_passed
- end
- private :passed?
-
- def size # :nodoc:
- 1
- end
-
- def add_assertion # :nodoc:
- @_result.add_assertion
- end
- private :add_assertion
-
- def add_failure(message, all_locations=caller()) # :nodoc:
- @test_passed = false
- @_result.add_failure(Failure.new(name, filter_backtrace(all_locations), message))
- end
- private :add_failure
-
- def add_error(exception) # :nodoc:
- @test_passed = false
- @_result.add_error(Error.new(name, exception))
- end
- private :add_error
-
- # Returns a human-readable name for the specific test that
- # this instance of TestCase represents.
- def name
- "#{@method_name}(#{self.class.name})"
- end
-
- # Overridden to return #name.
- def to_s
- name
- end
-
- # It's handy to be able to compare TestCase instances.
- def ==(other)
- return false unless(other.kind_of?(self.class))
- return false unless(@method_name == other.method_name)
- self.class == other.class
- end
- end
- end
-end
diff --git a/lib/test/unit/testresult.rb b/lib/test/unit/testresult.rb
deleted file mode 100644
index 3fe9b7c57f..0000000000
--- a/lib/test/unit/testresult.rb
+++ /dev/null
@@ -1,81 +0,0 @@
-#--
-#
-# Author:: Nathaniel Talbott.
-# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
-# License:: Ruby license.
-
-require 'test/unit/util/observable'
-
-module Test
- module Unit
-
- # Collects Test::Unit::Failure and Test::Unit::Error so that
- # they can be displayed to the user. To this end, observers
- # can be added to it, allowing the dynamic updating of, say, a
- # UI.
- class TestResult
- include Util::Observable
-
- CHANGED = "CHANGED"
- FAULT = "FAULT"
-
- attr_reader(:run_count, :assertion_count)
-
- # Constructs a new, empty TestResult.
- def initialize
- @run_count, @assertion_count = 0, 0
- @failures, @errors = Array.new, Array.new
- end
-
- # Records a test run.
- def add_run
- @run_count += 1
- notify_listeners(CHANGED, self)
- end
-
- # Records a Test::Unit::Failure.
- def add_failure(failure)
- @failures << failure
- notify_listeners(FAULT, failure)
- notify_listeners(CHANGED, self)
- end
-
- # Records a Test::Unit::Error.
- def add_error(error)
- @errors << error
- notify_listeners(FAULT, error)
- notify_listeners(CHANGED, self)
- end
-
- # Records an individual assertion.
- def add_assertion
- @assertion_count += 1
- notify_listeners(CHANGED, self)
- end
-
- # Returns a string contain the recorded runs, assertions,
- # failures and errors in this TestResult.
- def to_s
- "#{run_count} tests, #{assertion_count} assertions, #{failure_count} failures, #{error_count} errors"
- end
-
- # Returns whether or not this TestResult represents
- # successful completion.
- def passed?
- return @failures.empty? && @errors.empty?
- end
-
- # Returns the number of failures this TestResult has
- # recorded.
- def failure_count
- return @failures.size
- end
-
- # Returns the number of errors this TestResult has
- # recorded.
- def error_count
- return @errors.size
- end
- end
- end
-end
diff --git a/lib/test/unit/testsuite.rb b/lib/test/unit/testsuite.rb
deleted file mode 100644
index 6fea976c50..0000000000
--- a/lib/test/unit/testsuite.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-#--
-#
-# Author:: Nathaniel Talbott.
-# Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
-# License:: Ruby license.
-
-module Test
- module Unit
-
- # A collection of tests which can be #run.
- #
- # Note: It is easy to confuse a TestSuite instance with
- # something that has a static suite method; I know because _I_
- # have trouble keeping them straight. Think of something that
- # has a suite method as simply providing a way to get a
- # meaningful TestSuite instance.
- class TestSuite
- attr_reader :name, :tests
-
- STARTED = name + "::STARTED"
- FINISHED = name + "::FINISHED"
-
- # Creates a new TestSuite with the given name.
- def initialize(name="Unnamed TestSuite")
- @name = name
- @tests = []
- end
-
- # Runs the tests and/or suites contained in this
- # TestSuite.
- def run(result, &progress_block)
- yield(STARTED, name)
- @tests.each do |test|
- test.run(result, &progress_block)
- end
- yield(FINISHED, name)
- end
-
- # Adds the test to the suite.
- def <<(test)
- @tests << test
- self
- end
-
- def delete(test)
- @tests.delete(test)
- end
-
- # Retuns the rolled up number of tests in this suite;
- # i.e. if the suite contains other suites, it counts the
- # tests within those suites, not the suites themselves.
- def size
- total_size = 0
- @tests.each { |test| total_size += test.size }
- total_size
- end
-
- def empty?
- tests.empty?
- end
-
- # Overridden to return the name given the suite at
- # creation.
- def to_s
- @name
- end
-
- # It's handy to be able to compare TestSuite instances.
- def ==(other)
- return false unless(other.kind_of?(self.class))
- return false unless(@name == other.name)
- @tests == other.tests
- end
- end
- end
-end
diff --git a/lib/test/unit/ui/console/testrunner.rb b/lib/test/unit/ui/console/testrunner.rb
deleted file mode 100644
index b6475c0037..0000000000
--- a/lib/test/unit/ui/console/testrunner.rb
+++ /dev/null
@@ -1,130 +0,0 @@
-#--
-#
-# Author:: Nathaniel Talbott.
-# Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
-# License:: Ruby license.
-
-require 'test/unit/ui/testrunnermediator'
-require 'test/unit/ui/testrunnerutilities'
-
-module Test
- module Unit
- module UI
- module Console # :nodoc:
-
- # Runs a Test::Unit::TestSuite on the console.
- class TestRunner
- extend TestRunnerUtilities
-
- # Creates a new TestRunner for running the passed
- # suite. If quiet_mode is true, the output while
- # running is limited to progress dots, errors and
- # failures, and the final result. io specifies
- # where runner output should go to; defaults to
- # STDOUT.
- def initialize(suite, output_level=NORMAL, io=STDOUT)
- if (suite.respond_to?(:suite))
- @suite = suite.suite
- else
- @suite = suite
- end
- @output_level = output_level
- @io = io
- @already_outputted = false
- @faults = []
- end
-
- # Begins the test run.
- def start
- setup_mediator
- attach_to_mediator
- return start_mediator
- end
-
- private
- def setup_mediator # :nodoc:
- @mediator = create_mediator(@suite)
- suite_name = @suite.to_s
- if ( @suite.kind_of?(Module) )
- suite_name = @suite.name
- end
- output("Loaded suite #{suite_name}")
- end
-
- def create_mediator(suite) # :nodoc:
- return TestRunnerMediator.new(suite)
- end
-
- def attach_to_mediator # :nodoc:
- @mediator.add_listener(TestResult::FAULT, &method(:add_fault))
- @mediator.add_listener(TestRunnerMediator::STARTED, &method(:started))
- @mediator.add_listener(TestRunnerMediator::FINISHED, &method(:finished))
- @mediator.add_listener(TestCase::STARTED, &method(:test_started))
- @mediator.add_listener(TestCase::FINISHED, &method(:test_finished))
- end
-
- def start_mediator # :nodoc:
- return @mediator.run_suite
- end
-
- def add_fault(fault) # :nodoc:
- @faults << fault
- output_single(fault.single_character_display, PROGRESS_ONLY)
- @already_outputted = true
- end
-
- def started(result)
- @result = result
- output("Started")
- end
-
- def finished(elapsed_time)
- nl
- output("Finished in #{elapsed_time} seconds.")
- @faults.each_with_index do |fault, index|
- nl
- output("%3d) %s" % [index + 1, fault.long_display])
- end
- nl
- output(@result)
- end
-
- def test_started(name)
- $program_name = $0
- alias $0 $program_name
- $PROGRAM_NAME += "\0#{name}"
- output_single(name + ": ", VERBOSE)
- end
-
- def test_finished(name)
- output_single(".", PROGRESS_ONLY) unless (@already_outputted)
- nl(VERBOSE)
- @already_outputted = false
- end
-
- def nl(level=NORMAL)
- output("", level)
- end
-
- def output(something, level=NORMAL)
- @io.puts(something) if (output?(level))
- @io.flush
- end
-
- def output_single(something, level=NORMAL)
- @io.write(something) if (output?(level))
- @io.flush
- end
-
- def output?(level)
- level <= @output_level
- end
- end
- end
- end
- end
-end
-
-if __FILE__ == $0
- Test::Unit::UI::Console::TestRunner.start_command_line_test
-end
diff --git a/lib/test/unit/ui/fox/testrunner.rb b/lib/test/unit/ui/fox/testrunner.rb
deleted file mode 100644
index 34a8ff1288..0000000000
--- a/lib/test/unit/ui/fox/testrunner.rb
+++ /dev/null
@@ -1,268 +0,0 @@
-#--
-#
-# Author:: Nathaniel Talbott.
-# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
-# License:: Ruby license.
-
-require 'fox'
-require 'test/unit/ui/testrunnermediator'
-require 'test/unit/ui/testrunnerutilities'
-
-include Fox
-
-module Test
- module Unit
- module UI
- module Fox # :nodoc:
-
- # Runs a Test::Unit::TestSuite in a Fox UI. Obviously,
- # this one requires you to have Fox
- # (http://www.fox-toolkit.org/fox.html) and the Ruby
- # Fox extension (http://fxruby.sourceforge.net/)
- # installed.
- class TestRunner
-
- extend TestRunnerUtilities
-
- RED_STYLE = FXRGBA(0xFF,0,0,0xFF) #0xFF000000
- GREEN_STYLE = FXRGBA(0,0xFF,0,0xFF) #0x00FF0000
-
- # Creates a new TestRunner for running the passed
- # suite.
- def initialize(suite, output_level = NORMAL)
- if (suite.respond_to?(:suite))
- @suite = suite.suite
- else
- @suite = suite
- end
-
- @result = nil
- @red = false
- end
-
- # Begins the test run.
- def start
- setup_ui
- setup_mediator
- attach_to_mediator
- start_ui
- @result
- end
-
- def setup_mediator # :nodoc:
- @mediator = TestRunnerMediator.new(@suite)
- suite_name = @suite.to_s
- if ( @suite.kind_of?(Module) )
- suite_name = @suite.name
- end
- @suite_name_entry.text = suite_name
- end
-
- def attach_to_mediator # :nodoc:
- @mediator.add_listener(TestRunnerMediator::RESET, &method(:reset_ui))
- @mediator.add_listener(TestResult::FAULT, &method(:add_fault))
- @mediator.add_listener(TestResult::CHANGED, &method(:result_changed))
- @mediator.add_listener(TestRunnerMediator::STARTED, &method(:started))
- @mediator.add_listener(TestCase::STARTED, &method(:test_started))
- @mediator.add_listener(TestRunnerMediator::FINISHED, &method(:finished))
- end
-
- def start_ui # :nodoc:
- @application.create
- @window.show(PLACEMENT_SCREEN)
- @application.addTimeout(1) do
- @mediator.run_suite
- end
- @application.run
- end
-
- def stop # :nodoc:
- @application.exit(0)
- end
-
- def reset_ui(count) # :nodoc:
- @test_progress_bar.barColor = GREEN_STYLE
- @test_progress_bar.total = count
- @test_progress_bar.progress = 0
- @red = false
-
- @test_count_label.text = "0"
- @assertion_count_label.text = "0"
- @failure_count_label.text = "0"
- @error_count_label.text = "0"
-
- @fault_list.clearItems
- end
-
- def add_fault(fault) # :nodoc:
- if ( ! @red )
- @test_progress_bar.barColor = RED_STYLE
- @red = true
- end
- item = FaultListItem.new(fault)
- @fault_list.appendItem(item)
- end
-
- def show_fault(fault) # :nodoc:
- raw_show_fault(fault.long_display)
- end
-
- def raw_show_fault(string) # :nodoc:
- @detail_text.setText(string)
- end
-
- def clear_fault # :nodoc:
- raw_show_fault("")
- end
-
- def result_changed(result) # :nodoc:
- @test_progress_bar.progress = result.run_count
-
- @test_count_label.text = result.run_count.to_s
- @assertion_count_label.text = result.assertion_count.to_s
- @failure_count_label.text = result.failure_count.to_s
- @error_count_label.text = result.error_count.to_s
-
- # repaint now!
- @info_panel.repaint
- @application.flush
- end
-
- def started(result) # :nodoc:
- @result = result
- output_status("Started...")
- end
-
- def test_started(test_name)
- output_status("Running #{test_name}...")
- end
-
- def finished(elapsed_time)
- output_status("Finished in #{elapsed_time} seconds")
- end
-
- def output_status(string)
- @status_entry.text = string
- @status_entry.repaint
- end
-
- def setup_ui # :nodoc:
- @application = create_application
- create_tooltip(@application)
-
- @window = create_window(@application)
-
- @status_entry = create_entry(@window)
-
- main_panel = create_main_panel(@window)
-
- suite_panel = create_suite_panel(main_panel)
- create_label(suite_panel, "Suite:")
- @suite_name_entry = create_entry(suite_panel)
- create_button(suite_panel, "&Run\tRun the current suite", proc { @mediator.run_suite })
-
- @test_progress_bar = create_progress_bar(main_panel)
-
- @info_panel = create_info_panel(main_panel)
- create_label(@info_panel, "Tests:")
- @test_count_label = create_label(@info_panel, "0")
- create_label(@info_panel, "Assertions:")
- @assertion_count_label = create_label(@info_panel, "0")
- create_label(@info_panel, "Failures:")
- @failure_count_label = create_label(@info_panel, "0")
- create_label(@info_panel, "Errors:")
- @error_count_label = create_label(@info_panel, "0")
-
- list_panel = create_list_panel(main_panel)
- @fault_list = create_fault_list(list_panel)
-
- detail_panel = create_detail_panel(main_panel)
- @detail_text = create_text(detail_panel)
- end
-
- def create_application # :nodoc:
- app = FXApp.new("TestRunner", "Test::Unit")
- app.init([])
- app
- end
-
- def create_window(app)
- FXMainWindow.new(app, "Test::Unit TestRunner", nil, nil, DECOR_ALL, 0, 0, 450)
- end
-
- def create_tooltip(app)
- FXTooltip.new(app)
- end
-
- def create_main_panel(parent) # :nodoc:
- panel = FXVerticalFrame.new(parent, LAYOUT_FILL_X | LAYOUT_FILL_Y)
- panel.vSpacing = 10
- panel
- end
-
- def create_suite_panel(parent) # :nodoc:
- FXHorizontalFrame.new(parent, LAYOUT_SIDE_LEFT | LAYOUT_FILL_X)
- end
-
- def create_button(parent, text, action) # :nodoc:
- FXButton.new(parent, text).connect(SEL_COMMAND, &action)
- end
-
- def create_progress_bar(parent) # :nodoc:
- FXProgressBar.new(parent, nil, 0, PROGRESSBAR_NORMAL | LAYOUT_FILL_X)
- end
-
- def create_info_panel(parent) # :nodoc:
- FXMatrix.new(parent, 1, MATRIX_BY_ROWS | LAYOUT_FILL_X)
- end
-
- def create_label(parent, text)
- FXLabel.new(parent, text, nil, JUSTIFY_CENTER_X | LAYOUT_FILL_COLUMN)
- end
-
- def create_list_panel(parent) # :nodoc:
- FXHorizontalFrame.new(parent, LAYOUT_FILL_X | FRAME_SUNKEN | FRAME_THICK)
- end
-
- def create_fault_list(parent) # :nodoc:
- list = FXList.new(parent, 10, nil, 0, LIST_SINGLESELECT | LAYOUT_FILL_X) #, 0, 0, 0, 150)
- list.connect(SEL_COMMAND) do |sender, sel, ptr|
- if sender.retrieveItem(sender.currentItem).selected?
- show_fault(sender.retrieveItem(sender.currentItem).fault)
- else
- clear_fault
- end
- end
- list
- end
-
- def create_detail_panel(parent) # :nodoc:
- FXHorizontalFrame.new(parent, LAYOUT_FILL_X | LAYOUT_FILL_Y | FRAME_SUNKEN | FRAME_THICK)
- end
-
- def create_text(parent) # :nodoc:
- FXText.new(parent, nil, 0, TEXT_READONLY | LAYOUT_FILL_X | LAYOUT_FILL_Y)
- end
-
- def create_entry(parent) # :nodoc:
- entry = FXTextField.new(parent, 30, nil, 0, TEXTFIELD_NORMAL | LAYOUT_SIDE_BOTTOM | LAYOUT_FILL_X)
- entry.disable
- entry
- end
- end
-
- class FaultListItem < FXListItem # :nodoc: all
- attr_reader(:fault)
- def initialize(fault)
- super(fault.short_display)
- @fault = fault
- end
- end
- end
- end
- end
-end
-
-if __FILE__ == $0
- Test::Unit::UI::Fox::TestRunner.start_command_line_test
-end
diff --git a/lib/test/unit/ui/gtk/testrunner.rb b/lib/test/unit/ui/gtk/testrunner.rb
deleted file mode 100644
index c63cc6a39b..0000000000
--- a/lib/test/unit/ui/gtk/testrunner.rb
+++ /dev/null
@@ -1,416 +0,0 @@
-#--
-#
-# Author:: Nathaniel Talbott.
-# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
-# License:: Ruby license.
-
-require 'gtk'
-require 'test/unit/ui/testrunnermediator'
-require 'test/unit/ui/testrunnerutilities'
-
-module Test
- module Unit
- module UI
- module GTK # :nodoc:
-
- # Runs a Test::Unit::TestSuite in a Gtk UI. Obviously,
- # this one requires you to have Gtk
- # (http://www.gtk.org/) and the Ruby Gtk extension
- # (http://ruby-gnome.sourceforge.net/) installed.
- class TestRunner
- extend TestRunnerUtilities
-
- # Creates a new TestRunner for running the passed
- # suite.
- def initialize(suite, output_level = NORMAL)
- if (suite.respond_to?(:suite))
- @suite = suite.suite
- else
- @suite = suite
- end
- @result = nil
-
- @runner = Thread.current
- @restart_signal = Class.new(Exception)
- @viewer = Thread.start do
- @runner.join rescue @runner.run
- Gtk.main
- end
- @viewer.join rescue nil # wait deadlock to handshake
- end
-
- # Begins the test run.
- def start
- setup_mediator
- setup_ui
- attach_to_mediator
- start_ui
- @result
- end
-
- private
- def setup_mediator # :nodoc:
- @mediator = TestRunnerMediator.new(@suite)
- suite_name = @suite.to_s
- if ( @suite.kind_of?(Module) )
- suite_name = @suite.name
- end
- suite_name_entry.set_text(suite_name)
- end
-
- def attach_to_mediator # :nodoc:
- run_button.signal_connect("clicked", nil, &method(:run_test))
- @mediator.add_listener(TestRunnerMediator::RESET, &method(:reset_ui))
- @mediator.add_listener(TestResult::FAULT, &method(:add_fault))
- @mediator.add_listener(TestResult::CHANGED, &method(:result_changed))
- @mediator.add_listener(TestRunnerMediator::STARTED, &method(:started))
- @mediator.add_listener(TestCase::STARTED, &method(:test_started))
- @mediator.add_listener(TestCase::FINISHED, &method(:test_finished))
- @mediator.add_listener(TestRunnerMediator::FINISHED, &method(:finished))
- end
-
- def run_test(*)
- @runner.raise(@restart_signal)
- end
-
- def start_ui # :nodoc:
- @viewer.run
- running = false
- begin
- loop do
- if (running ^= true)
- run_button.child.text = "Stop"
- @mediator.run_suite
- else
- run_button.child.text = "Run"
- @viewer.join
- break
- end
- end
- rescue @restart_signal
- retry
- rescue
- end
- end
-
- def stop(*) # :nodoc:
- Gtk.main_quit
- end
-
- def reset_ui(count) # :nodoc:
- test_progress_bar.set_style(green_style)
- test_progress_bar.configure(0, 0, count)
- @red = false
-
- run_count_label.set_text("0")
- assertion_count_label.set_text("0")
- failure_count_label.set_text("0")
- error_count_label.set_text("0")
-
- fault_list.remove_items(fault_list.children)
- end
-
- def add_fault(fault) # :nodoc:
- if ( ! @red )
- test_progress_bar.set_style(red_style)
- @red = true
- end
- item = FaultListItem.new(fault)
- item.show
- fault_list.append_items([item])
- end
-
- def show_fault(fault) # :nodoc:
- raw_show_fault(fault.long_display)
- end
-
- def raw_show_fault(string) # :nodoc:
- fault_detail_label.set_text(string)
- outer_detail_sub_panel.queue_resize
- end
-
- def clear_fault # :nodoc:
- raw_show_fault("")
- end
-
- def result_changed(result) # :nodoc:
- run_count_label.set_text(result.run_count.to_s)
- assertion_count_label.set_text(result.assertion_count.to_s)
- failure_count_label.set_text(result.failure_count.to_s)
- error_count_label.set_text(result.error_count.to_s)
- end
-
- def started(result) # :nodoc:
- @result = result
- output_status("Started...")
- end
-
- def test_started(test_name)
- output_status("Running #{test_name}...")
- end
-
- def test_finished(test_name)
- test_progress_bar.set_value(test_progress_bar.get_value + 1)
- end
-
- def finished(elapsed_time)
- output_status("Finished in #{elapsed_time} seconds")
- end
-
- def output_status(string) # :nodoc:
- status_entry.set_text(string)
- end
-
- def setup_ui # :nodoc:
- main_window.signal_connect("destroy", nil, &method(:stop))
- main_window.show_all
- fault_list.signal_connect("select-child", nil) {
- | list, item, data |
- show_fault(item.fault)
- }
- fault_list.signal_connect("unselect-child", nil) {
- clear_fault
- }
- @red = false
- end
-
- def main_window # :nodoc:
- lazy_initialize(:main_window) {
- @main_window = Gtk::Window.new(Gtk::WINDOW_TOPLEVEL)
- @main_window.set_title("Test::Unit TestRunner")
- @main_window.set_usize(800, 600)
- @main_window.set_uposition(20, 20)
- @main_window.set_policy(true, true, false)
- @main_window.add(main_panel)
- }
- end
-
- def main_panel # :nodoc:
- lazy_initialize(:main_panel) {
- @main_panel = Gtk::VBox.new(false, 0)
- @main_panel.pack_start(suite_panel, false, false, 0)
- @main_panel.pack_start(progress_panel, false, false, 0)
- @main_panel.pack_start(info_panel, false, false, 0)
- @main_panel.pack_start(list_panel, false, false, 0)
- @main_panel.pack_start(detail_panel, true, true, 0)
- @main_panel.pack_start(status_panel, false, false, 0)
- }
- end
-
- def suite_panel # :nodoc:
- lazy_initialize(:suite_panel) {
- @suite_panel = Gtk::HBox.new(false, 10)
- @suite_panel.border_width(10)
- @suite_panel.pack_start(Gtk::Label.new("Suite:"), false, false, 0)
- @suite_panel.pack_start(suite_name_entry, true, true, 0)
- @suite_panel.pack_start(run_button, false, false, 0)
- }
- end
-
- def suite_name_entry # :nodoc:
- lazy_initialize(:suite_name_entry) {
- @suite_name_entry = Gtk::Entry.new
- @suite_name_entry.set_editable(false)
- }
- end
-
- def run_button # :nodoc:
- lazy_initialize(:run_button) {
- @run_button = Gtk::Button.new("Run")
- }
- end
-
- def progress_panel # :nodoc:
- lazy_initialize(:progress_panel) {
- @progress_panel = Gtk::HBox.new(false, 10)
- @progress_panel.border_width(10)
- @progress_panel.pack_start(test_progress_bar, true, true, 0)
- }
- end
-
- def test_progress_bar # :nodoc:
- lazy_initialize(:test_progress_bar) {
- @test_progress_bar = EnhancedProgressBar.new
- @test_progress_bar.set_usize(@test_progress_bar.allocation.width,
- info_panel.size_request.height)
- @test_progress_bar.set_style(green_style)
- }
- end
-
- def green_style # :nodoc:
- lazy_initialize(:green_style) {
- @green_style = Gtk::Style.new
- @green_style.set_bg(Gtk::STATE_PRELIGHT, 0x0000, 0xFFFF, 0x0000)
- }
- end
-
- def red_style # :nodoc:
- lazy_initialize(:red_style) {
- @red_style = Gtk::Style.new
- @red_style.set_bg(Gtk::STATE_PRELIGHT, 0xFFFF, 0x0000, 0x0000)
- }
- end
-
- def info_panel # :nodoc:
- lazy_initialize(:info_panel) {
- @info_panel = Gtk::HBox.new(false, 0)
- @info_panel.border_width(10)
- @info_panel.pack_start(Gtk::Label.new("Runs:"), false, false, 0)
- @info_panel.pack_start(run_count_label, true, false, 0)
- @info_panel.pack_start(Gtk::Label.new("Assertions:"), false, false, 0)
- @info_panel.pack_start(assertion_count_label, true, false, 0)
- @info_panel.pack_start(Gtk::Label.new("Failures:"), false, false, 0)
- @info_panel.pack_start(failure_count_label, true, false, 0)
- @info_panel.pack_start(Gtk::Label.new("Errors:"), false, false, 0)
- @info_panel.pack_start(error_count_label, true, false, 0)
- }
- end
-
- def run_count_label # :nodoc:
- lazy_initialize(:run_count_label) {
- @run_count_label = Gtk::Label.new("0")
- @run_count_label.set_justify(Gtk::JUSTIFY_LEFT)
- }
- end
-
- def assertion_count_label # :nodoc:
- lazy_initialize(:assertion_count_label) {
- @assertion_count_label = Gtk::Label.new("0")
- @assertion_count_label.set_justify(Gtk::JUSTIFY_LEFT)
- }
- end
-
- def failure_count_label # :nodoc:
- lazy_initialize(:failure_count_label) {
- @failure_count_label = Gtk::Label.new("0")
- @failure_count_label.set_justify(Gtk::JUSTIFY_LEFT)
- }
- end
-
- def error_count_label # :nodoc:
- lazy_initialize(:error_count_label) {
- @error_count_label = Gtk::Label.new("0")
- @error_count_label.set_justify(Gtk::JUSTIFY_LEFT)
- }
- end
-
- def list_panel # :nodoc:
- lazy_initialize(:list_panel) {
- @list_panel = Gtk::HBox.new
- @list_panel.border_width(10)
- @list_panel.pack_start(list_scrolled_window, true, true, 0)
- }
- end
-
- def list_scrolled_window # :nodoc:
- lazy_initialize(:list_scrolled_window) {
- @list_scrolled_window = Gtk::ScrolledWindow.new
- @list_scrolled_window.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC)
- @list_scrolled_window.set_usize(@list_scrolled_window.allocation.width, 150)
- @list_scrolled_window.add_with_viewport(fault_list)
- }
- end
-
- def fault_list # :nodoc:
- lazy_initialize(:fault_list) {
- @fault_list = Gtk::List.new
- }
- end
-
- def detail_panel # :nodoc:
- lazy_initialize(:detail_panel) {
- @detail_panel = Gtk::HBox.new
- @detail_panel.border_width(10)
- @detail_panel.pack_start(detail_scrolled_window, true, true, 0)
- }
- end
-
- def detail_scrolled_window # :nodoc:
- lazy_initialize(:detail_scrolled_window) {
- @detail_scrolled_window = Gtk::ScrolledWindow.new
- @detail_scrolled_window.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC)
- @detail_scrolled_window.set_usize(400, @detail_scrolled_window.allocation.height)
- @detail_scrolled_window.add_with_viewport(outer_detail_sub_panel)
- }
- end
-
- def outer_detail_sub_panel # :nodoc:
- lazy_initialize(:outer_detail_sub_panel) {
- @outer_detail_sub_panel = Gtk::VBox.new
- @outer_detail_sub_panel.pack_start(inner_detail_sub_panel, false, false, 0)
- }
- end
-
- def inner_detail_sub_panel # :nodoc:
- lazy_initialize(:inner_detail_sub_panel) {
- @inner_detail_sub_panel = Gtk::HBox.new
- @inner_detail_sub_panel.pack_start(fault_detail_label, false, false, 0)
- }
- end
-
- def fault_detail_label # :nodoc:
- lazy_initialize(:fault_detail_label) {
- @fault_detail_label = EnhancedLabel.new("")
- style = Gtk::Style.new
- font = Gdk::Font.font_load("-*-Courier New-medium-r-normal--*-120-*-*-*-*-*-*")
- begin
- style.set_font(font)
- rescue ArgumentError; end
- @fault_detail_label.set_style(style)
- @fault_detail_label.set_justify(Gtk::JUSTIFY_LEFT)
- @fault_detail_label.set_line_wrap(false)
- }
- end
-
- def status_panel # :nodoc:
- lazy_initialize(:status_panel) {
- @status_panel = Gtk::HBox.new
- @status_panel.border_width(10)
- @status_panel.pack_start(status_entry, true, true, 0)
- }
- end
-
- def status_entry # :nodoc:
- lazy_initialize(:status_entry) {
- @status_entry = Gtk::Entry.new
- @status_entry.set_editable(false)
- }
- end
-
- def lazy_initialize(symbol) # :nodoc:
- if (!instance_eval("defined?(@#{symbol.to_s})"))
- yield
- end
- return instance_eval("@" + symbol.to_s)
- end
- end
-
- class EnhancedProgressBar < Gtk::ProgressBar # :nodoc: all
- def set_style(style)
- super
- hide
- show
- end
- end
-
- class EnhancedLabel < Gtk::Label # :nodoc: all
- def set_text(text)
- super(text.gsub(/\n\t/, "\n" + (" " * 4)))
- end
- end
-
- class FaultListItem < Gtk::ListItem # :nodoc: all
- attr_reader(:fault)
- def initialize(fault)
- super(fault.short_display)
- @fault = fault
- end
- end
- end
- end
- end
-end
-
-if __FILE__ == $0
- Test::Unit::UI::GTK::TestRunner.start_command_line_test
-end
diff --git a/lib/test/unit/ui/gtk2/testrunner.rb b/lib/test/unit/ui/gtk2/testrunner.rb
deleted file mode 100644
index 128424cf34..0000000000
--- a/lib/test/unit/ui/gtk2/testrunner.rb
+++ /dev/null
@@ -1,465 +0,0 @@
-#--
-#
-# Author:: Kenta MURATA.
-# Copyright:: Copyright (c) 2000-2002 Kenta MURATA. All rights reserved.
-# License:: Ruby license.
-
-require "gtk2"
-require "test/unit/ui/testrunnermediator"
-require "test/unit/ui/testrunnerutilities"
-
-module Test
- module Unit
- module UI
- module GTK2 # :nodoc: all
-
- Gtk.init
-
- class EnhancedLabel < Gtk::Label # :nodoc: all
- def set_text(text)
- super(text.gsub(/\n\t/, "\n "))
- end
- end
-
- class FaultList < Gtk::TreeView # :nodoc: all
- def initialize
- @faults = []
- @model = Gtk::ListStore.new(String, String)
- super(@model)
- column = Gtk::TreeViewColumn.new
- column.visible = false
- append_column(column)
- renderer = Gtk::CellRendererText.new
- column = Gtk::TreeViewColumn.new("Failures", renderer, {:text => 1})
- append_column(column)
- selection.mode = Gtk::SELECTION_SINGLE
- set_rules_hint(true)
- set_headers_visible(false)
- end # def initialize
-
- def add_fault(fault)
- @faults.push(fault)
- iter = @model.append
- iter.set_value(0, (@faults.length - 1).to_s)
- iter.set_value(1, fault.short_display)
- end # def add_fault(fault)
-
- def get_fault(iter)
- @faults[iter.get_value(0).to_i]
- end # def get_fault
-
- def clear
- model.clear
- end # def clear
- end
-
- class TestRunner
- extend TestRunnerUtilities
-
- def lazy_initialize(symbol) # :nodoc:
- if !instance_eval("defined?(@#{symbol})") then
- yield
- end
- return instance_eval("@#{symbol}")
- end
- private :lazy_initialize
-
- def status_entry # :nodoc:
- lazy_initialize(:status_entry) do
- @status_entry = Gtk::Entry.new
- @status_entry.editable = false
- end
- end
- private :status_entry
-
- def status_panel # :nodoc:
- lazy_initialize(:status_panel) do
- @status_panel = Gtk::HBox.new
- @status_panel.border_width = 10
- @status_panel.pack_start(status_entry, true, true, 0)
- end
- end
- private :status_panel
-
- def fault_detail_label # :nodoc:
- lazy_initialize(:fault_detail_label) do
- @fault_detail_label = EnhancedLabel.new("")
-# style = Gtk::Style.new
-# font = Gdk::Font.
-# font_load("-*-Courier 10 Pitch-medium-r-normal--*-120-*-*-*-*-*-*")
-# style.set_font(font)
-# @fault_detail_label.style = style
- @fault_detail_label.justify = Gtk::JUSTIFY_LEFT
- @fault_detail_label.wrap = false
- end
- end
- private :fault_detail_label
-
- def inner_detail_sub_panel # :nodoc:
- lazy_initialize(:inner_detail_sub_panel) do
- @inner_detail_sub_panel = Gtk::HBox.new
- @inner_detail_sub_panel.pack_start(fault_detail_label, false, false, 0)
- end
- end
- private :inner_detail_sub_panel
-
- def outer_detail_sub_panel # :nodoc:
- lazy_initialize(:outer_detail_sub_panel) do
- @outer_detail_sub_panel = Gtk::VBox.new
- @outer_detail_sub_panel.pack_start(inner_detail_sub_panel, false, false, 0)
- end
- end
- private :outer_detail_sub_panel
-
- def detail_scrolled_window # :nodoc:
- lazy_initialize(:detail_scrolled_window) do
- @detail_scrolled_window = Gtk::ScrolledWindow.new
- @detail_scrolled_window.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC)
- @detail_scrolled_window.
- set_size_request(400, @detail_scrolled_window.allocation.height)
- @detail_scrolled_window.add_with_viewport(outer_detail_sub_panel)
- end
- end
- private :detail_scrolled_window
-
- def detail_panel # :nodoc:
- lazy_initialize(:detail_panel) do
- @detail_panel = Gtk::HBox.new
- @detail_panel.border_width = 10
- @detail_panel.pack_start(detail_scrolled_window, true, true, 0)
- end
- end
- private :detail_panel
-
- def fault_list # :nodoc:
- lazy_initialize(:fault_list) do
- @fault_list = FaultList.new
- end
- end
- private :fault_list
-
- def list_scrolled_window # :nodoc:
- lazy_initialize(:list_scrolled_window) do
- @list_scrolled_window = Gtk::ScrolledWindow.new
- @list_scrolled_window.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC)
- @list_scrolled_window.
- set_size_request(@list_scrolled_window.allocation.width, 150)
- @list_scrolled_window.add_with_viewport(fault_list)
- end
- end
- private :list_scrolled_window
-
- def list_panel # :nodoc:
- lazy_initialize(:list_panel) do
- @list_panel = Gtk::HBox.new
- @list_panel.border_width = 10
- @list_panel.pack_start(list_scrolled_window, true, true, 0)
- end
- end
- private :list_panel
-
- def error_count_label # :nodoc:
- lazy_initialize(:error_count_label) do
- @error_count_label = Gtk::Label.new("0")
- @error_count_label.justify = Gtk::JUSTIFY_LEFT
- end
- end
- private :error_count_label
-
- def failure_count_label # :nodoc:
- lazy_initialize(:failure_count_label) do
- @failure_count_label = Gtk::Label.new("0")
- @failure_count_label.justify = Gtk::JUSTIFY_LEFT
- end
- end
- private :failure_count_label
-
- def assertion_count_label # :nodoc:
- lazy_initialize(:assertion_count_label) do
- @assertion_count_label = Gtk::Label.new("0")
- @assertion_count_label.justify = Gtk::JUSTIFY_LEFT
- end
- end
- private :assertion_count_label
-
- def run_count_label # :nodoc:
- lazy_initialize(:run_count_label) do
- @run_count_label = Gtk::Label.new("0")
- @run_count_label.justify = Gtk::JUSTIFY_LEFT
- end
- end
- private :run_count_label
-
- def info_panel # :nodoc:
- lazy_initialize(:info_panel) do
- @info_panel = Gtk::HBox.new(false, 0)
- @info_panel.border_width = 10
- @info_panel.pack_start(Gtk::Label.new("Runs:"), false, false, 0)
- @info_panel.pack_start(run_count_label, true, false, 0)
- @info_panel.pack_start(Gtk::Label.new("Assertions:"), false, false, 0)
- @info_panel.pack_start(assertion_count_label, true, false, 0)
- @info_panel.pack_start(Gtk::Label.new("Failures:"), false, false, 0)
- @info_panel.pack_start(failure_count_label, true, false, 0)
- @info_panel.pack_start(Gtk::Label.new("Errors:"), false, false, 0)
- @info_panel.pack_start(error_count_label, true, false, 0)
- end
- end # def info_panel
- private :info_panel
-
- def green_style # :nodoc:
- lazy_initialize(:green_style) do
- @green_style = Gtk::Style.new
- @green_style.set_bg(Gtk::STATE_PRELIGHT, 0x0000, 0xFFFF, 0x0000)
- end
- end # def green_style
- private :green_style
-
- def red_style # :nodoc:
- lazy_initialize(:red_style) do
- @red_style = Gtk::Style.new
- @red_style.set_bg(Gtk::STATE_PRELIGHT, 0xFFFF, 0x0000, 0x0000)
- end
- end # def red_style
- private :red_style
-
- def test_progress_bar # :nodoc:
- lazy_initialize(:test_progress_bar) {
- @test_progress_bar = Gtk::ProgressBar.new
- @test_progress_bar.fraction = 0.0
- @test_progress_bar.
- set_size_request(@test_progress_bar.allocation.width,
- info_panel.size_request[1])
- @test_progress_bar.style = green_style
- }
- end # def test_progress_bar
- private :test_progress_bar
-
- def progress_panel # :nodoc:
- lazy_initialize(:progress_panel) do
- @progress_panel = Gtk::HBox.new(false, 10)
- @progress_panel.border_width = 10
- @progress_panel.pack_start(test_progress_bar, true, true, 0)
- end
- end # def progress_panel
-
- def run_button # :nodoc:
- lazy_initialize(:run_button) do
- @run_button = Gtk::Button.new("Run")
- end
- end # def run_button
-
- def suite_name_entry # :nodoc:
- lazy_initialize(:suite_name_entry) do
- @suite_name_entry = Gtk::Entry.new
- @suite_name_entry.editable = false
- end
- end # def suite_name_entry
- private :suite_name_entry
-
- def suite_panel # :nodoc:
- lazy_initialize(:suite_panel) do
- @suite_panel = Gtk::HBox.new(false, 10)
- @suite_panel.border_width = 10
- @suite_panel.pack_start(Gtk::Label.new("Suite:"), false, false, 0)
- @suite_panel.pack_start(suite_name_entry, true, true, 0)
- @suite_panel.pack_start(run_button, false, false, 0)
- end
- end # def suite_panel
- private :suite_panel
-
- def main_panel # :nodoc:
- lazy_initialize(:main_panel) do
- @main_panel = Gtk::VBox.new(false, 0)
- @main_panel.pack_start(suite_panel, false, false, 0)
- @main_panel.pack_start(progress_panel, false, false, 0)
- @main_panel.pack_start(info_panel, false, false, 0)
- @main_panel.pack_start(list_panel, false, false, 0)
- @main_panel.pack_start(detail_panel, true, true, 0)
- @main_panel.pack_start(status_panel, false, false, 0)
- end
- end # def main_panel
- private :main_panel
-
- def main_window # :nodoc:
- lazy_initialize(:main_window) do
- @main_window = Gtk::Window.new(Gtk::Window::TOPLEVEL)
- @main_window.set_title("Test::Unit TestRunner")
- @main_window.set_default_size(800, 600)
- @main_window.set_resizable(true)
- @main_window.add(main_panel)
- end
- end # def main_window
- private :main_window
-
- def setup_ui # :nodoc:
- main_window.signal_connect("destroy", nil) { stop }
- main_window.show_all
- fault_list.selection.signal_connect("changed", nil) do
- |selection, data|
- if selection.selected then
- show_fault(fault_list.get_fault(selection.selected))
- else
- clear_fault
- end
- end
- end # def setup_ui
- private :setup_ui
-
- def output_status(string) # :nodoc:
- status_entry.set_text(string)
- end # def output_status(string)
- private :output_status
-
- def finished(elapsed_time) # :nodoc:
- test_progress_bar.fraction = 1.0
- output_status("Finished in #{elapsed_time} seconds")
- end # def finished(elapsed_time)
- private :finished
-
- def test_started(test_name) # :nodoc:
- output_status("Running #{test_name}...")
- end # def test_started(test_name)
- private :test_started
-
- def started(result) # :nodoc:
- @result = result
- output_status("Started...")
- end # def started(result)
- private :started
-
- def test_finished(result) # :nodoc:
- test_progress_bar.fraction += 1.0 / @count
- end # def test_finished(result)
-
- def result_changed(result) # :nodoc:
- run_count_label.label = result.run_count.to_s
- assertion_count_label.label = result.assertion_count.to_s
- failure_count_label.label = result.failure_count.to_s
- error_count_label.label = result.error_count.to_s
- end # def result_changed(result)
- private :result_changed
-
- def clear_fault # :nodoc:
- raw_show_fault("")
- end # def clear_fault
- private :clear_fault
-
- def raw_show_fault(string) # :nodoc:
- fault_detail_label.set_text(string)
- outer_detail_sub_panel.queue_resize
- end # def raw_show_fault(string)
- private :raw_show_fault
-
- def show_fault(fault) # :nodoc:
- raw_show_fault(fault.long_display)
- end # def show_fault(fault)
- private :show_fault
-
- def add_fault(fault) # :nodoc:
- if not @red then
- test_progress_bar.style = red_style
- @red = true
- end
- fault_list.add_fault(fault)
- end # def add_fault(fault)
- private :add_fault
-
- def reset_ui(count) # :nodoc:
- test_progress_bar.style = green_style
- test_progress_bar.fraction = 0.0
- @count = count + 1
- @red = false
-
- run_count_label.set_text("0")
- assertion_count_label.set_text("0")
- failure_count_label.set_text("0")
- error_count_label.set_text("0")
-
- fault_list.clear
- end # def reset_ui(count)
- private :reset_ui
-
- def stop # :nodoc:
- Gtk.main_quit
- end # def stop
- private :stop
-
- def run_test
- @runner.raise(@restart_signal)
- end
- private :run_test
-
- def start_ui # :nodoc
- @viewer.run
- running = false
- begin
- loop do
- if (running ^= true)
- run_button.child.text = "Stop"
- @mediator.run_suite
- else
- run_button.child.text = "Run"
- @viewer.join
- break
- end
- end
- rescue @restart_signal
- retry
- rescue
- end
- end # def start_ui
- private :start_ui
-
- def attach_to_mediator
- run_button.signal_connect("clicked", nil) { run_test }
- @mediator.add_listener(TestRunnerMediator::RESET, &method(:reset_ui))
- @mediator.add_listener(TestRunnerMediator::STARTED, &method(:started))
- @mediator.add_listener(TestRunnerMediator::FINISHED, &method(:finished))
- @mediator.add_listener(TestResult::FAULT, &method(:add_fault))
- @mediator.add_listener(TestResult::CHANGED, &method(:result_changed))
- @mediator.add_listener(TestCase::STARTED, &method(:test_started))
- @mediator.add_listener(TestCase::FINISHED, &method(:test_finished))
- end # def attach_to_mediator
- private :attach_to_mediator
-
- def setup_mediator
- @mediator = TestRunnerMediator.new(@suite)
- suite_name = @suite.to_s
- if @suite.kind_of?(Module) then
- suite_name = @suite.name
- end
- suite_name_entry.set_text(suite_name)
- end # def setup_mediator
- private :setup_mediator
-
- def start
- setup_mediator
- setup_ui
- attach_to_mediator
- start_ui
- @result
- end # def start
-
- def initialize(suite, output_level = NORMAL)
- if suite.respond_to?(:suite) then
- @suite = suite.suite
- else
- @suite = suite
- end
- @result = nil
-
- @runner = Thread.current
- @restart_signal = Class.new(Exception)
- @viewer = Thread.start do
- @runner.join rescue @runner.run
- Gtk.main
- end
- @viewer.join rescue nil # wait deadlock to handshake
- end # def initialize(suite)
-
- end # class TestRunner
-
- end # module GTK2
- end # module UI
- end # module Unit
-end # module Test
diff --git a/lib/test/unit/ui/testrunnermediator.rb b/lib/test/unit/ui/testrunnermediator.rb
deleted file mode 100644
index 07bb462cc0..0000000000
--- a/lib/test/unit/ui/testrunnermediator.rb
+++ /dev/null
@@ -1,68 +0,0 @@
-#--
-#
-# Author:: Nathaniel Talbott.
-# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
-# License:: Ruby license.
-
-require 'test/unit'
-require 'test/unit/util/observable'
-require 'test/unit/testresult'
-
-module Test
- module Unit
- module UI # :nodoc:
-
- # Provides an interface to write any given UI against,
- # hopefully making it easy to write new UIs.
- class TestRunnerMediator
- RESET = name + "::RESET"
- STARTED = name + "::STARTED"
- FINISHED = name + "::FINISHED"
-
- include Util::Observable
-
- # Creates a new TestRunnerMediator initialized to run
- # the passed suite.
- def initialize(suite)
- @suite = suite
- end
-
- # Runs the suite the TestRunnerMediator was created
- # with.
- def run_suite
- Unit.run = true
- begin_time = Time.now
- notify_listeners(RESET, @suite.size)
- result = create_result
- notify_listeners(STARTED, result)
- result_listener = result.add_listener(TestResult::CHANGED) do |updated_result|
- notify_listeners(TestResult::CHANGED, updated_result)
- end
-
- fault_listener = result.add_listener(TestResult::FAULT) do |fault|
- notify_listeners(TestResult::FAULT, fault)
- end
-
- @suite.run(result) do |channel, value|
- notify_listeners(channel, value)
- end
-
- result.remove_listener(TestResult::FAULT, fault_listener)
- result.remove_listener(TestResult::CHANGED, result_listener)
- end_time = Time.now
- elapsed_time = end_time - begin_time
- notify_listeners(FINISHED, elapsed_time) #"Finished in #{elapsed_time} seconds.")
- return result
- end
-
- private
- # A factory method to create the result the mediator
- # should run with. Can be overridden by subclasses if
- # one wants to use a different result.
- def create_result
- return TestResult.new
- end
- end
- end
- end
-end
diff --git a/lib/test/unit/ui/testrunnerutilities.rb b/lib/test/unit/ui/testrunnerutilities.rb
deleted file mode 100644
index 70b885bd6c..0000000000
--- a/lib/test/unit/ui/testrunnerutilities.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-#--
-#
-# Author:: Nathaniel Talbott.
-# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
-# License:: Ruby license.
-
-module Test
- module Unit
- module UI
-
- SILENT = 0
- PROGRESS_ONLY = 1
- NORMAL = 2
- VERBOSE = 3
-
- # Provides some utilities common to most, if not all,
- # TestRunners.
- #
- #--
- #
- # Perhaps there ought to be a TestRunner superclass? There
- # seems to be a decent amount of shared code between test
- # runners.
-
- module TestRunnerUtilities
-
- # Creates a new TestRunner and runs the suite.
- def run(suite, output_level=NORMAL)
- return new(suite, output_level).start
- end
-
- # Takes care of the ARGV parsing and suite
- # determination necessary for running one of the
- # TestRunners from the command line.
- def start_command_line_test
- if ARGV.empty?
- puts "You should supply the name of a test suite file to the runner"
- exit
- end
- require ARGV[0].gsub(/.+::/, '')
- new(eval(ARGV[0])).start
- end
- end
- end
- end
-end
diff --git a/lib/test/unit/ui/tk/testrunner.rb b/lib/test/unit/ui/tk/testrunner.rb
deleted file mode 100644
index 4521b8e258..0000000000
--- a/lib/test/unit/ui/tk/testrunner.rb
+++ /dev/null
@@ -1,260 +0,0 @@
-#--
-#
-# Original Author:: Nathaniel Talbott.
-# Author:: Kazuhiro NISHIYAMA.
-# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
-# Copyright:: Copyright (c) 2003 Kazuhiro NISHIYAMA. All rights reserved.
-# License:: Ruby license.
-
-require 'tk'
-require 'test/unit/ui/testrunnermediator'
-require 'test/unit/ui/testrunnerutilities'
-
-module Test
- module Unit
- module UI
- module Tk # :nodoc:
-
- # Runs a Test::Unit::TestSuite in a Tk UI. Obviously,
- # this one requires you to have Tk
- # and the Ruby Tk extension installed.
- class TestRunner
- extend TestRunnerUtilities
-
- # Creates a new TestRunner for running the passed
- # suite.
- def initialize(suite, output_level = NORMAL)
- if (suite.respond_to?(:suite))
- @suite = suite.suite
- else
- @suite = suite
- end
- @result = nil
-
- @red = false
- @fault_detail_list = []
- @runner = Thread.current
- @restart_signal = Class.new(Exception)
- @viewer = Thread.start do
- @runner.join rescue @runner.run
- ::Tk.mainloop
- end
- @viewer.join rescue nil # wait deadlock to handshake
- end
-
- # Begins the test run.
- def start
- setup_ui
- setup_mediator
- attach_to_mediator
- start_ui
- @result
- end
-
- private
- def setup_mediator # :nodoc:
- @mediator = TestRunnerMediator.new(@suite)
- suite_name = @suite.to_s
- if ( @suite.kind_of?(Module) )
- suite_name = @suite.name
- end
- @suite_name_entry.value = suite_name
- end
-
- def attach_to_mediator # :nodoc:
- @run_button.command(method(:run_test))
- @fault_list.bind('ButtonPress-1', proc{|y|
- fault = @fault_detail_list[@fault_list.nearest(y)]
- if fault
- show_fault(fault)
- end
- }, '%y')
- @mediator.add_listener(TestRunnerMediator::RESET, &method(:reset_ui))
- @mediator.add_listener(TestResult::FAULT, &method(:add_fault))
- @mediator.add_listener(TestResult::CHANGED, &method(:result_changed))
- @mediator.add_listener(TestRunnerMediator::STARTED, &method(:started))
- @mediator.add_listener(TestCase::STARTED, &method(:test_started))
- @mediator.add_listener(TestRunnerMediator::FINISHED, &method(:finished))
- end
-
- def run_test
- @runner.raise(@restart_signal)
- end
-
- def start_ui # :nodoc:
- @viewer.run
- running = false
- begin
- loop do
- if (running ^= true)
- @run_button.configure('text'=>'Stop')
- @mediator.run_suite
- else
- @run_button.configure('text'=>'Run')
- @viewer.join
- break
- end
- end
- rescue @restart_signal
- retry
- rescue
- end
- end
-
- def stop # :nodoc:
- ::Tk.exit
- end
-
- def reset_ui(count) # :nodoc:
- @test_total_count = count.to_f
- @test_progress_bar.configure('background'=>'green')
- @test_progress_bar.place('relwidth'=>(count.zero? ? 0 : 0/count))
- @red = false
-
- @test_count_label.value = 0
- @assertion_count_label.value = 0
- @failure_count_label.value = 0
- @error_count_label.value = 0
-
- @fault_list.delete(0, 'end')
- @fault_detail_list = []
- clear_fault
- end
-
- def add_fault(fault) # :nodoc:
- if ( ! @red )
- @test_progress_bar.configure('background'=>'red')
- @red = true
- end
- @fault_detail_list.push fault
- @fault_list.insert('end', fault.short_display)
- end
-
- def show_fault(fault) # :nodoc:
- raw_show_fault(fault.long_display)
- end
-
- def raw_show_fault(string) # :nodoc:
- @detail_text.value = string
- end
-
- def clear_fault # :nodoc:
- raw_show_fault("")
- end
-
- def result_changed(result) # :nodoc:
- @test_count_label.value = result.run_count
- @test_progress_bar.place('relwidth'=>result.run_count/@test_total_count)
- @assertion_count_label.value = result.assertion_count
- @failure_count_label.value = result.failure_count
- @error_count_label.value = result.error_count
- end
-
- def started(result) # :nodoc:
- @result = result
- output_status("Started...")
- end
-
- def test_started(test_name)
- output_status("Running #{test_name}...")
- end
-
- def finished(elapsed_time)
- output_status("Finished in #{elapsed_time} seconds")
- end
-
- def output_status(string) # :nodoc:
- @status_entry.value = string
- end
-
- def setup_ui # :nodoc:
- @status_entry = TkVariable.new
- l = TkLabel.new(nil, 'textvariable'=>@status_entry, 'relief'=>'sunken')
- l.pack('side'=>'bottom', 'fill'=>'x')
-
- suite_frame = TkFrame.new.pack('fill'=>'x')
-
- @run_button = TkButton.new(suite_frame, 'text'=>'Run')
- @run_button.pack('side'=>'right')
-
- TkLabel.new(suite_frame, 'text'=>'Suite:').pack('side'=>'left')
- @suite_name_entry = TkVariable.new
- l = TkLabel.new(suite_frame, 'textvariable'=>@suite_name_entry, 'relief'=>'sunken')
- l.pack('side'=>'left', 'fill'=>'x', 'expand'=>true)
-
- f = TkFrame.new(nil, 'relief'=>'sunken', 'borderwidth'=>3, 'height'=>20).pack('fill'=>'x', 'padx'=>1)
- @test_progress_bar = TkFrame.new(f, 'background'=>'green').place('anchor'=>'nw', 'relwidth'=>0.0, 'relheight'=>1.0)
-
- info_frame = TkFrame.new.pack('fill'=>'x')
- @test_count_label = create_count_label(info_frame, 'Tests:')
- @assertion_count_label = create_count_label(info_frame, 'Assertions:')
- @failure_count_label = create_count_label(info_frame, 'Failures:')
- @error_count_label = create_count_label(info_frame, 'Errors:')
-
- if (::Tk.info('command', TkPanedWindow::TkCommandNames[0]) != "")
- # use panedwindow
- paned_frame = TkPanedWindow.new("orient"=>"vertical").pack('fill'=>'both', 'expand'=>true)
-
- fault_list_frame = TkFrame.new(paned_frame)
- detail_frame = TkFrame.new(paned_frame)
-
- paned_frame.add(fault_list_frame, detail_frame)
- else
- # no panedwindow
- paned_frame = nil
- fault_list_frame = TkFrame.new.pack('fill'=>'both', 'expand'=>true)
- detail_frame = TkFrame.new.pack('fill'=>'both', 'expand'=>true)
- end
-
- TkGrid.rowconfigure(fault_list_frame, 0, 'weight'=>1, 'minsize'=>0)
- TkGrid.columnconfigure(fault_list_frame, 0, 'weight'=>1, 'minsize'=>0)
-
- fault_scrollbar_y = TkScrollbar.new(fault_list_frame)
- fault_scrollbar_x = TkScrollbar.new(fault_list_frame)
- @fault_list = TkListbox.new(fault_list_frame)
- @fault_list.yscrollbar(fault_scrollbar_y)
- @fault_list.xscrollbar(fault_scrollbar_x)
-
- TkGrid.rowconfigure(detail_frame, 0, 'weight'=>1, 'minsize'=>0)
- TkGrid.columnconfigure(detail_frame, 0, 'weight'=>1, 'minsize'=>0)
-
- ::Tk.grid(@fault_list, fault_scrollbar_y, 'sticky'=>'news')
- ::Tk.grid(fault_scrollbar_x, 'sticky'=>'news')
-
- detail_scrollbar_y = TkScrollbar.new(detail_frame)
- detail_scrollbar_x = TkScrollbar.new(detail_frame)
- @detail_text = TkText.new(detail_frame, 'height'=>10, 'wrap'=>'none') {
- bindtags(bindtags - [TkText])
- }
- @detail_text.yscrollbar(detail_scrollbar_y)
- @detail_text.xscrollbar(detail_scrollbar_x)
-
- ::Tk.grid(@detail_text, detail_scrollbar_y, 'sticky'=>'news')
- ::Tk.grid(detail_scrollbar_x, 'sticky'=>'news')
-
- # rubber-style pane
- if paned_frame
- ::Tk.update
- @height = paned_frame.winfo_height
- paned_frame.bind('Configure', proc{|h|
- paned_frame.sash_place(0, 0, paned_frame.sash_coord(0)[1] * h / @height)
- @height = h
- }, '%h')
- end
- end
-
- def create_count_label(parent, label) # :nodoc:
- TkLabel.new(parent, 'text'=>label).pack('side'=>'left', 'expand'=>true)
- v = TkVariable.new(0)
- TkLabel.new(parent, 'textvariable'=>v).pack('side'=>'left', 'expand'=>true)
- v
- end
- end
- end
- end
- end
-end
-
-if __FILE__ == $0
- Test::Unit::UI::Tk::TestRunner.start_command_line_test
-end
diff --git a/lib/test/unit/util/backtracefilter.rb b/lib/test/unit/util/backtracefilter.rb
deleted file mode 100644
index 7ebec2dfef..0000000000
--- a/lib/test/unit/util/backtracefilter.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-module Test
- module Unit
- module Util
- module BacktraceFilter
- TESTUNIT_FILE_SEPARATORS = %r{[\\/:]}
- TESTUNIT_PREFIX = __FILE__.split(TESTUNIT_FILE_SEPARATORS)[0..-3]
- TESTUNIT_RB_FILE = /\.rb\Z/
-
- def filter_backtrace(backtrace, prefix=nil)
- return ["No backtrace"] unless(backtrace)
- split_p = if(prefix)
- prefix.split(TESTUNIT_FILE_SEPARATORS)
- else
- TESTUNIT_PREFIX
- end
- match = proc do |e|
- split_e = e.split(TESTUNIT_FILE_SEPARATORS)[0, split_p.size]
- next false unless(split_e[0..-2] == split_p[0..-2])
- split_e[-1].sub(TESTUNIT_RB_FILE, '') == split_p[-1]
- end
- return backtrace unless(backtrace.detect(&match))
- found_prefix = false
- new_backtrace = backtrace.reverse.reject do |e|
- if(match[e])
- found_prefix = true
- true
- elsif(found_prefix)
- false
- else
- true
- end
- end.reverse
- new_backtrace = (new_backtrace.empty? ? backtrace : new_backtrace)
- new_backtrace = new_backtrace.reject(&match)
- new_backtrace.empty? ? backtrace : new_backtrace
- end
- end
- end
- end
-end
diff --git a/lib/test/unit/util/observable.rb b/lib/test/unit/util/observable.rb
deleted file mode 100644
index 924c10f24c..0000000000
--- a/lib/test/unit/util/observable.rb
+++ /dev/null
@@ -1,90 +0,0 @@
-#--
-#
-# Author:: Nathaniel Talbott.
-# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
-# License:: Ruby license.
-
-require 'test/unit/util/procwrapper'
-
-module Test
- module Unit
- module Util # :nodoc:
-
- # This is a utility class that allows anything mixing
- # it in to notify a set of listeners about interesting
- # events.
- module Observable
- # We use this for defaults since nil might mean something
- NOTHING = "NOTHING/#{__id__}"
-
- # Adds the passed proc as a listener on the
- # channel indicated by channel_name. listener_key
- # is used to remove the listener later; if none is
- # specified, the proc itself is used.
- #
- # Whatever is used as the listener_key is
- # returned, making it very easy to use the proc
- # itself as the listener_key:
- #
- # listener = add_listener("Channel") { ... }
- # remove_listener("Channel", listener)
- def add_listener(channel_name, listener_key=NOTHING, &listener) # :yields: value
- unless(block_given?)
- raise ArgumentError.new("No callback was passed as a listener")
- end
-
- key = listener_key
- if (listener_key == NOTHING)
- listener_key = listener
- key = ProcWrapper.new(listener)
- end
-
- channels[channel_name] ||= {}
- channels[channel_name][key] = listener
- return listener_key
- end
-
- # Removes the listener indicated by listener_key
- # from the channel indicated by
- # channel_name. Returns the registered proc, or
- # nil if none was found.
- def remove_listener(channel_name, listener_key)
- channel = channels[channel_name]
- return nil unless (channel)
- key = listener_key
- if (listener_key.instance_of?(Proc))
- key = ProcWrapper.new(listener_key)
- end
- if (channel.has_key?(key))
- return channel.delete(key)
- end
- return nil
- end
-
- # Calls all the procs registered on the channel
- # indicated by channel_name. If value is
- # specified, it is passed in to the procs,
- # otherwise they are called with no arguments.
- #
- #--
- #
- # Perhaps this should be private? Would it ever
- # make sense for an external class to call this
- # method directly?
- def notify_listeners(channel_name, *arguments)
- channel = channels[channel_name]
- return 0 unless (channel)
- listeners = channel.values
- listeners.each { |listener| listener.call(*arguments) }
- return listeners.size
- end
-
- private
- def channels # :nodoc:
- @channels ||= {}
- return @channels
- end
- end
- end
- end
-end
diff --git a/lib/test/unit/util/procwrapper.rb b/lib/test/unit/util/procwrapper.rb
deleted file mode 100644
index ad3b4d8a6f..0000000000
--- a/lib/test/unit/util/procwrapper.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-#--
-#
-# Author:: Nathaniel Talbott.
-# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
-# License:: Ruby license.
-
-module Test
- module Unit
- module Util
-
- # Allows the storage of a Proc passed through '&' in a
- # hash.
- #
- # Note: this may be inefficient, since the hash being
- # used is not necessarily very good. In Observable,
- # efficiency is not too important, since the hash is
- # only accessed when adding and removing listeners,
- # not when notifying.
-
- class ProcWrapper
-
- # Creates a new wrapper for a_proc.
- def initialize(a_proc)
- @a_proc = a_proc
- @hash = a_proc.inspect.sub(/^(#<#{a_proc.class}:)/, '').sub(/(>)$/, '').hex
- end
-
- def hash # :nodoc:
- return @hash
- end
-
- def ==(other) # :nodoc:
- case(other)
- when ProcWrapper
- return @a_proc == other.to_proc
- else
- return super
- end
- end
- alias :eql? :==
-
- def to_proc # :nodoc:
- return @a_proc
- end
- end
- end
- end
-end
diff --git a/lib/time.rb b/lib/time.rb
index 96f3945320..2d0a96117d 100644
--- a/lib/time.rb
+++ b/lib/time.rb
@@ -1,37 +1,37 @@
#
# == Introduction
-#
+#
# This library extends the Time class:
# * conversion between date string and time object.
# * date-time defined by RFC 2822
# * HTTP-date defined by RFC 2616
# * dateTime defined by XML Schema Part 2: Datatypes (ISO 8601)
# * various formats handled by Date._parse (string to time only)
-#
+#
# == Design Issues
-#
+#
# === Specialized interface
-#
+#
# This library provides methods dedicated to special purposes:
# * RFC 2822, RFC 2616 and XML Schema.
# * They makes usual life easier.
-#
+#
# === Doesn't depend on strftime
-#
+#
# This library doesn't use +strftime+. Especially #rfc2822 doesn't depend
# on +strftime+ because:
-#
+#
# * %a and %b are locale sensitive
-#
+#
# Since they are locale sensitive, they may be replaced to
# invalid weekday/month name in some locales.
# Since ruby-1.6 doesn't invoke setlocale by default,
# the problem doesn't arise until some external library invokes setlocale.
# Ruby/GTK is the example of such library.
-#
+#
# * %z is not portable
-#
+#
# %z is required to generate zone in date-time of RFC 2822
# but it is not portable.
#
@@ -61,9 +61,9 @@ class Time
'PST' => -8, 'PDT' => -7,
# Following definition of military zones is original one.
# See RFC 1123 and RFC 2822 for the error in RFC 822.
- 'A' => +1, 'B' => +2, 'C' => +3, 'D' => +4, 'E' => +5, 'F' => +6,
+ 'A' => +1, 'B' => +2, 'C' => +3, 'D' => +4, 'E' => +5, 'F' => +6,
'G' => +7, 'H' => +8, 'I' => +9, 'K' => +10, 'L' => +11, 'M' => +12,
- 'N' => -1, 'O' => -2, 'P' => -3, 'Q' => -4, 'R' => -5, 'S' => -6,
+ 'N' => -1, 'O' => -2, 'P' => -3, 'Q' => -4, 'R' => -5, 'S' => -6,
'T' => -7, 'U' => -8, 'V' => -9, 'W' => -10, 'X' => -11, 'Y' => -12,
}
def zone_offset(zone, year=self.now.year)
@@ -84,9 +84,9 @@ class Time
end
def zone_utc?(zone)
- # * +0000 means localtime. [RFC 2822]
+ # * -0000 means localtime. [RFC 2822]
# * GMT is a localtime abbreviation in Europe/London, etc.
- if /\A(?:-00:00|-0000|-00|UTC|Z|UT)\z/i =~ zone
+ if /\A(?:\+00:00|\+0000|\+00|UTC|Z|UT)\z/i =~ zone
true
else
false
@@ -409,7 +409,7 @@ class Time
#
# where zone is [+-]hhmm.
#
- # If +self+ is a UTC time, -0000 is used as zone.
+ # If +self+ is a UTC time, +0000 is used as zone.
#
def rfc2822
sprintf('%s, %02d %s %d %02d:%02d:%02d ',
@@ -417,7 +417,7 @@ class Time
day, RFC2822_MONTH_NAME[mon-1], year,
hour, min, sec) +
if utc?
- '-0000'
+ '+0000'
else
off = utc_offset
sign = off < 0 ? '-' : '+'
@@ -436,8 +436,8 @@ class Time
#
# Returns a string which represents the time as rfc1123-date of HTTP-date
- # defined by RFC 2616:
- #
+ # defined by RFC 2616:
+ #
# day-of-week, DD month-name CCYY hh:mm:ss GMT
#
# Note that the result is always UTC (GMT).
@@ -730,86 +730,86 @@ if __FILE__ == $0
def test_zone_0000
assert_equal(true, Time.parse("2000-01-01T00:00:00Z").utc?)
- assert_equal(true, Time.parse("2000-01-01T00:00:00-00:00").utc?)
- assert_equal(false, Time.parse("2000-01-01T00:00:00+00:00").utc?)
+ assert_equal(true, Time.parse("2000-01-01T00:00:00+00:00").utc?)
+ assert_equal(false, Time.parse("2000-01-01T00:00:00-00:00").utc?)
assert_equal(false, Time.parse("Sat, 01 Jan 2000 00:00:00 GMT").utc?)
- assert_equal(true, Time.parse("Sat, 01 Jan 2000 00:00:00 -0000").utc?)
- assert_equal(false, Time.parse("Sat, 01 Jan 2000 00:00:00 +0000").utc?)
+ assert_equal(true, Time.parse("Sat, 01 Jan 2000 00:00:00 +0000").utc?)
+ assert_equal(false, Time.parse("Sat, 01 Jan 2000 00:00:00 -0000").utc?)
assert_equal(false, Time.rfc2822("Sat, 01 Jan 2000 00:00:00 GMT").utc?)
- assert_equal(true, Time.rfc2822("Sat, 01 Jan 2000 00:00:00 -0000").utc?)
- assert_equal(false, Time.rfc2822("Sat, 01 Jan 2000 00:00:00 +0000").utc?)
+ assert_equal(true, Time.rfc2822("Sat, 01 Jan 2000 00:00:00 +0000").utc?)
+ assert_equal(false, Time.rfc2822("Sat, 01 Jan 2000 00:00:00 -0000").utc?)
assert_equal(true, Time.rfc2822("Sat, 01 Jan 2000 00:00:00 UTC").utc?)
end
def test_parse_leap_second
t = Time.utc(1998,12,31,23,59,59)
assert_equal(t, Time.parse("Thu Dec 31 23:59:59 UTC 1998"))
- assert_equal(t, Time.parse("Fri Dec 31 23:59:59 -0000 1998"));t.localtime
+ assert_equal(t, Time.parse("Fri Dec 31 23:59:59 +0000 1998"));t.localtime
assert_equal(t, Time.parse("Fri Jan 1 08:59:59 +0900 1999"))
assert_equal(t, Time.parse("Fri Jan 1 00:59:59 +0100 1999"))
- assert_equal(t, Time.parse("Fri Dec 31 23:59:59 +0000 1998"))
+ assert_equal(t, Time.parse("Fri Dec 31 23:59:59 -0000 1998"))
assert_equal(t, Time.parse("Fri Dec 31 22:59:59 -0100 1998"));t.utc
t += 1
assert_equal(t, Time.parse("Thu Dec 31 23:59:60 UTC 1998"))
- assert_equal(t, Time.parse("Fri Dec 31 23:59:60 -0000 1998"));t.localtime
+ assert_equal(t, Time.parse("Fri Dec 31 23:59:60 +0000 1998"));t.localtime
assert_equal(t, Time.parse("Fri Jan 1 08:59:60 +0900 1999"))
assert_equal(t, Time.parse("Fri Jan 1 00:59:60 +0100 1999"))
- assert_equal(t, Time.parse("Fri Dec 31 23:59:60 +0000 1998"))
+ assert_equal(t, Time.parse("Fri Dec 31 23:59:60 -0000 1998"))
assert_equal(t, Time.parse("Fri Dec 31 22:59:60 -0100 1998"));t.utc
t += 1 if t.sec == 60
assert_equal(t, Time.parse("Thu Jan 1 00:00:00 UTC 1999"))
- assert_equal(t, Time.parse("Fri Jan 1 00:00:00 -0000 1999"));t.localtime
+ assert_equal(t, Time.parse("Fri Jan 1 00:00:00 +0000 1999"));t.localtime
assert_equal(t, Time.parse("Fri Jan 1 09:00:00 +0900 1999"))
assert_equal(t, Time.parse("Fri Jan 1 01:00:00 +0100 1999"))
- assert_equal(t, Time.parse("Fri Jan 1 00:00:00 +0000 1999"))
+ assert_equal(t, Time.parse("Fri Jan 1 00:00:00 -0000 1999"))
assert_equal(t, Time.parse("Fri Dec 31 23:00:00 -0100 1998"))
end
def test_rfc2822_leap_second
t = Time.utc(1998,12,31,23,59,59)
assert_equal(t, Time.rfc2822("Thu, 31 Dec 1998 23:59:59 UTC"))
- assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:59:59 -0000"));t.localtime
+ assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:59:59 +0000"));t.localtime
assert_equal(t, Time.rfc2822("Fri, 1 Jan 1999 08:59:59 +0900"))
assert_equal(t, Time.rfc2822("Fri, 1 Jan 1999 00:59:59 +0100"))
- assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:59:59 +0000"))
- assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 22:59:59 -0100"));t.utc
+ assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:59:59 -0000"))
+ assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 22:59:59 -0100"));t.utc
t += 1
assert_equal(t, Time.rfc2822("Thu, 31 Dec 1998 23:59:60 UTC"))
- assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:59:60 -0000"));t.localtime
+ assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:59:60 +0000"));t.localtime
assert_equal(t, Time.rfc2822("Fri, 1 Jan 1999 08:59:60 +0900"))
assert_equal(t, Time.rfc2822("Fri, 1 Jan 1999 00:59:60 +0100"))
- assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:59:60 +0000"))
- assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 22:59:60 -0100"));t.utc
+ assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:59:60 -0000"))
+ assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 22:59:60 -0100"));t.utc
t += 1 if t.sec == 60
assert_equal(t, Time.rfc2822("Thu, 1 Jan 1999 00:00:00 UTC"))
- assert_equal(t, Time.rfc2822("Fri, 1 Jan 1999 00:00:00 -0000"));t.localtime
+ assert_equal(t, Time.rfc2822("Fri, 1 Jan 1999 00:00:00 +0000"));t.localtime
assert_equal(t, Time.rfc2822("Fri, 1 Jan 1999 09:00:00 +0900"))
assert_equal(t, Time.rfc2822("Fri, 1 Jan 1999 01:00:00 +0100"))
- assert_equal(t, Time.rfc2822("Fri, 1 Jan 1999 00:00:00 +0000"))
+ assert_equal(t, Time.rfc2822("Fri, 1 Jan 1999 00:00:00 -0000"))
assert_equal(t, Time.rfc2822("Fri, 31 Dec 1998 23:00:00 -0100"))
end
def test_xmlschema_leap_second
t = Time.utc(1998,12,31,23,59,59)
assert_equal(t, Time.xmlschema("1998-12-31T23:59:59Z"))
- assert_equal(t, Time.xmlschema("1998-12-31T23:59:59-00:00"));t.localtime
+ assert_equal(t, Time.xmlschema("1998-12-31T23:59:59+00:00"));t.localtime
assert_equal(t, Time.xmlschema("1999-01-01T08:59:59+09:00"))
assert_equal(t, Time.xmlschema("1999-01-01T00:59:59+01:00"))
- assert_equal(t, Time.xmlschema("1998-12-31T23:59:59+00:00"))
+ assert_equal(t, Time.xmlschema("1998-12-31T23:59:59-00:00"))
assert_equal(t, Time.xmlschema("1998-12-31T22:59:59-01:00"));t.utc
t += 1
assert_equal(t, Time.xmlschema("1998-12-31T23:59:60Z"))
- assert_equal(t, Time.xmlschema("1998-12-31T23:59:60-00:00"));t.localtime
+ assert_equal(t, Time.xmlschema("1998-12-31T23:59:60+00:00"));t.localtime
assert_equal(t, Time.xmlschema("1999-01-01T08:59:60+09:00"))
assert_equal(t, Time.xmlschema("1999-01-01T00:59:60+01:00"))
- assert_equal(t, Time.xmlschema("1998-12-31T23:59:60+00:00"))
+ assert_equal(t, Time.xmlschema("1998-12-31T23:59:60-00:00"))
assert_equal(t, Time.xmlschema("1998-12-31T22:59:60-01:00"));t.utc
t += 1 if t.sec == 60
assert_equal(t, Time.xmlschema("1999-01-01T00:00:00Z"))
- assert_equal(t, Time.xmlschema("1999-01-01T00:00:00-00:00"));t.localtime
+ assert_equal(t, Time.xmlschema("1999-01-01T00:00:00+00:00"));t.localtime
assert_equal(t, Time.xmlschema("1999-01-01T09:00:00+09:00"))
assert_equal(t, Time.xmlschema("1999-01-01T01:00:00+01:00"))
- assert_equal(t, Time.xmlschema("1999-01-01T00:00:00+00:00"))
+ assert_equal(t, Time.xmlschema("1999-01-01T00:00:00-00:00"))
assert_equal(t, Time.xmlschema("1998-12-31T23:00:00-01:00"))
end
diff --git a/lib/tmpdir.rb b/lib/tmpdir.rb
index 2e82aa528e..bcd66ab424 100644
--- a/lib/tmpdir.rb
+++ b/lib/tmpdir.rb
@@ -14,7 +14,7 @@ class Dir
require 'Win32API'
CSIDL_LOCAL_APPDATA = 0x001c
max_pathlen = 260
- windir = ' '*(max_pathlen+1)
+ 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
diff --git a/lib/tsort.rb b/lib/tsort.rb
index a014e7f6c2..9fc4feadcd 100644
--- a/lib/tsort.rb
+++ b/lib/tsort.rb
@@ -32,7 +32,7 @@
# array using the user-supplied block.
#
# require 'tsort'
-#
+#
# class Hash
# include TSort
# alias tsort_each_node each_key
@@ -40,10 +40,10 @@
# fetch(node).each(&block)
# end
# end
-#
+#
# {1=>[2, 3], 2=>[3], 3=>[], 4=>[]}.tsort
# #=> [3, 2, 1, 4]
-#
+#
# {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}.strongly_connected_components
# #=> [[4], [2, 3], [1]]
#
@@ -52,19 +52,19 @@
# A very simple `make' like tool can be implemented as follows:
#
# require 'tsort'
-#
+#
# class Make
# def initialize
# @dep = {}
# @dep.default = []
# end
-#
+#
# def rule(outputs, inputs=[], &block)
# triple = [outputs, inputs, block]
# outputs.each {|f| @dep[f] = [triple]}
# @dep[triple] = inputs
# end
-#
+#
# def build(target)
# each_strongly_connected_component_from(target) {|ns|
# if ns.length != 1
@@ -88,18 +88,18 @@
# end
# }
# end
-#
+#
# def tsort_each_child(node, &block)
# @dep[node].each(&block)
# end
# include TSort
# end
-#
+#
# def command(arg)
# print arg, "\n"
# system arg
# end
-#
+#
# m = Make.new
# m.rule(%w[t1]) { command 'date > t1' }
# m.rule(%w[t2]) { command 'date > t2' }
@@ -189,7 +189,7 @@ module TSort
end
#
- # Iterates over strongly connected component in the subgraph reachable from
+ # Iterates over strongly connected component in the subgraph reachable from
# _node_.
#
# Return value is unspecified.
diff --git a/lib/uri/common.rb b/lib/uri/common.rb
index f0d68884de..9a6a06894a 100644
--- a/lib/uri/common.rb
+++ b/lib/uri/common.rb
@@ -38,22 +38,232 @@ module URI
# "$" | "," | "[" | "]" (RFC 2732)
RESERVED = ";/?:@&=+$,\\[\\]"
+ # domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
+ DOMLABEL = "(?:[#{ALNUM}](?:[-#{ALNUM}]*[#{ALNUM}])?)"
+ # toplabel = alpha | alpha *( alphanum | "-" ) alphanum
+ TOPLABEL = "(?:[#{ALPHA}](?:[-#{ALNUM}]*[#{ALNUM}])?)"
+ # hostname = *( domainlabel "." ) toplabel [ "." ]
+ HOSTNAME = "(?:#{DOMLABEL}\\.)*#{TOPLABEL}\\.?"
+
+ # :startdoc:
+ end # PATTERN
+
+ # :startdoc:
+ end # REGEXP
+
+ class Parser
+ include REGEXP
+
+ #
+ # == Synopsis
+ #
+ # URI::Parser.new([opts])
+ #
+ # == Args
+ #
+ # The constructor accepts a hash as options for parser.
+ # Keys of options are pattern names of URI components
+ # and values of options are pattern strings.
+ # The constructor generetes set of regexps for parsing URIs.
+ #
+ # You can use the following keys:
+ #
+ # * <tt>:ESCAPED</tt> (URI::PATTERN::ESCAPED in default)
+ # * <tt>:UNRESERVED</tt> (URI::PATTERN::UNRESERVED in default)
+ # * <tt>:DOMLABEL</tt> (URI::PATTERN::DOMLABEL in default)
+ # * <tt>:TOPLABEL</tt> (URI::PATTERN::TOPLABEL in default)
+ # * <tt>:HOSTNAME</tt> (URI::PATTERN::HOSTNAME in default)
+ #
+ # == Examples
+ #
+ # p = URI::Parser.new(:ESCPAED => "(?:%[a-fA-F0-9]{2}|%u[a-fA-F0-9]{4})"
+ # u = p.parse("http://example.jp/%uABCD") #=> #<URI::HTTP:0xb78cf4f8 URL:http://example.jp/%uABCD>
+ # URI.parse(u.to_s) #=> raises URI::InvalidURIError
+ #
+ # s = "http://examle.com/ABCD"
+ # u1 = p.parse(s) #=> #<URI::HTTP:0xb78c3220 URL:http://example.com/ABCD>
+ # u2 = URI.parse(s) #=> #<URI::HTTP:0xb78b6d54 URL:http://example.com/ABCD>
+ # u1 == u2 #=> true
+ # u1.eql?(u2) #=> false
+ #
+ def initialize(opts = {})
+ @pattern = initialize_pattern(opts)
+ @pattern.each_value {|v| v.freeze}
+ @pattern.freeze
+
+ @regexp = initialize_regexp(@pattern)
+ @regexp.each_value {|v| v.freeze}
+ @regexp.freeze
+ end
+ attr_reader :pattern, :regexp
+
+ def split(uri)
+ case uri
+ when ''
+ # null uri
+
+ when @regexp[:ABS_URI]
+ scheme, opaque, userinfo, host, port,
+ registry, path, query, fragment = $~[1..-1]
+
+ # URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
+
+ # absoluteURI = scheme ":" ( hier_part | opaque_part )
+ # hier_part = ( net_path | abs_path ) [ "?" query ]
+ # opaque_part = uric_no_slash *uric
+
+ # abs_path = "/" path_segments
+ # net_path = "//" authority [ abs_path ]
+
+ # authority = server | reg_name
+ # server = [ [ userinfo "@" ] hostport ]
+
+ if !scheme
+ raise InvalidURIError,
+ "bad URI(absolute but no scheme): #{uri}"
+ end
+ if !opaque && (!path && (!host && !registry))
+ raise InvalidURIError,
+ "bad URI(absolute but no path): #{uri}"
+ end
+
+ when @regexp[:REL_URI]
+ scheme = nil
+ opaque = nil
+
+ userinfo, host, port, registry,
+ rel_segment, abs_path, query, fragment = $~[1..-1]
+ if rel_segment && abs_path
+ path = rel_segment + abs_path
+ elsif rel_segment
+ path = rel_segment
+ elsif abs_path
+ path = abs_path
+ end
+
+ # URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
+
+ # relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ]
+
+ # net_path = "//" authority [ abs_path ]
+ # abs_path = "/" path_segments
+ # rel_path = rel_segment [ abs_path ]
+
+ # authority = server | reg_name
+ # server = [ [ userinfo "@" ] hostport ]
+
+ else
+ raise InvalidURIError, "bad URI(is not URI?): #{uri}"
+ end
+
+ path = '' if !path && !opaque # (see RFC2396 Section 5.2)
+ ret = [
+ scheme,
+ userinfo, host, port, # X
+ registry, # X
+ path, # Y
+ opaque, # Y
+ query,
+ fragment
+ ]
+ return ret
+ end
+
+ def parse(uri)
+ scheme, userinfo, host, port,
+ registry, path, opaque, query, fragment = self.split(uri)
+
+ if scheme && URI.scheme_list.include?(scheme.upcase)
+ URI.scheme_list[scheme.upcase].new(scheme, userinfo, host, port,
+ registry, path, opaque, query,
+ fragment, self)
+ else
+ Generic.new(scheme, userinfo, host, port,
+ registry, path, opaque, query,
+ fragment, self)
+ end
+ end
+
+ def join(*str)
+ u = self.parse(str[0])
+ str[1 .. -1].each do |x|
+ u = u.merge(x)
+ end
+ u
+ end
+
+ def extract(str, schemes = nil, &block)
+ if block_given?
+ str.scan(make_regexp(schemes)) { yield $& }
+ nil
+ else
+ result = []
+ str.scan(make_regexp(schemes)) { result.push $& }
+ result
+ end
+ end
+
+ def make_regexp(schemes = nil)
+ unless schemes
+ @regexp[:ABS_URI_REF]
+ else
+ /(?=#{Regexp.union(*schemes)}:)#{@pattern[:X_ABS_URI]}/x
+ end
+ end
+
+ def escape(str, unsafe = @regexp[:UNSAFE])
+ unless unsafe.kind_of?(Regexp)
+ # perhaps unsafe is String object
+ unsafe = Regexp.new("[#{Regexp.quote(unsafe)}]", false)
+ end
+ str.gsub(unsafe) do
+ us = $&
+ tmp = ''
+ us.each_byte do |uc|
+ tmp << sprintf('%%%02X', uc)
+ end
+ tmp
+ end
+ end
+
+ def unescape(str, escaped = @regexp[:ESCAPED])
+ str.gsub(escaped) { [$&[1, 2].hex].pack('U') }
+ end
+
+ @@to_s = Kernel.instance_method(:to_s)
+ def inspect
+ @@to_s.bind(self).call
+ end
+
+ private
+
+ def initialize_pattern(opts = {})
+ ret = {}
+ ret[:ESCAPED] = escaped = (opts.delete(:ESCAPED) || PATTERN::ESCAPED)
+ ret[:UNRESERVED] = unreserved = opts.delete(:UNRESERVED) || PATTERN::UNRESERVED
+ ret[:RESERVED] = reserved = opts.delete(:RESERVED) || PATTERN::RESERVED
+ ret[:DOMLABEL] = domlabel = opts.delete(:DOMLABEL) || PATTERN::DOMLABEL
+ ret[:TOPLABEL] = toplabel = opts.delete(:TOPLABEL) || PATTERN::TOPLABEL
+ ret[:HOSTNAME] = hostname = opts.delete(:HOSTNAME)
+
+ # RFC 2396 (URI Generic Syntax)
+ # RFC 2732 (IPv6 Literal Addresses in URL's)
+ # RFC 2373 (IPv6 Addressing Architecture)
+
# uric = reserved | unreserved | escaped
- URIC = "(?:[#{UNRESERVED}#{RESERVED}]|#{ESCAPED})"
+ ret[:URIC] = uric = "(?:[#{unreserved}#{reserved}]|#{escaped})"
# uric_no_slash = unreserved | escaped | ";" | "?" | ":" | "@" |
# "&" | "=" | "+" | "$" | ","
- URIC_NO_SLASH = "(?:[#{UNRESERVED};?:@&=+$,]|#{ESCAPED})"
+ ret[:URIC_NO_SLASH] = uric_no_slash = "(?:[#{unreserved};?:@&=+$,]|#{escaped})"
# query = *uric
- QUERY = "#{URIC}*"
+ ret[:QUERY] = query = "#{uric}*"
# fragment = *uric
- FRAGMENT = "#{URIC}*"
+ ret[:FRAGMENT] = fragment = "#{uric}*"
- # domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
- DOMLABEL = "(?:[#{ALNUM}](?:[-#{ALNUM}]*[#{ALNUM}])?)"
- # toplabel = alpha | alpha *( alphanum | "-" ) alphanum
- TOPLABEL = "(?:[#{ALPHA}](?:[-#{ALNUM}]*[#{ALNUM}])?)"
# hostname = *( domainlabel "." ) toplabel [ "." ]
- HOSTNAME = "(?:#{DOMLABEL}\\.)*#{TOPLABEL}\\.?"
+ unless hostname
+ ret[:HOSTNAME] = hostname = "(?:#{domlabel}\\.)*#{toplabel}\\.?"
+ end
# RFC 2373, APPENDIX B:
# IPv6address = hexpart [ ":" IPv4address ]
@@ -66,152 +276,164 @@ module URI
# allowed too. Here is a replacement.
#
# IPv4address = 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT
- IPV4ADDR = "\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"
+ ret[:IPV4ADDR] = ipv4addr = "\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"
# hex4 = 1*4HEXDIG
- HEX4 = "[#{HEX}]{1,4}"
+ hex4 = "[#{PATTERN::HEX}]{1,4}"
# lastpart = hex4 | IPv4address
- LASTPART = "(?:#{HEX4}|#{IPV4ADDR})"
+ lastpart = "(?:#{hex4}|#{ipv4addr})"
# hexseq1 = *( hex4 ":" ) hex4
- HEXSEQ1 = "(?:#{HEX4}:)*#{HEX4}"
+ hexseq1 = "(?:#{hex4}:)*#{hex4}"
# hexseq2 = *( hex4 ":" ) lastpart
- HEXSEQ2 = "(?:#{HEX4}:)*#{LASTPART}"
+ hexseq2 = "(?:#{hex4}:)*#{lastpart}"
# IPv6address = hexseq2 | [ hexseq1 ] "::" [ hexseq2 ]
- IPV6ADDR = "(?:#{HEXSEQ2}|(?:#{HEXSEQ1})?::(?:#{HEXSEQ2})?)"
+ ret[:IPV6ADDR] = ipv6addr = "(?:#{hexseq2}|(?:#{hexseq1})?::(?:#{hexseq2})?)"
# IPv6prefix = ( hexseq1 | [ hexseq1 ] "::" [ hexseq1 ] ) "/" 1*2DIGIT
# unused
# ipv6reference = "[" IPv6address "]" (RFC 2732)
- IPV6REF = "\\[#{IPV6ADDR}\\]"
+ ret[:IPV6REF] = ipv6ref = "\\[#{ipv6addr}\\]"
# host = hostname | IPv4address
# host = hostname | IPv4address | IPv6reference (RFC 2732)
- HOST = "(?:#{HOSTNAME}|#{IPV4ADDR}|#{IPV6REF})"
+ ret[:HOST] = host = "(?:#{hostname}|#{ipv4addr}|#{ipv6ref})"
# port = *digit
- PORT = '\d*'
+ port = '\d*'
# hostport = host [ ":" port ]
- HOSTPORT = "#{HOST}(?::#{PORT})?"
+ ret[:HOSTPORT] = hostport = "#{host}(?::#{port})?"
# userinfo = *( unreserved | escaped |
# ";" | ":" | "&" | "=" | "+" | "$" | "," )
- USERINFO = "(?:[#{UNRESERVED};:&=+$,]|#{ESCAPED})*"
+ ret[:USERINFO] = userinfo = "(?:[#{unreserved};:&=+$,]|#{escaped})*"
# pchar = unreserved | escaped |
# ":" | "@" | "&" | "=" | "+" | "$" | ","
- PCHAR = "(?:[#{UNRESERVED}:@&=+$,]|#{ESCAPED})"
+ pchar = "(?:[#{unreserved}:@&=+$,]|#{escaped})"
# param = *pchar
- PARAM = "#{PCHAR}*"
+ param = "#{pchar}*"
# segment = *pchar *( ";" param )
- SEGMENT = "#{PCHAR}*(?:;#{PARAM})*"
+ segment = "#{pchar}*(?:;#{param})*"
# path_segments = segment *( "/" segment )
- PATH_SEGMENTS = "#{SEGMENT}(?:/#{SEGMENT})*"
+ ret[:PATH_SEGMENTS] = path_segments = "#{segment}(?:/#{segment})*"
# server = [ [ userinfo "@" ] hostport ]
- SERVER = "(?:#{USERINFO}@)?#{HOSTPORT}"
+ server = "(?:#{userinfo}@)?#{hostport}"
# reg_name = 1*( unreserved | escaped | "$" | "," |
# ";" | ":" | "@" | "&" | "=" | "+" )
- REG_NAME = "(?:[#{UNRESERVED}$,;:@&=+]|#{ESCAPED})+"
+ ret[:REG_NAME] = reg_name = "(?:[#{unreserved}$,;:@&=+]|#{escaped})+"
# authority = server | reg_name
- AUTHORITY = "(?:#{SERVER}|#{REG_NAME})"
+ authority = "(?:#{server}|#{reg_name})"
# rel_segment = 1*( unreserved | escaped |
# ";" | "@" | "&" | "=" | "+" | "$" | "," )
- REL_SEGMENT = "(?:[#{UNRESERVED};@&=+$,]|#{ESCAPED})+"
+ ret[:REL_SEGMENT] = rel_segment = "(?:[#{unreserved};@&=+$,]|#{escaped})+"
# scheme = alpha *( alpha | digit | "+" | "-" | "." )
- SCHEME = "[#{ALPHA}][-+.#{ALPHA}\\d]*"
+ ret[:SCHEME] = scheme = "[#{PATTERN::ALPHA}][-+.#{PATTERN::ALPHA}\\d]*"
# abs_path = "/" path_segments
- ABS_PATH = "/#{PATH_SEGMENTS}"
+ ret[:ABS_PATH] = abs_path = "/#{path_segments}"
# rel_path = rel_segment [ abs_path ]
- REL_PATH = "#{REL_SEGMENT}(?:#{ABS_PATH})?"
+ ret[:REL_PATH] = rel_path = "#{rel_segment}(?:#{abs_path})?"
# net_path = "//" authority [ abs_path ]
- NET_PATH = "//#{AUTHORITY}(?:#{ABS_PATH})?"
+ ret[:NET_PATH] = net_path = "//#{authority}(?:#{abs_path})?"
# hier_part = ( net_path | abs_path ) [ "?" query ]
- HIER_PART = "(?:#{NET_PATH}|#{ABS_PATH})(?:\\?(?:#{QUERY}))?"
+ ret[:HIER_PART] = hier_part = "(?:#{net_path}|#{abs_path})(?:\\?(?:#{query}))?"
# opaque_part = uric_no_slash *uric
- OPAQUE_PART = "#{URIC_NO_SLASH}#{URIC}*"
+ ret[:OPAQUE_PART] = opaque_part = "#{uric_no_slash}#{uric}*"
# absoluteURI = scheme ":" ( hier_part | opaque_part )
- ABS_URI = "#{SCHEME}:(?:#{HIER_PART}|#{OPAQUE_PART})"
+ ret[:ABS_URI] = abs_uri = "#{scheme}:(?:#{hier_part}|#{opaque_part})"
# relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ]
- REL_URI = "(?:#{NET_PATH}|#{ABS_PATH}|#{REL_PATH})(?:\\?#{QUERY})?"
+ ret[:REL_URI] = rel_uri = "(?:#{net_path}|#{abs_path}|#{rel_path})(?:\\?#{query})?"
# URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
- URI_REF = "(?:#{ABS_URI}|#{REL_URI})?(?:##{FRAGMENT})?"
+ ret[:URI_REF] = uri_ref = "(?:#{abs_uri}|#{rel_uri})?(?:##{fragment})?"
- # XXX:
- X_ABS_URI = "
- (#{PATTERN::SCHEME}): (?# 1: scheme)
+ ret[:X_ABS_URI] = "
+ (#{scheme}): (?# 1: scheme)
(?:
- (#{PATTERN::OPAQUE_PART}) (?# 2: opaque)
+ (#{opaque_part}) (?# 2: opaque)
|
(?:(?:
//(?:
- (?:(?:(#{PATTERN::USERINFO})@)? (?# 3: userinfo)
- (?:(#{PATTERN::HOST})(?::(\\d*))?))?(?# 4: host, 5: port)
+ (?:(?:(#{userinfo})@)? (?# 3: userinfo)
+ (?:(#{host})(?::(\\d*))?))? (?# 4: host, 5: port)
|
- (#{PATTERN::REG_NAME}) (?# 6: registry)
+ (#{reg_name}) (?# 6: registry)
)
|
- (?!//)) (?# XXX: '//' is the mark for hostport)
- (#{PATTERN::ABS_PATH})? (?# 7: path)
- )(?:\\?(#{PATTERN::QUERY}))? (?# 8: query)
+ (?!//)) (?# XXX: '//' is the mark for hostport)
+ (#{abs_path})? (?# 7: path)
+ )(?:\\?(#{query}))? (?# 8: query)
)
- (?:\\#(#{PATTERN::FRAGMENT}))? (?# 9: fragment)
+ (?:\\#(#{fragment}))? (?# 9: fragment)
"
- X_REL_URI = "
+
+ ret[:X_REL_URI] = "
(?:
(?:
//
(?:
- (?:(#{PATTERN::USERINFO})@)? (?# 1: userinfo)
- (#{PATTERN::HOST})?(?::(\\d*))? (?# 2: host, 3: port)
+ (?:(#{userinfo})@)? (?# 1: userinfo)
+ (#{host})?(?::(\\d*))? (?# 2: host, 3: port)
|
- (#{PATTERN::REG_NAME}) (?# 4: registry)
+ (#{reg_name}) (?# 4: registry)
)
)
|
- (#{PATTERN::REL_SEGMENT}) (?# 5: rel_segment)
+ (#{rel_segment}) (?# 5: rel_segment)
)?
- (#{PATTERN::ABS_PATH})? (?# 6: abs_path)
- (?:\\?(#{PATTERN::QUERY}))? (?# 7: query)
- (?:\\#(#{PATTERN::FRAGMENT}))? (?# 8: fragment)
+ (#{abs_path})? (?# 6: abs_path)
+ (?:\\?(#{query}))? (?# 7: query)
+ (?:\\#(#{fragment}))? (?# 8: fragment)
"
- # :startdoc:
- end # PATTERN
- # :stopdoc:
-
- # for URI::split
- ABS_URI = Regexp.new('^' + PATTERN::X_ABS_URI + '$', #'
- Regexp::EXTENDED).freeze
- REL_URI = Regexp.new('^' + PATTERN::X_REL_URI + '$', #'
- Regexp::EXTENDED).freeze
-
- # for URI::extract
- URI_REF = Regexp.new(PATTERN::URI_REF).freeze
- ABS_URI_REF = Regexp.new(PATTERN::X_ABS_URI, Regexp::EXTENDED).freeze
- REL_URI_REF = Regexp.new(PATTERN::X_REL_URI, Regexp::EXTENDED).freeze
-
- # for URI::escape/unescape
- ESCAPED = Regexp.new(PATTERN::ESCAPED).freeze
- UNSAFE = Regexp.new("[^#{PATTERN::UNRESERVED}#{PATTERN::RESERVED}]").freeze
-
- # for Generic#initialize
- SCHEME = Regexp.new("^#{PATTERN::SCHEME}$").freeze #"
- USERINFO = Regexp.new("^#{PATTERN::USERINFO}$").freeze #"
- HOST = Regexp.new("^#{PATTERN::HOST}$").freeze #"
- PORT = Regexp.new("^#{PATTERN::PORT}$").freeze #"
- OPAQUE = Regexp.new("^#{PATTERN::OPAQUE_PART}$").freeze #"
- REGISTRY = Regexp.new("^#{PATTERN::REG_NAME}$").freeze #"
- ABS_PATH = Regexp.new("^#{PATTERN::ABS_PATH}$").freeze #"
- REL_PATH = Regexp.new("^#{PATTERN::REL_PATH}$").freeze #"
- QUERY = Regexp.new("^#{PATTERN::QUERY}$").freeze #"
- FRAGMENT = Regexp.new("^#{PATTERN::FRAGMENT}$").freeze #"
- # :startdoc:
- end # REGEXP
+ ret
+ end
+
+ def initialize_regexp(pattern)
+ ret = {}
+
+ # for URI::split
+ ret[:ABS_URI] = Regexp.new('^' + pattern[:X_ABS_URI] + '$', Regexp::EXTENDED)
+ ret[:REL_URI] = Regexp.new('^' + pattern[:X_REL_URI] + '$', Regexp::EXTENDED)
+
+ # for URI::extract
+ ret[:URI_REF] = Regexp.new(pattern[:URI_REF])
+ ret[:ABS_URI_REF] = Regexp.new(pattern[:X_ABS_URI], Regexp::EXTENDED)
+ ret[:REL_URI_REF] = Regexp.new(pattern[:X_REL_URI], Regexp::EXTENDED)
+
+ # for URI::escape/unescape
+ ret[:ESCAPED] = Regexp.new(pattern[:ESCAPED])
+ ret[:UNSAFE] = Regexp.new("[^#{pattern[:UNRESERVED]}#{pattern[:RESERVED]}]")
+
+ # for Generic#initialize
+ ret[:SCHEME] = Regexp.new("^#{pattern[:SCHEME]}$")
+ ret[:USERINFO] = Regexp.new("^#{pattern[:USERINFO]}$")
+ ret[:HOST] = Regexp.new("^#{pattern[:HOST]}$")
+ ret[:PORT] = Regexp.new("^#{pattern[:PORT]}$")
+ ret[:OPAQUE] = Regexp.new("^#{pattern[:OPAQUE_PART]}$")
+ ret[:REGISTRY] = Regexp.new("^#{pattern[:REG_NAME]}$")
+ ret[:ABS_PATH] = Regexp.new("^#{pattern[:ABS_PATH]}$")
+ ret[:REL_PATH] = Regexp.new("^#{pattern[:REL_PATH]}$")
+ ret[:QUERY] = Regexp.new("^#{pattern[:QUERY]}$")
+ ret[:FRAGMENT] = Regexp.new("^#{pattern[:FRAGMENT]}$")
+
+ ret
+ end
+ end # class Parser
+
+ DEFAULT_PARSER = Parser.new
+ DEFAULT_PARSER.pattern.each_pair do |sym, str|
+ unless REGEXP::PATTERN.const_defined?(sym)
+ REGEXP::PATTERN.const_set(sym, str)
+ end
+ end
+ DEFAULT_PARSER.regexp.each_pair do |sym, str|
+ const_set(sym, str)
+ end
module Util # :nodoc:
def make_components_hash(klass, array_hash)
@@ -246,8 +468,6 @@ module URI
end
module Escape
- include REGEXP
-
#
# == Synopsis
#
@@ -280,19 +500,8 @@ module URI
# p URI.escape("@?@!", "!?")
# # => "@%3F@%21"
#
- def escape(str, unsafe = UNSAFE)
- unless unsafe.kind_of?(Regexp)
- # perhaps unsafe is String object
- unsafe = Regexp.new("[#{Regexp.quote(unsafe)}]", false, 'N')
- end
- str.gsub(unsafe) do
- us = $&
- tmp = ''
- us.each_byte do |uc|
- tmp << sprintf('%%%02X', uc)
- end
- tmp
- end
+ def escape(*arg)
+ DEFAULT_PARSER.escape(*arg)
end
alias encode escape
#
@@ -316,18 +525,19 @@ module URI
# p URI.unescape(enc_uri)
# # => "http://example.com/?a=\t\r"
#
- def unescape(str)
- str.gsub(ESCAPED) do
- $&[1,2].hex.chr
- end
+ def unescape(*arg)
+ DEFAULT_PARSER.unescape(*arg)
end
alias decode unescape
end
- include REGEXP
extend Escape
+ include REGEXP
@@schemes = {}
+ def self.scheme_list
+ @@schemes
+ end
#
# Base class for all URI exceptions.
@@ -378,75 +588,7 @@ module URI
# # => ["http", nil, "www.ruby-lang.org", nil, nil, "/", nil, nil, nil]
#
def self.split(uri)
- case uri
- when ''
- # null uri
-
- when ABS_URI
- scheme, opaque, userinfo, host, port,
- registry, path, query, fragment = $~[1..-1]
-
- # URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
-
- # absoluteURI = scheme ":" ( hier_part | opaque_part )
- # hier_part = ( net_path | abs_path ) [ "?" query ]
- # opaque_part = uric_no_slash *uric
-
- # abs_path = "/" path_segments
- # net_path = "//" authority [ abs_path ]
-
- # authority = server | reg_name
- # server = [ [ userinfo "@" ] hostport ]
-
- if !scheme
- raise InvalidURIError,
- "bad URI(absolute but no scheme): #{uri}"
- end
- if !opaque && (!path && (!host && !registry))
- raise InvalidURIError,
- "bad URI(absolute but no path): #{uri}"
- end
-
- when REL_URI
- scheme = nil
- opaque = nil
-
- userinfo, host, port, registry,
- rel_segment, abs_path, query, fragment = $~[1..-1]
- if rel_segment && abs_path
- path = rel_segment + abs_path
- elsif rel_segment
- path = rel_segment
- elsif abs_path
- path = abs_path
- end
-
- # URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
-
- # relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ]
-
- # net_path = "//" authority [ abs_path ]
- # abs_path = "/" path_segments
- # rel_path = rel_segment [ abs_path ]
-
- # authority = server | reg_name
- # server = [ [ userinfo "@" ] hostport ]
-
- else
- raise InvalidURIError, "bad URI(is not URI?): #{uri}"
- end
-
- path = '' if !path && !opaque # (see RFC2396 Section 5.2)
- ret = [
- scheme,
- userinfo, host, port, # X
- registry, # X
- path, # Y
- opaque, # Y
- query,
- fragment
- ]
- return ret
+ DEFAULT_PARSER.split(uri)
end
#
@@ -481,18 +623,7 @@ module URI
# # => "www.ruby-lang.org"
#
def self.parse(uri)
- scheme, userinfo, host, port,
- registry, path, opaque, query, fragment = self.split(uri)
-
- if scheme && @@schemes.include?(scheme.upcase)
- @@schemes[scheme.upcase].new(scheme, userinfo, host, port,
- registry, path, opaque, query,
- fragment)
- else
- Generic.new(scheme, userinfo, host, port,
- registry, path, opaque, query,
- fragment)
- end
+ DEFAULT_PARSER.parse(uri)
end
#
@@ -517,11 +648,7 @@ module URI
# # => #<URI::HTTP:0x2022ac02 URL:http://localhost/main.rbx>
#
def self.join(*str)
- u = self.parse(str[0])
- str[1 .. -1].each do |x|
- u = u.merge(x)
- end
- u
+ DEFAULT_PARSER.join(*str)
end
#
@@ -549,14 +676,7 @@ module URI
# # => ["http://foo.example.com/bla", "mailto:test@example.com"]
#
def self.extract(str, schemes = nil, &block)
- if block_given?
- str.scan(regexp(schemes)) { yield $& }
- nil
- else
- result = []
- str.scan(regexp(schemes)) { result.push $& }
- result
- end
+ DEFAULT_PARSER.extract(str, schemes, &block)
end
#
@@ -591,11 +711,7 @@ module URI
# end
#
def self.regexp(schemes = nil)
- unless schemes
- ABS_URI_REF
- else
- /(?=#{Regexp.union(*schemes)}:)#{PATTERN::X_ABS_URI}/xn
- end
+ DEFAULT_PARSER.make_regexp(schemes)
end
end
diff --git a/lib/uri/generic.rb b/lib/uri/generic.rb
index d907e0b4b2..65c6c7379d 100644
--- a/lib/uri/generic.rb
+++ b/lib/uri/generic.rb
@@ -16,7 +16,6 @@ module URI
#
class Generic
include URI
- include REGEXP
DEFAULT_PORT = nil
@@ -74,7 +73,7 @@ module URI
if args.kind_of?(Array)
return self.build(args.collect{|x|
if x
- URI.escape(x)
+ @parser.escape(x)
else
x
end
@@ -83,7 +82,7 @@ module URI
tmp = {}
args.each do |key, value|
tmp[key] = if value
- URI.escape(value)
+ @parser.escape(value)
else
value
end
@@ -122,6 +121,7 @@ module URI
"expected Array of or Hash of components of #{self.class} (#{self.class.component.join(', ')})"
end
+ tmp << DEFAULT_PARSER
tmp << true
return self.new(*tmp)
end
@@ -146,6 +146,8 @@ module URI
# Query data
# +fragment+::
# A part of URI after '#' sign
+ # +parser+::
+ # Parser for internal use [URI::DEFAULT_PARSER by default]
# +arg_check+::
# Check arguments [false by default]
#
@@ -158,6 +160,7 @@ module URI
path, opaque,
query,
fragment,
+ parser = DEFAULT_PARSER,
arg_check = false)
@scheme = nil
@user = nil
@@ -169,6 +172,7 @@ module URI
@opaque = nil
@registry = nil
@fragment = nil
+ @parser = parser
if arg_check
self.scheme = scheme
@@ -208,6 +212,7 @@ module URI
attr_reader :query
attr_reader :opaque
attr_reader :fragment
+ attr_reader :parser
# replace self by other URI object
def replace!(oth)
@@ -226,7 +231,7 @@ module URI
end
def check_scheme(v)
- if v && SCHEME !~ v
+ if v && @parser.regexp[:SCHEME] !~ v
raise InvalidComponentError,
"bad component(expected scheme component): #{v}"
end
@@ -265,7 +270,7 @@ module URI
return v unless v
- if USERINFO !~ v
+ if @parser.regexp[:USERINFO] !~ v
raise InvalidComponentError,
"bad component(expected userinfo component or user component): #{v}"
end
@@ -286,7 +291,7 @@ module URI
"password component depends user component"
end
- if USERINFO !~ v
+ if @parser.regexp[:USERINFO] !~ v
raise InvalidComponentError,
"bad component(expected user component): #{v}"
end
@@ -351,7 +356,7 @@ module URI
private :split_userinfo
def escape_userpass(v)
- v = URI.escape(v, /[@:\/]/o) # RFC 1738 section 3.1 #/
+ v = @parser.escape(v, /[@:\/]/o) # RFC 1738 section 3.1 #/
end
private :escape_userpass
@@ -379,7 +384,7 @@ module URI
if @registry || @opaque
raise InvalidURIError,
"can not set host with registry or opaque"
- elsif HOST !~ v
+ elsif @parser.regexp[:HOST] !~ v
raise InvalidComponentError,
"bad component(expected host component): #{v}"
end
@@ -405,7 +410,7 @@ module URI
if @registry || @opaque
raise InvalidURIError,
"can not set port with registry or opaque"
- elsif !v.kind_of?(Fixnum) && PORT !~ v
+ elsif !v.kind_of?(Fixnum) && @parser.regexp[:PORT] !~ v
raise InvalidComponentError,
"bad component(expected port component): #{v}"
end
@@ -441,7 +446,7 @@ module URI
if @host || @port || @user # userinfo = @user + ':' + @password
raise InvalidURIError,
"can not set registry with host, port, or userinfo"
- elsif v && REGISTRY !~ v
+ elsif v && @parser.regexp[:REGISTRY] !~ v
raise InvalidComponentError,
"bad component(expected registry component): #{v}"
end
@@ -471,12 +476,12 @@ module URI
end
if @scheme
- if v && v != '' && ABS_PATH !~ v
+ if v && v != '' && @parser.regexp[:ABS_PATH] !~ v
raise InvalidComponentError,
"bad component(expected absolute path component): #{v}"
end
else
- if v && v != '' && ABS_PATH !~ v && REL_PATH !~ v
+ if v && v != '' && @parser.regexp[:ABS_PATH] !~ v && @parser.regexp[:REL_PATH] !~ v
raise InvalidComponentError,
"bad component(expected relative path component): #{v}"
end
@@ -508,10 +513,10 @@ module URI
"query conflicts with opaque"
end
- if v && v != '' && QUERY !~ v
+ if v && v != '' && @parser.regexp[:QUERY] !~ v
raise InvalidComponentError,
"bad component(expected query component): #{v}"
- end
+ end
return true
end
@@ -537,7 +542,7 @@ module URI
if @host || @port || @user || @path # userinfo = @user + ':' + @password
raise InvalidURIError,
"can not set opaque with host, port, userinfo or path"
- elsif v && OPAQUE !~ v
+ elsif v && @parser.regexp[:OPAQUE] !~ v
raise InvalidComponentError,
"bad component(expected opaque component): #{v}"
end
@@ -560,7 +565,7 @@ module URI
def check_fragment(v)
return v unless v
- if v && v != '' && FRAGMENT !~ v
+ if v && v != '' && @parser.regexp[:FRAGMENT] !~ v
raise InvalidComponentError,
"bad component(expected fragment component): #{v}"
end
@@ -772,7 +777,7 @@ module URI
case oth
when Generic
when String
- oth = URI.parse(oth)
+ oth = @parser.parse(oth)
else
raise ArgumentError,
"bad argument(expected URI object or URI string)"
@@ -843,7 +848,7 @@ module URI
case oth
when Generic
when String
- oth = URI.parse(oth)
+ oth = @parser.parse(oth)
else
raise ArgumentError,
"bad argument(expected URI object or URI string)"
@@ -864,7 +869,7 @@ module URI
rel = URI::Generic.new(nil, # it is relative URI
self.userinfo, self.host, self.port,
self.registry, self.path, self.opaque,
- self.query, self.fragment)
+ self.query, self.fragment, @parser)
if rel.userinfo != oth.userinfo ||
rel.host.to_s.downcase != oth.host.to_s.downcase ||
@@ -955,7 +960,7 @@ module URI
case oth
when Generic
when String
- oth = URI.parse(oth)
+ oth = @parser.parse(oth)
else
raise ArgumentError,
"bad argument(expected URI object or URI string)"
@@ -1054,6 +1059,7 @@ module URI
end
def eql?(oth)
+ @parser == oth.parser &&
self.component_ary.eql?(oth.component_ary)
end
@@ -1111,7 +1117,7 @@ module URI
def coerce(oth)
case oth
when String
- oth = URI.parse(oth)
+ oth = @parser.parse(oth)
else
super
end
diff --git a/lib/uri/mailto.rb b/lib/uri/mailto.rb
index 3a9d15318f..38f972e1fb 100644
--- a/lib/uri/mailto.rb
+++ b/lib/uri/mailto.rb
@@ -135,7 +135,7 @@ module URI
@headers = []
if MAILTO_REGEXP =~ @opaque
- if arg[-1]
+ if arg[-1]
self.to = $1
self.headers = $2
else
@@ -159,7 +159,7 @@ module URI
return true unless v
return true if v.size == 0
- if OPAQUE !~ v || /\A#{MAILBOX_PATTERN}*\z/o !~ v
+ if @parser.regexp[:OPAQUE] !~ v || /\A#{MAILBOX_PATTERN}*\z/o !~ v
raise InvalidComponentError,
"bad component(expected opaque component): #{v}"
end
@@ -183,7 +183,7 @@ module URI
return true unless v
return true if v.size == 0
- if OPAQUE !~ v ||
+ if @parser.regexp[:OPAQUE] !~ v ||
/\A(#{HEADER_PATTERN}(?:\&#{HEADER_PATTERN})*)\z/o !~ v
raise InvalidComponentError,
"bad component(expected opaque component): #{v}"
@@ -239,18 +239,18 @@ module URI
# # => "To: ruby-list@ruby-lang.org\nSubject: subscribe\nCc: myaddr\n\n\n"
#
def to_mailtext
- to = URI::unescape(@to)
+ to = @parser.unescape(@to)
head = ''
body = ''
@headers.each do |x|
case x[0]
when 'body'
- body = URI::unescape(x[1])
+ body = @parser.unescape(x[1])
when 'to'
- to << ', ' + URI::unescape(x[1])
+ to << ', ' + @parser.unescape(x[1])
else
- head << URI::unescape(x[0]).capitalize + ': ' +
- URI::unescape(x[1]) + "\n"
+ head << @parser.unescape(x[0]).capitalize + ': ' +
+ @parser.unescape(x[1]) + "\n"
end
end
diff --git a/lib/webrick/httpauth/digestauth.rb b/lib/webrick/httpauth/digestauth.rb
index 2bc3e97817..eec064ca26 100644
--- a/lib/webrick/httpauth/digestauth.rb
+++ b/lib/webrick/httpauth/digestauth.rb
@@ -52,7 +52,7 @@ module WEBrick
when 'SHA1','SHA1-sess' # it is a bonus feature :-)
@h = Digest::SHA1
else
- msg = format('Alogrithm "%s" is not supported.', @algorithm)
+ msg = format('Algorithm "%s" is not supported.', @algorithm)
raise ArgumentError.new(msg)
end
@@ -229,7 +229,7 @@ module WEBrick
def split_param_value(string)
ret = {}
- while string.size != 0
+ while string.bytesize != 0
case string
when /^\s*([\w\-\.\*\%\!]+)=\s*\"((\\.|[^\"])*)\"\s*,?/
key = $1
diff --git a/lib/webrick/httpproxy.rb b/lib/webrick/httpproxy.rb
index 29ee1057e9..f35a177777 100644
--- a/lib/webrick/httpproxy.rb
+++ b/lib/webrick/httpproxy.rb
@@ -146,11 +146,11 @@ module WEBrick
while fds = IO::select([ua, os])
if fds[0].member?(ua)
buf = ua.sysread(1024);
- @logger.debug("CONNECT: #{buf.size} byte from User-Agent")
+ @logger.debug("CONNECT: #{buf.bytesize} byte from User-Agent")
os.syswrite(buf)
elsif fds[0].member?(os)
buf = os.sysread(1024);
- @logger.debug("CONNECT: #{buf.size} byte from #{host}:#{port}")
+ @logger.debug("CONNECT: #{buf.bytesize} byte from #{host}:#{port}")
ua.syswrite(buf)
end
end
diff --git a/lib/webrick/httprequest.rb b/lib/webrick/httprequest.rb
index f0994ef253..3a8d744016 100644
--- a/lib/webrick/httprequest.rb
+++ b/lib/webrick/httprequest.rb
@@ -244,12 +244,12 @@ module WEBrick
def read_request_line(socket)
@request_line = read_line(socket, 1024) if socket
- if @request_line.size >= 1024 and @request_line[-1, 1] != LF
+ if @request_line.bytesize >= 1024 and @request_line[-1, 1] != LF
raise HTTPStatus::RequestURITooLarge
end
@request_time = Time.now
raise HTTPStatus::EOFError unless @request_line
- if /^(\S+)\s+(\S+)(?:\s+HTTP\/(\d+\.\d+))?\r?\n/mo =~ @request_line
+ if /^(\S+)\s+(\S++)(?:\s+HTTP\/(\d+\.\d+))?\r?\n/mo =~ @request_line
@request_method = $1
@unparsed_uri = $2
@http_version = HTTPVersion.new($3 ? $3 : "0.9")
@@ -307,7 +307,7 @@ module WEBrick
while @remaining_size > 0
sz = [@buffer_size, @remaining_size].min
break unless buf = read_data(socket, sz)
- @remaining_size -= buf.size
+ @remaining_size -= buf.bytesize
block.call(buf)
end
if @remaining_size > 0 && @socket.eof?
@@ -334,7 +334,7 @@ module WEBrick
chunk_size, = read_chunk_size(socket)
while chunk_size > 0
data = read_data(socket, chunk_size) # read chunk-data
- if data.nil? || data.size != chunk_size
+ if data.nil? || data.bytesize != chunk_size
raise BadRequest, "bad chunk data size."
end
read_line(socket) # skip CRLF
diff --git a/lib/webrick/httpresponse.rb b/lib/webrick/httpresponse.rb
index 301ecb8372..740a8fe921 100644
--- a/lib/webrick/httpresponse.rb
+++ b/lib/webrick/httpresponse.rb
@@ -142,7 +142,7 @@ module WEBrick
@header.delete('content-length')
elsif @header['content-length'].nil?
unless @body.is_a?(IO)
- @header['content-length'] = @body ? @body.size : 0
+ @header['content-length'] = @body ? @body.bytesize : 0
end
end
@@ -260,10 +260,10 @@ module WEBrick
while buf = @body.read(@buffer_size)
next if buf.empty?
data = ""
- data << format("%x", buf.size) << CRLF
+ data << format("%x", buf.bytesize) << CRLF
data << buf << CRLF
_write_data(socket, data)
- @sent_size += buf.size
+ @sent_size += buf.bytesize
end
_write_data(socket, "0#{CRLF}#{CRLF}")
else
@@ -280,20 +280,20 @@ module WEBrick
if @request_method == "HEAD"
# do nothing
elsif chunked?
- remain = body ? @body.size : 0
+ remain = body ? @body.bytesize : 0
while buf = @body[@sent_size, @buffer_size]
break if buf.empty?
data = ""
- data << format("%x", buf.size) << CRLF
+ data << format("%x", buf.bytesize) << CRLF
data << buf << CRLF
_write_data(socket, data)
- @sent_size += buf.size
+ @sent_size += buf.bytesize
end
_write_data(socket, "0#{CRLF}#{CRLF}")
else
- if @body && @body.size > 0
+ if @body && @body.bytesize > 0
_write_data(socket, @body)
- @sent_size = @body.size
+ @sent_size = @body.bytesize
end
end
end
@@ -302,7 +302,7 @@ module WEBrick
while offset > 0
sz = @buffer_size < size ? @buffer_size : size
buf = input.read(sz)
- offset -= buf.size
+ offset -= buf.bytesize
end
if size == 0
@@ -314,7 +314,7 @@ module WEBrick
sz = @buffer_size < size ? @buffer_size : size
buf = input.read(sz)
_write_data(output, buf)
- size -= buf.size
+ size -= buf.bytesize
end
end
end
diff --git a/lib/webrick/httpservlet/abstract.rb b/lib/webrick/httpservlet/abstract.rb
index 5375c4622d..2a0a4049f2 100644
--- a/lib/webrick/httpservlet/abstract.rb
+++ b/lib/webrick/httpservlet/abstract.rb
@@ -59,7 +59,7 @@ module WEBrick
def redirect_to_directory_uri(req, res)
if req.path[-1] != ?/
location = WEBrick::HTTPUtils.escape_path(req.path + "/")
- if req.query_string && req.query_string.size > 0
+ if req.query_string && req.query_string.bytesize > 0
location << "?" << req.query_string
end
res.set_redirect(HTTPStatus::MovedPermanently, location)
diff --git a/lib/webrick/httpservlet/cgi_runner.rb b/lib/webrick/httpservlet/cgi_runner.rb
index 006abd458e..dd7325d25c 100644
--- a/lib/webrick/httpservlet/cgi_runner.rb
+++ b/lib/webrick/httpservlet/cgi_runner.rb
@@ -13,7 +13,7 @@ def sysread(io, size)
while size > 0
tmp = io.sysread(size)
buf << tmp
- size -= tmp.size
+ size -= tmp.bytesize
end
return buf
end
diff --git a/lib/webrick/httpservlet/cgihandler.rb b/lib/webrick/httpservlet/cgihandler.rb
index 9211e95354..f504f4d63b 100644
--- a/lib/webrick/httpservlet/cgihandler.rb
+++ b/lib/webrick/httpservlet/cgihandler.rb
@@ -48,14 +48,14 @@ module WEBrick
end
dump = Marshal.dump(meta)
- cgi_in.write("%8d" % cgi_out.path.size)
+ cgi_in.write("%8d" % cgi_out.path.bytesize)
cgi_in.write(cgi_out.path)
- cgi_in.write("%8d" % cgi_err.path.size)
+ cgi_in.write("%8d" % cgi_err.path.bytesize)
cgi_in.write(cgi_err.path)
- cgi_in.write("%8d" % dump.size)
+ cgi_in.write("%8d" % dump.bytesize)
cgi_in.write(dump)
- if req.body and req.body.size > 0
+ if req.body and req.body.bytesize > 0
cgi_in.write(req.body)
end
ensure
@@ -65,7 +65,7 @@ module WEBrick
data = cgi_out.read
cgi_out.close(true)
if errmsg = cgi_err.read
- if errmsg.size > 0
+ if errmsg.bytesize > 0
@logger.error("CGIHandler: #{@script_filename}:\n" + errmsg)
end
end
diff --git a/lib/webrick/httpservlet/filehandler.rb b/lib/webrick/httpservlet/filehandler.rb
index 272ffbc3fc..f1cc88bed9 100644
--- a/lib/webrick/httpservlet/filehandler.rb
+++ b/lib/webrick/httpservlet/filehandler.rb
@@ -407,13 +407,13 @@ module WEBrick
list.each{ |name, time, size|
if name == ".."
dname = "Parent Directory"
- elsif name.size > 25
+ elsif name.bytesize > 25
dname = name.sub(/^(.{23})(?:.*)/, '\1..')
else
dname = name
end
s = " <A HREF=\"#{HTTPUtils::escape(name)}\">#{dname}</A>"
- s << " " * (30 - dname.size)
+ s << " " * (30 - dname.bytesize)
s << (time ? time.strftime("%Y/%m/%d %H:%M ") : " " * 22)
s << (size >= 0 ? size.to_s : "-") << "\n"
res.body << s
diff --git a/lib/webrick/utils.rb b/lib/webrick/utils.rb
index 654abb28b1..f2ecfc19a8 100644
--- a/lib/webrick/utils.rb
+++ b/lib/webrick/utils.rb
@@ -89,7 +89,7 @@ module WEBrick
"abcdefghijklmnopqrstuvwxyz"
def random_string(len)
- rand_max = RAND_CHARS.size
+ rand_max = RAND_CHARS.bytesize
ret = ""
len.times{ ret << RAND_CHARS[rand(rand_max)] }
ret
diff --git a/lib/xmlrpc/client.rb b/lib/xmlrpc/client.rb
index 278855e01d..9d0a8bbaf0 100644
--- a/lib/xmlrpc/client.rb
+++ b/lib/xmlrpc/client.rb
@@ -605,16 +605,16 @@ module XMLRPC
class Proxy
def initialize(server, prefix, args=[], meth=:call, delim=".")
- @server = server
- @prefix = prefix ? prefix + delim : ""
- @args = args
+ @server = server
+ @prefix = prefix ? prefix + delim : ""
+ @args = args
@meth = meth
end
def method_missing(mid, *args)
- pre = @prefix + mid.to_s
- arg = @args + args
- @server.send(@meth, pre, *arg)
+ pre = @prefix + mid.to_s
+ arg = @args + args
+ @server.send(@meth, pre, *arg)
end
end # class Proxy
diff --git a/lib/xmlrpc/create.rb b/lib/xmlrpc/create.rb
index 3c2bbd24e6..530d229f66 100644
--- a/lib/xmlrpc/create.rb
+++ b/lib/xmlrpc/create.rb
@@ -15,11 +15,11 @@ module XMLRPC
class Abstract
def ele(name, *children)
- element(name, nil, *children)
+ element(name, nil, *children)
end
def tag(name, txt)
- element(name, nil, text(txt))
+ element(name, nil, text(txt))
end
end
@@ -27,19 +27,19 @@ module XMLRPC
class Simple < Abstract
def document_to_str(doc)
- doc
+ doc
end
def document(*params)
- params.join("")
+ params.join("")
end
def pi(name, *params)
- "<?#{name} " + params.join(" ") + " ?>"
+ "<?#{name} " + params.join(" ") + " ?>"
end
def element(name, attrs, *children)
- raise "attributes not yet implemented" unless attrs.nil?
+ raise "attributes not yet implemented" unless attrs.nil?
if children.empty?
"<#{name}/>"
else
@@ -61,27 +61,27 @@ module XMLRPC
class XMLParser < Abstract
def initialize
- require "xmltreebuilder"
+ require "xmltreebuilder"
end
def document_to_str(doc)
- doc.to_s
+ doc.to_s
end
def document(*params)
- XML::SimpleTree::Document.new(*params)
+ XML::SimpleTree::Document.new(*params)
end
def pi(name, *params)
- XML::SimpleTree::ProcessingInstruction.new(name, *params)
+ XML::SimpleTree::ProcessingInstruction.new(name, *params)
end
def element(name, attrs, *children)
- XML::SimpleTree::Element.new(name, attrs, *children)
+ XML::SimpleTree::Element.new(name, attrs, *children)
end
def text(txt)
- XML::SimpleTree::Text.new(txt)
+ XML::SimpleTree::Text.new(txt)
end
end # class XMLParser
@@ -111,20 +111,20 @@ module XMLRPC
name = name.to_s
if name !~ /[a-zA-Z0-9_.:\/]+/
- raise ArgumentError, "Wrong XML-RPC method-name"
+ raise ArgumentError, "Wrong XML-RPC method-name"
end
parameter = params.collect do |param|
- @writer.ele("param", conv2value(param))
+ @writer.ele("param", conv2value(param))
end
tree = @writer.document(
- @writer.pi("xml", 'version="1.0"'),
- @writer.ele("methodCall",
- @writer.tag("methodName", name),
- @writer.ele("params", *parameter)
- )
- )
+ @writer.pi("xml", 'version="1.0"'),
+ @writer.ele("methodCall",
+ @writer.tag("methodName", name),
+ @writer.ele("params", *parameter)
+ )
+ )
@writer.document_to_str(tree) + "\n"
end
@@ -144,23 +144,23 @@ module XMLRPC
def methodResponse(is_ret, *params)
if is_ret
- resp = params.collect do |param|
- @writer.ele("param", conv2value(param))
- end
+ resp = params.collect do |param|
+ @writer.ele("param", conv2value(param))
+ end
- resp = [@writer.ele("params", *resp)]
+ resp = [@writer.ele("params", *resp)]
else
- if params.size != 1 or params[0] === XMLRPC::FaultException
- raise ArgumentError, "no valid fault-structure given"
- end
- resp = @writer.ele("fault", conv2value(params[0].to_h))
+ if params.size != 1 or params[0] === XMLRPC::FaultException
+ raise ArgumentError, "no valid fault-structure given"
+ end
+ resp = @writer.ele("fault", conv2value(params[0].to_h))
end
-
+
tree = @writer.document(
- @writer.pi("xml", 'version="1.0"'),
- @writer.ele("methodResponse", resp)
- )
+ @writer.pi("xml", 'version="1.0"'),
+ @writer.ele("methodResponse", resp)
+ )
@writer.document_to_str(tree) + "\n"
end
@@ -177,11 +177,11 @@ module XMLRPC
#
def conv2value(param)
- val = case param
- when Fixnum
- @writer.tag("i4", param.to_s)
+ val = case param
+ when Fixnum
+ @writer.tag("i4", param.to_s)
- when Bignum
+ when Bignum
if Config::ENABLE_BIGINT
@writer.tag("i4", param.to_s)
else
@@ -191,14 +191,14 @@ module XMLRPC
raise "Bignum is too big! Must be signed 32-bit integer!"
end
end
- when TrueClass, FalseClass
- @writer.tag("boolean", param ? "1" : "0")
+ when TrueClass, FalseClass
+ @writer.tag("boolean", param ? "1" : "0")
- when Symbol
- @writer.tag("string", param.to_s)
+ when Symbol
+ @writer.tag("string", param.to_s)
- when String
- @writer.tag("string", param)
+ when String
+ @writer.tag("string", param)
when NilClass
if Config::ENABLE_NIL_CREATE
@@ -207,51 +207,51 @@ module XMLRPC
raise "Wrong type NilClass. Not allowed!"
end
- when Float
- @writer.tag("double", param.to_s)
-
- when Struct
- h = param.members.collect do |key|
- value = param[key]
- @writer.ele("member",
- @writer.tag("name", key.to_s),
- conv2value(value)
- )
- end
-
- @writer.ele("struct", *h)
-
- when Hash
- # TODO: can a Hash be empty?
-
- h = param.collect do |key, value|
- @writer.ele("member",
- @writer.tag("name", key.to_s),
- conv2value(value)
- )
- end
-
- @writer.ele("struct", *h)
-
- when Array
- # TODO: can an Array be empty?
- a = param.collect {|v| conv2value(v) }
-
- @writer.ele("array",
- @writer.ele("data", *a)
- )
-
- when Time, Date, ::DateTime
- @writer.tag("dateTime.iso8601", param.strftime("%Y%m%dT%H:%M:%S"))
-
- when XMLRPC::DateTime
- @writer.tag("dateTime.iso8601",
- format("%.4d%02d%02dT%02d:%02d:%02d", *param.to_a))
+ when Float
+ @writer.tag("double", param.to_s)
+
+ when Struct
+ h = param.members.collect do |key|
+ value = param[key]
+ @writer.ele("member",
+ @writer.tag("name", key.to_s),
+ conv2value(value)
+ )
+ end
+
+ @writer.ele("struct", *h)
+
+ when Hash
+ # TODO: can a Hash be empty?
+
+ h = param.collect do |key, value|
+ @writer.ele("member",
+ @writer.tag("name", key.to_s),
+ conv2value(value)
+ )
+ end
+
+ @writer.ele("struct", *h)
+
+ when Array
+ # TODO: can an Array be empty?
+ a = param.collect {|v| conv2value(v) }
+
+ @writer.ele("array",
+ @writer.ele("data", *a)
+ )
+
+ when Time, Date, ::DateTime
+ @writer.tag("dateTime.iso8601", param.strftime("%Y%m%dT%H:%M:%S"))
+
+ when XMLRPC::DateTime
+ @writer.tag("dateTime.iso8601",
+ format("%.4d%02d%02dT%02d:%02d:%02d", *param.to_a))
- when XMLRPC::Base64
- @writer.tag("base64", param.encoded)
+ when XMLRPC::Base64
+ @writer.tag("base64", param.encoded)
- else
+ else
if Config::ENABLE_MARSHALLING and param.class.included_modules.include? XMLRPC::Marshallable
# convert Ruby object into Hash
ret = {"___class___" => param.class.name}
@@ -274,9 +274,9 @@ module XMLRPC
raise "Wrong type!"
end
end
- end
-
- @writer.ele("value", val)
+ end
+
+ @writer.ele("value", val)
end
def wrong_type(value)
diff --git a/lib/xmlrpc/httpserver.rb b/lib/xmlrpc/httpserver.rb
index 9afb5fd5ec..020e6cbcd9 100644
--- a/lib/xmlrpc/httpserver.rb
+++ b/lib/xmlrpc/httpserver.rb
@@ -156,7 +156,7 @@ private
# parse HTTP headers
while (line=io.gets) !~ /^(\n|\r)/
if line =~ /^([\w-]+):\s*(.*)$/
- request.header[$1] = $2.strip
+ request.header[$1] = $2.strip
end
end
diff --git a/lib/xmlrpc/parser.rb b/lib/xmlrpc/parser.rb
index 6d10fde9d9..2cf0530c9f 100644
--- a/lib/xmlrpc/parser.rb
+++ b/lib/xmlrpc/parser.rb
@@ -160,11 +160,11 @@ module XMLRPC
class AbstractTreeParser
def parseMethodResponse(str)
- methodResponse_document(createCleanedTree(str))
+ methodResponse_document(createCleanedTree(str))
end
def parseMethodCall(str)
- methodCall_document(createCleanedTree(str))
+ methodCall_document(createCleanedTree(str))
end
private
@@ -174,11 +174,11 @@ module XMLRPC
# and all comments
#
def removeWhitespacesAndComments(node)
- remove = []
- childs = node.childNodes.to_a
- childs.each do |nd|
- case _nodeType(nd)
- when :TEXT
+ remove = []
+ childs = node.childNodes.to_a
+ childs.each do |nd|
+ case _nodeType(nd)
+ when :TEXT
# TODO: add nil?
unless %w(i4 int boolean string double dateTime.iso8601 base64).include? node.nodeName
@@ -189,190 +189,190 @@ module XMLRPC
else
remove << nd if nd.nodeValue.strip == ""
end
- end
- when :COMMENT
- remove << nd
- else
- removeWhitespacesAndComments(nd)
- end
- end
+ end
+ when :COMMENT
+ remove << nd
+ else
+ removeWhitespacesAndComments(nd)
+ end
+ end
- remove.each { |i| node.removeChild(i) }
+ remove.each { |i| node.removeChild(i) }
end
def nodeMustBe(node, name)
- cmp = case name
- when Array
- name.include?(node.nodeName)
- when String
- name == node.nodeName
- else
- raise "error"
- end
+ cmp = case name
+ when Array
+ name.include?(node.nodeName)
+ when String
+ name == node.nodeName
+ else
+ raise "error"
+ end
- if not cmp then
- raise "wrong xml-rpc (name)"
- end
+ if not cmp then
+ raise "wrong xml-rpc (name)"
+ end
- node
+ node
end
#
# returns, when successfully the only child-node
#
def hasOnlyOneChild(node, name=nil)
- if node.childNodes.to_a.size != 1
- raise "wrong xml-rpc (size)"
- end
- if name != nil then
- nodeMustBe(node.firstChild, name)
- end
+ if node.childNodes.to_a.size != 1
+ raise "wrong xml-rpc (size)"
+ end
+ if name != nil then
+ nodeMustBe(node.firstChild, name)
+ end
end
def assert(b)
- if not b then
- raise "assert-fail"
- end
+ if not b then
+ raise "assert-fail"
+ end
end
# the node `node` has empty string or string
def text_zero_one(node)
- nodes = node.childNodes.to_a.size
+ nodes = node.childNodes.to_a.size
- if nodes == 1
- text(node.firstChild)
- elsif nodes == 0
- ""
- else
- raise "wrong xml-rpc (size)"
- end
+ if nodes == 1
+ text(node.firstChild)
+ elsif nodes == 0
+ ""
+ else
+ raise "wrong xml-rpc (size)"
+ end
end
def integer(node)
- #TODO: check string for float because to_i returnsa
- # 0 when wrong string
- nodeMustBe(node, %w(i4 int))
- hasOnlyOneChild(node)
-
- Convert.int(text(node.firstChild))
+ #TODO: check string for float because to_i returnsa
+ # 0 when wrong string
+ nodeMustBe(node, %w(i4 int))
+ hasOnlyOneChild(node)
+
+ Convert.int(text(node.firstChild))
end
def boolean(node)
- nodeMustBe(node, "boolean")
- hasOnlyOneChild(node)
-
+ nodeMustBe(node, "boolean")
+ hasOnlyOneChild(node)
+
Convert.boolean(text(node.firstChild))
end
def v_nil(node)
nodeMustBe(node, "nil")
- assert( node.childNodes.to_a.size == 0 )
+ assert( node.childNodes.to_a.size == 0 )
nil
end
def string(node)
- nodeMustBe(node, "string")
- text_zero_one(node)
+ nodeMustBe(node, "string")
+ text_zero_one(node)
end
def double(node)
- #TODO: check string for float because to_f returnsa
- # 0.0 when wrong string
- nodeMustBe(node, "double")
- hasOnlyOneChild(node)
-
- Convert.double(text(node.firstChild))
+ #TODO: check string for float because to_f returnsa
+ # 0.0 when wrong string
+ nodeMustBe(node, "double")
+ hasOnlyOneChild(node)
+
+ Convert.double(text(node.firstChild))
end
def dateTime(node)
- nodeMustBe(node, "dateTime.iso8601")
- hasOnlyOneChild(node)
-
+ nodeMustBe(node, "dateTime.iso8601")
+ hasOnlyOneChild(node)
+
Convert.dateTime( text(node.firstChild) )
end
def base64(node)
- nodeMustBe(node, "base64")
- #hasOnlyOneChild(node)
-
+ nodeMustBe(node, "base64")
+ #hasOnlyOneChild(node)
+
Convert.base64(text_zero_one(node))
end
def member(node)
- nodeMustBe(node, "member")
- assert( node.childNodes.to_a.size == 2 )
+ nodeMustBe(node, "member")
+ assert( node.childNodes.to_a.size == 2 )
- [ name(node[0]), value(node[1]) ]
+ [ name(node[0]), value(node[1]) ]
end
def name(node)
- nodeMustBe(node, "name")
- #hasOnlyOneChild(node)
- text_zero_one(node)
+ nodeMustBe(node, "name")
+ #hasOnlyOneChild(node)
+ text_zero_one(node)
end
def array(node)
- nodeMustBe(node, "array")
- hasOnlyOneChild(node, "data")
- data(node.firstChild)
+ nodeMustBe(node, "array")
+ hasOnlyOneChild(node, "data")
+ data(node.firstChild)
end
def data(node)
- nodeMustBe(node, "data")
+ nodeMustBe(node, "data")
- node.childNodes.to_a.collect do |val|
- value(val)
- end
+ node.childNodes.to_a.collect do |val|
+ value(val)
+ end
end
def param(node)
- nodeMustBe(node, "param")
- hasOnlyOneChild(node, "value")
- value(node.firstChild)
+ nodeMustBe(node, "param")
+ hasOnlyOneChild(node, "value")
+ value(node.firstChild)
end
def methodResponse(node)
- nodeMustBe(node, "methodResponse")
- hasOnlyOneChild(node, %w(params fault))
- child = node.firstChild
+ nodeMustBe(node, "methodResponse")
+ hasOnlyOneChild(node, %w(params fault))
+ child = node.firstChild
- case child.nodeName
- when "params"
- [ true, params(child,false) ]
- when "fault"
- [ false, fault(child) ]
- else
- raise "unexpected error"
- end
+ case child.nodeName
+ when "params"
+ [ true, params(child,false) ]
+ when "fault"
+ [ false, fault(child) ]
+ else
+ raise "unexpected error"
+ end
end
def methodName(node)
- nodeMustBe(node, "methodName")
- hasOnlyOneChild(node)
- text(node.firstChild)
+ nodeMustBe(node, "methodName")
+ hasOnlyOneChild(node)
+ text(node.firstChild)
end
def params(node, call=true)
- nodeMustBe(node, "params")
+ nodeMustBe(node, "params")
- if call
- node.childNodes.to_a.collect do |n|
- param(n)
- end
- else # response (only one param)
- hasOnlyOneChild(node)
- param(node.firstChild)
- end
+ if call
+ node.childNodes.to_a.collect do |n|
+ param(n)
+ end
+ else # response (only one param)
+ hasOnlyOneChild(node)
+ param(node.firstChild)
+ end
end
def fault(node)
- nodeMustBe(node, "fault")
- hasOnlyOneChild(node, "value")
- f = value(node.firstChild)
+ nodeMustBe(node, "fault")
+ hasOnlyOneChild(node, "value")
+ f = value(node.firstChild)
Convert.fault(f)
end
@@ -380,76 +380,76 @@ module XMLRPC
# _nodeType is defined in the subclass
def text(node)
- assert( _nodeType(node) == :TEXT )
- assert( node.hasChildNodes == false )
- assert( node.nodeValue != nil )
+ assert( _nodeType(node) == :TEXT )
+ assert( node.hasChildNodes == false )
+ assert( node.nodeValue != nil )
- node.nodeValue.to_s
+ node.nodeValue.to_s
end
def struct(node)
- nodeMustBe(node, "struct")
+ nodeMustBe(node, "struct")
- hash = {}
- node.childNodes.to_a.each do |me|
- n, v = member(me)
- hash[n] = v
- end
+ hash = {}
+ node.childNodes.to_a.each do |me|
+ n, v = member(me)
+ hash[n] = v
+ end
Convert.struct(hash)
- end
+ end
def value(node)
- nodeMustBe(node, "value")
- nodes = node.childNodes.to_a.size
+ nodeMustBe(node, "value")
+ nodes = node.childNodes.to_a.size
if nodes == 0
return ""
elsif nodes > 1
- raise "wrong xml-rpc (size)"
+ raise "wrong xml-rpc (size)"
end
- child = node.firstChild
+ child = node.firstChild
- case _nodeType(child)
- when :TEXT
+ case _nodeType(child)
+ when :TEXT
text_zero_one(node)
- when :ELEMENT
- case child.nodeName
- when "i4", "int" then integer(child)
- when "boolean" then boolean(child)
- when "string" then string(child)
- when "double" then double(child)
- when "dateTime.iso8601" then dateTime(child)
- when "base64" then base64(child)
- when "struct" then struct(child)
- when "array" then array(child)
+ when :ELEMENT
+ case child.nodeName
+ when "i4", "int" then integer(child)
+ when "boolean" then boolean(child)
+ when "string" then string(child)
+ when "double" then double(child)
+ when "dateTime.iso8601" then dateTime(child)
+ when "base64" then base64(child)
+ when "struct" then struct(child)
+ when "array" then array(child)
when "nil"
if Config::ENABLE_NIL_PARSER
v_nil(child)
else
raise "wrong/unknown XML-RPC type 'nil'"
end
- else
- raise "wrong/unknown XML-RPC type"
- end
- else
- raise "wrong type of node"
- end
+ else
+ raise "wrong/unknown XML-RPC type"
+ end
+ else
+ raise "wrong type of node"
+ end
end
def methodCall(node)
- nodeMustBe(node, "methodCall")
- assert( (1..2).include?( node.childNodes.to_a.size ) )
- name = methodName(node[0])
-
- if node.childNodes.to_a.size == 2 then
- pa = params(node[1])
- else # no parameters given
- pa = []
- end
- [name, pa]
+ nodeMustBe(node, "methodCall")
+ assert( (1..2).include?( node.childNodes.to_a.size ) )
+ name = methodName(node[0])
+
+ if node.childNodes.to_a.size == 2 then
+ pa = params(node[1])
+ else # no parameters given
+ pa = []
+ end
+ [name, pa]
end
end # module TreeParserMixin
@@ -635,34 +635,34 @@ module XMLRPC
private
def _nodeType(node)
- tp = node.nodeType
- if tp == XML::SimpleTree::Node::TEXT then :TEXT
- elsif tp == XML::SimpleTree::Node::COMMENT then :COMMENT
- elsif tp == XML::SimpleTree::Node::ELEMENT then :ELEMENT
- else :ELSE
- end
+ tp = node.nodeType
+ if tp == XML::SimpleTree::Node::TEXT then :TEXT
+ elsif tp == XML::SimpleTree::Node::COMMENT then :COMMENT
+ elsif tp == XML::SimpleTree::Node::ELEMENT then :ELEMENT
+ else :ELSE
+ end
end
def methodResponse_document(node)
- assert( node.nodeType == XML::SimpleTree::Node::DOCUMENT )
- hasOnlyOneChild(node, "methodResponse")
-
- methodResponse(node.firstChild)
+ assert( node.nodeType == XML::SimpleTree::Node::DOCUMENT )
+ hasOnlyOneChild(node, "methodResponse")
+
+ methodResponse(node.firstChild)
end
def methodCall_document(node)
- assert( node.nodeType == XML::SimpleTree::Node::DOCUMENT )
- hasOnlyOneChild(node, "methodCall")
-
- methodCall(node.firstChild)
+ assert( node.nodeType == XML::SimpleTree::Node::DOCUMENT )
+ hasOnlyOneChild(node, "methodCall")
+
+ methodCall(node.firstChild)
end
def createCleanedTree(str)
- doc = XML::SimpleTreeBuilder.new.parse(str)
- doc.documentElement.normalize
- removeWhitespacesAndComments(doc)
- doc
+ doc = XML::SimpleTreeBuilder.new.parse(str)
+ doc.documentElement.normalize
+ removeWhitespacesAndComments(doc)
+ doc
end
end # class XMLParser
@@ -676,21 +676,21 @@ module XMLRPC
private
def _nodeType(node)
- node.nodeType
+ node.nodeType
end
def methodResponse_document(node)
- methodResponse(node)
+ methodResponse(node)
end
def methodCall_document(node)
- methodCall(node)
+ methodCall(node)
end
def createCleanedTree(str)
doc = ::NQXML::TreeParser.new(str).document.rootNode
- removeWhitespacesAndComments(doc)
- doc
+ removeWhitespacesAndComments(doc)
+ doc
end
end # class NQXMLTreeParser
@@ -715,7 +715,7 @@ module XMLRPC
def parse(str)
parser = REXML::Document.parse_stream(str, self)
- end
+ end
end
end
diff --git a/lib/xmlrpc/utils.rb b/lib/xmlrpc/utils.rb
index f0966fee40..4c2b63c9c6 100644
--- a/lib/xmlrpc/utils.rb
+++ b/lib/xmlrpc/utils.rb
@@ -37,7 +37,7 @@ module XMLRPC
def create
# if set_writer was not already called then call it now
if @create.nil? then
- set_writer(Config::DEFAULT_WRITER.new)
+ set_writer(Config::DEFAULT_WRITER.new)
end
@create
end
@@ -45,7 +45,7 @@ module XMLRPC
def parser
# if set_parser was not already called then call it now
if @parser.nil? then
- set_parser(Config::DEFAULT_PARSER.new)
+ set_parser(Config::DEFAULT_PARSER.new)
end
@parser
end
diff --git a/lib/yaml.rb b/lib/yaml.rb
index a8da42a321..12853401c1 100644
--- a/lib/yaml.rb
+++ b/lib/yaml.rb
@@ -213,7 +213,7 @@ module YAML
# end
# end
#
- def YAML.each_document( io, &block )
+ def YAML.each_document( io, &block )
yp = parser.load_documents( io, &block )
end
@@ -228,7 +228,7 @@ module YAML
# end
# end
#
- def YAML.load_documents( io, &doc_proc )
+ def YAML.load_documents( io, &doc_proc )
YAML.each_document( io, &doc_proc )
end
@@ -243,7 +243,7 @@ module YAML
# end
# end
#
- def YAML.each_node( io, &doc_proc )
+ def YAML.each_node( io, &doc_proc )
yp = generic_parser.load_documents( io, &doc_proc )
end
@@ -258,7 +258,7 @@ module YAML
# end
# end
#
- def YAML.parse_documents( io, &doc_proc )
+ def YAML.parse_documents( io, &doc_proc )
YAML.each_node( io, &doc_proc )
end
diff --git a/lib/yaml/rubytypes.rb b/lib/yaml/rubytypes.rb
index 35b719196e..ae65b355e1 100644
--- a/lib/yaml/rubytypes.rb
+++ b/lib/yaml/rubytypes.rb
@@ -379,6 +379,44 @@ class Float
end
end
+class Rational
+ yaml_as "tag:ruby.yaml.org,2002:object:Rational"
+ def Rational.yaml_new( klass, tag, val )
+ if val.is_a? String
+ Rational( val )
+ else
+ Rational( val['numerator'], val['denominator'] )
+ end
+ end
+ def to_yaml( opts = {} )
+ YAML::quick_emit( self, opts ) do |out|
+ out.map( taguri, nil ) do |map|
+ map.add( 'denominator', denominator )
+ map.add( 'numerator', numerator )
+ end
+ end
+ end
+end
+
+class Complex
+ yaml_as "tag:ruby.yaml.org,2002:object:Complex"
+ def Complex.yaml_new( klass, tag, val )
+ if val.is_a? String
+ Complex( val )
+ else
+ Complex( val['real'], val['image'] )
+ end
+ end
+ def to_yaml( opts = {} )
+ YAML::quick_emit( self, opts ) do |out|
+ out.map( taguri, nil ) do |map|
+ map.add( 'image', imaginary )
+ map.add( 'real', real )
+ end
+ end
+ end
+end
+
class TrueClass
yaml_as "tag:yaml.org,2002:bool#yes"
def to_yaml( opts = {} )
diff --git a/load.c b/load.c
index 3e10a60823..f6a307df23 100644
--- a/load.c
+++ b/load.c
@@ -2,6 +2,9 @@
* load methods from eval.c
*/
+#include "ruby/ruby.h"
+#include "ruby/util.h"
+#include "dln.h"
#include "eval_intern.h"
VALUE ruby_dln_librefs;
@@ -277,8 +280,7 @@ rb_load(VALUE fname, int wrap)
th->mild_compile_error++;
node = (NODE *)rb_load_file(RSTRING_PTR(fname));
loaded = Qtrue;
- iseq = rb_iseq_new(node, rb_str_new2("<top (required)>"),
- fname, Qfalse, ISEQ_TYPE_TOP);
+ iseq = rb_iseq_new_top(node, rb_str_new2("<top (required)>"), fname, Qfalse);
th->mild_compile_error--;
rb_iseq_eval(iseq);
}
@@ -364,7 +366,7 @@ load_lock(const char *ftptr)
}
static void
-load_unlock(const char *ftptr)
+load_unlock(const char *ftptr, int done)
{
if (ftptr) {
st_data_t key = (st_data_t)ftptr;
@@ -372,8 +374,12 @@ load_unlock(const char *ftptr)
st_table *loading_tbl = get_loading_table();
if (st_delete(loading_tbl, &key, &data)) {
+ VALUE barrier = (VALUE)data;
xfree((char *)key);
- rb_barrier_release((VALUE)data);
+ if (done)
+ rb_barrier_destroy(barrier);
+ else
+ rb_barrier_release(barrier);
}
}
}
@@ -559,7 +565,7 @@ rb_require_safe(VALUE fname, int safe)
}
}
POP_TAG();
- load_unlock(ftptr);
+ load_unlock(ftptr, !state);
rb_set_safe_level_force(saved.safe);
if (state) {
@@ -598,7 +604,7 @@ ruby_init_ext(const char *name, void (*init)(void))
rb_vm_call_cfunc(rb_vm_top_self(), init_ext_call, (VALUE)init,
0, rb_str_new2(name));
rb_provide(name);
- load_unlock(name);
+ load_unlock(name, 1);
}
}
@@ -700,5 +706,5 @@ InitVM_load(rb_vm_t *vm)
rb_define_global_function("autoload?", rb_f_autoload_p, 1);
ruby_dln_librefs = rb_ary_new();
- rb_register_mark_object(ruby_dln_librefs);
+ rb_gc_register_mark_object(ruby_dln_librefs);
}
diff --git a/main.c b/main.c
index 4a94616e51..2c3dbf84fb 100644
--- a/main.c
+++ b/main.c
@@ -11,8 +11,9 @@
#undef RUBY_EXPORT
-#include "ruby/mvm.h"
+#include "ruby/vm.h"
+#include "debug.h"
#ifdef HAVE_LOCALE_H
#include <locale.h>
#endif
diff --git a/man/goruby.1 b/man/goruby.1
new file mode 100644
index 0000000000..340b6ceb18
--- /dev/null
+++ b/man/goruby.1
@@ -0,0 +1,39 @@
+.\"Ruby is copyrighted by Yukihiro Matsumoto <matz@netlab.jp>.
+.Dd October 25, 2008
+.Dt GORUBY(1) "" "Ruby Programmers Reference Guide"
+.Os UNIX
+.Sh NAME
+.Nm goruby
+.Nd Code-golfer's best friend
+.Sh SYNOPSIS
+.Nm
+.Op options ...
+.Op Fl -
+.Op Ar program_file
+.Op Ar argument ...
+.Sh DESCRIPTION
+.Sy goruby
+is a kind of Ruby language processor,
+which recognizes extremely shorten programs as bellow;
+.Bd -literal -offset indent
+rq"date";s De.td
+.Ed
+.Pp
+This means
+.Bd -literal -offset indent
+require"date";puts Date.today
+.Ed
+.Pp
+.Sh OPTIONS
+.Sy goruby
+takes same options as
+.Xr ruby 1 .
+.Sh SEE ALSO
+.Bl -hang -compact -width "ruby(1)"
+.It Xr ruby 1
+The stiff version of Ruby interpreter.
+.El
+.Pp
+.Sh AUTHORS
+Originally written by Nobuyoshi Nakada and developed by
+Ruby core team.
diff --git a/man/irb.1 b/man/irb.1
new file mode 100644
index 0000000000..63726f0a7a
--- /dev/null
+++ b/man/irb.1
@@ -0,0 +1,127 @@
+.\"Ruby is copyrighted by Yukihiro Matsumoto <matz@netlab.jp>.
+.Dd October 25, 2008
+.Dt IRB(1) "" "Ruby Programmers Reference Guide"
+.Os UNIX
+.Sh NAME
+.Nm irb
+.Nd Interactive Ruby Shell
+.Sh SYNOPSIS
+.Nm
+.Op Fl -version
+.Op Fl Idfmrv
+.Op Fl - Ns Oo no Oc Ns inspect
+.Op Fl - Ns Oo no Oc Ns readline
+.Op Fl -prompt Ar mode
+.Op Fl -prompt-mode Ar mode
+.Op Fl -inf-ruby-mode
+.Op Fl -simple-prompt
+.Op Fl -noprompt
+.Op Fl -tracer
+.Op Fl -back-trace-limit Ar n
+.Op Fl -irb_debug Ar n
+.Op Fl -
+.Op program_file
+.Op argument ...
+.Pp
+.Sh DESCRIPTION
+irb is the REPL(read-eval&print loop) environment for Ruby programs.
+.Pp
+.Sh OPTIONS
+.Bl -tag -width "1234567890123" -compact
+.Pp
+.It Fl d
+Sets
+.Li $DEBUG
+to true (same as `ruby -d')
+.Pp
+.It Fl f
+Suppresses read of ~/.irbrc
+.Pp
+.It Fl m
+Bc mode (load mathn, fraction or matrix are available)
+.Pp
+.It Fl -r Ar load-module
+Same as `ruby -r'
+.Pp
+.It Fl I Ar path
+Specifies
+.Li $LOAD_PATH
+directory
+.Pp
+.It Fl -inspect
+Uses `inspect' for output (default except for bc mode)
+.Pp
+.It Fl -noinspect
+Doesn't use inspect for output
+.Pp
+.It Fl -readline
+Uses Readline extension module.
+.Pp
+.It Fl -noreadline
+Doesn't use Readline extension module.
+.Pp
+.It Fl -prompt Ar mode
+.It Fl -prompt-mode Ar mode
+Switch prompt mode. Pre-defined prompt modes are
+`default', `simple', `xmp' and `inf-ruby'.
+.Pp
+.It Fl -inf-ruby-mode
+Uses prompt appropriate for inf-ruby-mode on emacs.
+Suppresses --readline.
+.Pp
+.It Fl -simple-prompt
+Makes prompts simple.
+.Pp
+.It Fl -noprompt
+No prompt mode.
+.Pp
+.It Fl -tracer
+Displays trace for each execution of commands.
+.Pp
+.It Fl -back-trace-limit Ar n
+Displays backtrace top
+.Ar n
+and tail
+.Ar n Ns .
+The default value is 16.
+.Pp
+.It Fl -irb_debug Ar n
+Sets internal debug level to n (not for popular use)
+.Pp
+.El
+.Pp
+.Sh ENVIRONMENT
+.Bl -tag -width "RUBYLIB_PREFIX" -compact
+.It Ev IRBRC
+.Pp
+.El
+.Pp
+Also
+.Nm
+depends on same variables as
+.Xr ruby 1 .
+.Pp
+.Sh FILES
+.Bl -tag -width "RUBYLIB_PREFIX" -compact
+.It Pa ~/.irbrc
+Personal irb initialization.
+.Pp
+.El
+.Pp
+.Sh SEE ALSO
+.Xr ruby 1 .
+.Pp
+.Sh REPORTING BUGS
+.Bl -bullet
+.Li Security vulnerabilities should be reported via an email to
+.Aq security@ruby-lang.org Ns
+.Li .
+Reported problems will be published after fixed.
+.Pp
+.Li And you can report other bugs and feature requests via the
+Ruby Issue Tracking System (http://redmine.ruby-lang.org).
+Do not report security vulnerabilities
+via the system because it publishes the vulnerabilities immedately.
+.El
+.Sh AUTHORS
+Written by Keiju ISHITSUKA.
diff --git a/ruby.1 b/man/ruby.1
index fb23590cec..e2d0abdefd 100644
--- a/ruby.1
+++ b/man/ruby.1
@@ -1,5 +1,5 @@
.\"Ruby is copyrighted by Yukihiro Matsumoto <matz@netlab.jp>.
-.Dd December 31, 2002
+.Dd October 25, 2008
.Dt RUBY(1) "" "Ruby Programmers Reference Guide"
.\".Dt RUBY 1
.Os UNIX
@@ -10,10 +10,10 @@
.Nm
.Op Fl -copyright
.Op Fl -version
-.Op Fl Sacdlnpswvy
+.Op Fl SUacdlnpswvy
.Op Fl 0 Ns Op Ar octal
.Op Fl C Ar directory
-.Op Fl E Ar encoding
+.Op Fl E Ar external Ns Op : Ns Ar internal
.Op Fl F Ar pattern
.Op Fl I Ar directory
.Op Fl K Ar c
@@ -24,6 +24,7 @@
.Op Fl r Ar library
.Op Fl x Ns Op Ar directory
.Op - Ns Bro Cm enable Ns | Ns Cm disable Brc Ns - Ns Ar FEATURE
+.Op Fl -dump Ns = Ns Ar target
.Op Fl -verbose
.Op Fl -
.Op Ar program_file
@@ -92,9 +93,19 @@ In Ruby, you can objectify the procedure.
.It Sy "Text processing and regular expression"
Ruby has a bunch of text processing features like in Perl.
.Pp
+.It Sy "M17N, character set independent"
+Ruby supports multilingualized programming. Easy to process texts
+written in many different natural languages and encoded in many
+different character encodings, without dependence on Unicode.
+.Pp
.It Sy "Bignums"
With built-in bignums, you can for example calculate factorial(400).
.Pp
+.It Sy "Reflection and domain specific languages"
+Class is also an instance of Class class. Definition of classes and methods
+is just an expression as 1+1 is. So your programs can even write and modify programs.
+Thus you can write your application in your own programming language on top of Ruby.
+.Pp
.It Sy "Exception handling"
As in Java(tm).
.Pp
@@ -108,6 +119,13 @@ On most
.Ux
systems, you can load object files into the Ruby interpreter
on-the-fly.
+.It Sy "Rich libraries"
+Libraries called "builtin libraries" and "standard libraries" are bundled with Ruby.
+And you can obtain more libraries via the package management system called `RubyGems'.
+
+Moreover there are thousands of Ruby projects in Rubyforge
+.Pf ( "http://www.rubyforge.org" ) and RAA
+.Pf ( "http://raa.ruby-lang.org" ) Ns .
.El
.Pp
.Sh OPTIONS
@@ -139,9 +157,12 @@ no legal character with that value.
.It Fl X Ar directory
Causes Ruby to switch to the directory.
.Pp
-.It Fl E Ar encname
-.It Fl -encoding Ar encname
-Specifies the encoding for the program codes.
+.It Fl E Ar external Ns Op : Ns Ar internal
+.It Fl -encoding Ar external Ns Op : Ns Ar internal
+Specifies the default value(s) for external encodings and internal encoding. Values should be separated with colon (:).
+
+You can ommit the one for internal encodings, then the value
+.Pf ( Li "Encoding.default_internal" ) will be nil.
.Pp
.It Fl F Ar pattern
Specifies input field separator
@@ -153,7 +174,23 @@ will be added to the load-path variable
.Pf ( Li "$:" ) .
.Pp
.It Fl K Ar kcode
-Specifies KANJI (Japanese) encoding.
+Specifies KANJI (Japanese) encoding. The default value for script encodings
+.Pf ( Li "__ENCODING__" ) and external encodings ( Li "Encoding.default_external" ) will be the specified one.
+.Ar kcode
+can be one of
+.Bl -hang -offset indent
+.It Sy e
+EUC-JP
+.Pp
+.It Sy s
+Windows-31J (CP932)
+.Pp
+.It Sy u
+UTF-8
+.Pp
+.It Sy n
+ASCII-8BIT (BINARY)
+.El
.Pp
.It Fl S
Makes Ruby use the
@@ -171,6 +208,10 @@ on machines that don't support it, in the following manner:
.It Fl T Ns Op Ar level
Turns on taint checks at the specified level (default 1).
.Pp
+.It Fl U
+Sets the defalut value for internal encodings
+.Pf ( Li "Encoding.default_internal" ) to UTF-8.
+.Pp
.It Fl W Ns Op Ar level
Turns on verbose mode at the specified level, without printing version
message at the beginning. The level can be;
@@ -333,6 +374,8 @@ before executing script.
.Pp
.It Fl y
.It Fl -yydebug
+DO NOT USE.
+
Turns on compiler debug mode. Ruby will print a bunch of internal
state messages during compiling scripts. You don't have to specify
this switch, unless you are going to debug the Ruby interpreter.
@@ -342,12 +385,12 @@ this switch, unless you are going to debug the Ruby interpreter.
Disables (or enables) the specified
.Ar FEATURE Ns
\&.
-.Pp
+.Bl -tag -width "--disable-rubyopt" -compact
.It Fl -disable-gems
.It Fl -enable-gems
Disables (or enables) RubyGems libraries. By default, Ruby will load the latest
version of each installed gem. The
-.Li Gem::Enable
+.Li Gem
constant is true if RubyGems is enabled, false if otherwise.
.Pp
.It Fl -disable-rubyopt
@@ -360,6 +403,22 @@ environment variable. By default, Ruby considers the variable.
.It Fl -enable-all
Disables (or enables) all features.
.Pp
+.El
+.Pp
+.It Fl -dump Ns = Ns Ar target
+DO NOT USE.
+
+Prints the specified target.
+.Ar target
+can be one of;
+.Bl -hang -offset indent
+.It Sy insns
+disassembed instructions
+.Pp
+.El
+.Pp
+You don't have to specify this switch, unless you are going to debug the Ruby interpreter.
+.Pp
.It Fl -verbose
Enables verbose mode without printing version message at the
beginning. It sets the
@@ -386,6 +445,12 @@ Additional Ruby options.
e.g.
.Dl RUBYOPT="-w -Ke"
.Pp
+Note that RUBYOPT can contain only
+.Fl d , Fl E , Fl I , Fl K , Fl r , Fl T , Fl U , Fl v , Fl w , Fl W, Fl -debug ,
+.Fl -disable- Ns Ar FEATURE
+and
+.Fl -enable- Ns Ar FEATURE .
+.Pp
.It Ev RUBYPATH
A colon-separated list of directories that Ruby searches for
Ruby programs when the
@@ -409,6 +474,38 @@ environment variable on calling Kernel#system.
This variable is obsolete.
.El
.Pp
+And Ruby depends on some RubyGems related environment variables unless disabled RubyGems.
+See the help of
+.Xr gem 1
+as bellow.
+.Bd -literal -offset indent
+% gem help
+.Ed
+.Pp
+.Sh SEE ALSO
+.Bl -hang -compact -width "http://www.ruby-lang.org/123"
+.It http://www.ruby-lang.org
+The official web site.
+.It http://www.rubyforge.org
+hosting many open source ruby projects.
+.It http://raa.ruby-lang.org
+Ruby Application Archive.
+.El
+.Pp
+.Sh REPORTING BUGS
+.Bl -bullet
+.Li Security vulnerabilities should be reported via an email to
+.Aq security@ruby-lang.org Ns
+.Li .
+Reported problems will be published after fixed.
+.Pp
+.Li And you can report other bugs and feature requests via the
+Ruby Issue Tracking System (http://redmine.ruby-lang.org).
+Do not report security vulnerabilities
+via the system because it publishes the vulnerabilities immedately.
+.El
.Sh AUTHORS
Ruby is designed and implemented by
.An Yukihiro Matsumoto Aq matz@netlab.jp .
+
+See <\fBhttp://redmine.ruby-lang.org/wiki/ruby/Contributors\fR> for contributors to Ruby.
diff --git a/marshal.c b/marshal.c
index 516be7e85e..0ac68c6e15 100644
--- a/marshal.c
+++ b/marshal.c
@@ -80,7 +80,7 @@ shortlen(long len, BDIGIT *ds)
#define TYPE_LINK '@'
static ID s_dump, s_load, s_mdump, s_mload;
-static ID s_dump_data, s_load_data, s_alloc;
+static ID s_dump_data, s_load_data, s_alloc, s_call;
static ID s_getbyte, s_read, s_write, s_binmode;
ID rb_id_encoding(void);
@@ -150,10 +150,11 @@ struct dump_call_arg {
};
static void
-check_dump_arg(struct dump_arg *arg)
+check_dump_arg(struct dump_arg *arg, ID sym)
{
if (!DATA_PTR(arg->wrapper)) {
- rb_raise(rb_eRuntimeError, "Marshal.dump reentered");
+ rb_raise(rb_eRuntimeError, "Marshal.dump reentered at %s",
+ rb_id2name(sym));
}
}
@@ -591,7 +592,7 @@ w_object(VALUE obj, struct dump_arg *arg, int limit)
st_add_direct(arg->data, obj, arg->data->num_entries);
v = rb_funcall(obj, s_mdump, 0, 0);
- check_dump_arg(arg);
+ check_dump_arg(arg, s_mdump);
w_class(TYPE_USRMARSHAL, obj, arg, Qfalse);
w_object(v, arg, limit);
if (hasiv) w_ivar(obj, 0, &c_arg);
@@ -603,7 +604,7 @@ w_object(VALUE obj, struct dump_arg *arg, int limit)
int hasiv2;
v = rb_funcall(obj, s_dump, 1, INT2NUM(limit));
- check_dump_arg(arg);
+ check_dump_arg(arg, s_dump);
if (TYPE(v) != T_STRING) {
rb_raise(rb_eTypeError, "_dump() must return string");
}
@@ -771,7 +772,7 @@ w_object(VALUE obj, struct dump_arg *arg, int limit)
rb_obj_classname(obj));
}
v = rb_funcall(obj, s_dump_data, 0);
- check_dump_arg(arg);
+ check_dump_arg(arg, s_dump_data);
w_class(TYPE_DATA, obj, arg, Qtrue);
w_object(v, arg, limit);
}
@@ -865,29 +866,30 @@ marshal_dump(int argc, VALUE *argv)
else port = a1;
}
arg.dest = 0;
+ arg.symbols = st_init_numtable();
+ arg.data = st_init_numtable();
+ arg.taint = Qfalse;
+ arg.untrust = Qfalse;
+ arg.compat_tbl = st_init_numtable();
+ arg.encodings = 0;
+ arg.str = rb_str_buf_new(0);
+ RBASIC(arg.str)->klass = 0;
+ arg.wrapper = Data_Wrap_Struct(rb_cData, mark_dump_arg, 0, &arg);
if (!NIL_P(port)) {
if (!rb_respond_to(port, s_write)) {
type_error:
rb_raise(rb_eTypeError, "instance of IO needed");
}
- arg.str = rb_str_buf_new(0);
arg.dest = port;
if (rb_respond_to(port, s_binmode)) {
rb_funcall2(port, s_binmode, 0, 0);
+ check_dump_arg(&arg, s_binmode);
}
}
else {
- port = rb_str_buf_new(0);
- arg.str = port;
+ port = arg.str;
}
- arg.symbols = st_init_numtable();
- arg.data = st_init_numtable();
- arg.taint = Qfalse;
- arg.untrust = Qfalse;
- arg.compat_tbl = st_init_numtable();
- arg.wrapper = Data_Wrap_Struct(rb_cData, mark_dump_arg, 0, &arg);
- arg.encodings = 0;
arg.compat_allocator_tbl = DATA_PTR(rb_compat_allocator_tbl);
c_arg.obj = obj;
c_arg.arg = &arg;
@@ -897,6 +899,7 @@ marshal_dump(int argc, VALUE *argv)
w_byte(MARSHAL_MINOR, &arg);
rb_ensure(dump, (VALUE)&c_arg, dump_ensure, (VALUE)&arg);
+ RBASIC(arg.str)->klass = rb_cString;
return port;
}
@@ -915,10 +918,11 @@ struct load_arg {
};
static void
-check_load_arg(struct load_arg *arg)
+check_load_arg(struct load_arg *arg, ID sym)
{
if (!DATA_PTR(arg->wrapper)) {
- rb_raise(rb_eRuntimeError, "Marshal.load reentered");
+ rb_raise(rb_eRuntimeError, "Marshal.load reentered at %s",
+ rb_id2name(sym));
}
}
@@ -952,7 +956,7 @@ r_byte(struct load_arg *arg)
else {
VALUE src = arg->src;
VALUE v = rb_funcall2(src, s_getbyte, 0, 0);
- check_load_arg(arg);
+ check_load_arg(arg, s_getbyte);
if (NIL_P(v)) rb_eof_error();
c = (unsigned char)NUM2CHR(v);
}
@@ -1029,7 +1033,7 @@ r_bytes0(long len, struct load_arg *arg)
VALUE src = arg->src;
VALUE n = LONG2NUM(len);
str = rb_funcall2(src, s_read, 1, &n);
- check_load_arg(arg);
+ check_load_arg(arg, s_read);
if (NIL_P(str)) goto too_short;
StringValue(str);
if (RSTRING_LEN(str) != len) goto too_short;
@@ -1129,8 +1133,8 @@ r_leave(VALUE v, struct load_arg *arg)
v = real_obj;
}
if (arg->proc) {
- v = rb_funcall(arg->proc, rb_intern("call"), 1, v);
- check_load_arg(arg);
+ v = rb_funcall(arg->proc, s_call, 1, v);
+ check_load_arg(arg, s_call);
}
return v;
}
@@ -1215,8 +1219,8 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
}
v = (VALUE)link;
if (arg->proc) {
- v = rb_funcall(arg->proc, rb_intern("call"), 1, v);
- check_load_arg(arg);
+ v = rb_funcall(arg->proc, s_call, 1, v);
+ check_load_arg(arg, s_call);
}
break;
@@ -1460,7 +1464,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
*ivp = Qfalse;
}
v = rb_funcall(klass, s_load, 1, data);
- check_load_arg(arg);
+ check_load_arg(arg, s_load);
v = r_entry(v, arg);
v = r_leave(v, arg);
}
@@ -1485,7 +1489,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
v = r_entry(v, arg);
data = r_object(arg);
rb_funcall(v, s_mload, 1, data);
- check_load_arg(arg);
+ check_load_arg(arg, s_mload);
v = r_leave(v, arg);
}
break;
@@ -1512,7 +1516,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
warn = Qfalse;
}
v = rb_funcall(klass, s_alloc, 0);
- check_load_arg(arg);
+ check_load_arg(arg, s_alloc);
}
else {
v = rb_obj_alloc(klass);
@@ -1527,7 +1531,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
rb_class2name(klass));
}
rb_funcall(v, s_load_data, 1, r_object0(arg, 0, extmod));
- check_load_arg(arg);
+ check_load_arg(arg, s_load_data);
v = r_leave(v, arg);
}
break;
@@ -1711,6 +1715,7 @@ Init_marshal(void)
s_dump_data = rb_intern("_dump_data");
s_load_data = rb_intern("_load_data");
s_alloc = rb_intern("_alloc");
+ s_call = rb_intern("call");
s_getbyte = rb_intern("getbyte");
s_read = rb_intern("read");
s_write = rb_intern("write");
diff --git a/math.c b/math.c
index ad7e863f46..b5d2439ca9 100644
--- a/math.c
+++ b/math.c
@@ -79,7 +79,7 @@ infinity_check(VALUE arg, double res, const char *msg)
*
*/
-VALUE
+static VALUE
math_atan2(VALUE obj, VALUE y, VALUE x)
{
Need_Float2(y, x);
@@ -95,7 +95,7 @@ math_atan2(VALUE obj, VALUE y, VALUE x)
* -1..1.
*/
-VALUE
+static VALUE
math_cos(VALUE obj, VALUE x)
{
Need_Float(x);
@@ -110,7 +110,7 @@ math_cos(VALUE obj, VALUE x)
* -1..1.
*/
-VALUE
+static VALUE
math_sin(VALUE obj, VALUE x)
{
Need_Float(x);
@@ -201,7 +201,7 @@ cosh(double x)
* Computes the hyperbolic cosine of <i>x</i> (expressed in radians).
*/
-VALUE
+static VALUE
math_cosh(VALUE obj, VALUE x)
{
Need_Float(x);
@@ -225,7 +225,7 @@ sinh(double x)
* radians).
*/
-VALUE
+static VALUE
math_sinh(VALUE obj, VALUE x)
{
Need_Float(x);
@@ -315,7 +315,7 @@ math_atanh(VALUE obj, VALUE x)
* Returns e**x.
*/
-VALUE
+static VALUE
math_exp(VALUE obj, VALUE x)
{
Need_Float(x);
@@ -341,7 +341,7 @@ math_exp(VALUE obj, VALUE x)
* of logarithm.
*/
-VALUE
+static VALUE
math_log(int argc, VALUE *argv)
{
VALUE x, base;
@@ -351,7 +351,7 @@ math_log(int argc, VALUE *argv)
Need_Float(x);
errno = 0;
d = log(RFLOAT_VALUE(x));
- if (!NIL_P(base)) {
+ if (argc == 2) {
Need_Float(base);
d /= log(RFLOAT_VALUE(base));
}
@@ -436,7 +436,7 @@ math_log10(VALUE obj, VALUE x)
*
*/
-VALUE
+static VALUE
math_sqrt(VALUE obj, VALUE x)
{
double d;
@@ -538,7 +538,7 @@ math_ldexp(VALUE obj, VALUE x, VALUE n)
* Math.hypot(3, 4) #=> 5.0
*/
-VALUE
+static VALUE
math_hypot(VALUE obj, VALUE x, VALUE y)
{
Need_Float2(x, y);
@@ -651,6 +651,38 @@ math_lgamma(VALUE obj, VALUE x)
return rb_assoc_new(v, INT2FIX(sign));
}
+
+#define exp1(n) \
+VALUE \
+rb_math_##n(VALUE x)\
+{\
+ return math_##n(rb_mMath, x);\
+}
+
+#define exp2(n) \
+VALUE \
+rb_math_##n(VALUE x, VALUE y)\
+{\
+ return math_##n(rb_mMath, x, y);\
+}
+
+exp2(atan2)
+exp1(cos)
+exp1(cosh)
+exp1(exp)
+exp2(hypot)
+
+VALUE
+rb_math_log(int argc, VALUE *argv)
+{
+ return math_log(argc, argv);
+}
+
+exp1(sin)
+exp1(sinh)
+exp1(sqrt)
+
+
/*
* The <code>Math</code> module contains module functions for basic
* trigonometric and transcendental functions. See class
diff --git a/misc/ruby-mode.el b/misc/ruby-mode.el
index 17ce8c33c7..39fc4a6257 100644
--- a/misc/ruby-mode.el
+++ b/misc/ruby-mode.el
@@ -13,6 +13,11 @@
(substring ruby-mode-revision (match-beginning 0) (match-end 0)))
"Ruby mode version number.")
+(defconst ruby-keyword-end-re
+ (if (string-match "\\_>" "ruby")
+ "\\_>"
+ "\\>"))
+
(defconst ruby-block-beg-keywords
'("class" "module" "def" "if" "unless" "case" "while" "until" "for" "begin" "do")
"Keywords at the beginning of blocks.")
@@ -22,7 +27,7 @@
"Regexp to match the beginning of blocks.")
(defconst ruby-non-block-do-re
- (concat (regexp-opt '("while" "until" "for" "rescue") t) "\\_>")
+ (concat (regexp-opt '("while" "until" "for" "rescue") t) ruby-keyword-end-re)
"Regexp to match")
(defconst ruby-indent-beg-re
@@ -163,19 +168,23 @@
(defcustom ruby-indent-tabs-mode nil
"*Indentation can insert tabs in ruby mode if this is non-nil."
:type 'boolean :group 'ruby)
+(put 'ruby-indent-tabs-mode 'safe-local-variable 'booleanp)
(defcustom ruby-indent-level 2
"*Indentation of ruby statements."
:type 'integer :group 'ruby)
+(put 'ruby-indent-level 'safe-local-variable 'integerp)
(defcustom ruby-comment-column 32
"*Indentation column of comments."
:type 'integer :group 'ruby)
+(put 'ruby-comment-column 'safe-local-variable 'integerp)
(defcustom ruby-deep-arglist t
"*Deep indent lists in parenthesis when non-nil.
Also ignores spaces after parenthesis when 'space."
:group 'ruby)
+(put 'ruby-deep-arglist 'safe-local-variable 'booleanp)
(defcustom ruby-deep-indent-paren '(?\( ?\[ ?\] t)
"*Deep indent lists in parenthesis when non-nil. t means continuous line.
@@ -570,7 +579,7 @@ The variable ruby-indent-level controls the amount of indentation.
((looking-at (concat "\\<\\(" ruby-block-beg-re "\\)\\>"))
(and
(save-match-data
- (or (not (looking-at "do\\_>"))
+ (or (not (looking-at (concat "do" ruby-keyword-end-re)))
(save-excursion
(back-to-indentation)
(not (looking-at ruby-non-block-do-re)))))
@@ -1140,13 +1149,33 @@ balanced expression is found."
(ruby-here-doc-beg-syntax))
(,ruby-here-doc-end-re 3 (ruby-here-doc-end-syntax))))
- (defun ruby-in-non-here-doc-string-p ()
- (let ((syntax (syntax-ppss)))
- (or (nth 4 syntax)
- ;; In a string *without* a generic delimiter
- ;; If it's generic, it's a heredoc and we don't care
- ;; See `parse-partial-sexp'
- (numberp (nth 3 syntax)))))
+ (unless (functionp 'syntax-ppss)
+ (defun syntax-ppss (&optional pos)
+ (parse-partial-sexp (point-min) (or pos (point)))))
+
+ (defun ruby-in-ppss-context-p (context &optional ppss)
+ (let ((ppss (or ppss (syntax-ppss (point)))))
+ (if (cond
+ ((eq context 'anything)
+ (or (nth 3 ppss)
+ (nth 4 ppss)))
+ ((eq context 'string)
+ (nth 3 ppss))
+ ((eq context 'heredoc)
+ (and (nth 3 ppss)
+ ;; If it's generic string, it's a heredoc and we don't care
+ ;; See `parse-partial-sexp'
+ (not (numberp (nth 3 ppss)))))
+ ((eq context 'non-heredoc)
+ (and (ruby-in-ppss-context-p 'anything)
+ (not (ruby-in-ppss-context-p 'heredoc))))
+ ((eq context 'comment)
+ (nth 4 ppss))
+ (t
+ (error (concat
+ "Internal error on `ruby-in-ppss-context-p': "
+ "context name `" (symbol-name context) "' is unknown"))))
+ t)))
(defun ruby-in-here-doc-p ()
(save-excursion
@@ -1154,7 +1183,7 @@ balanced expression is found."
(beginning-of-line)
(catch 'found-beg
(while (re-search-backward ruby-here-doc-beg-re nil t)
- (if (not (or (syntax-ppss-context (syntax-ppss))
+ (if (not (or (ruby-in-ppss-context-p 'anything)
(ruby-here-doc-find-end old-point)))
(throw 'found-beg t)))))))
@@ -1189,19 +1218,19 @@ buffer position `limit' or the end of the buffer."
(defun ruby-here-doc-beg-syntax ()
(save-excursion
(goto-char (match-beginning 0))
- (unless (or (ruby-in-non-here-doc-string-p)
+ (unless (or (ruby-in-ppss-context-p 'non-heredoc)
(ruby-in-here-doc-p))
(string-to-syntax "|"))))
(defun ruby-here-doc-end-syntax ()
(let ((pss (syntax-ppss)) (case-fold-search nil))
- (when (eq (syntax-ppss-context pss) 'string)
+ (when (ruby-in-ppss-context-p 'heredoc pss)
(save-excursion
- (goto-char (nth 8 pss))
+ (goto-char (nth 8 pss)) ; Go to the beginning of heredoc.
(let ((eol (point)))
(beginning-of-line)
(if (and (re-search-forward (ruby-here-doc-beg-match) eol t) ; If there is a heredoc that matches this line...
- (null (syntax-ppss-context (syntax-ppss))) ; And that's not inside a heredoc/string/comment...
+ (not (ruby-in-ppss-context-p 'anything)) ; And that's not inside a heredoc/string/comment...
(progn (goto-char (match-end 0)) ; And it's the last heredoc on its line...
(not (re-search-forward ruby-here-doc-beg-re eol t))))
(string-to-syntax "|")))))))
@@ -1291,7 +1320,8 @@ buffer position `limit' or the end of the buffer."
"yield"
)
t)
- "\\_>\\)")
+ "\\)"
+ ruby-keyword-end-re)
2)
;; here-doc beginnings
(list ruby-here-doc-beg-re 0 'font-lock-string-face)
diff --git a/misc/ruby-style.el b/misc/ruby-style.el
index b99e71b35c..0fe4a83089 100644
--- a/misc/ruby-style.el
+++ b/misc/ruby-style.el
@@ -7,6 +7,14 @@
;;; $Author$
;;; created at: Thu Apr 26 13:54:01 JST 2007
;;;
+;;; sets ruby style if it seems like a source of ruby.
+;;;
+;;; (require 'ruby-style)
+;;; (add-hook 'c-mode-hook 'ruby-style-c-mode)
+;;; (add-hook 'c++-mode-hook 'ruby-style-c-mode)
+;;;
+;;; uses ruby style always.
+;;; (setq-default c-file-style "ruby")
(defconst ruby-style-revision "$Revision$"
"Ruby style revision string.")
@@ -56,7 +64,7 @@
(defun ruby-style-c-mode ()
(interactive)
- (if (or (string-match "/ruby\\>" (buffer-file-name))
+ (if (or (let ((name (buffer-file-name))) (and name (string-match "/ruby\\>" name)))
(save-excursion
(goto-char (point-min))
(let ((head (progn (forward-line 100) (point)))
diff --git a/missing/vsnprintf.c b/missing/vsnprintf.c
index 17990a57fc..c4326b4634 100644
--- a/missing/vsnprintf.c
+++ b/missing/vsnprintf.c
@@ -238,7 +238,7 @@ static int BSD__sfvwrite(fp, uio)
register struct __suio *uio;
{
register size_t len;
- register char *p;
+ register const char *p;
register struct __siov *iov;
register int w;
diff --git a/missing/x68.c b/missing/x68.c
deleted file mode 100644
index ece840d9ce..0000000000
--- a/missing/x68.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/* x68 compatibility functions -- follows Ruby's license */
-
-#include "ruby/config.h"
-
-#if !HAVE_SELECT
-#include "x68/select.c"
-#endif
-#if MISSING__DTOS18
-#include "x68/_dtos18.c"
-#endif
-#if MISSING_FCONVERT
-#include "x68/_round.c"
-#include "x68/fconvert.c"
-#endif
-
-/* missing some basic syscalls */
-int
-link(const char *src, const char *dst)
-{
- return symlink(src, dst);
-}
-
-#ifndef HAVE_GETTIMEOFDAY
-#include <time.h>
-#include <sys/time.h>
-
-struct timezone {
- int tz_minuteswest;
- int tz_dsttime;
-};
-
-int
-gettimeofday(struct timeval *tv, struct timezone *tz)
-{
- tv->tv_sec = (long)time((time_t*)0);
- tv->tv_usec = 0;
-
- return 0;
-}
-#endif
diff --git a/mkconfig.rb b/mkconfig.rb
index 19e456c160..e56af5d043 100755
--- a/mkconfig.rb
+++ b/mkconfig.rb
@@ -141,7 +141,7 @@ end
print(*v_fast)
print(*v_others)
print <<EOS
- CONFIG["rubylibdir"] = "$(libdir)/ruby/$(ruby_version)"
+ CONFIG["rubylibdir"] = "$(libdir)/$(ruby_install_name)/$(ruby_version)"
CONFIG["archdir"] = "$(rubylibdir)/$(arch)"
CONFIG["sitelibdir"] = "$(sitedir)/$(ruby_version)"
CONFIG["sitearchdir"] = "$(sitelibdir)/$(sitearch)"
diff --git a/mvm.c b/mvm.c
index fed166529d..ec060039d2 100644
--- a/mvm.c
+++ b/mvm.c
@@ -9,7 +9,6 @@
**********************************************************************/
-#include "ruby/mvm.h"
#include "ruby/ruby.h"
#include "vm_core.h"
#include "eval_intern.h"
diff --git a/numeric.c b/numeric.c
index 354db12fcc..2ae4c6f4e5 100644
--- a/numeric.c
+++ b/numeric.c
@@ -78,6 +78,9 @@ round(double x)
}
return x;
}
+#elif defined(__BEOS__)
+/* appears to be a bug in the BeOS headers */
+double round(double x);
#endif
static ID id_coerce, id_to_i, id_eq;
@@ -191,11 +194,13 @@ rb_num_coerce_relop(VALUE x, VALUE y, ID func)
static VALUE
num_sadded(VALUE x, VALUE name)
{
+ const char *nstr = rb_id2name(rb_to_id(name));
/* ruby_frame = ruby_frame->prev; */ /* pop frame for "singleton_method_added" */
/* Numerics should be values; singleton_methods should not be added to them */
+ rb_remove_method(rb_singleton_class(x), nstr);
rb_raise(rb_eTypeError,
"can't define singleton method \"%s\" for %s",
- rb_id2name(rb_to_id(name)),
+ nstr,
rb_obj_classname(x));
return Qnil; /* not reached */
}
@@ -377,14 +382,14 @@ num_remainder(VALUE x, VALUE y)
/*
* call-seq:
- * num.scalar? -> true or false
+ * num.real? -> true or false
*
- * Returns <code>true</code> if <i>num</i> is an <code>Scalar</code>
+ * Returns <code>true</code> if <i>num</i> is a <code>Real</code>
* (i.e. non <code>Complex</code>).
*/
static VALUE
-num_scalar_p(VALUE num)
+num_real_p(VALUE num)
{
return Qtrue;
}
@@ -1940,66 +1945,6 @@ int_denominator(VALUE num)
/*
* call-seq:
- * Fixnum.induced_from(obj) => fixnum
- *
- * Convert <code>obj</code> to a Fixnum. Works with numeric parameters.
- * Also works with Symbols, but this is deprecated.
- */
-
-static VALUE
-rb_fix_induced_from(VALUE klass, VALUE x)
-{
- return rb_num2fix(x);
-}
-
-/*
- * call-seq:
- * Integer.induced_from(obj) => fixnum, bignum
- *
- * Convert <code>obj</code> to an Integer.
- */
-
-static VALUE
-rb_int_induced_from(VALUE klass, VALUE x)
-{
- switch (TYPE(x)) {
- case T_FIXNUM:
- case T_BIGNUM:
- return x;
- case T_FLOAT:
- case T_RATIONAL:
- return rb_funcall(x, id_to_i, 0);
- default:
- rb_raise(rb_eTypeError, "failed to convert %s into Integer",
- rb_obj_classname(x));
- }
-}
-
-/*
- * call-seq:
- * Float.induced_from(obj) => float
- *
- * Convert <code>obj</code> to a float.
- */
-
-static VALUE
-rb_flo_induced_from(VALUE klass, VALUE x)
-{
- switch (TYPE(x)) {
- case T_FIXNUM:
- case T_BIGNUM:
- case T_RATIONAL:
- return rb_funcall(x, rb_intern("to_f"), 0);
- case T_FLOAT:
- return x;
- default:
- rb_raise(rb_eTypeError, "failed to convert %s into Float",
- rb_obj_classname(x));
- }
-}
-
-/*
- * call-seq:
* -fix => integer
*
* Negates <code>fix</code> (which might return a Bignum).
@@ -2439,7 +2384,7 @@ fix_pow(VALUE x, VALUE y)
long b = FIX2LONG(y);
if (b < 0)
- return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
+ return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
if (b == 0) return INT2FIX(1);
if (b == 1) return x;
@@ -2460,7 +2405,7 @@ fix_pow(VALUE x, VALUE y)
case T_BIGNUM:
if (rb_funcall(y, '<', 1, INT2FIX(0)))
- return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
+ return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
if (a == 0) return INT2FIX(0);
if (a == 1) return INT2FIX(1);
@@ -3141,7 +3086,7 @@ InitVM_Numeric(rb_vm_t *vm)
rb_define_method(rb_cNumeric, "magnitude", num_abs, 0);
rb_define_method(rb_cNumeric, "to_int", num_to_int, 0);
- rb_define_method(rb_cNumeric, "scalar?", num_scalar_p, 0);
+ rb_define_method(rb_cNumeric, "real?", num_real_p, 0);
rb_define_method(rb_cNumeric, "integer?", num_int_p, 0);
rb_define_method(rb_cNumeric, "zero?", num_zero_p, 0);
rb_define_method(rb_cNumeric, "nonzero?", num_nonzero_p, 0);
@@ -3165,7 +3110,6 @@ InitVM_Numeric(rb_vm_t *vm)
rb_define_method(rb_cInteger, "upto", int_upto, 1);
rb_define_method(rb_cInteger, "downto", int_downto, 1);
rb_define_method(rb_cInteger, "times", int_dotimes, 0);
- rb_include_module(rb_cInteger, rb_mPrecision);
rb_define_method(rb_cInteger, "succ", int_succ, 0);
rb_define_method(rb_cInteger, "next", int_succ, 0);
rb_define_method(rb_cInteger, "pred", int_pred, 0);
@@ -3178,9 +3122,6 @@ InitVM_Numeric(rb_vm_t *vm)
rb_define_method(rb_cInteger, "round", int_round, -1);
rb_cFixnum = rb_define_class("Fixnum", rb_cInteger);
- rb_include_module(rb_cFixnum, rb_mPrecision);
- rb_define_singleton_method(rb_cFixnum, "induced_from", rb_fix_induced_from, 1);
- rb_define_singleton_method(rb_cInteger, "induced_from", rb_int_induced_from, 1);
rb_define_method(rb_cInteger, "numerator", int_numerator, 0);
rb_define_method(rb_cInteger, "denominator", int_denominator, 0);
@@ -3230,9 +3171,6 @@ InitVM_Numeric(rb_vm_t *vm)
rb_undef_alloc_func(rb_cFloat);
rb_undef_method(CLASS_OF(rb_cFloat), "new");
- rb_define_singleton_method(rb_cFloat, "induced_from", rb_flo_induced_from, 1);
- rb_include_module(rb_cFloat, rb_mPrecision);
-
rb_define_const(rb_cFloat, "ROUNDS", INT2FIX(FLT_ROUNDS));
rb_define_const(rb_cFloat, "RADIX", INT2FIX(FLT_RADIX));
rb_define_const(rb_cFloat, "MANT_DIG", INT2FIX(DBL_MANT_DIG));
diff --git a/object.c b/object.c
index 257d94b3e4..a73819f5da 100644
--- a/object.c
+++ b/object.c
@@ -2363,6 +2363,12 @@ boot_defclass(const char *name, VALUE super)
return obj;
}
+static void
+boot_defmetametaclass(VALUE klass, VALUE metametaclass)
+{
+ RBASIC(RBASIC(klass)->klass)->klass = metametaclass;
+}
+
/*
* Document-class: Class
*
@@ -2474,6 +2480,9 @@ InitVM_Object(rb_vm_t *vm)
metaclass = rb_make_metaclass(rb_cObject, metaclass);
metaclass = rb_make_metaclass(rb_cModule, metaclass);
metaclass = rb_make_metaclass(rb_cClass, metaclass);
+ boot_defmetametaclass(rb_cModule, metaclass);
+ boot_defmetametaclass(rb_cObject, metaclass);
+ boot_defmetametaclass(rb_cBasicObject, metaclass);
rb_define_private_method(rb_cBasicObject, "initialize", rb_obj_dummy, 0);
rb_define_alloc_func(rb_cBasicObject, rb_class_allocate_instance);
diff --git a/pack.c b/pack.c
index 11c8ac80f8..4de1a4ac75 100644
--- a/pack.c
+++ b/pack.c
@@ -10,8 +10,8 @@
**********************************************************************/
#include "ruby/ruby.h"
+#include "ruby/encoding.h"
#include "eval_intern.h"
-
#include <sys/types.h>
#include <ctype.h>
#include <errno.h>
@@ -364,7 +364,7 @@ num2i32(VALUE x)
#endif
static const char toofew[] = "too few arguments";
-static void encodes(VALUE,const char*,long,int);
+static void encodes(VALUE,const char*,long,int,int);
static void qpencode(VALUE,VALUE,long);
static unsigned long utf8_to_uv(const char*,long*);
@@ -416,7 +416,8 @@ static unsigned long utf8_to_uv(const char*,long*);
* L | Unsigned long
* l | Long
* M | Quoted printable, MIME encoding (see RFC2045)
- * m | Base64 encoded string
+ * m | Base64 encoded string (see RFC 2045, count is width)
+ * | (if count is 0, no line feed are added, see RFC 4648)
* N | Long, network (big-endian) byte order
* n | Short, network (big-endian) byte-order
* P | Pointer to a structure (fixed-length string)
@@ -444,6 +445,7 @@ pack_pack(VALUE ary, VALUE fmt)
char type;
long items, len, idx, plen;
const char *ptr;
+ rb_encoding *enc;
#ifdef NATINT_PACK
int natint; /* native integer */
#endif
@@ -518,6 +520,15 @@ pack_pack(VALUE ary, VALUE fmt)
ptr = RSTRING_PTR(from);
plen = RSTRING_LEN(from);
OBJ_INFECT(res, from);
+ switch (type) {
+ case 'a': case 'A': case 'Z':
+ enc = rb_enc_compatible(res, from);
+ rb_enc_associate(res, enc);
+ break;
+ default:
+ rb_enc_associate(res, rb_ascii8bit_encoding());
+ break;
+ }
}
if (p[-1] == '*')
@@ -866,6 +877,8 @@ pack_pack(VALUE ary, VALUE fmt)
break;
case 'U': /* Unicode character */
+ enc = rb_enc_compatible(res, rb_enc_from_encoding(rb_utf8_encoding()));
+ rb_enc_associate(res, enc);
while (len-- > 0) {
SIGNED_VALUE l;
char buf[8];
@@ -889,6 +902,11 @@ pack_pack(VALUE ary, VALUE fmt)
ptr = RSTRING_PTR(from);
plen = RSTRING_LEN(from);
+ if (len == 0) {
+ encodes(res, ptr, plen, type, 0);
+ ptr += plen;
+ break;
+ }
if (len <= 2)
len = 45;
else
@@ -900,7 +918,7 @@ pack_pack(VALUE ary, VALUE fmt)
todo = len;
else
todo = plen;
- encodes(res, ptr, todo, type);
+ encodes(res, ptr, todo, type, 1);
plen -= todo;
ptr += todo;
}
@@ -1009,7 +1027,7 @@ static const char b64_table[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static void
-encodes(VALUE str, const char *s, long len, int type)
+encodes(VALUE str, const char *s, long len, int type, int tail_lf)
{
char buff[4096];
long i = 0;
@@ -1050,7 +1068,7 @@ encodes(VALUE str, const char *s, long len, int type)
buff[i++] = padding;
buff[i++] = padding;
}
- buff[i++] = '\n';
+ if (tail_lf) buff[i++] = '\n';
rb_str_buf_cat(str, buff, i);
}
@@ -1256,7 +1274,8 @@ b64_xtable_once(volatile signed char *init, rb_thread_lock_t *lock)
* -------+---------+-----------------------------------------
* M | String | quoted-printable
* -------+---------+-----------------------------------------
- * m | String | base64-encoded
+ * m | String | base64-encoded (RFC 2045) (default)
+ * | | base64-encoded (RFC 4648) if followed by 0
* -------+---------+-----------------------------------------
* N | Integer | treat four characters as an unsigned
* | | long in network byte order
@@ -1807,7 +1826,7 @@ pack_unpack(VALUE str, VALUE fmt)
{
VALUE buf = infected_str_new(0, (send - s)*3/4, str);
char *ptr = RSTRING_PTR(buf);
- int a = -1,b = -1,c = 0,d;
+ int a = -1,b = -1,c = 0,d = 0;
static signed char b64_xtable[256];
static rb_thread_lock_t b64_xtable_lock;
@@ -1824,30 +1843,62 @@ pack_unpack(VALUE str, VALUE fmt)
}
ruby_native_thread_unlock(&b64_xtable_lock);
}
- while (s < send) {
- a = b = c = d = -1;
- while ((a = b64_xtable[(unsigned char)*s]) == -1 && s < send) {s++;}
- if (s >= send) break;
- s++;
- while ((b = b64_xtable[(unsigned char)*s]) == -1 && s < send) {s++;}
- if (s >= send) break;
- s++;
- while ((c = b64_xtable[(unsigned char)*s]) == -1 && s < send) {if (*s == '=') break; s++;}
- if (*s == '=' || s >= send) break;
- s++;
- while ((d = b64_xtable[(unsigned char)*s]) == -1 && s < send) {if (*s == '=') break; s++;}
- if (*s == '=' || s >= send) break;
- s++;
- *ptr++ = a << 2 | b >> 4;
- *ptr++ = b << 4 | c >> 2;
- *ptr++ = c << 6 | d;
- }
- if (a != -1 && b != -1) {
- if (c == -1 && *s == '=')
+ if (len == 0) {
+ while (s < send) {
+ a = b = c = d = -1;
+ a = b64_xtable[(unsigned char)*s++];
+ if (s >= send || a == -1) rb_raise(rb_eArgError, "invalid base64");
+ b = b64_xtable[(unsigned char)*s++];
+ if (s >= send || b == -1) rb_raise(rb_eArgError, "invalid base64");
+ if (*s == '=') {
+ if (s + 2 == send && *(s + 1) == '=') break;
+ rb_raise(rb_eArgError, "invalid base64");
+ }
+ c = b64_xtable[(unsigned char)*s++];
+ if (s >= send || c == -1) rb_raise(rb_eArgError, "invalid base64");
+ if (s + 1 == send && *s == '=') break;
+ d = b64_xtable[(unsigned char)*s++];
+ if (d == -1) rb_raise(rb_eArgError, "invalid base64");
+ *ptr++ = a << 2 | b >> 4;
+ *ptr++ = b << 4 | c >> 2;
+ *ptr++ = c << 6 | d;
+ }
+ if (c == -1) {
+ *ptr++ = a << 2 | b >> 4;
+ if (b & 0xf) rb_raise(rb_eArgError, "invalid base64");
+ }
+ else if (d == -1) {
*ptr++ = a << 2 | b >> 4;
- else if (c != -1 && *s == '=') {
+ *ptr++ = b << 4 | c >> 2;
+ if (c & 0x3) rb_raise(rb_eArgError, "invalid base64");
+ }
+ }
+ else {
+ while (s < send) {
+ a = b = c = d = -1;
+ while ((a = b64_xtable[(unsigned char)*s]) == -1 && s < send) {s++;}
+ if (s >= send) break;
+ s++;
+ while ((b = b64_xtable[(unsigned char)*s]) == -1 && s < send) {s++;}
+ if (s >= send) break;
+ s++;
+ while ((c = b64_xtable[(unsigned char)*s]) == -1 && s < send) {if (*s == '=') break; s++;}
+ if (*s == '=' || s >= send) break;
+ s++;
+ while ((d = b64_xtable[(unsigned char)*s]) == -1 && s < send) {if (*s == '=') break; s++;}
+ if (*s == '=' || s >= send) break;
+ s++;
*ptr++ = a << 2 | b >> 4;
*ptr++ = b << 4 | c >> 2;
+ *ptr++ = c << 6 | d;
+ }
+ if (a != -1 && b != -1) {
+ if (c == -1 && *s == '=')
+ *ptr++ = a << 2 | b >> 4;
+ else if (c != -1 && *s == '=') {
+ *ptr++ = a << 2 | b >> 4;
+ *ptr++ = b << 4 | c >> 2;
+ }
}
}
rb_str_set_len(buf, ptr - RSTRING_PTR(buf));
diff --git a/parse.y b/parse.y
index 59d54a9a2b..b593bba68f 100644
--- a/parse.y
+++ b/parse.y
@@ -16,11 +16,12 @@
#define YYSTACK_USE_ALLOCA 0
#include "ruby/ruby.h"
-#include "ruby/node.h"
#include "ruby/st.h"
#include "ruby/encoding.h"
#include "eval_intern.h"
#include "gc.h"
+#include "node.h"
+#include "parse.h"
#include "id.h"
#include "regenc.h"
#include <stdio.h>
@@ -266,12 +267,11 @@ struct parser_params {
#define UTF8_ENC() (parser->utf8 ? parser->utf8 : \
(parser->utf8 = rb_utf8_encoding()))
#define STR_NEW(p,n) rb_enc_str_new((p),(n),parser->enc)
-#define STR_NEW0() rb_usascii_str_new(0,0)
+#define STR_NEW0() rb_enc_str_new(0,0,parser->enc)
#define STR_NEW2(p) rb_enc_str_new((p),strlen(p),parser->enc)
#define STR_NEW3(p,n,e,func) parser_str_new((p),(n),(e),(func),parser->enc)
-#define STR_ENC(m) ((m)?parser->enc:rb_usascii_encoding())
#define ENC_SINGLE(cr) ((cr)==ENC_CODERANGE_7BIT)
-#define TOK_INTERN(mb) rb_intern3(tok(), toklen(), STR_ENC(mb))
+#define TOK_INTERN(mb) rb_intern3(tok(), toklen(), parser->enc)
#ifdef YYMALLOC
void *rb_parser_malloc(struct parser_params *, size_t);
@@ -982,7 +982,7 @@ stmt : keyword_alias fitem {lex_state = EXPR_FNAME;} fitem
$4);
/* NEW_PREEXE($4)); */
/* local_pop(); */
- $$ = 0;
+ $$ = NEW_BEGIN(0);
/*%
$$ = dispatch1(BEGIN, $4);
%*/
@@ -2401,6 +2401,10 @@ opt_block_arg : ',' block_arg
{
$$ = $2;
}
+ | ','
+ {
+ $$ = 0;
+ }
| none
{
$$ = 0;
@@ -2441,8 +2445,7 @@ args : arg_value
{
/*%%%*/
NODE *n1;
- if (nd_type($4) == NODE_ARRAY &&
- (n1 = splat_array($1)) != 0) {
+ if ((nd_type($4) == NODE_ARRAY) && (n1 = splat_array($1)) != 0) {
$$ = list_concat(n1, $4);
}
else {
@@ -2775,16 +2778,27 @@ primary : literal
NEW_CALL(NEW_CALL(NEW_DVAR(id), rb_intern("[]"), zero),
rb_intern("kind_of?"), NEW_LIST(NEW_LIT(rb_cArray))),
0),
- NEW_DASGN_CURR(id,
- NEW_CALL(NEW_DVAR(id), rb_intern("[]"), zero)),
- 0),
+ NEW_DASGN_CURR(id,
+ NEW_CALL(NEW_DVAR(id), rb_intern("[]"), zero)),
+ 0),
node_assign($2, NEW_DVAR(id)));
+
+ args = new_args(m, 0, id, 0, 0);
}
else {
- m->nd_next = node_assign(NEW_MASGN(NEW_LIST($2), 0), NEW_DVAR(id));
+ if (nd_type($2) == NODE_LASGN ||
+ nd_type($2) == NODE_DASGN ||
+ nd_type($2) == NODE_DASGN_CURR) {
+ $2->nd_value = NEW_DVAR(id);
+ m->nd_plen = 1;
+ m->nd_next = $2;
+ args = new_args(m, 0, 0, 0, 0);
+ }
+ else {
+ m->nd_next = node_assign(NEW_MASGN(NEW_LIST($2), 0), NEW_DVAR(id));
+ args = new_args(m, 0, id, 0, 0);
+ }
}
-
- args = new_args(m, 0, id, 0, 0);
scope = NEW_NODE(NODE_SCOPE, tbl, $8, args);
tbl[0] = 1; tbl[1] = id;
$$ = NEW_FOR(0, $5, scope);
@@ -2889,6 +2903,7 @@ primary : literal
reduce_nodes(&body);
$$ = NEW_DEFN($2, $4, body, NOEX_PRIVATE);
fixpos($$, $4);
+ fixpos($$->nd_defn, $4);
local_pop();
in_def--;
cur_mid = $<id>3;
@@ -2916,6 +2931,7 @@ primary : literal
reduce_nodes(&body);
$$ = NEW_DEFS($2, $5, $7, body);
fixpos($$, $2);
+ fixpos($$->nd_defn, $2);
local_pop();
in_single--;
/*%
@@ -3412,19 +3428,19 @@ bvar : tIDENTIFIER
lambda : {
/*%%%*/
dyna_push();
- $<num>$ = lpar_beg;
- lpar_beg = ++paren_nest;
/*%
%*/
+ $<num>$ = lpar_beg;
+ lpar_beg = ++paren_nest;
}
f_larglist
lambda_body
{
+ lpar_beg = $<num>1;
/*%%%*/
$$ = $2;
$$->nd_body = NEW_SCOPE($2->nd_head, $3);
dyna_pop();
- lpar_beg = $<num>1;
/*%
$$ = dispatch2(lambda, $2, $3);
%*/
@@ -3439,7 +3455,7 @@ f_larglist : '(' f_args opt_bv_decl rparen
$$ = dispatch1(paren, $2);
%*/
}
- | f_args opt_bv_decl
+ | f_args
{
/*%%%*/
$$ = NEW_LAMBDA($1);
@@ -3614,6 +3630,8 @@ brace_block : '{'
/*%%%*/
$$ = NEW_ITER($3,$4);
nd_set_line($$, $<num>2);
+ nd_set_line($$->nd_body, $<num>2);
+ nd_set_line($$->nd_body->nd_body, $<num>2);
dyna_pop();
/*%
$$ = dispatch2(brace_block, escape_Qundef($3), $4);
@@ -4813,8 +4831,10 @@ token_info_has_nonspaces(struct parser_params *parser, const char *token)
static void
token_info_push(struct parser_params *parser, const char *token)
{
- token_info *ptinfo = ALLOC(token_info);
+ token_info *ptinfo;
+ if (compile_for_eval) return;
+ ptinfo = ALLOC(token_info);
ptinfo->token = token;
ptinfo->linenum = ruby_sourceline;
ptinfo->column = token_info_get_column(parser, token);
@@ -4830,6 +4850,7 @@ token_info_pop(struct parser_params *parser, const char *token)
int linenum;
token_info *ptinfo = parser->parser_token_info;
+ if (!ptinfo) return;
parser->parser_token_info = ptinfo->next;
if (token_info_get_column(parser, token) == ptinfo->column) { /* OK */
goto finish;
@@ -4841,8 +4862,9 @@ token_info_pop(struct parser_params *parser, const char *token)
if (token_info_has_nonspaces(parser, token) || ptinfo->nonspc) { /* SKIP */
goto finish;
}
- rb_warning("mismatched indentations: line %d:'%s' and line %d:'%s'",
- ptinfo->linenum, ptinfo->token, linenum, token);
+ rb_compile_warning(ruby_sourcefile, linenum,
+ "mismatched indentations at '%s' with '%s' at %d",
+ token, ptinfo->token, ptinfo->linenum);
finish:
xfree(ptinfo);
@@ -4879,11 +4901,11 @@ parser_yyerror(struct parser_params *parser, const char *msg)
if (len > max_line_margin * 2 + 10) {
if (lex_p - p > max_line_margin) {
- p = rb_enc_prev_char(p, lex_p - max_line_margin, rb_enc_get(lex_lastline));
+ p = rb_enc_prev_char(p, lex_p - max_line_margin, pe, rb_enc_get(lex_lastline));
pre = "...";
}
if (pe - lex_p > max_line_margin) {
- pe = rb_enc_prev_char(lex_p, lex_p + max_line_margin, rb_enc_get(lex_lastline));
+ pe = rb_enc_prev_char(lex_p, lex_p + max_line_margin, pe, rb_enc_get(lex_lastline));
post = "...";
}
len = pe - p;
@@ -4941,7 +4963,7 @@ coverage(const char *f, int n)
int i;
RBASIC(lines)->klass = 0;
for (i = 0; i < n; i++) RARRAY_PTR(lines)[i] = Qnil;
- RARRAY(lines)->len = n;
+ RARRAY(lines)->as.heap.len = n;
rb_hash_aset(coverages, fname, lines);
return lines;
}
@@ -5152,7 +5174,6 @@ parser_str_new(const char *p, long n, rb_encoding *enc, int func, rb_encoding *e
str = rb_enc_str_new(p, n, enc);
if (!(func & STR_FUNC_REGEXP) && rb_enc_asciicompat(enc)) {
if (rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT) {
- rb_enc_associate(str, rb_usascii_encoding());
}
else if (enc0 == rb_usascii_encoding() && enc != rb_utf8_encoding()) {
rb_enc_associate(str, rb_ascii8bit_encoding());
@@ -5163,6 +5184,7 @@ parser_str_new(const char *p, long n, rb_encoding *enc, int func, rb_encoding *e
}
#define lex_goto_eol(parser) (parser->parser_lex_p = parser->parser_lex_pend)
+#define peek(c) (lex_p < lex_pend && (c) == *lex_p)
static inline int
parser_nextc(struct parser_params *parser)
@@ -5213,7 +5235,7 @@ parser_nextc(struct parser_params *parser)
}
}
c = (unsigned char)*lex_p++;
- if (c == '\r' && lex_p < lex_pend && *lex_p == '\n') {
+ if (c == '\r' && peek('\n')) {
lex_p++;
c = '\n';
}
@@ -5232,7 +5254,6 @@ parser_pushback(struct parser_params *parser, int c)
}
#define was_bol() (lex_p == lex_pbeg + 1)
-#define peek(c) (lex_p != lex_pend && (c) == *lex_p)
#define tokfix() (tokenbuf[tokidx]='\0')
#define tok() tokenbuf
@@ -6062,6 +6083,18 @@ parser_set_encode(struct parser_params *parser, const char *name)
parser->enc = enc;
}
+static int
+comment_at_top(struct parser_params *parser)
+{
+ const char *p = lex_pbeg, *pend = lex_p - 1;
+ if (parser->line_count != (parser->has_shebang ? 2 : 1)) return 0;
+ while (p < pend) {
+ if (!ISSPACE(*p)) return 0;
+ p++;
+ }
+ return 1;
+}
+
#ifndef RIPPER
typedef int (*rb_magic_comment_length_t)(struct parser_params *parser, const char *name, int len);
typedef void (*rb_magic_comment_setter_t)(struct parser_params *parser, const char *name, const char *val);
@@ -6069,8 +6102,11 @@ typedef void (*rb_magic_comment_setter_t)(struct parser_params *parser, const ch
static void
magic_comment_encoding(struct parser_params *parser, const char *name, const char *val)
{
- if (parser->line_count != (parser->has_shebang ? 2 : 1))
+ if (!comment_at_top(parser)) {
+ rb_warning("encoding '%s' is ignored, valid only in the first line except for shebang line.",
+ val);
return;
+ }
parser_set_encode(parser, val);
}
@@ -6140,7 +6176,8 @@ parser_magic_comment(struct parser_params *parser, const char *str, int len)
#ifndef RIPPER
const struct magic_comment *p = magic_comments;
#endif
- int n = 0;
+ char *s;
+ int i, n = 0;
for (; len > 0 && *str; str++, --len) {
switch (*str) {
@@ -6186,15 +6223,19 @@ parser_magic_comment(struct parser_params *parser, const char *str, int len)
n = end - beg;
str_copy(name, beg, n);
+ s = RSTRING_PTR(name);
+ for (i = 0; i < n; ++i) {
+ if (*s == '-') *s = '_';
+ }
#ifndef RIPPER
do {
- if (STRNCASECMP(p->name, RSTRING_PTR(name), n) == 0) {
+ if (STRNCASECMP(p->name, s, n) == 0) {
n = vend - vbeg;
if (p->length) {
n = (*p->length)(parser, vbeg, n);
}
str_copy(val, vbeg, n);
- (*p->func)(parser, RSTRING_PTR(name), RSTRING_PTR(val));
+ (*p->func)(parser, s, RSTRING_PTR(val));
break;
}
} while (++p < magic_comments + sizeof(magic_comments) / sizeof(*p));
@@ -6261,7 +6302,7 @@ parser_prepare(struct parser_params *parser)
if (lex_pend - lex_p >= 2 &&
(unsigned char)lex_p[0] == 0xbb &&
(unsigned char)lex_p[1] == 0xbf) {
- parser_set_encode(parser, "UTF-8");
+ parser->enc = rb_utf8_encoding();
lex_p += 2;
lex_pbeg = lex_p;
return;
@@ -6341,9 +6382,8 @@ parser_yylex(struct parser_params *parser)
case '#': /* it's a comment */
/* no magic_comment in shebang line */
- if (parser->line_count == (parser->has_shebang ? 2 : 1)
- && (lex_p - lex_pbeg) == 1) {
- if (!parser_magic_comment(parser, lex_p, lex_pend - lex_p)) {
+ if (!parser_magic_comment(parser, lex_p, lex_pend - lex_p)) {
+ if (comment_at_top(parser)) {
set_file_encoding(parser, lex_p, lex_pend);
}
}
@@ -6752,7 +6792,7 @@ parser_yylex(struct parser_params *parser)
if (IS_ARG()) arg_ambiguous();
lex_state = EXPR_BEG;
pushback(c);
- if (ISDIGIT(c)) {
+ if (c != -1 && ISDIGIT(c)) {
c = '+';
goto start_num;
}
@@ -6786,7 +6826,7 @@ parser_yylex(struct parser_params *parser)
if (IS_ARG()) arg_ambiguous();
lex_state = EXPR_BEG;
pushback(c);
- if (ISDIGIT(c)) {
+ if (c != -1 && ISDIGIT(c)) {
return tUMINUS_NUM;
}
return tUMINUS;
@@ -6805,7 +6845,7 @@ parser_yylex(struct parser_params *parser)
return tDOT2;
}
pushback(c);
- if (ISDIGIT(c)) {
+ if (c != -1 && ISDIGIT(c)) {
yyerror("no .<digit> floating literal anymore; put 0 before dot");
}
lex_state = EXPR_DOT;
@@ -6830,7 +6870,7 @@ parser_yylex(struct parser_params *parser)
if (c == 'x' || c == 'X') {
/* hexadecimal */
c = nextc();
- if (ISXDIGIT(c)) {
+ if (c != -1 && ISXDIGIT(c)) {
do {
if (c == '_') {
if (nondigit) break;
@@ -6878,7 +6918,7 @@ parser_yylex(struct parser_params *parser)
if (c == 'd' || c == 'D') {
/* decimal */
c = nextc();
- if (ISDIGIT(c)) {
+ if (c != -1 && ISDIGIT(c)) {
do {
if (c == '_') {
if (nondigit) break;
@@ -6906,7 +6946,7 @@ parser_yylex(struct parser_params *parser)
if (c == 'o' || c == 'O') {
/* prefixed octal */
c = nextc();
- if (c == '_' || !ISDIGIT(c)) {
+ if (c == -1 || c == '_' || !ISDIGIT(c)) {
yyerror("numeric literal without digits");
}
}
@@ -6965,7 +7005,7 @@ parser_yylex(struct parser_params *parser)
}
else {
int c0 = nextc();
- if (!ISDIGIT(c0)) {
+ if (c == -1 || !ISDIGIT(c0)) {
pushback(c0);
goto decode_num;
}
@@ -7054,7 +7094,7 @@ parser_yylex(struct parser_params *parser)
lex_state = EXPR_DOT;
return tCOLON2;
}
- if (lex_state == EXPR_END || lex_state == EXPR_ENDARG || ISSPACE(c)) {
+ if (lex_state == EXPR_END || lex_state == EXPR_ENDARG || (c != -1 && ISSPACE(c))) {
pushback(c);
lex_state = EXPR_BEG;
return ':';
@@ -7213,7 +7253,7 @@ parser_yylex(struct parser_params *parser)
c = nextc();
quotation:
- if (!ISALNUM(c)) {
+ if (c == -1 || !ISALNUM(c)) {
term = c;
c = 'Q';
}
@@ -7363,7 +7403,7 @@ parser_yylex(struct parser_params *parser)
do {
tokadd(c);
c = nextc();
- } while (ISDIGIT(c));
+ } while (c != -1 && ISDIGIT(c));
pushback(c);
if (last_state == EXPR_FNAME) goto gvar;
tokfix();
@@ -7388,7 +7428,7 @@ parser_yylex(struct parser_params *parser)
tokadd('@');
c = nextc();
}
- if (ISDIGIT(c)) {
+ if (c != -1 && ISDIGIT(c)) {
if (tokidx == 1) {
compile_error(PARSER_ARG "`@%c' is not allowed as an instance variable name", c);
}
@@ -7489,6 +7529,16 @@ parser_yylex(struct parser_params *parser)
}
}
+ if ((lex_state == EXPR_BEG && !cmd_state) ||
+ lex_state == EXPR_ARG ||
+ lex_state == EXPR_CMDARG) {
+ if (peek(':') && !(lex_p + 1 < lex_pend && lex_p[1] == ':')) {
+ lex_state = EXPR_BEG;
+ nextc();
+ set_yylval_id(TOK_INTERN(!ENC_SINGLE(mb)));
+ return tLABEL;
+ }
+ }
if (mb == ENC_CODERANGE_7BIT && lex_state != EXPR_DOT) {
const struct kwtable *kw;
@@ -7525,16 +7575,6 @@ parser_yylex(struct parser_params *parser)
}
}
- if ((lex_state == EXPR_BEG && !cmd_state) ||
- lex_state == EXPR_ARG ||
- lex_state == EXPR_CMDARG) {
- if (peek(':') && !(lex_p + 1 < lex_pend && lex_p[1] == ':')) {
- lex_state = EXPR_BEG;
- nextc();
- set_yylval_id(TOK_INTERN(!ENC_SINGLE(mb)));
- return tLABEL;
- }
- }
if (IS_BEG() ||
lex_state == EXPR_DOT ||
IS_ARG()) {
@@ -8092,7 +8132,8 @@ arg_concat_gen(struct parser_params *parser, NODE *node1, NODE *node2)
nd_set_type(node1, NODE_ARGSCAT);
return node1;
case NODE_ARGSCAT:
- if (nd_type(node2) != NODE_ARRAY) break;
+ if (nd_type(node2) != NODE_ARRAY ||
+ nd_type(node1->nd_body) != NODE_ARRAY) break;
node1->nd_body = list_concat(node1->nd_body, node2);
return node1;
}
@@ -8729,7 +8770,6 @@ local_tbl_gen(struct parser_params *parser)
return buf;
}
-#include "debug.h"
static int
arg_var_gen(struct parser_params *parser, ID id)
{
diff --git a/prec.c b/prec.c
deleted file mode 100644
index 7b79fc1be6..0000000000
--- a/prec.c
+++ /dev/null
@@ -1,140 +0,0 @@
-/**********************************************************************
-
- prec.c -
-
- $Author$
- created at: Tue Jan 26 02:40:41 2000
-
- Copyright (C) 1993-2007 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#include "ruby/ruby.h"
-
-static ID prc_pr, prc_if;
-
-
-/*
- * call-seq:
- * num.prec(klass) => a_class
- *
- * Converts _self_ into an instance of _klass_. By default,
- * +prec+ invokes
- *
- * klass.induced_from(num)
- *
- * and returns its value. So, if <code>klass.induced_from</code>
- * doesn't return an instance of _klass_, it will be necessary
- * to reimplement +prec+.
- */
-
-static VALUE
-prec_prec(VALUE x, VALUE klass)
-{
- return rb_funcall(klass, prc_if, 1, x);
-}
-
-/*
- * call-seq:
- * num.prec_i => Integer
- *
- * Returns an +Integer+ converted from _num_. It is equivalent
- * to <code>prec(Integer)</code>.
- */
-
-static VALUE
-prec_prec_i(VALUE x)
-{
- VALUE klass = rb_cInteger;
-
- return rb_funcall(x, prc_pr, 1, klass);
-}
-
-/*
- * call-seq:
- * num.prec_f => Float
- *
- * Returns a +Float+ converted from _num_. It is equivalent
- * to <code>prec(Float)</code>.
- */
-
-static VALUE
-prec_prec_f(VALUE x)
-{
- VALUE klass = rb_cFloat;
-
- return rb_funcall(x, prc_pr, 1, klass);
-}
-
-/*
- * call-seq:
- * Mod.induced_from(number) => a_mod
- *
- * Creates an instance of mod from. This method is overridden
- * by concrete +Numeric+ classes, so that (for example)
- *
- * Fixnum.induced_from(9.9) #=> 9
- *
- * Note that a use of +prec+ in a redefinition may cause
- * an infinite loop.
- */
-
-static VALUE
-prec_induced_from(VALUE module, VALUE x)
-{
- rb_raise(rb_eTypeError, "undefined conversion from %s into %s",
- rb_obj_classname(x), rb_class2name(module));
- return Qnil; /* not reached */
-}
-
-/*
- * call_seq:
- * included
- *
- * When the +Precision+ module is mixed-in to a class, this +included+
- * method is used to add our default +induced_from+ implementation
- * to the host class.
- */
-
-static VALUE
-prec_included(VALUE module, VALUE include)
-{
- switch (TYPE(include)) {
- case T_CLASS:
- case T_MODULE:
- break;
- default:
- Check_Type(include, T_CLASS);
- break;
- }
- rb_define_singleton_method(include, "induced_from", prec_induced_from, 1);
- return module;
-}
-
-/*
- * Precision is a mixin for concrete numeric classes with
- * precision. Here, `precision' means the fineness of approximation
- * of a real number, so, this module should not be included into
- * anything which is not a subset of Real (so it should not be
- * included in classes such as +Complex+ or +Matrix+).
-*/
-
-void
-Init_Precision(void)
-{
-#undef rb_intern
-#define rb_intern(str) rb_intern_const(str)
-
- prc_pr = rb_intern("prec");
- prc_if = rb_intern("induced_from");
-}
-
-void
-InitVM_Precision(rb_vm_t *vm)
-{
- rb_mPrecision = rb_define_module("Precision");
- rb_define_singleton_method(rb_mPrecision, "included", prec_included, 1);
- rb_define_method(rb_mPrecision, "prec", prec_prec, 1);
- rb_define_method(rb_mPrecision, "prec_i", prec_prec_i, 0);
- rb_define_method(rb_mPrecision, "prec_f", prec_prec_f, 0);
-}
diff --git a/proc.c b/proc.c
index 11595d7669..3be8484150 100644
--- a/proc.c
+++ b/proc.c
@@ -504,11 +504,11 @@ proc_call(int argc, VALUE *argv, VALUE procval)
{
rb_proc_t *proc;
rb_block_t *blockptr = 0;
+ rb_iseq_t *iseq;
GetProcPtr(procval, proc);
- if (BUILTIN_TYPE(proc->block.iseq) == T_NODE ||
- proc->block.iseq->arg_block != -1) {
-
+ iseq = proc->block.iseq;
+ if (BUILTIN_TYPE(iseq) == T_NODE || iseq->arg_block != -1) {
if (rb_block_given_p()) {
rb_proc_t *proc;
VALUE procval;
@@ -615,16 +615,15 @@ get_proc_iseq(VALUE self)
return iseq;
}
-VALUE
-rb_proc_location(VALUE self)
+static VALUE
+iseq_location(rb_iseq_t *iseq)
{
- rb_iseq_t *iseq = get_proc_iseq(self);
VALUE loc[2];
if (!iseq) return Qnil;
loc[0] = iseq->filename;
if (iseq->insn_info_table) {
- loc[1] = INT2FIX(iseq->insn_info_table[0].line_no);
+ loc[1] = INT2FIX(rb_iseq_first_lineno(iseq));
}
else {
loc[1] = Qnil;
@@ -634,6 +633,20 @@ rb_proc_location(VALUE self)
/*
* call-seq:
+ * prc.source_location => [String, Fixnum]
+ *
+ * returns the ruby source filename and line number containing this proc
+ * or nil if this proc was not defined in ruby (i.e. native)
+ */
+
+VALUE
+rb_proc_location(VALUE self)
+{
+ return iseq_location(get_proc_iseq(self));
+}
+
+/*
+ * call-seq:
* prc == other_proc => true or false
*
* Return <code>true</code> if <i>prc</i> is the same object as
@@ -648,12 +661,15 @@ proc_eq(VALUE self, VALUE other)
}
else {
if (TYPE(other) == T_DATA &&
- RBASIC(other)->klass == rb_cProc &&
- CLASS_OF(self) == CLASS_OF(other)) {
+ RDATA(other)->dmark == proc_mark) {
rb_proc_t *p1, *p2;
GetProcPtr(self, p1);
GetProcPtr(other, p2);
- if (p1->block.iseq == p2->block.iseq && p1->envval == p2->envval) {
+ if (p1->envval == p2->envval &&
+ p1->block.iseq->iseq_size == p2->block.iseq->iseq_size &&
+ p1->block.iseq->local_size == p2->block.iseq->local_size &&
+ MEMCMP(p1->block.iseq->iseq, p2->block.iseq->iseq, VALUE,
+ p1->block.iseq->iseq_size) == 0) {
return Qtrue;
}
}
@@ -705,7 +721,7 @@ proc_to_s(VALUE self)
int line_no = 0;
if (iseq->insn_info_table) {
- line_no = iseq->insn_info_table[0].line_no;
+ line_no = rb_iseq_first_lineno(iseq);
}
str = rb_sprintf("#<%s:%p@%s:%d%s>", cname, (void *)self,
RSTRING_PTR(iseq->filename),
@@ -1432,6 +1448,39 @@ rb_obj_method_arity(VALUE obj, ID id)
return rb_mod_method_arity(CLASS_OF(obj), id);
}
+static rb_iseq_t *
+get_method_iseq(VALUE method)
+{
+ struct METHOD *data;
+ NODE *body;
+ rb_iseq_t *iseq;
+
+ Data_Get_Struct(method, struct METHOD, data);
+ body = data->body;
+ switch (nd_type(body)) {
+ case RUBY_VM_METHOD_NODE:
+ GetISeqPtr((VALUE)body->nd_body, iseq);
+ if (RUBY_VM_NORMAL_ISEQ_P(iseq)) break;
+ default:
+ return 0;
+ }
+ return iseq;
+}
+
+/*
+ * call-seq:
+ * meth.source_location => [String, Fixnum]
+ *
+ * returns the ruby source filename and line number containing this method
+ * or nil if this method was not defined in ruby (i.e. native)
+ */
+
+VALUE
+rb_method_location(VALUE method)
+{
+ return iseq_location(get_method_iseq(method));
+}
+
/*
* call-seq:
* meth.to_s => string
@@ -1623,11 +1672,7 @@ static VALUE curry(VALUE dummy, VALUE args, int argc, VALUE *argv, VALUE passed_
static VALUE
make_curry_proc(VALUE proc, VALUE passed, VALUE arity)
{
- VALUE args = rb_ary_new2(3);
- RARRAY_PTR(args)[0] = proc;
- RARRAY_PTR(args)[1] = passed;
- RARRAY_PTR(args)[2] = arity;
- RARRAY_LEN(args) = 3;
+ VALUE args = rb_ary_new3(3, proc, passed, arity);
rb_ary_freeze(passed);
rb_ary_freeze(args);
return rb_proc_new(curry, args);
@@ -1768,6 +1813,7 @@ InitVM_Proc(rb_vm_t *vm)
rb_define_method(rb_cProc, "lambda?", proc_lambda_p, 0);
rb_define_method(rb_cProc, "binding", proc_binding, 0);
rb_define_method(rb_cProc, "curry", proc_curry, -1);
+ rb_define_method(rb_cProc, "source_location", rb_proc_location, 0);
/* Exceptions */
rb_eLocalJumpError = rb_define_class("LocalJumpError", rb_eStandardError);
@@ -1802,6 +1848,7 @@ InitVM_Proc(rb_vm_t *vm)
rb_define_method(rb_cMethod, "name", method_name, 0);
rb_define_method(rb_cMethod, "owner", method_owner, 0);
rb_define_method(rb_cMethod, "unbind", method_unbind, 0);
+ rb_define_method(rb_cMethod, "source_location", rb_method_location, 0);
rb_define_method(rb_mKernel, "method", rb_obj_method, 1);
rb_define_method(rb_mKernel, "public_method", rb_obj_public_method, 1);
@@ -1819,6 +1866,7 @@ InitVM_Proc(rb_vm_t *vm)
rb_define_method(rb_cUnboundMethod, "name", method_name, 0);
rb_define_method(rb_cUnboundMethod, "owner", method_owner, 0);
rb_define_method(rb_cUnboundMethod, "bind", umethod_bind, 1);
+ rb_define_method(rb_cUnboundMethod, "source_location", rb_method_location, 0);
/* Module#*_method */
rb_define_method(rb_cModule, "instance_method", rb_mod_instance_method, 1);
diff --git a/process.c b/process.c
index ecfd1ed44f..5dadfd6852 100644
--- a/process.c
+++ b/process.c
@@ -28,9 +28,6 @@
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
-#ifdef __DJGPP__
-#include <process.h>
-#endif
#include <time.h>
#include <ctype.h>
@@ -998,17 +995,9 @@ proc_exec_v(char **argv, const char *prog)
return -1;
}
-#if (defined(MSDOS) && !defined(DJGPP)) || defined(__human68k__) || defined(__EMX__) || defined(OS2)
+#if defined(__EMX__) || defined(OS2)
{
-#if defined(__human68k__)
-#define COMMAND "command.x"
-#endif
-#if defined(__EMX__) || defined(OS2) /* OS/2 emx */
#define COMMAND "cmd.exe"
-#endif
-#if (defined(MSDOS) && !defined(DJGPP))
-#define COMMAND "command.com"
-#endif
char *extension;
if ((extension = strrchr(prog, '.')) != NULL && STRCASECMP(extension, ".bat") == 0) {
@@ -1034,7 +1023,7 @@ proc_exec_v(char **argv, const char *prog)
}
}
}
-#endif /* MSDOS or __human68k__ or __EMX__ */
+#endif /* __EMX__ */
before_exec();
execv(prog, argv);
preserving_errno(after_exec());
@@ -1085,14 +1074,7 @@ rb_proc_exec(const char *str)
if (nl) s = nl;
}
if (*s != ' ' && !ISALPHA(*s) && strchr("*?{}[]<>()~&|\\$;'`\"\n",*s)) {
-#if defined(MSDOS)
- int status;
- before_exec();
- status = system(str);
- after_exec();
- if (status != -1)
- exit(status);
-#elif defined(__human68k__) || defined(__CYGWIN32__) || defined(__EMX__)
+#if defined(__CYGWIN32__) || defined(__EMX__)
char fbuf[MAXPATHLEN];
char *shell = dln_find_exe_r("sh", 0, fbuf, sizeof(fbuf));
int status = -1;
@@ -1152,30 +1134,6 @@ proc_spawn_v(char **argv, char *prog)
if (!prog)
return -1;
-#if defined(__human68k__)
- if ((extension = strrchr(prog, '.')) != NULL && STRCASECMP(extension, ".bat") == 0) {
- char **new_argv;
- char *p;
- int n;
-
- for (n = 0; argv[n]; n++)
- /* no-op */;
- new_argv = ALLOCA_N(char*, n + 2);
- for (; n > 0; n--)
- new_argv[n + 1] = argv[n];
- new_argv[1] = strcpy(ALLOCA_N(char, strlen(argv[0]) + 1), argv[0]);
- for (p = new_argv[1]; *p != '\0'; p++)
- if (*p == '/')
- *p = '\\';
- new_argv[0] = COMMAND;
- argv = new_argv;
- prog = dln_find_exe_r(argv[0], 0, fbuf, sizeof(fbuf));
- if (!prog) {
- errno = ENOENT;
- return -1;
- }
- }
-#endif
before_exec();
status = spawnv(P_WAIT, prog, argv);
rb_last_status_set(status == -1 ? 127 : status, 0);
@@ -1328,8 +1286,9 @@ check_exec_redirect(VALUE key, VALUE val, VALUE options)
index = EXEC_OPTION_OPEN;
path = val;
FilePathValue(path);
- if ((FIXNUM_P(key) && (FIX2INT(key) == 1 || FIX2INT(key) == 2)) ||
- key == rb_stdout || key == rb_stderr)
+ if (TYPE(key) == T_FILE)
+ key = check_exec_redirect_fd(key);
+ if (FIXNUM_P(key) && (FIX2INT(key) == 1 || FIX2INT(key) == 2))
flags = INT2NUM(O_WRONLY|O_CREAT|O_TRUNC);
else
flags = INT2NUM(O_RDONLY);
@@ -1686,10 +1645,9 @@ rb_exec_arg_fixup(struct rb_exec_arg *e)
* expansion. If +command+ is a two-element array, the first
* element is the command to be executed, and the second argument is
* used as the <code>argv[0]</code> value, which may show up in process
- * listings. In MSDOS environments, the command is executed in a
- * subshell; otherwise, one of the <code>exec(2)</code> system calls is
- * used, so the running command may inherit some of the environment of
- * the original program (including open file descriptors).
+ * listings. In order to execute the command, one of the <code>exec(2)</code>
+ * system calls is used, so the running command may inherit some of the environment
+ * of the original program (including open file descriptors).
*
* The hash arguments, env and options, are same as
* <code>system</code> and <code>spawn</code>.
@@ -1890,7 +1848,7 @@ run_exec_dup2(VALUE ary, VALUE save)
int j = i;
while (j != -1 && pairs[j].oldfd != -1 && pairs[j].num_newer == 0) {
if (save_redirect_fd(pairs[j].newfd, save) < 0)
- return -1;
+ goto fail;
ret = redirect_dup2(pairs[j].oldfd, pairs[j].newfd);
if (ret == -1)
goto fail;
@@ -2125,6 +2083,7 @@ rb_run_exec_options(const struct rb_exec_arg *e, struct rb_exec_arg *s)
char *cwd = my_getcwd();
rb_ary_store(soptions, EXEC_OPTION_CHDIR,
hide_obj(rb_str_new2(cwd)));
+ xfree(cwd);
}
if (chdir(RSTRING_PTR(obj)) == -1)
return -1;
@@ -2301,15 +2260,10 @@ rb_fork(int *status, int (*chfunc)(void*), void *charg, VALUE fds)
int ep[2];
#endif
-#ifndef __VMS
#define prefork() ( \
rb_io_flush(rb_stdout), \
rb_io_flush(rb_stderr) \
)
-#else
-#define prefork() ((void)0)
-#endif
-
prefork();
#ifdef FD_CLOEXEC
@@ -2696,11 +2650,7 @@ rb_spawn_internal(int argc, VALUE *argv, int default_close_others)
# else
if (argc) prog = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" "));
status = system(StringValuePtr(prog));
-# if defined(__human68k__) || defined(__DJGPP__)
- rb_last_status_set(status == -1 ? 127 : status, 0);
-# else
rb_last_status_set((status & 0xff) << 8, 0);
-# endif
# endif
rb_run_exec_options(&sarg, NULL);
diff --git a/range.c b/range.c
index 2fcf5cfaba..7231db2f1a 100644
--- a/range.c
+++ b/range.c
@@ -635,7 +635,7 @@ rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err)
out_of_range:
if (err) {
rb_raise(rb_eRangeError, "%ld..%s%ld out of range",
- b, excl ? "." : "", e);
+ NUM2LONG(b), excl ? "." : "", NUM2LONG(e));
}
return Qnil;
}
@@ -662,6 +662,24 @@ range_to_s(VALUE range)
return str;
}
+static VALUE
+inspect_range(VALUE range, VALUE dummy, int recur)
+{
+ VALUE str, str2;
+
+ if (recur) {
+ return rb_str_new2(EXCL(range) ? "(... ... ...)" : "(... .. ...)");
+ }
+ str = rb_inspect(RANGE_BEG(range));
+ str2 = rb_inspect(RANGE_END(range));
+ str = rb_str_dup(str);
+ rb_str_cat(str, "...", EXCL(range) ? 3 : 2);
+ rb_str_append(str, str2);
+ OBJ_INFECT(str, str2);
+
+ return str;
+}
+
/*
* call-seq:
* rng.inspect => string
@@ -675,16 +693,7 @@ range_to_s(VALUE range)
static VALUE
range_inspect(VALUE range)
{
- VALUE str, str2;
-
- str = rb_inspect(RANGE_BEG(range));
- str2 = rb_inspect(RANGE_END(range));
- str = rb_str_dup(str);
- rb_str_cat(str, "...", EXCL(range) ? 3 : 2);
- rb_str_append(str, str2);
- OBJ_INFECT(str, str2);
-
- return str;
+ return rb_exec_recursive(inspect_range, range, 0);
}
/*
diff --git a/rational.c b/rational.c
index f2ab575379..04335c5d24 100644
--- a/rational.c
+++ b/rational.c
@@ -9,13 +9,13 @@
#include <math.h>
#include <float.h>
-#define NDEBUG
-#include <assert.h>
-
#ifdef HAVE_IEEEFP_H
#include <ieeefp.h>
#endif
+#define NDEBUG
+#include <assert.h>
+
#ifndef RATIONAL_NAME
#define RATIONAL_NAME "Rational"
#endif
@@ -24,9 +24,9 @@
#define ONE INT2FIX(1)
#define TWO INT2FIX(2)
-static ID id_Unify, id_abs, id_cmp, id_convert, id_equal_p, id_expt,
- id_floor, id_format, id_idiv, id_inspect, id_negate, id_new, id_new_bang,
- id_to_f, id_to_i, id_to_s, id_truncate;
+static ID id_abs, id_cmp, id_convert, id_equal_p, id_expt, id_floor,
+ id_format, id_hash, id_idiv, id_inspect, id_integer_p, id_negate,
+ id_to_f, id_to_i, id_to_s, id_truncate;
#define f_boolcast(x) ((x) ? Qtrue : Qfalse)
@@ -54,14 +54,10 @@ f_##n(VALUE x, VALUE y)\
inline static VALUE
f_add(VALUE x, VALUE y)
{
- if (FIXNUM_P(y)) {
- if (FIX2LONG(y) == 0)
- return x;
- }
- else if (FIXNUM_P(x)) {
- if (FIX2LONG(x) == 0)
- return y;
- }
+ if (FIXNUM_P(y) && FIX2LONG(y) == 0)
+ return x;
+ else if (FIXNUM_P(x) && FIX2LONG(x) == 0)
+ return y;
return rb_funcall(x, '+', 1, y);
}
@@ -109,25 +105,21 @@ inline static VALUE
f_mul(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
- long _iy = FIX2LONG(y);
- if (_iy == 0) {
- if (TYPE(x) == T_FLOAT)
- return rb_float_new(0.0);
- else
+ long iy = FIX2LONG(y);
+ if (iy == 0) {
+ if (FIXNUM_P(x) || TYPE(x) == T_BIGNUM)
return ZERO;
}
- else if (_iy == 1)
+ else if (iy == 1)
return x;
}
else if (FIXNUM_P(x)) {
- long _ix = FIX2LONG(x);
- if (_ix == 0) {
- if (TYPE(y) == T_FLOAT)
- return rb_float_new(0.0);
- else
+ long ix = FIX2LONG(x);
+ if (ix == 0) {
+ if (FIXNUM_P(y) || TYPE(y) == T_BIGNUM)
return ZERO;
}
- else if (_ix == 1)
+ else if (ix == 1)
return y;
}
return rb_funcall(x, '*', 1, y);
@@ -136,9 +128,8 @@ f_mul(VALUE x, VALUE y)
inline static VALUE
f_sub(VALUE x, VALUE y)
{
- if (FIXNUM_P(y))
- if (FIX2LONG(y) == 0)
- return x;
+ if (FIXNUM_P(y) && FIX2LONG(y) == 0)
+ return x;
return rb_funcall(x, '-', 1, y);
}
@@ -146,7 +137,9 @@ binop(xor, '^')
fun1(abs)
fun1(floor)
+fun1(hash)
fun1(inspect)
+fun1(integer_p)
fun1(negate)
fun1(to_f)
fun1(to_i)
@@ -172,6 +165,8 @@ f_negative_p(VALUE x)
return rb_funcall(x, '<', 1, ZERO);
}
+#define f_positive_p(x) (!f_negative_p(x))
+
inline static VALUE
f_zero_p(VALUE x)
{
@@ -180,6 +175,8 @@ f_zero_p(VALUE x)
return rb_funcall(x, id_equal_p, 1, ZERO);
}
+#define f_nonzero_p(x) (!f_zero_p(x))
+
inline static VALUE
f_one_p(VALUE x)
{
@@ -218,6 +215,9 @@ k_rational_p(VALUE x)
return f_kind_of_p(x, rb_cRational);
}
+#define k_exact_p(x) (!k_float_p(x))
+#define k_inexact_p(x) k_float_p(x)
+
#ifndef NDEBUG
#define f_gcd f_gcd_orig
#endif
@@ -282,7 +282,7 @@ inline static VALUE
f_gcd(VALUE x, VALUE y)
{
VALUE r = f_gcd_orig(x, y);
- if (!f_zero_p(r)) {
+ if (f_nonzero_p(r)) {
assert(f_zero_p(f_mod(x, r)));
assert(f_zero_p(f_mod(y, r)));
}
@@ -327,6 +327,7 @@ nurat_s_alloc(VALUE klass)
#define rb_raise_zerodiv() rb_raise(rb_eZeroDivError, "divided by zero")
+#if 0
static VALUE
nurat_s_new_bang(int argc, VALUE *argv, VALUE klass)
{
@@ -358,6 +359,7 @@ nurat_s_new_bang(int argc, VALUE *argv, VALUE klass)
return nurat_s_new_internal(klass, num, den);
}
+#endif
inline static VALUE
f_rational_new_bang1(VALUE klass, VALUE x)
@@ -368,12 +370,24 @@ f_rational_new_bang1(VALUE klass, VALUE x)
inline static VALUE
f_rational_new_bang2(VALUE klass, VALUE x, VALUE y)
{
- assert(!f_negative_p(y));
- assert(!f_zero_p(y));
+ assert(f_positive_p(y));
+ assert(f_nonzero_p(y));
return nurat_s_new_internal(klass, x, y);
}
-#define f_unify_p(klass) rb_const_defined(klass, id_Unify)
+#if RUBY_VERSION_CODE < 200
+#define CANON
+#endif
+
+#ifdef CANON
+static int canonicalization = 0;
+
+void
+nurat_canonicalize(int f)
+{
+ canonicalization = f;
+}
+#endif
inline static void
nurat_int_check(VALUE num)
@@ -383,11 +397,21 @@ nurat_int_check(VALUE num)
case T_BIGNUM:
break;
default:
- rb_raise(rb_eArgError, "not an integer");
+ if (!k_numeric_p(num) || !f_integer_p(num))
+ rb_raise(rb_eArgError, "not an integer");
}
}
inline static VALUE
+nurat_int_value(VALUE num)
+{
+ nurat_int_check(num);
+ if (!k_integer_p(num))
+ num = f_to_i(num);
+ return num;
+}
+
+inline static VALUE
nurat_s_canonicalize_internal(VALUE klass, VALUE num, VALUE den)
{
VALUE gcd;
@@ -406,8 +430,10 @@ nurat_s_canonicalize_internal(VALUE klass, VALUE num, VALUE den)
num = f_idiv(num, gcd);
den = f_idiv(den, gcd);
- if (f_one_p(den) && f_unify_p(klass))
+#ifdef CANON
+ if (f_one_p(den) && canonicalization)
return num;
+#endif
return nurat_s_new_internal(klass, num, den);
}
@@ -424,38 +450,28 @@ nurat_s_canonicalize_internal_no_reduce(VALUE klass, VALUE num, VALUE den)
break;
}
- if (f_equal_p(den, ONE) && f_unify_p(klass))
+#ifdef CANON
+ if (f_one_p(den) && canonicalization)
return num;
+#endif
return nurat_s_new_internal(klass, num, den);
}
-#if 0
-static VALUE
-nurat_s_canonicalize(int argc, VALUE *argv, VALUE klass)
-{
- VALUE num, den;
-
- if (rb_scan_args(argc, argv, "11", &num, &den) == 1) {
- den = ONE;
- }
-
- nurat_int_check(num);
- nurat_int_check(den);
-
- return nurat_s_canonicalize_internal(klass, num, den);
-}
-#endif
-
static VALUE
nurat_s_new(int argc, VALUE *argv, VALUE klass)
{
VALUE num, den;
- if (rb_scan_args(argc, argv, "11", &num, &den) == 1)
+ switch (rb_scan_args(argc, argv, "11", &num, &den)) {
+ case 1:
+ num = nurat_int_value(num);
den = ONE;
-
- nurat_int_check(num);
- nurat_int_check(den);
+ break;
+ default:
+ num = nurat_int_value(num);
+ den = nurat_int_value(den);
+ break;
+ }
return nurat_s_canonicalize_internal(klass, num, den);
}
@@ -759,7 +775,7 @@ nurat_fdiv(VALUE self, VALUE other)
static VALUE
nurat_expt(VALUE self, VALUE other)
{
- if (f_zero_p(other))
+ if (k_exact_p(other) && f_zero_p(other))
return f_rational_new_bang1(CLASS_OF(self), ONE);
if (k_rational_p(other)) {
@@ -938,7 +954,7 @@ nurat_quotrem(VALUE self, VALUE other)
static VALUE
nurat_abs(VALUE self)
{
- if (!f_negative_p(self))
+ if (f_positive_p(self))
return self;
return f_negate(self);
}
@@ -1089,7 +1105,7 @@ static VALUE
nurat_hash(VALUE self)
{
get_dat1(self);
- return f_xor(dat->num, dat->den);
+ return f_xor(f_hash(dat->num), f_hash(dat->den));
}
static VALUE
@@ -1111,8 +1127,12 @@ nurat_inspect(VALUE self)
static VALUE
nurat_marshal_dump(VALUE self)
{
+ VALUE a;
get_dat1(self);
- return rb_assoc_new(dat->num, dat->den);
+
+ a = rb_assoc_new(dat->num, dat->den);
+ rb_copy_generic_ivar(a, self);
+ return a;
}
static VALUE
@@ -1121,6 +1141,7 @@ nurat_marshal_load(VALUE self, VALUE a)
get_dat1(self);
dat->num = RARRAY_PTR(a)[0];
dat->den = RARRAY_PTR(a)[1];
+ rb_copy_generic_ivar(self, a);
if (f_zero_p(dat->den))
rb_raise_zerodiv();
@@ -1133,21 +1154,21 @@ nurat_marshal_load(VALUE self, VALUE a)
VALUE
rb_gcd(VALUE self, VALUE other)
{
- nurat_int_check(other);
+ other = nurat_int_value(other);
return f_gcd(self, other);
}
VALUE
rb_lcm(VALUE self, VALUE other)
{
- nurat_int_check(other);
+ other = nurat_int_value(other);
return f_lcm(self, other);
}
VALUE
rb_gcdlcm(VALUE self, VALUE other)
{
- nurat_int_check(other);
+ other = nurat_int_value(other);
return rb_assoc_new(f_gcd(self, other), f_lcm(self, other));
}
@@ -1388,26 +1409,18 @@ nurat_s_convert(int argc, VALUE *argv, VALUE klass)
{
VALUE a1, a2, backref;
- rb_scan_args(argc, argv, "02", &a1, &a2);
+ rb_scan_args(argc, argv, "11", &a1, &a2);
switch (TYPE(a1)) {
case T_COMPLEX:
- if (k_float_p(RCOMPLEX(a1)->image) || !f_zero_p(RCOMPLEX(a1)->image)) {
- VALUE s = f_to_s(a1);
- rb_raise(rb_eRangeError, "can't accept %s",
- StringValuePtr(s));
- }
- a1 = RCOMPLEX(a1)->real;
+ if (k_exact_p(RCOMPLEX(a1)->imag) && f_zero_p(RCOMPLEX(a1)->imag))
+ a1 = RCOMPLEX(a1)->real;
}
switch (TYPE(a2)) {
case T_COMPLEX:
- if (k_float_p(RCOMPLEX(a2)->image) || !f_zero_p(RCOMPLEX(a2)->image)) {
- VALUE s = f_to_s(a2);
- rb_raise(rb_eRangeError, "can't accept %s",
- StringValuePtr(s));
- }
- a2 = RCOMPLEX(a2)->real;
+ if (k_exact_p(RCOMPLEX(a2)->imag) && f_zero_p(RCOMPLEX(a2)->imag))
+ a2 = RCOMPLEX(a2)->real;
}
backref = rb_backref_get();
@@ -1441,14 +1454,18 @@ nurat_s_convert(int argc, VALUE *argv, VALUE klass)
switch (TYPE(a1)) {
case T_RATIONAL:
- if (NIL_P(a2) || f_zero_p(a2))
+ if (argc == 1 || (k_exact_p(a2) && f_one_p(a2)))
return a1;
- return f_div(a1, a2);
}
- switch (TYPE(a2)) {
- case T_RATIONAL:
- return f_div(a1, a2);
+ if (argc == 1) {
+ if (k_numeric_p(a1) && !f_integer_p(a1))
+ return a1;
+ }
+ else {
+ if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
+ (!f_integer_p(a1) || !f_integer_p(a2)))
+ return f_div(a1, a2);
}
{
@@ -1459,19 +1476,12 @@ nurat_s_convert(int argc, VALUE *argv, VALUE klass)
}
}
-static VALUE
-nurat_s_induced_from(VALUE klass, VALUE n)
-{
- return f_to_r(n);
-}
-
void
Init_Rational(void)
{
#undef rb_intern
#define rb_intern(str) rb_intern_const(str)
- id_Unify = rb_intern("Unify");
id_abs = rb_intern("abs");
id_cmp = rb_intern("<=>");
id_convert = rb_intern("convert");
@@ -1479,11 +1489,11 @@ Init_Rational(void)
id_expt = rb_intern("**");
id_floor = rb_intern("floor");
id_format = rb_intern("format");
+ id_hash = rb_intern("hash");
id_idiv = rb_intern("div");
id_inspect = rb_intern("inspect");
+ id_integer_p = rb_intern("integer?");
id_negate = rb_intern("-@");
- id_new = rb_intern("new");
- id_new_bang = rb_intern("new!");
id_to_f = rb_intern("to_f");
id_to_i = rb_intern("to_i");
id_to_s = rb_intern("to_s");
@@ -1498,16 +1508,14 @@ InitVM_Rational(rb_vm_t *vm)
rb_cRational = rb_define_class(RATIONAL_NAME, rb_cNumeric);
rb_define_alloc_func(rb_cRational, nurat_s_alloc);
- rb_funcall(rb_cRational, rb_intern("private_class_method"), 1,
- ID2SYM(rb_intern("allocate")));
-
- rb_define_singleton_method(rb_cRational, "new!", nurat_s_new_bang, -1);
- rb_funcall(rb_cRational, rb_intern("private_class_method"), 1,
- ID2SYM(rb_intern("new!")));
+ rb_undef_method(CLASS_OF(rb_cRational), "allocate");
- rb_define_singleton_method(rb_cRational, "new", nurat_s_new, -1);
- rb_funcall(rb_cRational, rb_intern("private_class_method"), 1,
- ID2SYM(rb_intern("new")));
+#if 0
+ rb_define_private_method(CLASS_OF(rb_cRational), "new!", nurat_s_new_bang, -1);
+ rb_define_private_method(CLASS_OF(rb_cRational), "new", nurat_s_new, -1);
+#else
+ rb_undef_method(CLASS_OF(rb_cRational), "new");
+#endif
rb_define_global_function(RATIONAL_NAME, nurat_f_rational, -1);
@@ -1580,11 +1588,11 @@ InitVM_Rational(rb_vm_t *vm)
rb_define_method(rb_cString, "to_r", string_to_r, 0);
- rb_define_singleton_method(rb_cRational, "convert", nurat_s_convert, -1);
- rb_funcall(rb_cRational, rb_intern("private_class_method"), 1,
- ID2SYM(rb_intern("convert")));
-
- rb_include_module(rb_cRational, rb_mPrecision);
- rb_define_singleton_method(rb_cRational, "induced_from",
- nurat_s_induced_from, 1);
+ rb_define_private_method(CLASS_OF(rb_cRational), "convert", nurat_s_convert, -1);
}
+
+/*
+Local variables:
+c-file-style: "ruby"
+End:
+*/
diff --git a/re.c b/re.c
index 6a685f774a..d7830ef053 100644
--- a/re.c
+++ b/re.c
@@ -378,8 +378,12 @@ static VALUE
rb_reg_desc(const char *s, long len, VALUE re)
{
VALUE str = rb_str_buf_new2("/");
-
- rb_enc_copy(str, re);
+ if (re && rb_enc_asciicompat(rb_enc_get(re))) {
+ rb_enc_copy(str, re);
+ }
+ else {
+ rb_enc_associate(str, rb_usascii_encoding());
+ }
rb_reg_expr_str(str, s, len);
rb_str_buf_cat2(str, "/");
if (re) {
@@ -1260,10 +1264,10 @@ rb_reg_adjust_startpos(VALUE re, VALUE str, int pos, int reverse)
string = (UChar*)RSTRING_PTR(str);
if (range > 0) {
- p = onigenc_get_right_adjust_char_head(enc, string, string + pos);
+ p = onigenc_get_right_adjust_char_head(enc, string, string + pos, string + RSTRING_LEN(str));
}
else {
- p = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, string, string + pos);
+ p = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, string, string + pos, string + RSTRING_LEN(str));
}
return p - string;
}
@@ -2561,11 +2565,13 @@ reg_match_pos(VALUE re, VALUE *strp, long pos)
* p rhs #=> nil
*
* This assignment is implemented in the Ruby parser.
- * So a regexp literal is required for the assignment.
+ * The parser detects 'regexp-literal =~ expression' for the assignment.
+ * The regexp must be a literal without interpolation and placed at left hand side.
+ *
* The assignment is not occur if the regexp is not a literal.
*
* re = /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/
- * re =~ " x = "
+ * re =~ " x = y "
* p lhs # undefined local variable
* p rhs # undefined local variable
*
@@ -2576,6 +2582,11 @@ reg_match_pos(VALUE re, VALUE *strp, long pos)
* /(?<lhs>\w+)\s*=\s*#{rhs_pat}/ =~ "x = y"
* p lhs # undefined local variable
*
+ * The assignment is not occur if the regexp is placed at right hand side.
+ *
+ * " x = y " =~ /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/
+ * p lhs, rhs # undefined local variable
+ *
*/
VALUE
@@ -2776,10 +2787,10 @@ rb_reg_initialize_m(int argc, VALUE *argv, VALUE self)
char *kcode = StringValuePtr(argv[2]);
if (kcode[0] == 'n' || kcode[1] == 'N') {
enc = rb_ascii8bit_encoding();
- flags |= ARG_ENCODING_FIXED;
+ flags |= ARG_ENCODING_NONE;
}
else {
- rb_warning("encoding option is obsolete - %s", kcode);
+ rb_warn("encoding option is ignored - %s", kcode);
}
}
str = argv[0];
@@ -2856,34 +2867,34 @@ rb_reg_quote(VALUE str)
case '*': case '.': case '\\':
case '?': case '+': case '^': case '$':
case '#':
- *t++ = '\\';
+ t += rb_enc_mbcput('\\', t, enc);
break;
case ' ':
- *t++ = '\\';
- *t++ = ' ';
+ t += rb_enc_mbcput('\\', t, enc);
+ t += rb_enc_mbcput(' ', t, enc);
continue;
case '\t':
- *t++ = '\\';
- *t++ = 't';
+ t += rb_enc_mbcput('\\', t, enc);
+ t += rb_enc_mbcput('t', t, enc);
continue;
case '\n':
- *t++ = '\\';
- *t++ = 'n';
+ t += rb_enc_mbcput('\\', t, enc);
+ t += rb_enc_mbcput('n', t, enc);
continue;
case '\r':
- *t++ = '\\';
- *t++ = 'r';
+ t += rb_enc_mbcput('\\', t, enc);
+ t += rb_enc_mbcput('r', t, enc);
continue;
case '\f':
- *t++ = '\\';
- *t++ = 'f';
+ t += rb_enc_mbcput('\\', t, enc);
+ t += rb_enc_mbcput('f', t, enc);
continue;
case '\v':
- *t++ = '\\';
- *t++ = 'v';
+ t += rb_enc_mbcput('\\', t, enc);
+ t += rb_enc_mbcput('v', t, enc);
continue;
}
- *t++ = c;
+ t += rb_enc_mbcput(c, t, enc);
}
rb_str_resize(tmp, t - RSTRING_PTR(tmp));
OBJ_INFECT(tmp, str);
@@ -3126,7 +3137,7 @@ rb_reg_regsub(VALUE str, VALUE src, struct re_registers *regs, VALUE regexp)
rb_encoding *str_enc = rb_enc_get(str);
rb_encoding *src_enc = rb_enc_get(src);
int acompat = rb_enc_asciicompat(str_enc);
-#define ASCGET(s,e,cl) (acompat ? (*cl=1,s[0]) : rb_enc_ascget(s, e, cl, str_enc))
+#define ASCGET(s,e,cl) (acompat ? (*cl=1,ISASCII(s[0])?s[0]:-1) : rb_enc_ascget(s, e, cl, str_enc))
p = s = RSTRING_PTR(str);
e = s + RSTRING_LEN(str);
diff --git a/regenc.c b/regenc.c
index 5afa1807b9..634afd8883 100644
--- a/regenc.c
+++ b/regenc.c
@@ -62,24 +62,24 @@ onigenc_mbclen_approximate(const OnigUChar* p,const OnigUChar* e, struct OnigEnc
}
extern UChar*
-onigenc_get_right_adjust_char_head(OnigEncoding enc, const UChar* start, const UChar* s)
+onigenc_get_right_adjust_char_head(OnigEncoding enc, const UChar* start, const UChar* s, const UChar* end)
{
- UChar* p = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s);
+ UChar* p = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s, end);
if (p < s) {
- p += enclen(enc, p, s);
+ p += enclen(enc, p, end);
}
return p;
}
extern UChar*
onigenc_get_right_adjust_char_head_with_prev(OnigEncoding enc,
- const UChar* start, const UChar* s, const UChar** prev)
+ const UChar* start, const UChar* s, const UChar* end, const UChar** prev)
{
- UChar* p = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s);
+ UChar* p = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s, end);
if (p < s) {
if (prev) *prev = (const UChar* )p;
- p += enclen(enc, p, s);
+ p += enclen(enc, p, end);
}
else {
if (prev) *prev = (const UChar* )NULL; /* Sorry */
@@ -88,22 +88,22 @@ onigenc_get_right_adjust_char_head_with_prev(OnigEncoding enc,
}
extern UChar*
-onigenc_get_prev_char_head(OnigEncoding enc, const UChar* start, const UChar* s)
+onigenc_get_prev_char_head(OnigEncoding enc, const UChar* start, const UChar* s, const UChar* end)
{
if (s <= start)
return (UChar* )NULL;
- return ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s - 1);
+ return ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s - 1, end);
}
extern UChar*
-onigenc_step_back(OnigEncoding enc, const UChar* start, const UChar* s, int n)
+onigenc_step_back(OnigEncoding enc, const UChar* start, const UChar* s, const UChar* end, int n)
{
while (ONIG_IS_NOT_NULL(s) && n-- > 0) {
if (s <= start)
return (UChar* )NULL;
- s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s - 1);
+ s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s - 1, end);
}
return (UChar* )s;
}
@@ -369,9 +369,9 @@ onigenc_set_default_caseconv_table(const UChar* table ARG_UNUSED)
}
extern UChar*
-onigenc_get_left_adjust_char_head(OnigEncoding enc, const UChar* start, const UChar* s)
+onigenc_get_left_adjust_char_head(OnigEncoding enc, const UChar* start, const UChar* s, const UChar* end)
{
- return ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s);
+ return ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s, end);
}
const OnigPairCaseFoldCodes OnigAsciiLowerMap[] = {
@@ -630,13 +630,14 @@ extern int
onigenc_single_byte_code_to_mbc(OnigCodePoint code, UChar *buf, OnigEncoding enc ARG_UNUSED)
{
if (code > 0xff)
- rb_raise(rb_eRangeError, "%"PRIdVALUE " out of char range", code);
+ rb_raise(rb_eRangeError, "%u out of char range", code);
*buf = (UChar )(code & 0xff);
return 1;
}
extern UChar*
onigenc_single_byte_left_adjust_char_head(const UChar* start ARG_UNUSED, const UChar* s,
+ const UChar* end,
OnigEncoding enc ARG_UNUSED)
{
return (UChar* )s;
diff --git a/regenc.h b/regenc.h
index 317175f5df..3844e4108d 100644
--- a/regenc.h
+++ b/regenc.h
@@ -125,7 +125,7 @@ ONIG_EXTERN int onigenc_single_byte_mbc_enc_len P_((const UChar* p, const UChar*
ONIG_EXTERN OnigCodePoint onigenc_single_byte_mbc_to_code P_((const UChar* p, const UChar* end, OnigEncoding enc));
ONIG_EXTERN int onigenc_single_byte_code_to_mbclen P_((OnigCodePoint code, OnigEncoding enc));
ONIG_EXTERN int onigenc_single_byte_code_to_mbc P_((OnigCodePoint code, UChar *buf, OnigEncoding enc));
-ONIG_EXTERN UChar* onigenc_single_byte_left_adjust_char_head P_((const UChar* start, const UChar* s, OnigEncoding enc));
+ONIG_EXTERN UChar* onigenc_single_byte_left_adjust_char_head P_((const UChar* start, const UChar* s, const OnigUChar* end, OnigEncoding enc));
ONIG_EXTERN int onigenc_always_true_is_allowed_reverse_match P_((const UChar* s, const UChar* end, OnigEncoding enc));
ONIG_EXTERN int onigenc_always_false_is_allowed_reverse_match P_((const UChar* s, const UChar* end, OnigEncoding enc));
ONIG_EXTERN int onigenc_ascii_is_code_ctype P_((OnigCodePoint code, unsigned int ctype, OnigEncoding enc));
diff --git a/regerror.c b/regerror.c
index d5d1f4008e..780ba94a0e 100644
--- a/regerror.c
+++ b/regerror.c
@@ -51,7 +51,7 @@ onig_error_code_to_format(int code)
case ONIG_NO_SUPPORT_CONFIG:
p = "no support in this configuration"; break;
case ONIGERR_MEMORY:
- p = "fail to memory allocation"; break;
+ p = "failed to allocate memory"; break;
case ONIGERR_MATCH_STACK_LIMIT_OVER:
p = "match-stack limit over"; break;
case ONIGERR_TYPE_BUG:
diff --git a/regexec.c b/regexec.c
index b0cc6647a0..260505901d 100644
--- a/regexec.c
+++ b/regexec.c
@@ -977,25 +977,24 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
}\
} while(0)
-#define STRING_CMP_IC(case_fold_flag,s1,ps2,len) do {\
- if (string_cmp_ic(encode, case_fold_flag, s1, ps2, len) == 0) \
+#define STRING_CMP_IC(case_fold_flag,s1,ps2,len,text_end) do {\
+ if (string_cmp_ic(encode, case_fold_flag, s1, ps2, len, text_end) == 0) \
goto fail; \
} while(0)
static int string_cmp_ic(OnigEncoding enc, int case_fold_flag,
- UChar* s1, UChar** ps2, int mblen)
+ UChar* s1, UChar** ps2, int mblen, const UChar* text_end)
{
UChar buf1[ONIGENC_MBC_CASE_FOLD_MAXLEN];
UChar buf2[ONIGENC_MBC_CASE_FOLD_MAXLEN];
- UChar *p1, *p2, *end1, *s2, *end2;
+ UChar *p1, *p2, *end1, *s2;
int len1, len2;
s2 = *ps2;
end1 = s1 + mblen;
- end2 = s2 + mblen;
while (s1 < end1) {
- len1 = ONIGENC_MBC_CASE_FOLD(enc, case_fold_flag, &s1, end1, buf1);
- len2 = ONIGENC_MBC_CASE_FOLD(enc, case_fold_flag, &s2, end2, buf2);
+ len1 = ONIGENC_MBC_CASE_FOLD(enc, case_fold_flag, &s1, text_end, buf1);
+ len2 = ONIGENC_MBC_CASE_FOLD(enc, case_fold_flag, &s2, text_end, buf2);
if (len1 != len2) return 0;
p1 = buf1;
p2 = buf2;
@@ -1019,8 +1018,8 @@ static int string_cmp_ic(OnigEncoding enc, int case_fold_flag,
}\
} while(0)
-#define STRING_CMP_VALUE_IC(case_fold_flag,s1,ps2,len,is_fail) do {\
- if (string_cmp_ic(encode, case_fold_flag, s1, ps2, len) == 0) \
+#define STRING_CMP_VALUE_IC(case_fold_flag,s1,ps2,len,text_end,is_fail) do {\
+ if (string_cmp_ic(encode, case_fold_flag, s1, ps2, len, text_end) == 0) \
is_fail = 1; \
else \
is_fail = 0; \
@@ -1126,7 +1125,7 @@ static int backref_match_at_nested_level(regex_t* reg
if (ignore_case != 0) {
if (string_cmp_ic(reg->enc, case_fold_flag,
- pstart, &ss, (int )(pend - pstart)) == 0)
+ pstart, &ss, (int )(pend - pstart), send) == 0)
return 0; /* or goto next_mem; */
}
else {
@@ -2199,7 +2198,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
n = pend - pstart;
DATA_ENSURE(n);
sprev = s;
- STRING_CMP_IC(case_fold_flag, pstart, &s, n);
+ STRING_CMP_IC(case_fold_flag, pstart, &s, n, end);
while (sprev + (len = enclen(encode, sprev, end)) < s)
sprev += len;
@@ -2271,7 +2270,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
DATA_ENSURE(n);
sprev = s;
swork = s;
- STRING_CMP_VALUE_IC(case_fold_flag, pstart, &swork, n, is_fail);
+ STRING_CMP_VALUE_IC(case_fold_flag, pstart, &swork, n, end, is_fail);
if (is_fail) continue;
s = swork;
while (sprev + (len = enclen(encode, sprev, end)) < s)
@@ -2647,9 +2646,9 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
case OP_LOOK_BEHIND: MOP_IN(OP_LOOK_BEHIND);
GET_LENGTH_INC(tlen, p);
- s = (UChar* )ONIGENC_STEP_BACK(encode, str, s, (int )tlen);
+ s = (UChar* )ONIGENC_STEP_BACK(encode, str, s, end, (int )tlen);
if (IS_NULL(s)) goto fail;
- sprev = (UChar* )onigenc_get_prev_char_head(encode, str, s);
+ sprev = (UChar* )onigenc_get_prev_char_head(encode, str, s, end);
MOP_OUT;
continue;
break;
@@ -2657,7 +2656,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
case OP_PUSH_LOOK_BEHIND_NOT: MOP_IN(OP_PUSH_LOOK_BEHIND_NOT);
GET_RELADDR_INC(addr, p);
GET_LENGTH_INC(tlen, p);
- q = (UChar* )ONIGENC_STEP_BACK(encode, str, s, (int )tlen);
+ q = (UChar* )ONIGENC_STEP_BACK(encode, str, s, end, (int )tlen);
if (IS_NULL(q)) {
/* too short case -> success. ex. /(?<!XXX)a/.match("a")
If you want to change to fail, replace following line. */
@@ -2667,7 +2666,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
else {
STACK_PUSH_LOOK_BEHIND_NOT(p + addr, s, sprev);
s = q;
- sprev = (UChar* )onigenc_get_prev_char_head(encode, str, s);
+ sprev = (UChar* )onigenc_get_prev_char_head(encode, str, s, end);
}
MOP_OUT;
continue;
@@ -2780,7 +2779,7 @@ slow_search(OnigEncoding enc, UChar* target, UChar* target_end,
if (target_end == t || memcmp(t, p, target_end - t) == 0)
return s;
}
- s += enclen(enc, s, end);
+ s += enclen(enc, s, text_end);
}
return (UChar* )NULL;
@@ -2843,7 +2842,7 @@ slow_search_backward(OnigEncoding enc, UChar* target, UChar* target_end,
if (s > text_start)
s = (UChar* )text_start;
else
- s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, adjust_text, s);
+ s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, adjust_text, s, text_end);
while (s >= text) {
if (*s == *target) {
@@ -2857,7 +2856,7 @@ slow_search_backward(OnigEncoding enc, UChar* target, UChar* target_end,
if (t == target_end)
return s;
}
- s = (UChar* )onigenc_get_prev_char_head(enc, adjust_text, s);
+ s = (UChar* )onigenc_get_prev_char_head(enc, adjust_text, s, text_end);
}
return (UChar* )NULL;
@@ -2876,14 +2875,14 @@ slow_search_backward_ic(OnigEncoding enc, int case_fold_flag,
if (s > text_start)
s = (UChar* )text_start;
else
- s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, adjust_text, s);
+ s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, adjust_text, s, text_end);
while (s >= text) {
if (str_lower_case_match(enc, case_fold_flag,
target, target_end, s, text_end))
return s;
- s = (UChar* )onigenc_get_prev_char_head(enc, adjust_text, s);
+ s = (UChar* )onigenc_get_prev_char_head(enc, adjust_text, s, text_end);
}
return (UChar* )NULL;
@@ -3018,7 +3017,7 @@ bm_search_backward(regex_t* reg, const UChar* target, const UChar* target_end,
if (text_start < s)
s = text_start;
else
- s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, adjust_text, s);
+ s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, adjust_text, s, text_end);
while (s >= text) {
p = s;
@@ -3030,7 +3029,7 @@ bm_search_backward(regex_t* reg, const UChar* target, const UChar* target_end,
return (UChar* )s;
s -= reg->int_map_backward[*s];
- s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, adjust_text, s);
+ s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, adjust_text, s, text_end);
}
return (UChar* )NULL;
@@ -3038,14 +3037,14 @@ bm_search_backward(regex_t* reg, const UChar* target, const UChar* target_end,
static UChar*
map_search(OnigEncoding enc, UChar map[],
- const UChar* text, const UChar* text_range)
+ const UChar* text, const UChar* text_range, const UChar* text_end)
{
const UChar *s = text;
while (s < text_range) {
if (map[*s]) return (UChar* )s;
- s += enclen(enc, s, text_range);
+ s += enclen(enc, s, text_end);
}
return (UChar* )NULL;
}
@@ -3053,14 +3052,14 @@ map_search(OnigEncoding enc, UChar map[],
static UChar*
map_search_backward(OnigEncoding enc, UChar map[],
const UChar* text, const UChar* adjust_text,
- const UChar* text_start)
+ const UChar* text_start, const UChar* text_end)
{
const UChar *s = text_start;
while (s >= text) {
if (map[*s]) return (UChar* )s;
- s = onigenc_get_prev_char_head(enc, adjust_text, s);
+ s = onigenc_get_prev_char_head(enc, adjust_text, s, text_end);
}
return (UChar* )NULL;
}
@@ -3117,7 +3116,7 @@ onig_match(regex_t* reg, const UChar* str, const UChar* end, const UChar* at, On
r = 0;
if (r == 0) {
- prev = (UChar* )onigenc_get_prev_char_head(reg->enc, str, at);
+ prev = (UChar* )onigenc_get_prev_char_head(reg->enc, str, at, end);
r = match_at(reg, str, end,
#ifdef USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE
end,
@@ -3171,7 +3170,7 @@ forward_search_range(regex_t* reg, const UChar* str, const UChar* end, UChar* s,
break;
case ONIG_OPTIMIZE_MAP:
- p = map_search(reg->enc, reg->map, p, range);
+ p = map_search(reg->enc, reg->map, p, range, end);
break;
}
@@ -3190,7 +3189,7 @@ forward_search_range(regex_t* reg, const UChar* str, const UChar* end, UChar* s,
case ANCHOR_BEGIN_LINE:
if (!ON_STR_BEGIN(p)) {
prev = onigenc_get_prev_char_head(reg->enc,
- (pprev ? pprev : str), p);
+ (pprev ? pprev : str), p, end);
if (!ONIGENC_IS_MBC_NEWLINE(reg->enc, prev, end))
goto retry_gate;
}
@@ -3219,10 +3218,10 @@ forward_search_range(regex_t* reg, const UChar* str, const UChar* end, UChar* s,
*low = p;
if (low_prev) {
if (*low > s)
- *low_prev = onigenc_get_prev_char_head(reg->enc, s, p);
+ *low_prev = onigenc_get_prev_char_head(reg->enc, s, p, end);
else
*low_prev = onigenc_get_prev_char_head(reg->enc,
- (pprev ? pprev : str), p);
+ (pprev ? pprev : str), p, end);
}
}
else {
@@ -3230,15 +3229,15 @@ forward_search_range(regex_t* reg, const UChar* str, const UChar* end, UChar* s,
*low = p - reg->dmax;
if (*low > s) {
*low = onigenc_get_right_adjust_char_head_with_prev(reg->enc, s,
- *low, (const UChar** )low_prev);
+ *low, end, (const UChar** )low_prev);
if (low_prev && IS_NULL(*low_prev))
*low_prev = onigenc_get_prev_char_head(reg->enc,
- (pprev ? pprev : s), *low);
+ (pprev ? pprev : s), *low, end);
}
else {
if (low_prev)
*low_prev = onigenc_get_prev_char_head(reg->enc,
- (pprev ? pprev : str), *low);
+ (pprev ? pprev : str), *low, end);
}
}
}
@@ -3301,7 +3300,7 @@ backward_search_range(regex_t* reg, const UChar* str, const UChar* end,
break;
case ONIG_OPTIMIZE_MAP:
- p = map_search_backward(reg->enc, reg->map, range, adjrange, p);
+ p = map_search_backward(reg->enc, reg->map, range, adjrange, p, end);
break;
}
@@ -3312,7 +3311,7 @@ backward_search_range(regex_t* reg, const UChar* str, const UChar* end,
switch (reg->sub_anchor) {
case ANCHOR_BEGIN_LINE:
if (!ON_STR_BEGIN(p)) {
- prev = onigenc_get_prev_char_head(reg->enc, str, p);
+ prev = onigenc_get_prev_char_head(reg->enc, str, p, end);
if (!ONIGENC_IS_MBC_NEWLINE(reg->enc, prev, end)) {
p = prev;
goto retry;
@@ -3336,7 +3335,7 @@ backward_search_range(regex_t* reg, const UChar* str, const UChar* end,
&& ! ONIGENC_IS_MBC_CRNL(reg->enc, p, end)
#endif
) {
- p = onigenc_get_prev_char_head(reg->enc, adjrange, p);
+ p = onigenc_get_prev_char_head(reg->enc, adjrange, p, end);
if (IS_NULL(p)) goto fail;
goto retry;
}
@@ -3348,7 +3347,7 @@ backward_search_range(regex_t* reg, const UChar* str, const UChar* end,
if (reg->dmax != ONIG_INFINITE_DISTANCE) {
*low = p - reg->dmax;
*high = p - reg->dmin;
- *high = onigenc_get_right_adjust_char_head(reg->enc, adjrange, *high);
+ *high = onigenc_get_right_adjust_char_head(reg->enc, adjrange, *high, end);
}
#ifdef ONIG_DEBUG_SEARCH
@@ -3506,9 +3505,9 @@ onig_search(regex_t* reg, const UChar* str, const UChar* end,
if ((OnigDistance )(min_semi_end - start) > reg->anchor_dmax) {
start = min_semi_end - reg->anchor_dmax;
if (start < end)
- start = onigenc_get_right_adjust_char_head(reg->enc, str, start);
+ start = onigenc_get_right_adjust_char_head(reg->enc, str, start, end);
else { /* match with empty at end */
- start = onigenc_get_prev_char_head(reg->enc, str, end);
+ start = onigenc_get_prev_char_head(reg->enc, str, end, end);
}
}
if ((OnigDistance )(max_semi_end - (range - 1)) < reg->anchor_dmin) {
@@ -3523,20 +3522,20 @@ onig_search(regex_t* reg, const UChar* str, const UChar* end,
}
if ((OnigDistance )(max_semi_end - start) < reg->anchor_dmin) {
start = max_semi_end - reg->anchor_dmin;
- start = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, str, start);
+ start = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, str, start, end);
}
if (range > start) goto mismatch_no_msa;
}
}
else if (reg->anchor & ANCHOR_SEMI_END_BUF) {
- UChar* pre_end = ONIGENC_STEP_BACK(reg->enc, str, end, 1);
+ UChar* pre_end = ONIGENC_STEP_BACK(reg->enc, str, end, end, 1);
max_semi_end = (UChar* )end;
if (ONIGENC_IS_MBC_NEWLINE(reg->enc, pre_end, end)) {
min_semi_end = pre_end;
#ifdef USE_CRNL_AS_LINE_TERMINATOR
- pre_end = ONIGENC_STEP_BACK(reg->enc, str, pre_end, 1);
+ pre_end = ONIGENC_STEP_BACK(reg->enc, str, pre_end, end, 1);
if (IS_NOT_NULL(pre_end) &&
ONIGENC_IS_MBC_CRNL(reg->enc, pre_end, end)) {
min_semi_end = pre_end;
@@ -3594,7 +3593,7 @@ onig_search(regex_t* reg, const UChar* str, const UChar* end,
s = (UChar* )start;
if (range > start) { /* forward search */
if (s > str)
- prev = onigenc_get_prev_char_head(reg->enc, str, s);
+ prev = onigenc_get_prev_char_head(reg->enc, str, s, end);
else
prev = (UChar* )NULL;
@@ -3670,7 +3669,7 @@ onig_search(regex_t* reg, const UChar* str, const UChar* end,
UChar *low, *high, *adjrange, *sch_start;
if (range < end)
- adjrange = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, str, range);
+ adjrange = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, str, range, end);
else
adjrange = (UChar* )end;
@@ -3687,7 +3686,7 @@ onig_search(regex_t* reg, const UChar* str, const UChar* end,
s = high;
while (s >= low) {
- prev = onigenc_get_prev_char_head(reg->enc, str, s);
+ prev = onigenc_get_prev_char_head(reg->enc, str, s, end);
MATCH_AND_RETURN_CHECK(orig_start);
s = prev;
}
@@ -3706,7 +3705,7 @@ onig_search(regex_t* reg, const UChar* str, const UChar* end,
if (sch_start > end) sch_start = (UChar* )end;
else
sch_start = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc,
- start, sch_start);
+ start, sch_start, end);
}
}
if (backward_search_range(reg, str, end, sch_start, range, adjrange,
@@ -3715,7 +3714,7 @@ onig_search(regex_t* reg, const UChar* str, const UChar* end,
}
do {
- prev = onigenc_get_prev_char_head(reg->enc, str, s);
+ prev = onigenc_get_prev_char_head(reg->enc, str, s, end);
MATCH_AND_RETURN_CHECK(orig_start);
s = prev;
} while (s >= range);
diff --git a/regparse.c b/regparse.c
index 3d2c57a25a..c7b42eaf74 100644
--- a/regparse.c
+++ b/regparse.c
@@ -1540,7 +1540,7 @@ str_node_split_last_char(StrNode* sn, OnigEncoding enc)
Node* n = NULL_NODE;
if (sn->end > sn->s) {
- p = onigenc_get_prev_char_head(enc, sn->s, sn->end);
+ p = onigenc_get_prev_char_head(enc, sn->s, sn->end, sn->end);
if (p && p > sn->s) { /* can be splitted. */
n = node_new_str(p, sn->end);
if ((sn->flag & NSTR_RAW) != 0)
@@ -4218,8 +4218,8 @@ parse_char_class(Node** np, OnigToken* tok, UChar** src, UChar* end,
fetched = 0;
switch (r) {
case TK_CHAR:
- len = ONIGENC_CODE_TO_MBCLEN(env->enc, tok->u.c);
- if (len > 1) {
+ if ((tok->u.code >= SINGLE_BYTE_SIZE) ||
+ (len = ONIGENC_CODE_TO_MBCLEN(env->enc, tok->u.c)) > 1) {
in_type = CCV_CODE_POINT;
}
else if (len < 0) {
@@ -5387,7 +5387,10 @@ parse_exp(Node** np, OnigToken* tok, int term,
if (tok->u.repeat.possessive != 0) {
Node* en;
en = node_new_enclose(ENCLOSE_STOP_BACKTRACK);
- CHECK_NULL_RETURN_MEMERR(en);
+ if (IS_NULL(en)) {
+ onig_node_free(qn);
+ return ONIGERR_MEMORY;
+ }
NENCLOSE(en)->target = qn;
qn = en;
}
diff --git a/ruby.c b/ruby.c
index d1003341a8..949d7db648 100644
--- a/ruby.c
+++ b/ruby.c
@@ -15,12 +15,7 @@
#include <windows.h>
#include <sys/cygwin.h>
#endif
-#ifdef _WIN32_WCE
-#include <winsock.h>
-#include "ruby/wince.h"
-#endif
#include "ruby/ruby.h"
-#include "ruby/node.h"
#include "ruby/encoding.h"
#include "eval_intern.h"
#include "dln.h"
@@ -47,10 +42,6 @@
# define MAXPATHLEN 1024
#endif
-#if defined(__MACOS__) && defined(__MWERKS__)
-#include <console.h>
-#endif
-
#include "ruby/util.h"
#ifndef HAVE_STDLIB_H
@@ -82,6 +73,7 @@ struct cmdline_options {
unsigned int disable;
int verbose;
int yydebug;
+ int safe_level;
unsigned int setids;
unsigned int dump;
const char *script;
@@ -92,7 +84,7 @@ struct cmdline_options {
VALUE name;
int index;
} enc;
- } src, ext;
+ } src, ext, intern;
VALUE req_list;
};
@@ -141,7 +133,7 @@ usage(const char *name)
"-Cdirectory cd to directory, before executing your script",
"-d set debugging flags (set $DEBUG to true)",
"-e 'command' one line of script. Several -e's allowed. Omit [programfile]",
- "-Eencoding specifies the character encoding for the program codes",
+ "-Eex[:in] specify the default external and internal character encodings",
"-Fpattern split() pattern for autosplit (-a)",
"-i[extension] edit ARGV files in place (make backup if extension supplied)",
"-Idirectory specify $LOAD_PATH directory (may be used more than once)",
@@ -185,7 +177,7 @@ translate_char(char *p, int from, int to)
}
#endif
-#if defined _WIN32 || defined __CYGWIN__ || defined __DJGPP__
+#if defined _WIN32 || defined __CYGWIN__
static VALUE
rubylib_mangled_path(const char *s, unsigned int l)
{
@@ -344,9 +336,17 @@ DllMain(HINSTANCE dll, DWORD reason, LPVOID reserved)
}
#endif
+void ruby_init_loadpath_safe(int safe_level);
+
void
ruby_init_loadpath(void)
{
+ ruby_init_loadpath_safe(0);
+}
+
+void
+ruby_init_loadpath_safe(int safe_level)
+{
VALUE load_path;
#if defined LOAD_RELATIVE
char libpath[MAXPATHLEN + 1];
@@ -355,12 +355,6 @@ ruby_init_loadpath(void)
#if defined _WIN32 || defined __CYGWIN__
GetModuleFileName(libruby, libpath, sizeof libpath);
-#elif defined(DJGPP)
- extern char *__dos_argv0;
- strncpy(libpath, __dos_argv0, sizeof(libpath) - 1);
-#elif defined(__human68k__)
- extern char **_argv;
- strncpy(libpath, _argv[0], sizeof(libpath) - 1);
#elif defined(__EMX__)
_execname(libpath, sizeof(libpath) - 1);
#endif
@@ -397,7 +391,7 @@ ruby_init_loadpath(void)
#define incpush(path) rb_ary_push(load_path, rubylib_mangled_path2(path))
load_path = GET_VM()->load_path;
- if (rb_safe_level() == 0) {
+ if (safe_level == 0) {
ruby_incpush(getenv("RUBYLIB"));
}
@@ -425,7 +419,7 @@ ruby_init_loadpath(void)
#endif
incpush(RUBY_RELATIVE(RUBY_ARCHLIB));
- if (rb_safe_level() == 0) {
+ if (safe_level == 0) {
incpush(".");
}
}
@@ -527,27 +521,53 @@ process_sflag(rb_vm_t *vm, struct cmdline_options *opt)
NODE *rb_parser_append_print(VALUE, NODE *);
NODE *rb_parser_while_loop(VALUE, NODE *, int, int);
-static int proc_options(rb_vm_t *vm, int argc, char **argv, struct cmdline_options *opt);
+static int proc_options(rb_vm_t *vm, int argc, char **argv, struct cmdline_options *opt, int envopt);
-static char *
-moreswitches(rb_vm_t *vm, const char *s, struct cmdline_options *opt)
+static void
+moreswitches(rb_vm_t *vm, const char *s, struct cmdline_options *opt, int envopt)
{
- int argc;
- char *argv[3];
- const char *p = s;
-
- argc = 2;
- argv[0] = argv[2] = 0;
- while (*s && !ISSPACE(*s))
- s++;
- argv[1] = ALLOCA_N(char, s - p + 2);
- argv[1][0] = '-';
- strncpy(argv[1] + 1, p, s - p);
- argv[1][s - p + 1] = '\0';
- proc_options(vm, argc, argv, opt);
- while (*s && ISSPACE(*s))
- s++;
- return (char *)s;
+ int argc, i;
+ char **argv, *p;
+ const char *ap = 0;
+ VALUE argstr, argary;
+
+ while (ISSPACE(*s)) s++;
+ if (!*s) return;
+ argstr = rb_str_tmp_new(strlen(s) + 2);
+ argary = rb_str_tmp_new(0);
+
+ p = RSTRING_PTR(argstr);
+ *p++ = ' ';
+ strcpy(p, s);
+ ap = 0;
+ rb_str_cat(argary, (char *)&ap, sizeof(ap));
+ while (*p) {
+ ap = p;
+ rb_str_cat(argary, (char *)&ap, sizeof(ap));
+ while (*p && !ISSPACE(*p)) ++p;
+ if (!*p) break;
+ *p++ = '\0';
+ while (ISSPACE(*p)) ++p;
+ }
+ argc = RSTRING_LEN(argary) / sizeof(ap);
+ ap = 0;
+ rb_str_cat(argary, (char *)&ap, sizeof(ap));
+ argv = (char **)RSTRING_PTR(argary);
+
+ while ((i = proc_options(vm, argc, argv, opt, envopt)) > 1 && (argc -= i) > 0) {
+ argv += i;
+ if (**argv != '-') {
+ *--*argv = '-';
+ }
+ if ((*argv)[1]) {
+ ++argc;
+ --argv;
+ }
+ }
+
+ /* get rid of GC */
+ rb_str_resize(argary, 0);
+ rb_str_resize(argstr, 0);
}
#define NAME_MATCH_P(name, str, len) \
@@ -602,8 +622,40 @@ dump_option(const char *str, int len, void *arg)
#define RUBY_VM_OBJECT(vm, name) \
(*((VALUE *)ruby_vm_specific_ptr(vm, rb_vmkey_##name)))
+static void
+set_internal_encoding_once(struct cmdline_options *opt, const char *e, int elen)
+{
+ VALUE ename;
+
+ if (!elen) elen = strlen(e);
+ ename = rb_str_new(e, elen);
+
+ if (opt->intern.enc.name &&
+ rb_funcall(ename, rb_intern("casecmp"), 1, opt->intern.enc.name) != INT2FIX(0)) {
+ rb_raise(rb_eRuntimeError,
+ "default_internal already set to %s", RSTRING_PTR(opt->intern.enc.name));
+ }
+ opt->intern.enc.name = ename;
+}
+
+static void
+set_external_encoding_once(struct cmdline_options *opt, const char *e, int elen)
+{
+ VALUE ename;
+
+ if (!elen) elen = strlen(e);
+ ename = rb_str_new(e, elen);
+
+ if (opt->ext.enc.name &&
+ rb_funcall(ename, rb_intern("casecmp"), 1, opt->ext.enc.name) != INT2FIX(0)) {
+ rb_raise(rb_eRuntimeError,
+ "default_external already set to %s", RSTRING_PTR(opt->ext.enc.name));
+ }
+ opt->ext.enc.name = ename;
+}
+
static int
-proc_options(rb_vm_t *vm, int argc, char **argv, struct cmdline_options *opt)
+proc_options(rb_vm_t *vm, int argc, char **argv, struct cmdline_options *opt, int envopt)
{
int n, argc0 = argc;
const char *s;
@@ -619,14 +671,17 @@ proc_options(rb_vm_t *vm, int argc, char **argv, struct cmdline_options *opt)
reswitch:
switch (*s) {
case 'a':
+ if (envopt) goto noenvopt;
opt->do_split = Qtrue;
s++;
goto reswitch;
case 'p':
+ if (envopt) goto noenvopt;
opt->do_print = Qtrue;
/* through */
case 'n':
+ if (envopt) goto noenvopt;
opt->do_loop = Qtrue;
s++;
goto reswitch;
@@ -638,6 +693,7 @@ proc_options(rb_vm_t *vm, int argc, char **argv, struct cmdline_options *opt)
goto reswitch;
case 'y':
+ if (envopt) goto noenvopt;
opt->yydebug = 1;
s++;
goto reswitch;
@@ -680,34 +736,40 @@ proc_options(rb_vm_t *vm, int argc, char **argv, struct cmdline_options *opt)
goto reswitch;
case 'c':
+ if (envopt) goto noenvopt;
opt->do_check = Qtrue;
s++;
goto reswitch;
case 's':
+ if (envopt) goto noenvopt;
forbid_setid("-s");
opt->sflag = 1;
s++;
goto reswitch;
case 'h':
+ if (envopt) goto noenvopt;
usage(origarg.argv[0]);
rb_exit(EXIT_SUCCESS);
break;
case 'l':
+ if (envopt) goto noenvopt;
opt->do_line = Qtrue;
rb_output_rs = rb_rs;
s++;
goto reswitch;
case 'S':
+ if (envopt) goto noenvopt;
forbid_setid("-S");
opt->do_search = Qtrue;
s++;
goto reswitch;
case 'e':
+ if (envopt) goto noenvopt;
forbid_setid("-e");
if (!*++s) {
s = argv[1];
@@ -737,11 +799,13 @@ proc_options(rb_vm_t *vm, int argc, char **argv, struct cmdline_options *opt)
break;
case 'i':
+ if (envopt) goto noenvopt;
forbid_setid("-i");
ruby_vm_set_inplace_mode(vm, s + 1);
break;
case 'x':
+ if (envopt) goto noenvopt;
opt->xflag = Qtrue;
s++;
if (*s && chdir(s) < 0) {
@@ -751,6 +815,7 @@ proc_options(rb_vm_t *vm, int argc, char **argv, struct cmdline_options *opt)
case 'C':
case 'X':
+ if (envopt) goto noenvopt;
s++;
if (!*s) {
s = argv[1];
@@ -765,15 +830,23 @@ proc_options(rb_vm_t *vm, int argc, char **argv, struct cmdline_options *opt)
break;
case 'F':
+ if (envopt) goto noenvopt;
if (*++s) {
rb_fs = rb_reg_new(s, strlen(s), 0);
}
break;
case 'E':
- if (!*++s) goto next_encoding;
+ if (!*++s && (!--argc || !(s = *++argv))) {
+ rb_raise(rb_eRuntimeError, "missing argument for -E");
+ }
goto encoding;
+ case 'U':
+ set_internal_encoding_once(opt, "UTF-8", 0);
+ ++s;
+ goto reswitch;
+
case 'K':
if (*++s) {
const char *enc_name = 0;
@@ -793,7 +866,8 @@ proc_options(rb_vm_t *vm, int argc, char **argv, struct cmdline_options *opt)
}
if (enc_name) {
opt->src.enc.name = rb_str_new2(enc_name);
- opt->ext.enc.name = opt->src.enc.name;
+ if (!opt->ext.enc.name)
+ opt->ext.enc.name = opt->src.enc.name;
}
s++;
}
@@ -810,7 +884,7 @@ proc_options(rb_vm_t *vm, int argc, char **argv, struct cmdline_options *opt)
v = 1;
s += numlen;
}
- rb_set_safe_level(v);
+ if (v > opt->safe_level) opt->safe_level = v;
}
goto reswitch;
@@ -825,6 +899,7 @@ proc_options(rb_vm_t *vm, int argc, char **argv, struct cmdline_options *opt)
break;
case '0':
+ if (envopt) goto noenvopt;
{
int numlen;
int v;
@@ -850,50 +925,64 @@ proc_options(rb_vm_t *vm, int argc, char **argv, struct cmdline_options *opt)
goto switch_end;
}
s++;
- if (strcmp("copyright", s) == 0)
+
+# define is_option_end(c, allow_hyphen) \
+ (!(c) || (allow_hyphen && (c) == '-') || (c) == '=')
+# define check_envopt(name, allow_envopt) \
+ ((allow_envopt || !envopt) ? (void)0 : \
+ rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: --" name))
+# define need_argument(name, s) \
+ ((*s++ ? !*s : (!--argc || !(s = *++argv))) ? \
+ rb_raise(rb_eRuntimeError, "missing argument for --" name) \
+ : (void)0)
+# define is_option_with_arg(name, allow_hyphen, allow_envopt) \
+ (strncmp(name, s, n = sizeof(name) - 1) == 0 && is_option_end(s[n], allow_hyphen) ? \
+ (check_envopt(name, allow_envopt), s += n, need_argument(name, s), 1) : 0)
+
+ if (strcmp("copyright", s) == 0) {
+ if (envopt) goto noenvopt_long;
opt->copyright = 1;
+ }
else if (strcmp("debug", s) == 0) {
RUBY_VM_OBJECT(vm, debug) = Qtrue;
RUBY_VM_OBJECT(vm, verbose) = Qtrue;
}
- else if (strncmp("enable", s, n = 6) == 0 &&
- (!s[n] || s[n] == '-' || s[n] == '=')) {
- if ((s += n + 1)[-1] ? !*s : (!--argc || !(s = *++argv))) {
- rb_raise(rb_eRuntimeError, "missing argument for --enable");
- }
+ else if (is_option_with_arg("enable", Qtrue, Qtrue)) {
ruby_each_words(s, enable_option, &opt->disable);
}
- else if (strncmp("disable", s, n = 7) == 0 &&
- (!s[n] || s[n] == '-' || s[n] == '=')) {
- if ((s += n + 1)[-1] ? !*s : (!--argc || !(s = *++argv))) {
- rb_raise(rb_eRuntimeError, "missing argument for --disable");
- }
+ else if (is_option_with_arg("disable", Qtrue, Qtrue)) {
ruby_each_words(s, disable_option, &opt->disable);
}
- else if (strncmp("encoding", s, n = 8) == 0 && (!s[n] || s[n] == '=')) {
- s += n;
- if (!*s++) {
- next_encoding:
- if (!--argc || !(s = *++argv)) {
- rb_raise(rb_eRuntimeError, "missing argument for --encoding");
- }
- }
+ else if (is_option_with_arg("encoding", Qfalse, Qtrue)) {
+ char *p;
encoding:
- opt->ext.enc.name = rb_str_new2(s);
+ p = strchr(s, ':');
+ if (p) {
+ if (p > s)
+ set_external_encoding_once(opt, s, p-s);
+ if (*++p)
+ set_internal_encoding_once(opt, p, 0);
+ }
+ else
+ set_external_encoding_once(opt, s, 0);
}
- else if (strcmp("version", s) == 0)
+ else if (strcmp("version", s) == 0) {
+ if (envopt) goto noenvopt_long;
opt->version = 1;
+ }
else if (strcmp("verbose", s) == 0) {
opt->verbose = 1;
RUBY_VM_OBJECT(vm, verbose) = Qtrue;
}
- else if (strcmp("yydebug", s) == 0)
+ else if (strcmp("yydebug", s) == 0) {
+ if (envopt) goto noenvopt_long;
opt->yydebug = 1;
- else if (strncmp("dump", s, n = 4) == 0 && (!s[n] || s[n] == '=')) {
- if (!(s += n + 1)[-1] && (!--argc || !(s = *++argv)) && *s != '-') break;
+ }
+ else if (is_option_with_arg("dump", Qfalse, Qfalse)) {
ruby_each_words(s, dump_option, &opt->dump);
}
else if (strcmp("help", s) == 0) {
+ if (envopt) goto noenvopt_long;
usage(origarg.argv[0]);
rb_exit(EXIT_SUCCESS);
}
@@ -922,8 +1011,21 @@ proc_options(rb_vm_t *vm, int argc, char **argv, struct cmdline_options *opt)
}
goto switch_end;
+ noenvopt:
+ /* "EIdvwWrKU" only */
+ rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: -%c", *s);
+ break;
+
+ noenvopt_long:
+ rb_raise(rb_eRuntimeError, "invalid switch in RUBYOPT: --%s", s);
+ break;
+
case 0:
break;
+# undef is_option_end
+# undef check_envopt
+# undef need_argument
+# undef is_option_with_arg
}
}
@@ -972,55 +1074,25 @@ process_options(VALUE arg)
rb_encoding *enc, *lenc;
const char *s;
char fbuf[MAXPATHLEN];
- int i = proc_options(vm, argc, argv, opt);
- int safe;
+ int i = proc_options(vm, argc, argv, opt, 0);
argc -= i;
argv += i;
if (!(opt->disable & DISABLE_BIT(rubyopt)) &&
- rb_safe_level() == 0 && (s = getenv("RUBYOPT"))) {
+ opt->safe_level == 0 && (s = getenv("RUBYOPT"))) {
VALUE src_enc_name = opt->src.enc.name;
VALUE ext_enc_name = opt->ext.enc.name;
+ VALUE int_enc_name = opt->intern.enc.name;
- while (ISSPACE(*s))
- s++;
- if (*s == 'T' || (*s == '-' && *(s + 1) == 'T')) {
- int numlen;
- int v = 1;
-
- if (*s != 'T')
- ++s;
- if (*++s) {
- v = scan_oct(s, 2, &numlen);
- if (numlen == 0)
- v = 1;
- }
- rb_set_safe_level(v);
- }
- else {
- while (s && *s) {
- if (*s == '-') {
- s++;
- if (ISSPACE(*s)) {
- do {
- s++;
- } while (ISSPACE(*s));
- continue;
- }
- }
- if (!*s)
- break;
- if (!strchr("EIdvwWrK", *s))
- rb_raise(rb_eRuntimeError,
- "invalid switch in RUBYOPT: -%c", *s);
- s = moreswitches(vm, s, opt);
- }
- }
+ opt->src.enc.name = opt->ext.enc.name = opt->intern.enc.name = 0;
+ moreswitches(vm, s, opt, 1);
if (src_enc_name)
opt->src.enc.name = src_enc_name;
if (ext_enc_name)
opt->ext.enc.name = ext_enc_name;
+ if (int_enc_name)
+ opt->intern.enc.name = int_enc_name;
}
if (opt->version) {
@@ -1031,7 +1103,7 @@ process_options(VALUE arg)
ruby_show_copyright();
}
- if (rb_safe_level() >= 4) {
+ if (opt->safe_level >= 4) {
OBJ_TAINT(rb_argv);
OBJ_TAINT(GET_VM()->load_path);
}
@@ -1070,24 +1142,22 @@ process_options(VALUE arg)
#if defined DOSISH || defined __CYGWIN__
translate_char(RSTRING_PTR(opt->script_name), '\\', '/');
#endif
- OBJ_FREEZE(opt->script_name);
+ opt->script_name = rb_progname;
opt->script = RSTRING_PTR(opt->script_name);
- safe = rb_safe_level();
- rb_set_safe_level_force(0);
- ruby_vm_set_argv(vm, argc, argv);
- process_sflag(vm, opt);
- ruby_init_loadpath();
+ ruby_init_loadpath_safe(opt->safe_level);
ruby_init_gems(!(opt->disable & DISABLE_BIT(gems)));
lenc = rb_locale_encoding();
- for (i = 0; i < RARRAY_LEN(rb_argv); i++) {
- rb_enc_associate(RARRAY_PTR(rb_argv)[i], lenc);
- }
+ rb_enc_associate(rb_progname, lenc);
+ opt->script_name = rb_str_new4(rb_progname);
parser = rb_parser_new();
if (opt->yydebug) rb_parser_set_yydebug(parser, Qtrue);
if (opt->ext.enc.name != 0) {
opt->ext.enc.index = opt_enc_index(opt->ext.enc.name);
}
+ if (opt->intern.enc.name != 0) {
+ opt->intern.enc.index = opt_enc_index(opt->intern.enc.name);
+ }
if (opt->src.enc.name != 0) {
opt->src.enc.index = opt_enc_index(opt->src.enc.name);
src_encoding_index = opt->src.enc.index;
@@ -1099,8 +1169,14 @@ process_options(VALUE arg)
enc = lenc;
}
rb_enc_set_default_external(rb_enc_from_encoding(enc));
+ if (opt->intern.enc.index >= 0) {
+ enc = rb_enc_from_index(opt->intern.enc.index);
+ rb_enc_set_default_internal(rb_enc_from_encoding(enc));
+ opt->intern.enc.index = -1;
+ }
+ ruby_vm_set_argv(vm, argc, argv);
+ process_sflag(vm, opt);
- rb_set_safe_level_force(safe);
if (opt->e_script) {
rb_encoding *eenc;
if (opt->src.enc.index >= 0) {
@@ -1120,12 +1196,21 @@ process_options(VALUE arg)
tree = load_file(vm, parser, opt->script, 1, opt);
}
+ if (opt->intern.enc.index >= 0) {
+ /* Set in the shebang line */
+ enc = rb_enc_from_index(opt->intern.enc.index);
+ rb_enc_set_default_internal(rb_enc_from_encoding(enc));
+ }
+ else
+ /* Freeze default_internal */
+ rb_enc_set_default_internal(Qnil);
+
if (!tree) return Qfalse;
process_sflag(vm, opt);
opt->xflag = 0;
- if (rb_safe_level() >= 4) {
+ if (opt->safe_level >= 4) {
FL_UNSET(rb_argv, FL_TAINT);
FL_UNSET(GET_VM()->load_path, FL_TAINT);
}
@@ -1142,8 +1227,8 @@ process_options(VALUE arg)
tree = rb_parser_while_loop(parser, tree, opt->do_line, opt->do_split);
}
- iseq = rb_iseq_new(tree, rb_str_new2("<main>"),
- opt->script_name, Qfalse, ISEQ_TYPE_TOP);
+ iseq = rb_iseq_new_top(tree, rb_str_new2("<main>"),
+ opt->script_name, Qfalse);
if (opt->dump & DUMP_BIT(insns)) {
rb_io_write(rb_stdout, ruby_iseq_disasm(iseq));
@@ -1151,16 +1236,33 @@ process_options(VALUE arg)
return Qtrue;
}
+ rb_set_safe_level(opt->safe_level);
+
return iseq;
}
-static NODE *
-load_file(rb_vm_t *vm, VALUE parser, const char *fname, int script, struct cmdline_options *opt)
+struct load_file_arg {
+ rb_vm_t *vm;
+ VALUE parser;
+ const char *fname;
+ int script;
+ struct cmdline_options *opt;
+};
+
+static VALUE
+load_file_internal(VALUE arg)
{
+ struct load_file_arg *argp = (struct load_file_arg *)arg;
+ rb_vm_t *vm = argp->vm;
+ VALUE parser = argp->parser;
+ const char *fname = argp->fname;
+ int script = argp->script;
+ struct cmdline_options *opt = argp->opt;
VALUE f;
int line_start = 1;
NODE *tree = 0;
rb_encoding *enc;
+ ID set_encoding;
if (!fname)
rb_load_fail(fname);
@@ -1183,15 +1285,17 @@ load_file(rb_vm_t *vm, VALUE parser, const char *fname, int script, struct cmdli
f = rb_io_fdopen(fd, mode, fname);
}
+ CONST_ID(set_encoding, "set_encoding");
if (script) {
VALUE c = 1; /* something not nil */
VALUE line;
char *p;
int no_src_enc = !opt->src.enc.name;
int no_ext_enc = !opt->ext.enc.name;
+ int no_int_enc = !opt->intern.enc.name;
- enc = rb_usascii_encoding();
- rb_funcall(f, rb_intern("set_encoding"), 1, rb_enc_from_encoding(enc));
+ enc = rb_ascii8bit_encoding();
+ rb_funcall(f, set_encoding, 1, rb_enc_from_encoding(enc));
if (opt->xflag) {
forbid_setid("-x");
@@ -1255,10 +1359,7 @@ load_file(rb_vm_t *vm, VALUE parser, const char *fname, int script, struct cmdli
if (RSTRING_PTR(line)[RSTRING_LEN(line) - 2] == '\r')
RSTRING_PTR(line)[RSTRING_LEN(line) - 2] = '\0';
if ((p = strstr(p, " -")) != 0) {
- p++; /* skip space before `-' */
- while (*p == '-') {
- p = moreswitches(vm, p + 1, opt);
- }
+ moreswitches(vm, p + 1, opt, 0);
}
/* push back shebang for pragma may exist in next line */
@@ -1275,6 +1376,9 @@ load_file(rb_vm_t *vm, VALUE parser, const char *fname, int script, struct cmdli
if (no_ext_enc && opt->ext.enc.name) {
opt->ext.enc.index = opt_enc_index(opt->ext.enc.name);
}
+ if (no_int_enc && opt->intern.enc.name) {
+ opt->intern.enc.index = opt_enc_index(opt->intern.enc.name);
+ }
}
else if (!NIL_P(c)) {
rb_io_ungetbyte(f, c);
@@ -1290,16 +1394,34 @@ load_file(rb_vm_t *vm, VALUE parser, const char *fname, int script, struct cmdli
else {
enc = rb_usascii_encoding();
}
- rb_funcall(f, rb_intern("set_encoding"), 1, rb_enc_from_encoding(enc));
+ rb_funcall(f, set_encoding, 2, rb_enc_from_encoding(enc), rb_str_new_cstr("-"));
tree = (NODE *)rb_parser_compile_file(parser, fname, f, line_start);
- rb_funcall(f, rb_intern("set_encoding"), 1, rb_parser_encoding(parser));
+ rb_funcall(f, set_encoding, 1, rb_parser_encoding(parser));
if (script && rb_parser_end_seen_p(parser)) {
rb_define_global_const("DATA", f);
}
else if (f != rb_stdin) {
rb_io_close(f);
}
- return tree;
+ return (VALUE)tree;
+}
+
+static VALUE
+restore_lineno(VALUE lineno)
+{
+ return rb_gv_set("$.", lineno);
+}
+
+static NODE *
+load_file(rb_vm_t *vm, VALUE parser, const char *fname, int script, struct cmdline_options *opt)
+{
+ struct load_file_arg arg;
+ arg.vm = vm;
+ arg.parser = parser;
+ arg.fname = fname;
+ arg.script = script;
+ arg.opt = opt;
+ return (NODE *)rb_ensure(load_file_internal, (VALUE)&arg, restore_lineno, rb_gv_get("$."));
}
void *
@@ -1399,14 +1521,14 @@ set_arg0(VALUE val, ID id, VALUE *var)
}
}
#endif
- *var = rb_obj_freeze(rb_tainted_str_new(s, i));
+ *var = rb_obj_freeze(rb_external_str_new(s, i));
}
void
ruby_script(const char *name)
{
if (name) {
- *rb_vm_specific_ptr(rb_vmkey_progname) = rb_obj_freeze(rb_tainted_str_new2(name));
+ *rb_vm_specific_ptr(rb_vmkey_progname) = rb_obj_freeze(rb_external_str_new(name, strlen(name)));
}
}
@@ -1418,14 +1540,10 @@ init_ids(struct cmdline_options *opt)
rb_gid_t gid = getgid();
rb_gid_t egid = getegid();
-#ifdef VMS
- uid |= gid << 16;
- euid |= egid << 16;
-#endif
if (uid != euid) opt->setids |= 1;
if (egid != gid) opt->setids |= 2;
if (uid && opt->setids) {
- rb_set_safe_level(1);
+ if (opt->safe_level < 1) opt->safe_level = 1;
}
}
@@ -1437,7 +1555,7 @@ forbid_setid(const char *s, struct cmdline_options *opt)
rb_raise(rb_eSecurityError, "no %s allowed while running setuid", s);
if (opt->setids & 2)
rb_raise(rb_eSecurityError, "no %s allowed while running setgid", s);
- if (rb_safe_level() > 0)
+ if (opt->safe_level > 0)
rb_raise(rb_eSecurityError, "no %s allowed in tainted mode", s);
}
@@ -1482,17 +1600,7 @@ ruby_vm_prog_init(rb_vm_t *vm)
void
ruby_prog_init(void)
{
- ruby_vm_prog_init(GET_VM());
rb_global_variable(&rb_argv0);
-
-#ifdef MSDOS
- /*
- * There is no way we can refer to them from ruby, so close them to save
- * space.
- */
- (void)fclose(stdaux);
- (void)fclose(stdprn);
-#endif
}
void
@@ -1503,7 +1611,7 @@ ruby_vm_set_argv(rb_vm_t *vm, int argc, char **argv)
rb_ary_clear(av);
for (i = 0; i < argc; i++) {
- VALUE arg = rb_tainted_str_new2(argv[i]);
+ VALUE arg = rb_external_str_new(argv[i], strlen(argv[i]));
OBJ_FREEZE(arg);
rb_ary_push(av, arg);
@@ -1547,13 +1655,15 @@ ruby_vm_process_options(rb_vm_t *vm, int argc, char **argv)
RUBY_VM_OBJECT(vm, progname) = rb_tainted_str_new2(argv[0]);
}
args.vm = vm;
+ rb_gc_register_mark_object(rb_argv0);
args.argc = argc;
args.argv = argv;
args.opt = cmdline_options_init(&opt);
opt.ext.enc.index = -1;
+ opt.intern.enc.index = -1;
tree = rb_vm_call_cfunc(vm->top_self,
- process_options, (VALUE)&args,
- 0, RUBY_VM_OBJECT(vm, progname));
+ process_options, (VALUE)&args,
+ 0, RUBY_VM_OBJECT(vm, progname));
rb_define_readonly_boolean("$-p", opt.do_print);
rb_define_readonly_boolean("$-l", opt.do_line);
@@ -1590,8 +1700,6 @@ ruby_sysinit(int *argc, char ***argv)
}
v2[n] = 0;
*argv = v2;
-#elif defined(__MACOS__) && defined(__MWERKS__)
- *argc = ccommand(argv);
#elif defined(_WIN32)
void rb_w32_sysinit(int *argc, char ***argv);
rb_w32_sysinit(argc, argv);
diff --git a/eval_safe.c b/safe.c
index 7d0a077880..9f0a69c9d7 100644
--- a/eval_safe.c
+++ b/safe.c
@@ -1,7 +1,13 @@
-/* -*-c-*- */
-/*
- * This file is included by eval.c
- */
+/**********************************************************************
+
+ eval.c -
+
+ $Author$
+ created at: Tue Sep 23 09:44:32 JST 2008
+
+ Copyright (C) 2008 Yukihiro Matsumoto
+
+**********************************************************************/
/* safe-level:
0 - strings from streams/environment/ARGV are tainted (default)
@@ -13,6 +19,9 @@
#define SAFE_LEVEL_MAX 4
+#include "ruby/ruby.h"
+#include "vm_core.h"
+
/* $SAFE accessor */
int
@@ -57,6 +66,9 @@ safe_setter(VALUE val)
"tried to downgrade safe level from %d to %d",
th->safe_level, level);
}
+ if (level == 3) {
+ rb_warning("$SAFE=3 does no sandboxing; you might want to use $SAFE=4");
+ }
if (level > SAFE_LEVEL_MAX) {
level = SAFE_LEVEL_MAX;
}
@@ -109,3 +121,14 @@ rb_check_safe_str(VALUE x)
rb_obj_classname(x));
}
}
+
+void
+Init_safe(void)
+{
+}
+
+void
+InitVM_safe(void)
+{
+ rb_define_virtual_variable("$SAFE", safe_getter, safe_setter);
+}
diff --git a/signal.c b/signal.c
index f42452c72f..7629807ebe 100644
--- a/signal.c
+++ b/signal.c
@@ -12,7 +12,6 @@
**********************************************************************/
#include "ruby/ruby.h"
-#include "ruby/node.h"
#include "vm_core.h"
#include "eval_intern.h"
#include <signal.h>
@@ -46,11 +45,7 @@ typedef int rb_atomic_t;
#endif
#ifndef NSIG
-# ifdef DJGPP
-# define NSIG SIGMAX
-# else
-# define NSIG (_SIGMAX + 1) /* For QNX */
-# endif
+# define NSIG (_SIGMAX + 1) /* For QNX */
#endif
static const struct signals {
@@ -304,10 +299,8 @@ interrupt_init(int argc, VALUE *argv, VALUE self)
void
ruby_default_signal(int sig)
{
-#ifndef MACOS_UNUSE_SIGNAL
signal(sig, SIG_DFL);
raise(sig);
-#endif
}
/*
@@ -406,7 +399,7 @@ rb_f_kill(int argc, VALUE *argv)
return INT2FIX(i-1);
}
-struct {
+static struct {
rb_atomic_t cnt[RUBY_NSIG];
rb_atomic_t size;
} signal_buff;
@@ -617,15 +610,8 @@ sigpipe(int sig)
static void
signal_exec(VALUE cmd, int safe, int sig)
{
- rb_proc_t *proc;
- VALUE signum = INT2FIX(sig);
-
- if (TYPE(cmd) == T_STRING) {
- rb_eval_cmd(cmd, rb_ary_new3(1, signum), safe);
- return;
- }
- GetProcPtr(cmd, proc);
- vm_invoke_proc(GET_THREAD(), proc, proc->block.self, 1, &signum, 0);
+ VALUE signum = INT2NUM(sig);
+ rb_eval_cmd(cmd, rb_ary_new3(1, signum), safe);
}
void
@@ -1093,7 +1079,6 @@ ruby_sig_finalize()
void
Init_signal(void)
{
-#ifndef MACOS_UNUSE_SIGNAL
install_sighandler(SIGINT, sighandler);
#ifdef SIGHUP
@@ -1136,8 +1121,6 @@ Init_signal(void)
#elif defined(SIGCHLD)
init_sigchld(SIGCHLD);
#endif
-
-#endif /* MACOS_UNUSE_SIGNAL */
}
void
diff --git a/spec/default.mspec b/spec/default.mspec
index e4b9dae523..a018b4020c 100644
--- a/spec/default.mspec
+++ b/spec/default.mspec
@@ -7,11 +7,14 @@ class MSpecScript
spec/rubyspec/1.9/library
]
- srcdir = File.expand_path(File.join(File.dirname(__FILE__), '..'))
- config = proc{|name| `#{srcdir}/miniruby -I#{srcdir} -rrbconfig -e 'print Config::CONFIG["#{name}"]'`}
+ builddir = File.expand_path(File.join(File.dirname(__FILE__), '..'))
+ srcdir = ENV['SRCDIR']
+ srcdir ||= $1 if File.read("#{builddir}/Makefile")[/^\s*srcdir\s*=\s*(.+)/i]
+ srcdir ||= builddir
+ config = proc{|name| `#{builddir}/miniruby -I#{srcdir} -rrbconfig -e 'print Config::CONFIG["#{name}"]'`}
# The default implementation to run the specs.
- set :target, File.join(srcdir, "miniruby#{config['exeext']}")
+ set :target, File.join(builddir, "miniruby#{config['exeext']}")
set :flags, %W[
-I#{srcdir}/lib
-I#{srcdir}/#{config['EXTOUT']}/common
diff --git a/sprintf.c b/sprintf.c
index 16a8f61b90..23671e6b93 100644
--- a/sprintf.c
+++ b/sprintf.c
@@ -103,18 +103,28 @@ sign_bits(int base, const char *p)
} while (0)
#define GETARG() (nextvalue != Qundef ? nextvalue : \
- posarg < 0 ? \
+ posarg == -1 ? \
(rb_raise(rb_eArgError, "unnumbered(%d) mixed with numbered", nextarg), 0) : \
+ posarg == -2 ? \
+ (rb_raise(rb_eArgError, "unnumbered(%d) mixed with named", nextarg), 0) : \
(posarg = nextarg++, GETNTHARG(posarg)))
#define GETPOSARG(n) (posarg > 0 ? \
(rb_raise(rb_eArgError, "numbered(%d) after unnumbered(%d)", n, posarg), 0) : \
+ posarg == -2 ? \
+ (rb_raise(rb_eArgError, "numbered(%d) after named", n), 0) : \
((n < 1) ? (rb_raise(rb_eArgError, "invalid index - %d$", n), 0) : \
(posarg = -1, GETNTHARG(n))))
#define GETNTHARG(nth) \
((nth >= argc) ? (rb_raise(rb_eArgError, "too few arguments"), 0) : argv[nth])
+#define GETNAMEARG(id) (posarg > 0 ? \
+ (rb_raise(rb_eArgError, "named after unnumbered(%d)", posarg), 0) : \
+ posarg == -1 ? \
+ (rb_raise(rb_eArgError, "named after numbered"), 0) : \
+ rb_hash_fetch(get_hash(&hash, argc, argv), id))
+
#define GETNUM(n, val) \
for (; p < end && rb_enc_isdigit(*p, enc); p++) { \
int next_n = 10 * n + (*p - '0'); \
@@ -141,6 +151,21 @@ sign_bits(int base, const char *p)
val = NUM2INT(tmp); \
} while (0)
+static VALUE
+get_hash(volatile VALUE *hash, int argc, const VALUE *argv)
+{
+ VALUE tmp;
+
+ if (*hash != Qundef) return *hash;
+ if (argc != 2) {
+ rb_raise(rb_eArgError, "one hash required");
+ }
+ tmp = rb_check_convert_type(argv[1], T_HASH, "Hash", "to_hash");
+ if (NIL_P(tmp)) {
+ rb_raise(rb_eArgError, "one hash required");
+ }
+ return (*hash = tmp);
+}
/*
* call-seq:
@@ -412,6 +437,7 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
VALUE nextvalue;
VALUE tmp;
VALUE str;
+ volatile VALUE hash = Qundef;
#define CHECK_FOR_WIDTH(f) \
if ((f) & FWIDTH) { \
@@ -513,6 +539,26 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
flags |= FWIDTH;
goto retry;
+ case '<':
+ case '{':
+ {
+ const char *start = p;
+ char term = (*p == '<') ? '>' : '}';
+ ID id;
+
+ for (; p < end && *p != term; ) {
+ p += rb_enc_mbclen(p, end, enc);
+ }
+ if (p >= end) {
+ rb_raise(rb_eArgError, "malformed name - unmatched parenthesis");
+ }
+ id = rb_intern3(start + 1, p - start - 1, enc);
+ nextvalue = GETNAMEARG(ID2SYM(id));
+ if (term == '}') goto format_s;
+ p++;
+ goto retry;
+ }
+
case '*':
CHECK_FOR_WIDTH(flags);
flags |= FWIDTH;
@@ -558,7 +604,8 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
{
VALUE val = GETARG();
VALUE tmp;
- int c, n;
+ unsigned int c;
+ int n;
tmp = rb_check_string_type(val);
if (!NIL_P(tmp)) {
@@ -571,7 +618,7 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
c = NUM2INT(val);
}
n = rb_enc_codelen(c, enc);
- if (n == 0) {
+ if (n <= 0) {
rb_raise(rb_eArgError, "invalid character");
}
if (!(flags & FWIDTH)) {
@@ -596,6 +643,7 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
case 's':
case 'p':
+ format_s:
{
VALUE arg = GETARG();
long len, slen;
@@ -1035,7 +1083,7 @@ fmt_setup(char *buf, int c, int flags, int width, int prec)
#undef vsnprintf
#undef snprintf
#define FLOATING_POINT 1
-#define BSD__dtoa dtoa
+#define BSD__dtoa ruby_dtoa
#include "missing/vsnprintf.c"
static int
diff --git a/st.c b/st.c
index b90e8343a3..ccb173cf75 100644
--- a/st.c
+++ b/st.c
@@ -6,9 +6,7 @@
#include "regint.h"
#include "st.h"
#else
-#include "ruby/config.h"
-#include "ruby/defines.h"
-#include "ruby/st.h"
+#include "ruby/ruby.h"
#endif
#include <stdio.h>
@@ -136,6 +134,9 @@ new_size(int size)
if (newsize > size) return primes[i];
}
/* Ran out of polynomials */
+#ifndef NOT_RUBY
+ rb_raise(rb_eRuntimeError, "st_table too big");
+#endif
return -1; /* should raise exception */
#endif
}
diff --git a/strftime.c b/strftime.c
index 0f5214990f..af66fa6377 100644
--- a/strftime.c
+++ b/strftime.c
@@ -57,7 +57,7 @@
#include <sys/types.h>
#include <errno.h>
#endif
-#if defined(TM_IN_SYS_TIME) || !defined(GAWK) && !defined(_WIN32_WCE)
+#if defined(TM_IN_SYS_TIME) || !defined(GAWK)
#include <sys/types.h>
#if HAVE_SYS_TIME_H
#include <sys/time.h>
@@ -126,7 +126,7 @@ extern char *strchr();
#ifndef DLL_IMPORT
#define DLL_IMPORT
#endif
-#if !defined(OS2) && !defined(MSDOS) && defined(HAVE_TZNAME)
+#if !defined(OS2) && defined(HAVE_TZNAME)
extern DLL_IMPORT char *tzname[2];
#ifdef HAVE_DAYLIGHT
extern DLL_IMPORT int daylight;
@@ -195,12 +195,11 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept
#endif /* POSIX_SEMANTICS */
#ifndef HAVE_TM_ZONE
#ifndef HAVE_TM_NAME
-#if !defined HAVE_VAR_TIMEZONE || defined HAVE_TIMEZONE
+#if ((defined(MAILHEADER_EXT) && !HAVE_VAR_TIMEZONE && HAVE_GETTIMEOFDAY) || \
+ (!HAVE_TZNAME && HAVE_TIMEZONE))
struct timeval tv;
-#endif
-#ifdef HAVE_TIMEZONE
struct timezone zone;
-#endif /* HAVE_TIMEZONE */
+#endif
#endif /* HAVE_TM_NAME */
#endif /* HAVE_TM_ZONE */
int precision, flags;
@@ -473,7 +472,7 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept
#else
off = -timezone / 60;
#endif
-#else /* !HAVE_TIMEZONE */
+#else /* !HAVE_VAR_TIMEZONE */
#ifdef HAVE_GETTIMEOFDAY
gettimeofday(&tv, &zone);
off = -zone.tz_minuteswest;
@@ -487,7 +486,7 @@ rb_strftime(char *s, size_t maxsize, const char *format, const struct tm *timept
off = (now - mktime(&utc)) / 60;
}
#endif
-#endif /* !HAVE_TIMEZONE */
+#endif /* !HAVE_VAR_TIMEZONE */
#endif /* !HAVE_TM_ZONE */
#endif /* !HAVE_TM_NAME */
}
diff --git a/string.c b/string.c
index 635d148d8c..5ffa99416b 100644
--- a/string.c
+++ b/string.c
@@ -28,6 +28,8 @@
#undef rb_str_new_cstr
#undef rb_tainted_str_new_cstr
#undef rb_usascii_str_new_cstr
+#undef rb_external_str_new_cstr
+#undef rb_locale_str_new_cstr
#undef rb_str_new2
#undef rb_str_new3
#undef rb_str_new4
@@ -40,6 +42,7 @@
#undef rb_str_buf_cat2
#undef rb_str_cat2
+#define RUBY_MAX_CHAR_LEN 16
#define STR_TMPLOCK FL_USER7
#define STR_NOEMBED FL_USER1
#define STR_SHARED FL_USER2 /* = ELTS_SHARED */
@@ -108,18 +111,19 @@
#define STR_ENC_GET(str) rb_enc_from_index(ENCODING_GET(str))
-static int
+static inline int
single_byte_optimizable(VALUE str)
{
- rb_encoding *enc = STR_ENC_GET(str);
-
- if (rb_enc_mbmaxlen(enc) == 1)
- return 1;
+ rb_encoding *enc;
/* Conservative. It may be ENC_CODERANGE_UNKNOWN. */
if (ENC_CODERANGE(str) == ENC_CODERANGE_7BIT)
return 1;
+ enc = STR_ENC_GET(str);
+ if (rb_enc_mbmaxlen(enc) == 1)
+ return 1;
+
/* Conservative. Possibly single byte.
* "\xa1" in Shift_JIS for example. */
return 0;
@@ -390,6 +394,9 @@ str_new(VALUE klass, const char *ptr, long len)
RSTRING(str)->as.heap.ptr = ALLOC_N(char,len+1);
STR_SET_NOEMBED(str);
}
+ else if (len == 0) {
+ ENC_CODERANGE_SET(str, ENC_CODERANGE_7BIT);
+ }
if (ptr) {
memcpy(RSTRING_PTR(str), ptr, len);
}
@@ -491,6 +498,116 @@ rb_tainted_str_new_cstr(const char *ptr)
RUBY_ALIAS_FUNCTION(rb_tainted_str_new2(const char *ptr), rb_tainted_str_new_cstr, (ptr))
#define rb_tainted_str_new2 rb_tainted_str_new_cstr
+VALUE
+rb_str_conv_enc_opts(VALUE str, rb_encoding *from, rb_encoding *to, int ecflags, VALUE ecopts)
+{
+ rb_econv_t *ec;
+ rb_econv_result_t ret;
+ long len;
+ VALUE newstr;
+ const unsigned char *sp;
+ unsigned char *dp;
+
+ if (!to) return str;
+ if (from == to) return str;
+ if ((rb_enc_asciicompat(to) && ENC_CODERANGE(str) == ENC_CODERANGE_7BIT) ||
+ to == rb_ascii8bit_encoding()) {
+ if (STR_ENC_GET(str) != to) {
+ str = rb_str_dup(str);
+ rb_enc_associate(str, to);
+ }
+ return str;
+ }
+
+ len = RSTRING_LEN(str);
+ newstr = rb_str_new(0, len);
+
+ retry:
+ ec = rb_econv_open_opts(from->name, to->name, ecflags, ecopts);
+ if (!ec) return str;
+
+ sp = (unsigned char*)RSTRING_PTR(str);
+ dp = (unsigned char*)RSTRING_PTR(newstr);
+ ret = rb_econv_convert(ec, &sp, (unsigned char*)RSTRING_END(str),
+ &dp, (unsigned char*)RSTRING_END(newstr), 0);
+ rb_econv_close(ec);
+ switch (ret) {
+ case econv_destination_buffer_full:
+ /* destination buffer short */
+ len *= 2;
+ rb_str_resize(newstr, len);
+ goto retry;
+
+ case econv_finished:
+ len = dp - (unsigned char*)RSTRING_PTR(newstr);
+ rb_str_set_len(newstr, len);
+ rb_enc_associate(newstr, to);
+ return newstr;
+
+ default:
+ /* some error, return original */
+ return str;
+ }
+}
+
+VALUE
+rb_str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to)
+{
+ return rb_str_conv_enc_opts(str, from, to, 0, Qnil);
+}
+
+VALUE
+rb_external_str_new_with_enc(const char *ptr, long len, rb_encoding *eenc)
+{
+ VALUE str;
+
+ str = rb_tainted_str_new(ptr, len);
+ rb_enc_associate(str, eenc);
+ return rb_str_conv_enc(str, eenc, rb_default_internal_encoding());
+}
+
+VALUE
+rb_external_str_new(const char *ptr, long len)
+{
+ return rb_external_str_new_with_enc(ptr, len, rb_default_external_encoding());
+}
+
+VALUE
+rb_external_str_new_cstr(const char *ptr)
+{
+ return rb_external_str_new_with_enc(ptr, strlen(ptr), rb_default_external_encoding());
+}
+
+VALUE
+rb_locale_str_new(const char *ptr, long len)
+{
+ return rb_external_str_new_with_enc(ptr, len, rb_locale_encoding());
+}
+
+VALUE
+rb_locale_str_new_cstr(const char *ptr)
+{
+ return rb_external_str_new_with_enc(ptr, strlen(ptr), rb_locale_encoding());
+}
+
+VALUE
+rb_str_export(VALUE str)
+{
+ return rb_str_conv_enc(str, STR_ENC_GET(str), rb_default_external_encoding());
+}
+
+VALUE
+rb_str_export_locale(VALUE str)
+{
+ return rb_str_conv_enc(str, STR_ENC_GET(str), rb_locale_encoding());
+}
+
+VALUE
+rb_str_export_to_enc(VALUE str, rb_encoding *enc)
+{
+ return rb_str_conv_enc(str, STR_ENC_GET(str), enc);
+}
+
static VALUE
str_replace_shared(VALUE str2, VALUE str)
{
@@ -1081,6 +1198,17 @@ rb_str_modify(VALUE str)
ENC_CODERANGE_CLEAR(str);
}
+/* As rb_str_modify(), but don't clear coderange */
+static void
+str_modify_keep_cr(VALUE str)
+{
+ if (!str_independent(str))
+ str_make_independent(str);
+ if (ENC_CODERANGE(str) == ENC_CODERANGE_BROKEN)
+ /* Force re-scan later */
+ ENC_CODERANGE_CLEAR(str);
+}
+
void
rb_str_associate(VALUE str, VALUE add)
{
@@ -1291,7 +1419,16 @@ rb_str_sublen(VALUE str, long pos)
VALUE
rb_str_subseq(VALUE str, long beg, long len)
{
- VALUE str2 = rb_str_new5(str, RSTRING_PTR(str)+beg, len);
+ VALUE str2;
+
+ if (RSTRING_LEN(str) == beg + len &&
+ RSTRING_EMBED_LEN_MAX < len) {
+ str2 = rb_str_new_shared(rb_str_new_frozen(str));
+ rb_str_drop_bytes(str2, beg);
+ }
+ else {
+ str2 = rb_str_new5(str, RSTRING_PTR(str)+beg, len);
+ }
rb_enc_cr_str_copy_for_substr(str2, str);
OBJ_INFECT(str2, str);
@@ -1305,20 +1442,35 @@ rb_str_substr(VALUE str, long beg, long len)
rb_encoding *enc = STR_ENC_GET(str);
VALUE str2;
char *p, *s = RSTRING_PTR(str), *e = s + RSTRING_LEN(str);
- int singlebyte;
if (len < 0) return Qnil;
if (!RSTRING_LEN(str)) {
len = 0;
}
+ if (single_byte_optimizable(str)) {
+ if (beg > RSTRING_LEN(str)) return Qnil;
+ if (beg < 0) {
+ beg += RSTRING_LEN(str);
+ if (beg < 0) return Qnil;
+ }
+ if (beg + len > RSTRING_LEN(str))
+ len = RSTRING_LEN(str) - beg;
+ if (len <= 0) {
+ len = 0;
+ p = 0;
+ }
+ else
+ p = s + beg;
+ goto sub;
+ }
if (beg < 0) {
if (len > -beg) len = -beg;
if (-beg * rb_enc_mbmaxlen(enc) < RSTRING_LEN(str) / 8) {
beg = -beg;
- while (beg-- > len && (e = rb_enc_prev_char(s, e, enc)) != 0);
+ while (beg-- > len && (e = rb_enc_prev_char(s, e, e, enc)) != 0);
p = e;
if (!p) return Qnil;
- while (len-- > 0 && (p = rb_enc_prev_char(s, p, enc)) != 0);
+ while (len-- > 0 && (p = rb_enc_prev_char(s, p, e, enc)) != 0);
if (!p) return Qnil;
len = e - p;
goto sub;
@@ -1331,7 +1483,6 @@ rb_str_substr(VALUE str, long beg, long len)
else if (beg > 0 && beg > str_strlen(str, enc)) {
return Qnil;
}
- singlebyte = single_byte_optimizable(str);
if (len == 0) {
p = 0;
}
@@ -1342,17 +1493,24 @@ rb_str_substr(VALUE str, long beg, long len)
len = str_utf8_offset(p, e, len);
}
#endif
- else if ((p = str_nth(s, e, beg, enc, singlebyte)) == e) {
- len = 0;
- }
else if (rb_enc_mbmaxlen(enc) == rb_enc_mbminlen(enc)) {
- if (len * rb_enc_mbmaxlen(enc) > e - p)
+ int char_sz = rb_enc_mbmaxlen(enc);
+
+ p = s + beg * char_sz;
+ if (p > e) {
+ p = e;
+ len = 0;
+ }
+ else if (len * char_sz > e - p)
len = e - p;
else
- len *= rb_enc_mbmaxlen(enc);
+ len *= char_sz;
+ }
+ else if ((p = str_nth(s, e, beg, enc, 0)) == e) {
+ len = 0;
}
else {
- len = str_offset(p, e, len, enc, singlebyte);
+ len = str_offset(p, e, len, enc, 0);
}
sub:
if (len > RSTRING_EMBED_LEN_MAX && beg + len == RSTRING_LEN(str)) {
@@ -1647,7 +1805,7 @@ rb_str_buf_cat_ascii(VALUE str, const char *ptr)
else {
char *buf = ALLOCA_N(char, rb_enc_mbmaxlen(enc));
while (*ptr) {
- int c = (unsigned char)*ptr;
+ unsigned int c = (unsigned char)*ptr;
int len = rb_enc_codelen(c, enc);
rb_enc_mbcput(c, buf, enc);
rb_enc_cr_str_buf_cat(str, buf, len,
@@ -1702,13 +1860,13 @@ rb_str_append(VALUE str, VALUE str2)
/*
* call-seq:
- * str << fixnum => str
- * str.concat(fixnum) => str
+ * str << integer => str
+ * str.concat(integer) => str
* str << obj => str
* str.concat(obj) => str
*
* Append---Concatenates the given object to <i>str</i>. If the object is a
- * <code>Fixnum</code>, it is considered as a codepoint, and is converted
+ * <code>Integer</code>, it is considered as a codepoint, and is converted
* to a character before concatenation.
*
* a = "hello "
@@ -1719,9 +1877,9 @@ rb_str_append(VALUE str, VALUE str2)
VALUE
rb_str_concat(VALUE str1, VALUE str2)
{
- if (FIXNUM_P(str2)) {
+ if (FIXNUM_P(str2) || TYPE(str2) == T_BIGNUM) {
rb_encoding *enc = STR_ENC_GET(str1);
- int c = FIX2INT(str2);
+ unsigned int c = NUM2UINT(str2);
int pos = RSTRING_LEN(str1);
int len = rb_enc_codelen(c, enc);
int cr = ENC_CODERANGE(str1);
@@ -1946,8 +2104,8 @@ rb_str_cmp(VALUE str1, VALUE str2)
retval = memcmp(RSTRING_PTR(str1), RSTRING_PTR(str2), len);
if (retval == 0) {
if (RSTRING_LEN(str1) == RSTRING_LEN(str2)) {
- if (!rb_enc_compatible(str1, str2)) {
- if (ENCODING_GET(str1) - ENCODING_GET(str2) > 0)
+ if (!rb_str_comparable(str1, str2)) {
+ if (ENCODING_GET(str1) > ENCODING_GET(str2))
return 1;
return -1;
}
@@ -2089,19 +2247,43 @@ rb_str_casecmp(VALUE str1, VALUE str2)
p1 = RSTRING_PTR(str1); p1end = RSTRING_END(str1);
p2 = RSTRING_PTR(str2); p2end = RSTRING_END(str2);
- while (p1 < p1end && p2 < p2end) {
- int c1 = rb_enc_codepoint(p1, p1end, enc);
- int c2 = rb_enc_codepoint(p2, p2end, enc);
-
- if (c1 != c2) {
- c1 = rb_enc_toupper(c1, enc);
- c2 = rb_enc_toupper(c2, enc);
- if (c1 > c2) return INT2FIX(1);
- if (c1 < c2) return INT2FIX(-1);
+ if (single_byte_optimizable(str1) && single_byte_optimizable(str2)) {
+ while (p1 < p1end && p2 < p2end) {
+ if (*p1 != *p2) {
+ unsigned int c1 = TOUPPER(*p1 & 0xff);
+ unsigned int c2 = TOUPPER(*p2 & 0xff);
+ if (c1 != c2)
+ return INT2FIX(c1 < c2 ? -1 : 1);
+ }
+ p1++;
+ p2++;
+ }
+ }
+ else {
+ while (p1 < p1end && p2 < p2end) {
+ int l1, c1 = rb_enc_ascget(p1, p1end, &l1, enc);
+ int l2, c2 = rb_enc_ascget(p2, p2end, &l2, enc);
+
+ if (0 <= c1 && 0 <= c2) {
+ c1 = TOUPPER(c1);
+ c2 = TOUPPER(c2);
+ if (c1 != c2)
+ return INT2FIX(c1 < c2 ? -1 : 1);
+ }
+ else {
+ int r;
+ l1 = rb_enc_mbclen(p1, p1end, enc);
+ l2 = rb_enc_mbclen(p2, p2end, enc);
+ len = l1 < l2 ? l1 : l2;
+ r = memcmp(p1, p2, len);
+ if (r != 0)
+ return INT2FIX(r < 0 ? -1 : 1);
+ if (l1 != l2)
+ return INT2FIX(l1 < l2 ? -1 : 1);
+ }
+ p1 += l1;
+ p2 += l2;
}
- len = rb_enc_codelen(c1, enc);
- p1 += len;
- p2 += len;
}
if (RSTRING_LEN(str1) == RSTRING_LEN(str2)) return INT2FIX(0);
if (RSTRING_LEN(str1) > RSTRING_LEN(str2)) return INT2FIX(1);
@@ -2112,7 +2294,7 @@ static long
rb_str_index(VALUE str, VALUE sub, long offset)
{
long pos;
- char *s, *sptr;
+ char *s, *sptr, *e;
long len, slen;
rb_encoding *enc;
@@ -2128,6 +2310,7 @@ rb_str_index(VALUE str, VALUE sub, long offset)
}
if (len - offset < slen) return -1;
s = RSTRING_PTR(str);
+ e = s + RSTRING_LEN(str);
if (offset) {
offset = str_offset(s, RSTRING_END(str), offset, enc, single_byte_optimizable(str));
s += offset;
@@ -2141,7 +2324,7 @@ rb_str_index(VALUE str, VALUE sub, long offset)
char *t;
pos = rb_memsearch(sptr, slen, s, len, enc);
if (pos < 0) return pos;
- t = rb_enc_right_char_head(s, s+pos, enc);
+ t = rb_enc_right_char_head(s, s+pos, e, enc);
if (t == s + pos) break;
if ((len -= t - s) <= 0) return -1;
offset += t - s;
@@ -2308,7 +2491,7 @@ rb_str_rindex_m(int argc, VALUE *argv, VALUE str)
case T_REGEXP:
/* enc = rb_get_check(str, sub); */
pos = str_offset(RSTRING_PTR(str), RSTRING_END(str), pos,
- rb_enc_check(str, sub), single_byte_optimizable(str));
+ STR_ENC_GET(str), single_byte_optimizable(str));
if (!RREGEXP(sub)->ptr || RREGEXP_SRC_LEN(sub)) {
pos = rb_reg_adjust_startpos(sub, str, pos, 1);
@@ -2496,7 +2679,7 @@ static enum neighbor_char
enc_succ_alnum_char(char *p, int len, rb_encoding *enc, char *carry)
{
enum neighbor_char ret;
- int c;
+ unsigned int c;
int ctype;
int range;
char save[ONIGENC_CODE_TO_MBC_MAXLEN];
@@ -2595,7 +2778,7 @@ rb_str_succ(VALUE orig)
sbeg = RSTRING_PTR(str);
s = e = sbeg + RSTRING_LEN(str);
- while ((s = rb_enc_prev_char(sbeg, s, enc)) != 0) {
+ while ((s = rb_enc_prev_char(sbeg, s, e, enc)) != 0) {
if (neighbor == NEIGHBOR_NOT_CHAR && last_alnum) {
if (ISALPHA(*last_alnum) ? ISDIGIT(*s) :
ISDIGIT(*last_alnum) ? ISALPHA(*s) : 0) {
@@ -2620,7 +2803,7 @@ rb_str_succ(VALUE orig)
}
if (c == -1) { /* str contains no alnum */
s = e;
- while ((s = rb_enc_prev_char(sbeg, s, enc)) != 0) {
+ while ((s = rb_enc_prev_char(sbeg, s, e, enc)) != 0) {
enum neighbor_char neighbor;
if ((l = rb_enc_precise_mbclen(s, e, enc)) <= 0) continue;
neighbor = enc_succ_char(s, l, enc);
@@ -2918,11 +3101,11 @@ rb_str_splice(VALUE str, long beg, long len, VALUE val)
char *p, *e;
rb_encoding *enc;
int singlebyte = single_byte_optimizable(str);
+ int cr;
if (len < 0) rb_raise(rb_eIndexError, "negative length %ld", len);
StringValue(val);
- rb_str_modify(str);
enc = rb_enc_check(str, val);
slen = str_strlen(str, enc);
@@ -2939,6 +3122,7 @@ rb_str_splice(VALUE str, long beg, long len, VALUE val)
if (slen < len || slen < beg + len) {
len = slen - beg;
}
+ str_modify_keep_cr(str);
p = str_nth(RSTRING_PTR(str), RSTRING_END(str), beg, enc, singlebyte);
if (!p) p = RSTRING_END(str);
e = str_nth(p, RSTRING_END(str), len, enc, singlebyte);
@@ -2948,6 +3132,9 @@ rb_str_splice(VALUE str, long beg, long len, VALUE val)
len = e - p; /* physical length */
rb_str_splice_0(str, beg, len, val);
rb_enc_associate(str, enc);
+ cr = ENC_CODERANGE_AND(ENC_CODERANGE(str), ENC_CODERANGE(val));
+ if (cr != ENC_CODERANGE_BROKEN)
+ ENC_CODERANGE_SET(str, cr);
}
void
@@ -3138,7 +3325,7 @@ rb_str_slice_bang(int argc, VALUE *argv, VALUE str)
for (i=0; i<argc; i++) {
buf[i] = argv[i];
}
- rb_str_modify(str);
+ str_modify_keep_cr(str);
buf[i] = rb_str_new(0,0);
result = rb_str_aref_m(argc, buf, str);
if (!NIL_P(result)) {
@@ -3253,7 +3440,11 @@ rb_str_sub_bang(int argc, VALUE *argv, VALUE str)
if (OBJ_UNTRUSTED(repl)) untrusted = 1;
if (ENC_CODERANGE_UNKNOWN < cr && cr < ENC_CODERANGE_BROKEN) {
int cr2 = ENC_CODERANGE(repl);
- if (cr2 == ENC_CODERANGE_UNKNOWN || cr2 > cr) cr = cr2;
+ if (cr2 == ENC_CODERANGE_BROKEN ||
+ (cr == ENC_CODERANGE_VALID && cr2 == ENC_CODERANGE_7BIT))
+ cr = ENC_CODERANGE_UNKNOWN;
+ else
+ cr = cr2;
}
plen = end0 - beg0;
if (RSTRING_LEN(repl) > plen) {
@@ -3548,7 +3739,10 @@ rb_str_clear(VALUE str)
STR_SET_EMBED(str);
STR_SET_EMBED_LEN(str, 0);
RSTRING_PTR(str)[0] = 0;
- ENC_CODERANGE_CLEAR(str);
+ if (rb_enc_asciicompat(STR_ENC_GET(str)))
+ ENC_CODERANGE_SET(str, ENC_CODERANGE_7BIT);
+ else
+ ENC_CODERANGE_SET(str, ENC_CODERANGE_VALID);
return str;
}
@@ -3680,22 +3874,15 @@ rb_str_reverse_bang(VALUE str)
if (RSTRING_LEN(str) > 1) {
if (single_byte_optimizable(str)) {
char *s, *e, c;
- int cr = ENC_CODERANGE(str);
- int single = 1;
- rb_str_modify(str);
+ str_modify_keep_cr(str);
s = RSTRING_PTR(str);
e = RSTRING_END(str) - 1;
while (s < e) {
c = *s;
- if (*s & 0x80) single = 0;
*s++ = *e;
*e-- = c;
}
- if (cr == ENC_CODERANGE_UNKNOWN && single) {
- cr = ENC_CODERANGE_7BIT;
- }
- ENC_CODERANGE_SET(str, cr);
}
else {
rb_str_shared_replace(str, rb_str_reverse(str));
@@ -3811,9 +3998,9 @@ rb_str_to_s(VALUE str)
}
static void
-str_cat_char(VALUE str, int c, rb_encoding *enc)
+str_cat_char(VALUE str, unsigned int c, rb_encoding *enc)
{
- char s[16];
+ char s[RUBY_MAX_CHAR_LEN];
int n = rb_enc_codelen(c, enc);
rb_enc_mbcput(c, s, enc);
@@ -3821,7 +4008,7 @@ str_cat_char(VALUE str, int c, rb_encoding *enc)
}
static void
-prefix_escape(VALUE str, int c, rb_encoding *enc)
+prefix_escape(VALUE str, unsigned int c, rb_encoding *enc)
{
str_cat_char(str, '\\', enc);
str_cat_char(str, c, enc);
@@ -3851,9 +4038,8 @@ rb_str_inspect(VALUE str)
str_cat_char(result, '"', enc);
p = RSTRING_PTR(str); pend = RSTRING_END(str);
while (p < pend) {
- int c;
+ unsigned int c, cc;
int n;
- int cc;
n = rb_enc_precise_mbclen(p, pend, enc);
if (!MBCLEN_CHARFOUND_P(n)) {
@@ -3936,11 +4122,12 @@ rb_str_inspect(VALUE str)
VALUE
rb_str_dump(VALUE str)
{
- rb_encoding *enc0 = rb_enc_get(str);
+ rb_encoding *enc = rb_enc_get(str);
long len;
const char *p, *pend;
char *q, *qend;
VALUE result;
+ int u8 = (enc == rb_utf8_encoding());
len = 2; /* "" */
p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str);
@@ -3963,14 +4150,25 @@ rb_str_dump(VALUE str)
len++;
}
else {
- len += 4; /* \xNN */
+ if (u8) { /* \u{NN} */
+ char buf[32];
+ int n = rb_enc_precise_mbclen(p-1, pend, enc) - 1;
+ if (MBCLEN_CHARFOUND_P(n)) {
+ int cc = rb_enc_codepoint(p-1, pend, enc);
+ sprintf(buf, "%x", cc);
+ len += strlen(buf)+4;
+ p += n;
+ break;
+ }
+ }
+ len += 4; /* \xNN */
}
break;
}
}
- if (!rb_enc_asciicompat(enc0)) {
+ if (!rb_enc_asciicompat(enc)) {
len += 19; /* ".force_encoding('')" */
- len += strlen(enc0->name);
+ len += strlen(enc->name);
}
result = rb_str_new5(str, 0, len);
@@ -4026,23 +4224,43 @@ rb_str_dump(VALUE str)
}
else {
*q++ = '\\';
+ if (u8) {
+ int n = rb_enc_precise_mbclen(p-1, pend, enc) - 1;
+ if (MBCLEN_CHARFOUND_P(n)) {
+ int cc = rb_enc_codepoint(p-1, pend, enc);
+ p += n;
+ sprintf(q, "u{%x}", cc);
+ q += strlen(q);
+ continue;
+ }
+ }
sprintf(q, "x%02X", c);
q += 3;
}
}
*q++ = '"';
- if (!rb_enc_asciicompat(enc0)) {
- sprintf(q, ".force_encoding(\"%s\")", enc0->name);
- enc0 = rb_ascii8bit_encoding();
+ *q = '\0';
+ if (!rb_enc_asciicompat(enc)) {
+ sprintf(q, ".force_encoding(\"%s\")", enc->name);
+ enc = rb_ascii8bit_encoding();
}
-
OBJ_INFECT(result, str);
/* result from dump is ASCII */
- rb_enc_associate(result, enc0);
+ rb_enc_associate(result, enc);
+ ENC_CODERANGE_SET(result, ENC_CODERANGE_7BIT);
return result;
}
+static void
+rb_str_check_dummy_enc(rb_encoding *enc)
+{
+ if (rb_enc_dummy_p(enc)) {
+ rb_raise(rb_eEncCompatError, "incompatible encoding with this operation: %s",
+ rb_enc_name(enc));
+ }
+}
+
/*
* call-seq:
* str.upcase! => str or nil
@@ -4058,23 +4276,47 @@ rb_str_upcase_bang(VALUE str)
rb_encoding *enc;
char *s, *send;
int modify = 0;
- int cr = ENC_CODERANGE(str);
- rb_str_modify(str);
+ str_modify_keep_cr(str);
enc = STR_ENC_GET(str);
+ rb_str_check_dummy_enc(enc);
s = RSTRING_PTR(str); send = RSTRING_END(str);
- while (s < send) {
- int c = rb_enc_codepoint(s, send, enc);
+ if (single_byte_optimizable(str)) {
+ while (s < send) {
+ unsigned int c = *(unsigned char*)s;
- if (rb_enc_islower(c, enc)) {
- /* assuming toupper returns codepoint with same size */
- rb_enc_mbcput(rb_enc_toupper(c, enc), s, enc);
- modify = 1;
+ if (rb_enc_isascii(c, enc) && 'a' <= c && c <= 'z') {
+ *s = 'A' + (c - 'a');
+ modify = 1;
+ }
+ s++;
+ }
+ }
+ else {
+ int ascompat = rb_enc_asciicompat(enc);
+
+ while (s < send) {
+ unsigned int c;
+
+ if (ascompat && (c = *(unsigned char*)s) < 0x80) {
+ if (rb_enc_isascii(c, enc) && 'a' <= c && c <= 'z') {
+ *s = 'A' + (c - 'a');
+ modify = 1;
+ }
+ s++;
+ }
+ else {
+ c = rb_enc_codepoint(s, send, enc);
+ if (rb_enc_islower(c, enc)) {
+ /* assuming toupper returns codepoint with same size */
+ rb_enc_mbcput(rb_enc_toupper(c, enc), s, enc);
+ modify = 1;
+ }
+ s += rb_enc_codelen(c, enc);
+ }
}
- s += rb_enc_codelen(c, enc);
}
- ENC_CODERANGE_SET(str, cr);
if (modify) return str;
return Qnil;
}
@@ -4116,23 +4358,47 @@ rb_str_downcase_bang(VALUE str)
rb_encoding *enc;
char *s, *send;
int modify = 0;
- int cr = ENC_CODERANGE(str);
- rb_str_modify(str);
+ str_modify_keep_cr(str);
enc = STR_ENC_GET(str);
+ rb_str_check_dummy_enc(enc);
s = RSTRING_PTR(str); send = RSTRING_END(str);
- while (s < send) {
- int c = rb_enc_codepoint(s, send, enc);
+ if (single_byte_optimizable(str)) {
+ while (s < send) {
+ unsigned int c = *(unsigned char*)s;
- if (rb_enc_isupper(c, enc)) {
- /* assuming toupper returns codepoint with same size */
- rb_enc_mbcput(rb_enc_tolower(c, enc), s, enc);
- modify = 1;
+ if (rb_enc_isascii(c, enc) && 'A' <= c && c <= 'Z') {
+ *s = 'a' + (c - 'A');
+ modify = 1;
+ }
+ s++;
+ }
+ }
+ else {
+ int ascompat = rb_enc_asciicompat(enc);
+
+ while (s < send) {
+ unsigned int c;
+
+ if (ascompat && (c = *(unsigned char*)s) < 0x80) {
+ if (rb_enc_isascii(c, enc) && 'A' <= c && c <= 'Z') {
+ *s = 'a' + (c - 'A');
+ modify = 1;
+ }
+ s++;
+ }
+ else {
+ c = rb_enc_codepoint(s, send, enc);
+ if (rb_enc_isupper(c, enc)) {
+ /* assuming toupper returns codepoint with same size */
+ rb_enc_mbcput(rb_enc_tolower(c, enc), s, enc);
+ modify = 1;
+ }
+ s += rb_enc_codelen(c, enc);
+ }
}
- s += rb_enc_codelen(c, enc);
}
- ENC_CODERANGE_SET(str, cr);
if (modify) return str;
return Qnil;
}
@@ -4179,11 +4445,11 @@ rb_str_capitalize_bang(VALUE str)
rb_encoding *enc;
char *s, *send;
int modify = 0;
- int c;
- int cr = ENC_CODERANGE(str);
+ unsigned int c;
- rb_str_modify(str);
+ str_modify_keep_cr(str);
enc = STR_ENC_GET(str);
+ rb_str_check_dummy_enc(enc);
if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return Qnil;
s = RSTRING_PTR(str); send = RSTRING_END(str);
@@ -4202,7 +4468,6 @@ rb_str_capitalize_bang(VALUE str)
s += rb_enc_codelen(c, enc);
}
- ENC_CODERANGE_SET(str, cr);
if (modify) return str;
return Qnil;
}
@@ -4245,13 +4510,13 @@ rb_str_swapcase_bang(VALUE str)
rb_encoding *enc;
char *s, *send;
int modify = 0;
- int cr = ENC_CODERANGE(str);
- rb_str_modify(str);
+ str_modify_keep_cr(str);
enc = STR_ENC_GET(str);
+ rb_str_check_dummy_enc(enc);
s = RSTRING_PTR(str); send = RSTRING_END(str);
while (s < send) {
- int c = rb_enc_codepoint(s, send, enc);
+ unsigned int c = rb_enc_codepoint(s, send, enc);
if (rb_enc_isupper(c, enc)) {
/* assuming toupper returns codepoint with same size */
@@ -4259,14 +4524,13 @@ rb_str_swapcase_bang(VALUE str)
modify = 1;
}
else if (rb_enc_islower(c, enc)) {
- /* assuming toupper returns codepoint with same size */
+ /* assuming tolower returns codepoint with same size */
rb_enc_mbcput(rb_enc_toupper(c, enc), s, enc);
modify = 1;
}
- s += rb_enc_codelen(c, enc);
+ s += rb_enc_mbclen(s, send, enc);
}
- ENC_CODERANGE_SET(str, cr);
if (modify) return str;
return Qnil;
}
@@ -4295,11 +4559,12 @@ rb_str_swapcase(VALUE str)
typedef unsigned char *USTR;
struct tr {
- int gen, now, max;
+ int gen;
+ unsigned int now, max;
char *p, *pend;
};
-static int
+static unsigned int
trnext(struct tr *t, rb_encoding *enc)
{
for (;;) {
@@ -4313,7 +4578,7 @@ trnext(struct tr *t, rb_encoding *enc)
if (t->p < t->pend - 1 && *t->p == '-') {
t->p++;
if (t->p < t->pend) {
- int c = rb_enc_codepoint(t->p, t->pend, enc);
+ unsigned int c = rb_enc_codepoint(t->p, t->pend, enc);
t->p += rb_enc_codelen(c, enc);
if (t->now > c) continue;
t->gen = 1;
@@ -4337,14 +4602,17 @@ static VALUE rb_str_delete_bang(int,VALUE*,VALUE);
static VALUE
tr_trans(VALUE str, VALUE src, VALUE repl, int sflag)
{
- int trans[256];
+ const unsigned int errc = -1;
+ unsigned int trans[256];
rb_encoding *enc, *e1, *e2;
struct tr trsrc, trrepl;
int cflag = 0;
- int c, c0, last = 0, modify = 0, i, l;
+ unsigned int c, c0;
+ int last = 0, modify = 0, i, l;
char *s, *send;
VALUE hash = 0;
int singlebyte = single_byte_optimizable(str);
+ int cr;
StringValue(src);
StringValue(repl);
@@ -4353,6 +4621,7 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag)
return rb_str_delete_bang(1, &src, str);
}
+ cr = ENC_CODERANGE(str);
e1 = rb_enc_check(str, src);
e2 = rb_enc_check(str, repl);
if (e1 == e2) {
@@ -4378,45 +4647,45 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag)
for (i=0; i<256; i++) {
trans[i] = 1;
}
- while ((c = trnext(&trsrc, enc)) >= 0) {
+ while ((c = trnext(&trsrc, enc)) != errc) {
if (c < 256) {
- trans[c] = -1;
+ trans[c] = errc;
}
else {
if (!hash) hash = rb_hash_new();
- rb_hash_aset(hash, INT2NUM(c), Qtrue);
+ rb_hash_aset(hash, UINT2NUM(c), Qtrue);
}
}
- while ((c = trnext(&trrepl, enc)) >= 0)
+ while ((c = trnext(&trrepl, enc)) != errc)
/* retrieve last replacer */;
last = trrepl.now;
for (i=0; i<256; i++) {
- if (trans[i] >= 0) {
+ if (trans[i] != errc) {
trans[i] = last;
}
}
}
else {
- int r;
+ unsigned int r;
for (i=0; i<256; i++) {
- trans[i] = -1;
+ trans[i] = errc;
}
- while ((c = trnext(&trsrc, enc)) >= 0) {
+ while ((c = trnext(&trsrc, enc)) != errc) {
r = trnext(&trrepl, enc);
- if (r == -1) r = trrepl.now;
+ if (r == errc) r = trrepl.now;
if (c < 256) {
trans[c] = r;
if (r > 255) singlebyte = 0;
}
else {
if (!hash) hash = rb_hash_new();
- rb_hash_aset(hash, INT2NUM(c), INT2NUM(r));
+ rb_hash_aset(hash, UINT2NUM(c), UINT2NUM(r));
}
}
}
- rb_str_modify(str);
+ str_modify_keep_cr(str);
s = RSTRING_PTR(str); send = RSTRING_END(str);
if (sflag) {
int clen, tlen, max = RSTRING_LEN(str);
@@ -4432,18 +4701,18 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag)
c = trans[c];
}
else if (hash) {
- VALUE tmp = rb_hash_lookup(hash, INT2NUM(c));
+ VALUE tmp = rb_hash_lookup(hash, UINT2NUM(c));
if (NIL_P(tmp)) {
if (cflag) c = last;
- else c = -1;
+ else c = errc;
}
- else if (cflag) c = -1;
+ else if (cflag) c = errc;
else c = NUM2INT(tmp);
}
else {
- c = -1;
+ c = errc;
}
- if (c >= 0) {
+ if (c != -1) {
if (save == c) continue;
save = c;
tlen = rb_enc_codelen(c, enc);
@@ -4471,7 +4740,7 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag)
else if (rb_enc_mbmaxlen(enc) == 1 || (singlebyte && !hash)) {
while (s < send) {
c = (unsigned char)*s;
- if (trans[c] >= 0) {
+ if (trans[c] != errc) {
if (!cflag) {
c = trans[c];
*s = c;
@@ -4498,18 +4767,18 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag)
c = trans[c];
}
else if (hash) {
- VALUE tmp = rb_hash_lookup(hash, INT2NUM(c));
+ VALUE tmp = rb_hash_lookup(hash, UINT2NUM(c));
if (NIL_P(tmp)) {
if (cflag) c = last;
- else c = -1;
+ else c = errc;
}
- else if (cflag) c = -1;
+ else if (cflag) c = errc;
else c = NUM2INT(tmp);
}
else {
- c = -1;
+ c = errc;
}
- if (c >= 0) {
+ if (c != errc) {
tlen = rb_enc_codelen(c, enc);
modify = 1;
}
@@ -4538,6 +4807,9 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag)
}
if (modify) {
+ cr = ENC_CODERANGE_AND(cr, ENC_CODERANGE(repl));
+ if (cr != ENC_CODERANGE_BROKEN)
+ ENC_CODERANGE_SET(str, cr);
rb_enc_associate(str, enc);
return str;
}
@@ -4590,11 +4862,12 @@ static void
tr_setup_table(VALUE str, char stable[256], int first,
VALUE *tablep, VALUE *ctablep, rb_encoding *enc)
{
+ const unsigned int errc = -1;
char buf[256];
struct tr tr;
- int c, l;
+ unsigned int c;
VALUE table = 0, ptable = 0;
- int i, cflag = 0;
+ int i, l, cflag = 0;
tr.p = RSTRING_PTR(str); tr.pend = tr.p + RSTRING_LEN(str);
tr.gen = tr.now = tr.max = 0;
@@ -4612,12 +4885,12 @@ tr_setup_table(VALUE str, char stable[256], int first,
buf[i] = cflag;
}
- while ((c = trnext(&tr, enc)) >= 0) {
+ while ((c = trnext(&tr, enc)) != errc) {
if (c < 256) {
buf[c & 0xff] = !cflag;
}
else {
- VALUE key = INT2NUM(c);
+ VALUE key = UINT2NUM(c);
if (!table) {
table = rb_hash_new();
@@ -4642,13 +4915,13 @@ tr_setup_table(VALUE str, char stable[256], int first,
static int
-tr_find(int c, char table[256], VALUE del, VALUE nodel)
+tr_find(unsigned int c, char table[256], VALUE del, VALUE nodel)
{
if (c < 256) {
return table[c] ? Qtrue : Qfalse;
}
else {
- VALUE v = INT2NUM(c);
+ VALUE v = UINT2NUM(c);
if (del && !NIL_P(rb_hash_lookup(del, v))) {
if (!nodel || NIL_P(rb_hash_lookup(nodel, v))) {
@@ -4675,11 +4948,9 @@ rb_str_delete_bang(int argc, VALUE *argv, VALUE str)
char *s, *send, *t;
VALUE del = 0, nodel = 0;
int modify = 0;
- int i;
- int cr;
+ int i, ascompat;
if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return Qnil;
- cr = ENC_CODERANGE(str);
if (argc < 1) {
rb_raise(rb_eArgError, "wrong number of arguments");
}
@@ -4691,27 +4962,41 @@ rb_str_delete_bang(int argc, VALUE *argv, VALUE str)
tr_setup_table(s, squeez, i==0, &del, &nodel, enc);
}
- rb_str_modify(str);
+ str_modify_keep_cr(str);
+ ascompat = rb_enc_asciicompat(enc);
s = t = RSTRING_PTR(str);
- if (!s || RSTRING_LEN(str) == 0) return Qnil;
send = RSTRING_END(str);
while (s < send) {
- int c = rb_enc_codepoint(s, send, enc);
- int clen = rb_enc_codelen(c, enc);
+ unsigned int c;
+ int clen;
- if (tr_find(c, squeez, del, nodel)) {
- modify = 1;
+ if (ascompat && (c = *(unsigned char*)s) < 0x80) {
+ if (squeez[c]) {
+ modify = 1;
+ }
+ else {
+ if (t != s) *t = c;
+ t++;
+ }
+ s++;
}
else {
- if (t != s) rb_enc_mbcput(c, t, enc);
- t += clen;
+ c = rb_enc_codepoint(s, send, enc);
+ clen = rb_enc_codelen(c, enc);
+
+ if (tr_find(c, squeez, del, nodel)) {
+ modify = 1;
+ }
+ else {
+ if (t != s) rb_enc_mbcput(c, t, enc);
+ t += clen;
+ }
+ s += clen;
}
- s += clen;
}
*t = '\0';
STR_SET_LEN(str, t - RSTRING_PTR(str));
- ENC_CODERANGE_SET(str, cr);
if (modify) return str;
return Qnil;
}
@@ -4757,6 +5042,7 @@ rb_str_squeeze_bang(int argc, VALUE *argv, VALUE str)
char *s, *send, *t;
int save, modify = 0;
int i;
+ int ascompat, singlebyte = single_byte_optimizable(str);
if (argc == 0) {
enc = STR_ENC_GET(str);
@@ -4767,26 +5053,51 @@ rb_str_squeeze_bang(int argc, VALUE *argv, VALUE str)
StringValue(s);
enc = rb_enc_check(str, s);
+ if (singlebyte && !single_byte_optimizable(s))
+ singlebyte = 0;
tr_setup_table(s, squeez, i==0, &del, &nodel, enc);
}
}
- rb_str_modify(str);
+ str_modify_keep_cr(str);
s = t = RSTRING_PTR(str);
if (!s || RSTRING_LEN(str) == 0) return Qnil;
send = RSTRING_END(str);
save = -1;
- while (s < send) {
- int c = rb_enc_codepoint(s, send, enc);
- int clen = rb_enc_codelen(c, enc);
+ ascompat = rb_enc_asciicompat(enc);
+
+ if (singlebyte) {
+ while (s < send) {
+ unsigned int c = *(unsigned char*)s++;
+ if (c != save || (argc > 0 && !squeez[c])) {
+ *t++ = save = c;
+ }
+ }
+ } else {
+ while (s < send) {
+ unsigned int c;
+ int clen;
- if (c != save || (argc > 0 && !tr_find(c, squeez, del, nodel))) {
- if (t != s) rb_enc_mbcput(c, t, enc);
- save = c;
- t += clen;
+ if (ascompat && (c = *(unsigned char*)s) < 0x80) {
+ if (c != save || (argc > 0 && !squeez[c])) {
+ *t++ = save = c;
+ }
+ s++;
+ }
+ else {
+ c = rb_enc_codepoint(s, send, enc);
+ clen = rb_enc_codelen(c, enc);
+
+ if (c != save || (argc > 0 && !tr_find(c, squeez, del, nodel))) {
+ if (t != s) rb_enc_mbcput(c, t, enc);
+ save = c;
+ t += clen;
+ }
+ s += clen;
+ }
}
- s += clen;
}
+
*t = '\0';
if (t - RSTRING_PTR(str) != RSTRING_LEN(str)) {
STR_SET_LEN(str, t - RSTRING_PTR(str));
@@ -4798,7 +5109,7 @@ rb_str_squeeze_bang(int argc, VALUE *argv, VALUE str)
}
-/*
+/*
* call-seq:
* str.squeeze([other_str]*) => new_str
*
@@ -4883,6 +5194,7 @@ rb_str_count(int argc, VALUE *argv, VALUE str)
VALUE del = 0, nodel = 0;
char *s, *send;
int i;
+ int ascompat;
if (argc < 1) {
rb_raise(rb_eArgError, "wrong number of arguments");
@@ -4892,22 +5204,36 @@ rb_str_count(int argc, VALUE *argv, VALUE str)
StringValue(s);
enc = rb_enc_check(str, s);
- tr_setup_table(s, table,i==0, &del, &nodel, enc);
+ tr_setup_table(s, table, i==0, &del, &nodel, enc);
}
s = RSTRING_PTR(str);
if (!s || RSTRING_LEN(str) == 0) return INT2FIX(0);
send = RSTRING_END(str);
i = 0;
+ ascompat = rb_enc_asciicompat(enc);
+
while (s < send) {
- int c = rb_enc_codepoint(s, send, enc);
- int clen = rb_enc_codelen(c, enc);
+ unsigned int c;
+ int clen;
- if (tr_find(c, table, del, nodel)) {
- i++;
+ if (ascompat && (c = *(unsigned char*)s) < 0x80) {
+ clen = 1;
+ if (table[c]) {
+ i++;
+ }
+ s++;
+ }
+ else {
+ c = rb_enc_codepoint(s, send, enc);
+ clen = rb_enc_codelen(c, enc);
+ if (tr_find(c, table, del, nodel)) {
+ i++;
+ }
+ s += clen;
}
- s += clen;
}
+
return INT2NUM(i);
}
@@ -4960,7 +5286,7 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str)
rb_encoding *enc;
VALUE spat;
VALUE limit;
- int awk_split = Qfalse;
+ enum {awk, string, regexp} split_type;
long beg, end, i = 0;
int lim = 0;
VALUE result, tmp;
@@ -4982,42 +5308,46 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str)
spat = rb_fs;
goto fs_set;
}
- awk_split = Qtrue;
+ split_type = awk;
}
else {
fs_set:
if (TYPE(spat) == T_STRING) {
rb_encoding *enc2 = STR_ENC_GET(spat);
- if (rb_enc_mbminlen(enc2) == 1) {
+ split_type = string;
+ if (RSTRING_LEN(spat) == 0) {
+ /* Special case - split into chars */
+ spat = rb_reg_regcomp(spat);
+ split_type = regexp;
+ }
+ else if (rb_enc_asciicompat(enc2) == 1) {
if (RSTRING_LEN(spat) == 1 && RSTRING_PTR(spat)[0] == ' '){
- awk_split = Qtrue;
+ split_type = awk;
}
}
else {
int l;
if (rb_enc_ascget(RSTRING_PTR(spat), RSTRING_END(spat), &l, enc2) == ' ' &&
RSTRING_LEN(spat) == l) {
- awk_split = Qtrue;
+ split_type = awk;
}
}
- if (!awk_split) {
- spat = rb_reg_regcomp(rb_reg_quote(spat));
- }
}
else {
spat = get_pat(spat, 1);
+ split_type = regexp;
}
}
result = rb_ary_new();
beg = 0;
- if (awk_split) {
+ if (split_type == awk) {
char *ptr = RSTRING_PTR(str);
char *eptr = RSTRING_END(str);
char *bptr = ptr;
int skip = 1;
- int c;
+ unsigned int c;
end = beg;
while (ptr < eptr) {
@@ -5046,6 +5376,33 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str)
}
}
}
+ else if (split_type == string) {
+ char *ptr = RSTRING_PTR(str);
+ char *eptr = RSTRING_END(str);
+ char *sptr = RSTRING_PTR(spat);
+ int slen = RSTRING_LEN(spat);
+
+ if (is_broken_string(str)) {
+ rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(STR_ENC_GET(str)));
+ }
+ if (is_broken_string(spat)) {
+ rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(STR_ENC_GET(spat)));
+ }
+ enc = rb_enc_check(str, spat);
+ while (ptr < eptr &&
+ (end = rb_memsearch(sptr, slen, ptr, eptr - ptr, enc)) >= 0) {
+ /* Check we are at the start of a char */
+ char *t = rb_enc_right_char_head(ptr, ptr + end, eptr, enc);
+ if (t != ptr + end) {
+ ptr = t;
+ continue;
+ }
+ rb_ary_push(result, rb_str_subseq(str, ptr - RSTRING_PTR(str), end));
+ ptr += end + slen;
+ if (!NIL_P(limit) && lim <= ++i) break;
+ }
+ beg = ptr - RSTRING_PTR(str);
+ }
else {
long start = beg;
long idx;
@@ -5169,7 +5526,7 @@ rb_str_each_line(int argc, VALUE *argv, VALUE str)
{
rb_encoding *enc;
VALUE rs;
- int newline;
+ unsigned int newline;
char *p, *pend, *s, *ptr;
long len, rslen;
VALUE line;
@@ -5199,7 +5556,7 @@ rb_str_each_line(int argc, VALUE *argv, VALUE str)
p = memchr(p, '\n', pend - p);
if (!p) break;
- p0 = rb_enc_left_char_head(s, p, enc);
+ p0 = rb_enc_left_char_head(s, p, pend, enc);
if (!rb_enc_is_newline(p0, pend, enc)) {
p++;
continue;
@@ -5225,7 +5582,7 @@ rb_str_each_line(int argc, VALUE *argv, VALUE str)
}
while (p < pend) {
- int c = rb_enc_codepoint(p, pend, enc);
+ unsigned int c = rb_enc_codepoint(p, pend, enc);
again:
n = rb_enc_codelen(c, enc);
@@ -5347,6 +5704,59 @@ rb_str_each_char(VALUE str)
return str;
}
+/*
+ * Document-method: codepoints
+ * call-seq:
+ * str.codepoints => anEnumerator
+ * str.codepoints {|fixnum| block } => str
+ *
+ * Returns an enumerator that gives the <code>Integer</code> ordinal
+ * of each character in the string, also known as a <i>codepoint</i>
+ * when applied to Unicode strings. If a block is given, it iterates
+ * over each character in the string.
+ *
+ * "foo\u0635".chars.to_a #=> [102, 111, 111, 1589]
+ */
+
+/*
+ * Document-method: each_codepoint
+ * call-seq:
+ * str.each_codepoint {|integer| block } => str
+ *
+ * Passes the <code>Integer</code> ordinal of each character in <i>str</i>,
+ * also known as a <i>codepoint</i> when applied to Unicode strings to the
+ * given block.
+ *
+ * "hello\u0639".each_codepoint {|c| print c, ' ' }
+ *
+ * <em>produces:</em>
+ *
+ * 104 101 108 108 111 1593
+ */
+
+static VALUE
+rb_str_each_codepoint(VALUE str)
+{
+ int len, n;
+ unsigned int c;
+ const char *ptr, *end;
+ rb_encoding *enc;
+
+ if (single_byte_optimizable(str)) return rb_str_each_byte(str);
+ RETURN_ENUMERATOR(str, 0, 0);
+ ptr = RSTRING_PTR(str);
+ len = RSTRING_LEN(str);
+ end = RSTRING_END(str);
+ enc = STR_ENC_GET(str);
+ while (ptr < end) {
+ c = rb_enc_codepoint(ptr, end, enc);
+ n = rb_enc_codelen(c, enc);
+ rb_yield(UINT2NUM(c));
+ ptr += n;
+ }
+ return str;
+}
+
static long
chopped_length(VALUE str)
{
@@ -5356,10 +5766,10 @@ chopped_length(VALUE str)
beg = RSTRING_PTR(str);
end = beg + RSTRING_LEN(str);
if (beg > end) return 0;
- p = rb_enc_prev_char(beg, end, enc);
+ p = rb_enc_prev_char(beg, end, end, enc);
if (!p) return 0;
if (p > beg && rb_enc_codepoint(p, end, enc) == '\n') {
- p2 = rb_enc_prev_char(beg, p, enc);
+ p2 = rb_enc_prev_char(beg, p, end, enc);
if (p2 && rb_enc_codepoint(p2, end, enc) == '\r') p = p2;
}
return p - beg;
@@ -5379,7 +5789,7 @@ rb_str_chop_bang(VALUE str)
{
if (RSTRING_LEN(str) > 0) {
long len;
- rb_str_modify(str);
+ str_modify_keep_cr(str);
len = chopped_length(str);
STR_SET_LEN(str, len);
RSTRING_PTR(str)[len] = '\0';
@@ -5441,16 +5851,16 @@ rb_str_chomp_bang(int argc, VALUE *argv, VALUE str)
rs = rb_rs;
if (rs == rb_default_rs) {
smart_chomp:
- rb_str_modify(str);
+ str_modify_keep_cr(str);
enc = rb_enc_get(str);
if (rb_enc_mbminlen(enc) > 1) {
- pp = rb_enc_left_char_head(p, e-rb_enc_mbminlen(enc), enc);
+ pp = rb_enc_left_char_head(p, e-rb_enc_mbminlen(enc), e, enc);
if (rb_enc_is_newline(pp, e, enc)) {
e = pp;
}
pp = e - rb_enc_mbminlen(enc);
if (pp >= p) {
- pp = rb_enc_left_char_head(p, pp, enc);
+ pp = rb_enc_left_char_head(p, pp, e, enc);
if (rb_enc_ascget(pp, e, 0, enc) == '\r') {
e = pp;
}
@@ -5493,7 +5903,7 @@ rb_str_chomp_bang(int argc, VALUE *argv, VALUE str)
len--;
}
if (len < RSTRING_LEN(str)) {
- rb_str_modify(str);
+ str_modify_keep_cr(str);
STR_SET_LEN(str, len);
RSTRING_PTR(str)[len] = '\0';
return str;
@@ -5513,9 +5923,9 @@ rb_str_chomp_bang(int argc, VALUE *argv, VALUE str)
if (p[len-1] == newline &&
(rslen <= 1 ||
memcmp(RSTRING_PTR(rs), pp, rslen) == 0)) {
- if (rb_enc_left_char_head(p, pp, enc) != pp)
+ if (rb_enc_left_char_head(p, pp, e, enc) != pp)
return Qnil;
- rb_str_modify(str);
+ str_modify_keep_cr(str);
STR_SET_LEN(str, RSTRING_LEN(str) - rslen);
RSTRING_PTR(str)[RSTRING_LEN(str)] = '\0';
return str;
@@ -5569,21 +5979,20 @@ rb_str_lstrip_bang(VALUE str)
rb_encoding *enc;
char *s, *t, *e;
- rb_str_modify(str);
+ str_modify_keep_cr(str);
enc = STR_ENC_GET(str);
s = RSTRING_PTR(str);
if (!s || RSTRING_LEN(str) == 0) return Qnil;
e = t = RSTRING_END(str);
/* remove spaces at head */
while (s < e) {
- int cc = rb_enc_codepoint(s, e, enc);
+ unsigned int cc = rb_enc_codepoint(s, e, enc);
if (!rb_enc_isspace(cc, enc)) break;
s += rb_enc_codelen(cc, enc);
}
if (s > RSTRING_PTR(str)) {
- rb_str_modify(str);
STR_SET_LEN(str, t-s);
memmove(RSTRING_PTR(str), s, RSTRING_LEN(str));
RSTRING_PTR(str)[RSTRING_LEN(str)] = '\0';
@@ -5630,30 +6039,32 @@ rb_str_rstrip_bang(VALUE str)
{
rb_encoding *enc;
char *s, *t, *e;
- int space_seen = Qfalse;
- rb_str_modify(str);
enc = STR_ENC_GET(str);
+ rb_str_check_dummy_enc(enc);
s = RSTRING_PTR(str);
if (!s || RSTRING_LEN(str) == 0) return Qnil;
t = e = RSTRING_END(str);
- while (s < e) {
- int cc = rb_enc_codepoint(s, e, enc);
- if (!cc || rb_enc_isspace(cc, enc)) {
- if (!space_seen) t = s;
- space_seen = Qtrue;
- }
- else {
- space_seen = Qfalse;
+ /* remove trailing spaces or '\0's */
+ if (single_byte_optimizable(str)) {
+ while (s < t && (*(t-1) == '\0' || rb_enc_isspace(*(t-1), enc))) t--;
+ }
+ else {
+ char *tp;
+
+ while ((tp = rb_enc_prev_char(s, t, e, enc)) != NULL) {
+ unsigned int c = rb_enc_codepoint(tp, e, enc);
+ if (c && !rb_enc_isspace(c, enc)) break;
+ t = tp;
}
- s += rb_enc_codelen(cc, enc);
}
- if (!space_seen) t = s;
if (t < e) {
- rb_str_modify(str);
- STR_SET_LEN(str, t-RSTRING_PTR(str));
- RSTRING_PTR(str)[RSTRING_LEN(str)] = '\0';
+ int len = t-RSTRING_PTR(str);
+
+ str_modify_keep_cr(str);
+ STR_SET_LEN(str, len);
+ RSTRING_PTR(str)[len] = '\0';
return str;
}
return Qnil;
@@ -5885,30 +6296,27 @@ rb_str_crypt(VALUE str, VALUE salt)
{
extern char *crypt(const char *, const char *);
VALUE result;
- const char *s;
+ const char *s, *saltp;
#ifdef BROKEN_CRYPT
- VALUE salt_8bit_clean;
- rb_encoding *enc;
+ char salt_8bit_clean[3];
#endif
StringValue(salt);
if (RSTRING_LEN(salt) < 2)
rb_raise(rb_eArgError, "salt too short (need >=2 bytes)");
- if (RSTRING_PTR(str)) s = RSTRING_PTR(str);
- else s = "";
+ s = RSTRING_PTR(str);
+ if (!s) s = "";
+ saltp = RSTRING_PTR(salt);
#ifdef BROKEN_CRYPT
- salt_8bit_clean = rb_str_dup(salt);
- enc = rb_ascii8bit_encoding();
- str_modifiable(salt_8bit_clean);
- rb_enc_associate(salt_8bit_clean, enc);
- salt_8bit_clean = rb_str_tr(salt_8bit_clean,
- rb_enc_str_new("\x80-\xFF", 3, enc),
- rb_usascii_str_new("\x00-\x7F", 3));
- result = rb_str_new2(crypt(s, RSTRING_PTR(salt_8bit_clean)));
-#else
- result = rb_str_new2(crypt(s, RSTRING_PTR(salt)));
+ if (!ISASCII((unsigned char)saltp[0]) || !ISASCII((unsigned char)saltp[1])) {
+ salt_8bit_clean[0] = saltp[0] & 0x7f;
+ salt_8bit_clean[1] = saltp[1] & 0x7f;
+ salt_8bit_clean[2] = '\0';
+ saltp = salt_8bit_clean;
+ }
#endif
+ result = rb_str_new2(crypt(s, saltp));
OBJ_INFECT(result, str);
OBJ_INFECT(result, salt);
return result;
@@ -5973,10 +6381,10 @@ rb_str_intern(VALUE s)
VALUE
rb_str_ord(VALUE s)
{
- int c;
+ unsigned int c;
c = rb_enc_codepoint(RSTRING_PTR(s), RSTRING_END(s), STR_ENC_GET(s));
- return INT2NUM(c);
+ return UINT2NUM(c);
}
/*
* call-seq:
@@ -6050,7 +6458,7 @@ rb_str_justify(int argc, VALUE *argv, VALUE str, char jflag)
const char *f = " ";
long n, llen, rlen;
volatile VALUE pad;
- int singlebyte = 1;
+ int singlebyte = 1, cr;
rb_scan_args(argc, argv, "11", &w, &pad);
enc = STR_ENC_GET(str);
@@ -6071,6 +6479,7 @@ rb_str_justify(int argc, VALUE *argv, VALUE str, char jflag)
n = width - len;
llen = (jflag == 'l') ? 0 : ((jflag == 'r') ? n : n/2);
rlen = n - llen;
+ cr = ENC_CODERANGE(str);
res = rb_str_new5(str, 0, RSTRING_LEN(str)+n*flen/fclen+2);
p = RSTRING_PTR(res);
while (llen) {
@@ -6116,6 +6525,10 @@ rb_str_justify(int argc, VALUE *argv, VALUE str, char jflag)
OBJ_INFECT(res, str);
if (!NIL_P(pad)) OBJ_INFECT(res, pad);
rb_enc_associate(res, enc);
+ if (argc == 2)
+ cr = ENC_CODERANGE_AND(cr, ENC_CODERANGE(pad));
+ if (cr != ENC_CODERANGE_BROKEN)
+ ENC_CODERANGE_SET(res, cr);
return res;
}
@@ -6304,7 +6717,7 @@ static VALUE
rb_str_end_with(int argc, VALUE *argv, VALUE str)
{
int i;
- char *p, *s;
+ char *p, *s, *e;
rb_encoding *enc;
for (i=0; i<argc; i++) {
@@ -6313,8 +6726,9 @@ rb_str_end_with(int argc, VALUE *argv, VALUE str)
enc = rb_enc_check(str, tmp);
if (RSTRING_LEN(str) < RSTRING_LEN(tmp)) continue;
p = RSTRING_PTR(str);
- s = p + RSTRING_LEN(str) - RSTRING_LEN(tmp);
- if (rb_enc_left_char_head(p, s, enc) != s)
+ e = p + RSTRING_LEN(str);
+ s = e - RSTRING_LEN(tmp);
+ if (rb_enc_left_char_head(p, s, e, enc) != s)
continue;
if (memcmp(s, RSTRING_PTR(tmp), RSTRING_LEN(tmp)) == 0)
return Qtrue;
@@ -6560,13 +6974,6 @@ sym_match(VALUE sym, VALUE other)
}
static VALUE
-sym_eqq(VALUE sym, VALUE other)
-{
- if (sym == other) return Qtrue;
- return rb_str_equal(rb_sym_to_s(sym), other);
-}
-
-static VALUE
sym_aref(int argc, VALUE *argv, VALUE sym)
{
return rb_str_aref_m(argc, argv, rb_sym_to_s(sym));
@@ -6722,6 +7129,7 @@ InitVM_String(rb_vm_t *vm)
rb_define_method(rb_cString, "lines", rb_str_each_line, -1);
rb_define_method(rb_cString, "bytes", rb_str_each_byte, 0);
rb_define_method(rb_cString, "chars", rb_str_each_char, 0);
+ rb_define_method(rb_cString, "codepoints", rb_str_each_codepoint, 0);
rb_define_method(rb_cString, "reverse", rb_str_reverse, 0);
rb_define_method(rb_cString, "reverse!", rb_str_reverse_bang, 0);
rb_define_method(rb_cString, "concat", rb_str_concat, 1);
@@ -6771,6 +7179,7 @@ InitVM_String(rb_vm_t *vm)
rb_define_method(rb_cString, "each_line", rb_str_each_line, -1);
rb_define_method(rb_cString, "each_byte", rb_str_each_byte, 0);
rb_define_method(rb_cString, "each_char", rb_str_each_char, 0);
+ rb_define_method(rb_cString, "each_codepoint", rb_str_each_codepoint, 0);
rb_define_method(rb_cString, "sum", rb_str_sum, -1);
@@ -6808,7 +7217,6 @@ InitVM_String(rb_vm_t *vm)
rb_define_method(rb_cSymbol, "<=>", sym_cmp, 1);
rb_define_method(rb_cSymbol, "casecmp", sym_casecmp, 1);
rb_define_method(rb_cSymbol, "=~", sym_match, 1);
- rb_define_method(rb_cSymbol, "===", sym_eqq, 1);
rb_define_method(rb_cSymbol, "[]", sym_aref, -1);
rb_define_method(rb_cSymbol, "slice", sym_aref, -1);
diff --git a/struct.c b/struct.c
index 41833b08da..c7902c90ef 100644
--- a/struct.c
+++ b/struct.c
@@ -350,25 +350,30 @@ num_members(VALUE klass)
/*
*/
-VALUE
-rb_struct_initialize(VALUE self, VALUE values)
+static VALUE
+rb_struct_initialize_m(int argc, VALUE *argv, VALUE self)
{
VALUE klass = rb_obj_class(self);
long n;
rb_struct_modify(self);
n = num_members(klass);
- if (n < RARRAY_LEN(values)) {
+ if (n < argc) {
rb_raise(rb_eArgError, "struct size differs");
}
- MEMCPY(RSTRUCT_PTR(self), RARRAY_PTR(values), VALUE, RARRAY_LEN(values));
- if (n > RARRAY_LEN(values)) {
- rb_mem_clear(RSTRUCT_PTR(self)+RARRAY_LEN(values),
- n-RARRAY_LEN(values));
+ MEMCPY(RSTRUCT_PTR(self), argv, VALUE, argc);
+ if (n > argc) {
+ rb_mem_clear(RSTRUCT_PTR(self)+argc, n-argc);
}
return Qnil;
}
+VALUE
+rb_struct_initialize(VALUE self, VALUE values)
+{
+ return rb_struct_initialize_m(RARRAY_LEN(values), RARRAY_PTR(values), self);
+}
+
static VALUE
struct_alloc(VALUE klass)
{
@@ -882,7 +887,7 @@ InitVM_Struct(rb_vm_t *vm)
rb_undef_alloc_func(rb_cStruct);
rb_define_singleton_method(rb_cStruct, "new", rb_struct_s_def, -1);
- rb_define_method(rb_cStruct, "initialize", rb_struct_initialize, -2);
+ rb_define_method(rb_cStruct, "initialize", rb_struct_initialize_m, -1);
rb_define_method(rb_cStruct, "initialize_copy", rb_struct_init_copy, 1);
rb_define_method(rb_cStruct, "==", rb_struct_equal, 1);
diff --git a/template/id.h.tmpl b/template/id.h.tmpl
new file mode 100644
index 0000000000..5fc0c528db
--- /dev/null
+++ b/template/id.h.tmpl
@@ -0,0 +1,117 @@
+%# -*- c -*-
+/* DO NOT EDIT THIS FILE DIRECTLY */
+/**********************************************************************
+
+ id.h -
+
+ $Author$
+ created at: Sun Oct 19 21:12:51 2008
+
+ Copyright (C) 2007 Koichi Sasada
+
+**********************************************************************/
+<%
+require 'optparse'
+vpath = ["."]
+input = nil
+opt = OptionParser.new do |o|
+ o.on('-v', '--vpath=DIR') {|dirs| vpath.concat dirs.split(File::PATH_SEPARATOR)}
+ input, = o.order!(ARGV)
+end or abort opt.opt_s
+
+tokens = nil
+vpath.find do |dir|
+ begin
+ if line = File.read(File.join(dir, input))[/^\s*enum\s+yytokentype\s*\{([^{}]*)\s*\};/m, 1]
+ tokens = line.scan(/\b(t(?:LAST_TOKEN|U(?:PLUS|MINUS)|POW|CMP|EQQ?|[NGL]EQ|(?:AND|OR)OP|N?MATCH|DOT\d|AREF|ASET|[LR]SHFT|LAMBDA)|id\w+)\s*=\s*(\d+),?/m)
+ end
+ rescue Errno::ENOENT
+ nil
+ else
+ true
+ end
+end
+%>
+#ifndef RUBY_ID_H
+#define RUBY_ID_H
+
+#define ID_SCOPE_SHIFT 3
+#define ID_SCOPE_MASK 0x07
+#define ID_LOCAL 0x00
+#define ID_INSTANCE 0x01
+#define ID_GLOBAL 0x03
+#define ID_ATTRSET 0x04
+#define ID_CONST 0x05
+#define ID_CLASS 0x06
+#define ID_JUNK 0x07
+#define ID_INTERNAL ID_JUNK
+
+#ifdef USE_PARSE_H
+#include "parse.h"
+#endif
+
+#define symIFUNC ID2SYM(idIFUNC)
+#define symCFUNC ID2SYM(idCFUNC)
+
+enum ruby_method_ids {
+#ifndef tLAST_TOKEN
+% tokens.each do |token, value|
+ <%=token%> = <%=value%>,
+% end
+% tokens.map do |token, value|
+#elif <%=token%> != <%=value%>
+#error <%=token%> differs
+% end
+#endif
+ idPLUS = '+',
+ idMINUS = '-',
+ idMULT = '*',
+ idDIV = '/',
+ idMOD = '%',
+ idLT = '<',
+ idLTLT = tLSHFT,
+ idLE = tLEQ,
+ idGT = '>',
+ idGE = tGEQ,
+ idEq = tEQ,
+ idEqq = tEQQ,
+ idNeq = tNEQ,
+ idNot = '!',
+ idBackquote = '`',
+ idEqTilde = tMATCH,
+ idAREF = tAREF,
+ idASET = tASET,
+ idLAST_TOKEN = tLAST_TOKEN >> ID_SCOPE_SHIFT,
+ tIntern,
+ tMethodMissing,
+ tLength,
+ tGets,
+ tSucc,
+ tEach,
+ tLambda,
+ tSend,
+ t__send__,
+ tInitialize,
+#if SUPPORT_JOKE
+ tBitblt,
+ tAnswer,
+#endif
+ tLAST_ID,
+#define TOKEN2ID(n) id##n = ((t##n<<ID_SCOPE_SHIFT)|ID_LOCAL)
+#if SUPPORT_JOKE
+ TOKEN2ID(Bitblt),
+ TOKEN2ID(Answer),
+#endif
+ TOKEN2ID(Intern),
+ TOKEN2ID(MethodMissing),
+ TOKEN2ID(Length),
+ TOKEN2ID(Gets),
+ TOKEN2ID(Succ),
+ TOKEN2ID(Each),
+ TOKEN2ID(Lambda),
+ TOKEN2ID(Send),
+ TOKEN2ID(__send__),
+ TOKEN2ID(Initialize)
+};
+
+#endif /* RUBY_ID_H */
diff --git a/template/known_errors.inc.tmpl b/template/known_errors.inc.tmpl
new file mode 100644
index 0000000000..23bca21362
--- /dev/null
+++ b/template/known_errors.inc.tmpl
@@ -0,0 +1,14 @@
+/** -*-c-*-
+ * DO NOT EDIT
+ * This file is automatically generated by tools/generic_erb.rb from
+ * template/known_errors.inc.tmpl and defs/known_errors.def.
+ */
+
+% error_names = ARGF.read.split(/\s+/)
+% error_names.each do |name|
+#ifdef <%=name%>
+ set_syserr(<%=name%>, "<%=name%>");
+#else
+ set_syserr(0, "<%=name%>");
+#endif
+% end
diff --git a/template/public_object.h.tmpl b/template/public_object.h.tmpl
new file mode 100644
index 0000000000..ed5916b2fa
--- /dev/null
+++ b/template/public_object.h.tmpl
@@ -0,0 +1,52 @@
+#ifndef RUBY_PUBLIC_OBJECT_H
+#define RUBY_PUBLIC_OBJECT_H 1
+
+#include "ruby/vm.h"
+
+<%
+public_vars = %w{
+
+ mKernel mComparable mEnumerable mErrno mFileTest mGC mMath mProcess
+
+ cBasicObject cObject cArray cBignum cBinding cClass cDir cData
+ cFalseClass cEncoding cEncodingConverter cEnumerator cFile
+ cFixnum cFloat cHash cInteger cIO cMatch cMethod cModule
+ cNameErrorMesg cNilClass cNumeric cProc cRange cRational cComplex
+ cRegexp cStat cString cStruct cSymbol cThread cTime cTrueClass
+ cUnboundMethod cMutex cBarrier
+
+ eException eStandardError eSystemExit eInterrupt eSignal eFatal
+ eArgError eEOFError eIndexError eStopIteration eKeyError eRangeError
+ eIOError eRuntimeError eSecurityError eSystemCallError eThreadError
+ eTypeError eZeroDivError eNotImpError eNoMemError eNoMethodError
+ eFloatDomainError eLocalJumpError eSysStackError eRegexpError
+ eEncodingError eEncCompatError eScriptError eNameError eSyntaxError
+ eLoadError eUndefinedConversionError
+ eInvalidByteSequenceError eConverterNotFoundError
+
+ stdin stdout stderr argf
+
+}
+
+public_vars2 = %w{
+ verbose debug progname
+}
+%>
+
+VALUE *rb_vm_specific_ptr(int key);
+
+enum ruby_public_object_vmkey {
+% public_vars.each{|var|
+ rb_vmkey_<%=var%>,
+#define rb_<%=var%> (*rb_vm_specific_ptr(rb_vmkey_<%=var%>))
+% }
+% public_vars2.each{|var|
+ rb_vmkey_<%=var%>,
+#define ruby_<%=var%> (*rb_vm_specific_ptr(rb_vmkey_<%=var%>))
+% }
+
+ ruby_public_object_count
+};
+
+#undef RUBY_PUBLIC_OBJECT_ACCESSOR
+#endif /* RUBY_PUBLIC_OBJECT_H */
diff --git a/test/base64/test_base64.rb b/test/base64/test_base64.rb
new file mode 100644
index 0000000000..9ae54cb405
--- /dev/null
+++ b/test/base64/test_base64.rb
@@ -0,0 +1,99 @@
+require "test/unit"
+require "base64"
+
+class TestBase64 < Test::Unit::TestCase
+ def test_sample
+ assert_equal("U2VuZCByZWluZm9yY2VtZW50cw==\n", Base64.encode64('Send reinforcements'))
+ assert_equal('Send reinforcements', Base64.decode64("U2VuZCByZWluZm9yY2VtZW50cw==\n"))
+ assert_equal(
+ "Tm93IGlzIHRoZSB0aW1lIGZvciBhbGwgZ29vZCBjb2RlcnMKdG8gbGVhcm4g\nUnVieQ==\n",
+ Base64.encode64("Now is the time for all good coders\nto learn Ruby"))
+ assert_equal(
+ "Now is the time for all good coders\nto learn Ruby",
+ Base64.decode64("Tm93IGlzIHRoZSB0aW1lIGZvciBhbGwgZ29vZCBjb2RlcnMKdG8gbGVhcm4g\nUnVieQ==\n"))
+ assert_equal(
+ "VGhpcyBpcyBsaW5lIG9uZQpUaGlzIGlzIGxpbmUgdHdvClRoaXMgaXMgbGlu\nZSB0aHJlZQpBbmQgc28gb24uLi4K\n",
+ Base64.encode64("This is line one\nThis is line two\nThis is line three\nAnd so on...\n"))
+ assert_equal(
+ "This is line one\nThis is line two\nThis is line three\nAnd so on...\n",
+ Base64.decode64("VGhpcyBpcyBsaW5lIG9uZQpUaGlzIGlzIGxpbmUgdHdvClRoaXMgaXMgbGluZSB0aHJlZQpBbmQgc28gb24uLi4K"))
+ end
+
+ def test_encode64
+ assert_equal("", Base64.encode64(""))
+ assert_equal("AA==\n", Base64.encode64("\0"))
+ assert_equal("AAA=\n", Base64.encode64("\0\0"))
+ assert_equal("AAAA\n", Base64.encode64("\0\0\0"))
+ assert_equal("/w==\n", Base64.encode64("\377"))
+ assert_equal("//8=\n", Base64.encode64("\377\377"))
+ assert_equal("////\n", Base64.encode64("\377\377\377"))
+ assert_equal("/+8=\n", Base64.encode64("\xff\xef"))
+ end
+
+ def test_decode64
+ assert_equal("", Base64.decode64(""))
+ assert_equal("\0", Base64.decode64("AA==\n"))
+ assert_equal("\0\0", Base64.decode64("AAA=\n"))
+ assert_equal("\0\0\0", Base64.decode64("AAAA\n"))
+ assert_equal("\377", Base64.decode64("/w==\n"))
+ assert_equal("\377\377", Base64.decode64("//8=\n"))
+ assert_equal("\377\377\377", Base64.decode64("////\n"))
+ assert_equal("\xff\xef", Base64.decode64("/+8=\n"))
+ end
+
+ def test_strict_encode64
+ assert_equal("", Base64.strict_encode64(""))
+ assert_equal("AA==", Base64.strict_encode64("\0"))
+ assert_equal("AAA=", Base64.strict_encode64("\0\0"))
+ assert_equal("AAAA", Base64.strict_encode64("\0\0\0"))
+ assert_equal("/w==", Base64.strict_encode64("\377"))
+ assert_equal("//8=", Base64.strict_encode64("\377\377"))
+ assert_equal("////", Base64.strict_encode64("\377\377\377"))
+ assert_equal("/+8=", Base64.strict_encode64("\xff\xef"))
+ end
+
+ def test_strict_decode64
+ assert_equal("", Base64.strict_decode64(""))
+ assert_equal("\0", Base64.strict_decode64("AA=="))
+ assert_equal("\0\0", Base64.strict_decode64("AAA="))
+ assert_equal("\0\0\0", Base64.strict_decode64("AAAA"))
+ assert_equal("\377", Base64.strict_decode64("/w=="))
+ assert_equal("\377\377", Base64.strict_decode64("//8="))
+ assert_equal("\377\377\377", Base64.strict_decode64("////"))
+ assert_equal("\xff\xef", Base64.strict_decode64("/+8="))
+
+ assert_raise(ArgumentError) { Base64.strict_decode64("^") }
+ assert_raise(ArgumentError) { Base64.strict_decode64("A") }
+ assert_raise(ArgumentError) { Base64.strict_decode64("A^") }
+ assert_raise(ArgumentError) { Base64.strict_decode64("AA") }
+ assert_raise(ArgumentError) { Base64.strict_decode64("AA=") }
+ assert_raise(ArgumentError) { Base64.strict_decode64("AA===") }
+ assert_raise(ArgumentError) { Base64.strict_decode64("AA=x") }
+ assert_raise(ArgumentError) { Base64.strict_decode64("AAA") }
+ assert_raise(ArgumentError) { Base64.strict_decode64("AAA^") }
+ assert_raise(ArgumentError) { Base64.strict_decode64("AB==") }
+ assert_raise(ArgumentError) { Base64.strict_decode64("AAB=") }
+ end
+
+ def test_urlsafe_encode64
+ assert_equal("", Base64.urlsafe_encode64(""))
+ assert_equal("AA==", Base64.urlsafe_encode64("\0"))
+ assert_equal("AAA=", Base64.urlsafe_encode64("\0\0"))
+ assert_equal("AAAA", Base64.urlsafe_encode64("\0\0\0"))
+ assert_equal("_w==", Base64.urlsafe_encode64("\377"))
+ assert_equal("__8=", Base64.urlsafe_encode64("\377\377"))
+ assert_equal("____", Base64.urlsafe_encode64("\377\377\377"))
+ assert_equal("_-8=", Base64.urlsafe_encode64("\xff\xef"))
+ end
+
+ def test_urlsafe_decode64
+ assert_equal("", Base64.urlsafe_decode64(""))
+ assert_equal("\0", Base64.urlsafe_decode64("AA=="))
+ assert_equal("\0\0", Base64.urlsafe_decode64("AAA="))
+ assert_equal("\0\0\0", Base64.urlsafe_decode64("AAAA"))
+ assert_equal("\377", Base64.urlsafe_decode64("_w=="))
+ assert_equal("\377\377", Base64.urlsafe_decode64("__8="))
+ assert_equal("\377\377\377", Base64.urlsafe_decode64("____"))
+ assert_equal("\xff\xef", Base64.urlsafe_decode64("_+8="))
+ end
+end
diff --git a/test/bigdecimal/test_bigdecimal.rb b/test/bigdecimal/test_bigdecimal.rb
new file mode 100644
index 0000000000..35edc7a44a
--- /dev/null
+++ b/test/bigdecimal/test_bigdecimal.rb
@@ -0,0 +1,692 @@
+require "test/unit"
+require "bigdecimal"
+
+class TestBigDecimal < Test::Unit::TestCase
+ def setup
+ BigDecimal.mode(BigDecimal::EXCEPTION_ALL, true)
+ BigDecimal.mode(BigDecimal::EXCEPTION_UNDERFLOW, true)
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, true)
+ BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_UP)
+ BigDecimal.limit(0)
+ end
+
+ def test_version
+ assert_equal("1.0.1", BigDecimal.ver)
+ end
+
+ def test_global_new
+ assert_equal(1, BigDecimal("1"))
+ assert_equal(1, BigDecimal("1", 1))
+ assert_raise(ArgumentError) { BigDecimal("1", -1) }
+ end
+
+ def test_new
+ assert_equal(1, BigDecimal.new("1"))
+ assert_equal(1, BigDecimal.new("1", 1))
+ assert_equal(1, BigDecimal.new(" 1 "))
+ assert_equal(111, BigDecimal.new("1_1_1_"))
+ assert_equal(0, BigDecimal.new("_1_1_1"))
+
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
+ assert_equal( 1, BigDecimal.new("Infinity").infinite?)
+ assert_equal(-1, BigDecimal.new("-Infinity").infinite?)
+ assert_equal(true, BigDecimal.new("NaN").nan?)
+ end
+
+ def _test_mode(type)
+ BigDecimal.mode(type, true)
+ assert_raise(FloatDomainError) { yield }
+
+ BigDecimal.mode(type, false)
+ assert_nothing_raised { yield }
+ end
+
+ def test_mode
+ assert_raise(TypeError) { BigDecimal.mode(BigDecimal::EXCEPTION_ALL, 1) }
+ assert_raise(TypeError) { BigDecimal.mode(BigDecimal::ROUND_MODE, 256) }
+ assert_raise(TypeError) { BigDecimal.mode(0xf000, true) }
+ end
+
+ def test_exception_nan
+ _test_mode(BigDecimal::EXCEPTION_NaN) { BigDecimal.new("NaN") }
+ end
+
+ def test_exception_infinity
+ _test_mode(BigDecimal::EXCEPTION_INFINITY) { BigDecimal.new("Infinity") }
+ end
+
+ def test_exception_underflow
+ _test_mode(BigDecimal::EXCEPTION_UNDERFLOW) do
+ x = BigDecimal.new("0.1")
+ 100.times do
+ x *= x
+ break if x == false
+ end
+ end
+ end
+
+ def test_exception_overflow
+ _test_mode(BigDecimal::EXCEPTION_OVERFLOW) do
+ x = BigDecimal.new("10")
+ 100.times do
+ x *= x
+ break if x == false
+ end
+ end
+ end
+
+ def test_exception_zerodivide
+ _test_mode(BigDecimal::EXCEPTION_ZERODIVIDE) { 1 / BigDecimal.new("0") }
+ _test_mode(BigDecimal::EXCEPTION_ZERODIVIDE) { -1 / BigDecimal.new("0") }
+ end
+
+ def test_round_up
+ n4 = BigDecimal.new("4") # n4 / 9 = 0.44444...
+ n5 = BigDecimal.new("5") # n5 / 9 = 0.55555...
+ n6 = BigDecimal.new("6") # n6 / 9 = 0.66666...
+ m4, m5, m6 = -n4, -n5, -n6
+ n2h = BigDecimal.new("2.5")
+ n3h = BigDecimal.new("3.5")
+ m2h, m3h = -n2h, -n3h
+
+ BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_UP)
+ assert_operator(n4, :<, n4 / 9 * 9)
+ assert_operator(n5, :<, n5 / 9 * 9)
+ assert_operator(n6, :<, n6 / 9 * 9)
+ assert_operator(m4, :>, m4 / 9 * 9)
+ assert_operator(m5, :>, m5 / 9 * 9)
+ assert_operator(m6, :>, m6 / 9 * 9)
+ assert_equal(3, n2h.round)
+ assert_equal(4, n3h.round)
+ assert_equal(-3, m2h.round)
+ assert_equal(-4, m3h.round)
+
+ BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_DOWN)
+ assert_operator(n4, :>, n4 / 9 * 9)
+ assert_operator(n5, :>, n5 / 9 * 9)
+ assert_operator(n6, :>, n6 / 9 * 9)
+ assert_operator(m4, :<, m4 / 9 * 9)
+ assert_operator(m5, :<, m5 / 9 * 9)
+ assert_operator(m6, :<, m6 / 9 * 9)
+ assert_equal(2, n2h.round)
+ assert_equal(3, n3h.round)
+ assert_equal(-2, m2h.round)
+ assert_equal(-3, m3h.round)
+
+ BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_UP)
+ assert_operator(n4, :>, n4 / 9 * 9)
+ assert_operator(n5, :<, n5 / 9 * 9)
+ assert_operator(n6, :<, n6 / 9 * 9)
+ assert_operator(m4, :<, m4 / 9 * 9)
+ assert_operator(m5, :>, m5 / 9 * 9)
+ assert_operator(m6, :>, m6 / 9 * 9)
+ assert_equal(3, n2h.round)
+ assert_equal(4, n3h.round)
+ assert_equal(-3, m2h.round)
+ assert_equal(-4, m3h.round)
+
+ BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_DOWN)
+ assert_operator(n4, :>, n4 / 9 * 9)
+ assert_operator(n5, :>, n5 / 9 * 9)
+ assert_operator(n6, :<, n6 / 9 * 9)
+ assert_operator(m4, :<, m4 / 9 * 9)
+ assert_operator(m5, :<, m5 / 9 * 9)
+ assert_operator(m6, :>, m6 / 9 * 9)
+ assert_equal(2, n2h.round)
+ assert_equal(3, n3h.round)
+ assert_equal(-2, m2h.round)
+ assert_equal(-3, m3h.round)
+
+ BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_EVEN)
+ assert_operator(n4, :>, n4 / 9 * 9)
+ assert_operator(n5, :<, n5 / 9 * 9)
+ assert_operator(n6, :<, n6 / 9 * 9)
+ assert_operator(m4, :<, m4 / 9 * 9)
+ assert_operator(m5, :>, m5 / 9 * 9)
+ assert_operator(m6, :>, m6 / 9 * 9)
+ assert_equal(2, n2h.round)
+ assert_equal(4, n3h.round)
+ assert_equal(-2, m2h.round)
+ assert_equal(-4, m3h.round)
+
+ BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_CEILING)
+ assert_operator(n4, :<, n4 / 9 * 9)
+ assert_operator(n5, :<, n5 / 9 * 9)
+ assert_operator(n6, :<, n6 / 9 * 9)
+ assert_operator(m4, :<, m4 / 9 * 9)
+ assert_operator(m5, :<, m5 / 9 * 9)
+ assert_operator(m6, :<, m6 / 9 * 9)
+ assert_equal(3, n2h.round)
+ assert_equal(4, n3h.round)
+ assert_equal(-2, m2h.round)
+ assert_equal(-3, m3h.round)
+
+ BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_FLOOR)
+ assert_operator(n4, :>, n4 / 9 * 9)
+ assert_operator(n5, :>, n5 / 9 * 9)
+ assert_operator(n6, :>, n6 / 9 * 9)
+ assert_operator(m4, :>, m4 / 9 * 9)
+ assert_operator(m5, :>, m5 / 9 * 9)
+ assert_operator(m6, :>, m6 / 9 * 9)
+ assert_equal(2, n2h.round)
+ assert_equal(3, n3h.round)
+ assert_equal(-3, m2h.round)
+ assert_equal(-4, m3h.round)
+ end
+
+ def test_zero_p
+ assert_equal(true, BigDecimal.new("0").zero?)
+ assert_equal(false, BigDecimal.new("1").zero?)
+ end
+
+ def test_nonzero_p
+ assert_equal(nil, BigDecimal.new("0").nonzero?)
+ assert_equal(BigDecimal.new("1"), BigDecimal.new("1").nonzero?)
+ end
+
+ def test_double_fig
+ assert_kind_of(Integer, BigDecimal.double_fig)
+ end
+
+ def test_cmp
+ n1 = BigDecimal.new("1")
+ n2 = BigDecimal.new("2")
+ assert_equal( 0, n1 <=> n1)
+ assert_equal( 1, n2 <=> n1)
+ assert_equal(-1, n1 <=> n2)
+ assert_operator(n1, :==, n1)
+ assert_operator(n1, :!=, n2)
+ assert_operator(n1, :<, n2)
+ assert_operator(n1, :<=, n1)
+ assert_operator(n1, :<=, n2)
+ assert_operator(n2, :>, n1)
+ assert_operator(n2, :>=, n1)
+ assert_operator(n1, :>=, n1)
+
+ assert_operator(BigDecimal.new("-0"), :==, BigDecimal.new("0"))
+ assert_operator(BigDecimal.new("0"), :<, BigDecimal.new("1"))
+ assert_operator(BigDecimal.new("1"), :>, BigDecimal.new("0"))
+ assert_operator(BigDecimal.new("1"), :>, BigDecimal.new("-1"))
+ assert_operator(BigDecimal.new("-1"), :<, BigDecimal.new("1"))
+ assert_operator(BigDecimal.new((2**100).to_s), :>, BigDecimal.new("1"))
+ assert_operator(BigDecimal.new("1"), :<, BigDecimal.new((2**100).to_s))
+
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+ inf = BigDecimal.new("Infinity")
+ assert_operator(inf, :>, 1)
+ assert_operator(1, :<, inf)
+ end
+
+ def test_cmp_corece
+ n1 = BigDecimal.new("1")
+ n2 = BigDecimal.new("2")
+ o1 = Object.new; def o1.coerce(x); [x, BigDecimal.new("1")]; end
+ o2 = Object.new; def o2.coerce(x); [x, BigDecimal.new("2")]; end
+ assert_equal( 0, n1 <=> o1)
+ assert_equal( 1, n2 <=> o1)
+ assert_equal(-1, n1 <=> o2)
+ assert_operator(n1, :==, o1)
+ assert_operator(n1, :!=, o2)
+ assert_operator(n1, :<, o2)
+ assert_operator(n1, :<=, o1)
+ assert_operator(n1, :<=, o2)
+ assert_operator(n2, :>, o1)
+ assert_operator(n2, :>=, o1)
+ assert_operator(n1, :>=, 1)
+ end
+
+ def test_cmp_bignum
+ assert_operator(BigDecimal.new((2**100).to_s), :==, 2**100)
+ end
+
+ def test_cmp_data
+ d = Time.now; def d.coerce(x); [x, x]; end
+ assert_operator(BigDecimal.new((2**100).to_s), :==, d)
+ end
+
+ def test_precs
+ a = BigDecimal.new("1").precs
+ assert_instance_of(Array, a)
+ assert_equal(2, a.size)
+ assert_kind_of(Integer, a[0])
+ assert_kind_of(Integer, a[1])
+ end
+
+ def test_hash
+ a = []
+ x = BigDecimal.new("1")
+ 10.times { a << x *= 10 }
+ h = {}
+ a.each_with_index {|x, i| h[x] = i }
+ a.each_with_index do |x, i|
+ assert_equal(i, h[x])
+ end
+ end
+
+ def test_marshal
+ s = Marshal.dump(BigDecimal("1", 1))
+ assert_equal(BigDecimal("1", 1), Marshal.load(s))
+
+ # corrupt data
+ s = s.gsub(/BigDecimal.*\z/m) {|x| x.gsub(/\d/m, "-") }
+ assert_raise(TypeError) { Marshal.load(s) }
+ end
+
+ def test_finite_infinite_nan
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+
+ x = BigDecimal.new("0")
+ assert_equal(true, x.finite?)
+ assert_equal(nil, x.infinite?)
+ assert_equal(false, x.nan?)
+ y = 1 / x
+ assert_equal(false, y.finite?)
+ assert_equal(1, y.infinite?)
+ assert_equal(false, y.nan?)
+ y = -1 / x
+ assert_equal(false, y.finite?)
+ assert_equal(-1, y.infinite?)
+ assert_equal(false, y.nan?)
+
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
+ y = 0 / x
+ assert_equal(false, y.finite?)
+ assert_equal(nil, y.infinite?)
+ assert_equal(true, y.nan?)
+ end
+
+ def test_to_i
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
+
+ x = BigDecimal.new("0")
+ assert_kind_of(Integer, x.to_i)
+ assert_equal(0, x.to_i)
+ assert_nil(( 1 / x).to_i)
+ assert_nil((-1 / x).to_i)
+ assert_nil(( 0 / x).to_i)
+ x = BigDecimal.new("1")
+ assert_equal(1, x.to_i)
+ x = BigDecimal.new((2**100).to_s)
+ assert_equal(2**100, x.to_i)
+ end
+
+ def test_to_f
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
+
+ x = BigDecimal.new("0")
+ assert_instance_of(Float, x.to_f)
+ assert_equal(0.0, x.to_f)
+ assert_equal( 1.0 / 0.0, ( 1 / x).to_f)
+ assert_equal(-1.0 / 0.0, (-1 / x).to_f)
+ assert_equal(true, ( 0 / x).to_f.nan?)
+ x = BigDecimal.new("1")
+ assert_equal(1.0, x.to_f)
+ x = BigDecimal.new((2**100).to_s)
+ assert_equal((2**100).to_f, x.to_f)
+ x = BigDecimal.new("1" + "0" * 10000)
+ assert_equal(0, BigDecimal.new("-0").to_f)
+
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, true)
+ assert_raise(FloatDomainError) { x.to_f }
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+ assert_kind_of(Float, x .to_f)
+ assert_kind_of(Float, (-x).to_f)
+ end
+
+ def test_coerce
+ a, b = BigDecimal.new("1").coerce(1.0)
+ assert_instance_of(Float, a)
+ assert_instance_of(Float, b)
+ end
+
+ def test_uplus
+ x = BigDecimal.new("1")
+ assert_equal(x, x.send(:+@))
+ end
+
+ def test_add
+ x = BigDecimal.new("1")
+ assert_equal(BigDecimal.new("2"), x + x)
+ assert_equal(1, BigDecimal.new("0") + 1)
+ assert_equal(1, x + 0)
+
+ assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, (BigDecimal.new("0") + 0).sign)
+ assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, (BigDecimal.new("-0") + 0).sign)
+ assert_equal(BigDecimal::SIGN_NEGATIVE_ZERO, (BigDecimal.new("-0") + BigDecimal.new("-0")).sign)
+
+ x = BigDecimal.new((2**100).to_s)
+ assert_equal(BigDecimal.new((2**100+1).to_s), x + 1)
+ end
+
+ def test_sub
+ x = BigDecimal.new("1")
+ assert_equal(BigDecimal.new("0"), x - x)
+ assert_equal(-1, BigDecimal.new("0") - 1)
+ assert_equal(1, x - 0)
+
+ assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, (BigDecimal.new("0") - 0).sign)
+ assert_equal(BigDecimal::SIGN_NEGATIVE_ZERO, (BigDecimal.new("-0") - 0).sign)
+ assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, (BigDecimal.new("-0") - BigDecimal.new("-0")).sign)
+
+ x = BigDecimal.new((2**100).to_s)
+ assert_equal(BigDecimal.new((2**100-1).to_s), x - 1)
+ end
+
+ def test_mult
+ x = BigDecimal.new((2**100).to_s)
+ assert_equal(BigDecimal.new((2**100 * 3).to_s), (x * 3).to_i)
+ assert_equal(x, (x * 1).to_i)
+ assert_equal(x, (BigDecimal("1") * x).to_i)
+ assert_equal(BigDecimal.new((2**200).to_s), (x * x).to_i)
+ end
+
+ def test_div
+ x = BigDecimal.new((2**100).to_s)
+ assert_equal(BigDecimal.new((2**100 / 3).to_s), (x / 3).to_i)
+ assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, (BigDecimal.new("0") / 1).sign)
+ assert_equal(BigDecimal::SIGN_NEGATIVE_ZERO, (BigDecimal.new("-0") / 1).sign)
+ assert_equal(2, BigDecimal.new("2") / 1)
+ assert_equal(-2, BigDecimal.new("2") / -1)
+ end
+
+ def test_mod
+ x = BigDecimal.new((2**100).to_s)
+ assert_equal(1, x % 3)
+ assert_equal(2, (-x) % 3)
+ assert_equal(-2, x % -3)
+ assert_equal(-1, (-x) % -3)
+ end
+
+ def test_remainder
+ x = BigDecimal.new((2**100).to_s)
+ assert_equal(1, x.remainder(3))
+ assert_equal(-1, (-x).remainder(3))
+ assert_equal(1, x.remainder(-3))
+ assert_equal(-1, (-x).remainder(-3))
+ end
+
+ def test_divmod
+ x = BigDecimal.new((2**100).to_s)
+ assert_equal([(x / 3).floor, 1], x.divmod(3))
+ assert_equal([(-x / 3).floor, 2], (-x).divmod(3))
+
+ assert_equal([0, 0], BigDecimal.new("0").divmod(2))
+
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
+ a, b = BigDecimal.new("0").divmod(0)
+ assert_equal(true, a.nan?)
+ assert_equal(true, b.nan?)
+ end
+
+ def test_add_bigdecimal
+ x = BigDecimal.new((2**100).to_s)
+ assert_equal(3000000000000000000000000000000, x.add(x, 1))
+ assert_equal(2500000000000000000000000000000, x.add(x, 2))
+ assert_equal(2540000000000000000000000000000, x.add(x, 3))
+ end
+
+ def test_sub_bigdecimal
+ x = BigDecimal.new((2**100).to_s)
+ assert_equal(1000000000000000000000000000000, x.sub(1, 1))
+ assert_equal(1300000000000000000000000000000, x.sub(1, 2))
+ assert_equal(1270000000000000000000000000000, x.sub(1, 3))
+ end
+
+ def test_mult_bigdecimal
+ x = BigDecimal.new((2**100).to_s)
+ assert_equal(4000000000000000000000000000000, x.mult(3, 1))
+ assert_equal(3800000000000000000000000000000, x.mult(3, 2))
+ assert_equal(3800000000000000000000000000000, x.mult(3, 3))
+ end
+
+ def test_div_bigdecimal
+ x = BigDecimal.new((2**100).to_s)
+ assert_equal(422550200076076467165567735125, x.div(3))
+ assert_equal(400000000000000000000000000000, x.div(3, 1))
+ assert_equal(420000000000000000000000000000, x.div(3, 2))
+ assert_equal(423000000000000000000000000000, x.div(3, 3))
+ end
+
+ def test_abs_bigdecimal
+ x = BigDecimal.new((2**100).to_s)
+ assert_equal(1267650600228229401496703205376, x.abs)
+ x = BigDecimal.new("-" + (2**100).to_s)
+ assert_equal(1267650600228229401496703205376, x.abs)
+ x = BigDecimal.new("0")
+ assert_equal(0, x.abs)
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
+ x = BigDecimal.new("NaN")
+ assert_equal(true, x.abs.nan?)
+ end
+
+ def test_sqrt_bigdecimal
+ x = BigDecimal.new("0.09")
+ assert_in_delta(0.3, x.sqrt(1), 0.001)
+ x = BigDecimal.new((2**100).to_s)
+ y = BigDecimal("1125899906842624")
+ e = y.exponent
+ assert_equal(true, (x.sqrt(100) - y).abs < BigDecimal("1E#{e-100}"))
+ assert_equal(true, (x.sqrt(200) - y).abs < BigDecimal("1E#{e-200}"))
+ assert_equal(true, (x.sqrt(300) - y).abs < BigDecimal("1E#{e-300}"))
+ x = BigDecimal.new("-" + (2**100).to_s)
+ assert_raise(FloatDomainError) { x.sqrt(1) }
+ x = BigDecimal.new((2**200).to_s)
+ assert_equal(2**100, x.sqrt(1))
+
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
+ assert_raise(FloatDomainError) { BigDecimal.new("NaN").sqrt(1) }
+
+ assert_equal(0, BigDecimal.new("0").sqrt(1))
+ assert_equal(1, BigDecimal.new("1").sqrt(1))
+ end
+
+ def test_fix
+ x = BigDecimal.new("1.1")
+ assert_equal(1, x.fix)
+ end
+
+ def test_frac
+ x = BigDecimal.new("1.1")
+ assert_equal(0.1, x.frac)
+ assert_equal(0.1, BigDecimal.new("0.1").frac)
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
+ assert_equal(true, BigDecimal.new("NaN").frac.nan?)
+ end
+
+ def test_round
+ assert_equal(3, BigDecimal.new("3.14159").round)
+ assert_equal(9, BigDecimal.new("8.7").round)
+ assert_equal(3.142, BigDecimal.new("3.14159").round(3))
+ assert_equal(13300.0, BigDecimal.new("13345.234").round(-2))
+
+ x = BigDecimal.new("111.111")
+ assert_equal(111 , x.round)
+ assert_equal(111.1 , x.round(1))
+ assert_equal(111.11 , x.round(2))
+ assert_equal(111.111, x.round(3))
+ assert_equal(111.111, x.round(4))
+ assert_equal(110 , x.round(-1))
+ assert_equal(100 , x.round(-2))
+ assert_equal( 0 , x.round(-3))
+ assert_equal( 0 , x.round(-4))
+
+ x = BigDecimal.new("2.5")
+ assert_equal(3, x.round(0, BigDecimal::ROUND_UP))
+ assert_equal(2, x.round(0, BigDecimal::ROUND_DOWN))
+ assert_equal(3, x.round(0, BigDecimal::ROUND_HALF_UP))
+ assert_equal(2, x.round(0, BigDecimal::ROUND_HALF_DOWN))
+ assert_equal(2, x.round(0, BigDecimal::ROUND_HALF_EVEN))
+ assert_equal(3, x.round(0, BigDecimal::ROUND_CEILING))
+ assert_equal(2, x.round(0, BigDecimal::ROUND_FLOOR))
+ assert_raise(TypeError) { x.round(0, 256) }
+ end
+
+ def test_truncate
+ assert_equal(3, BigDecimal.new("3.14159").truncate)
+ assert_equal(8, BigDecimal.new("8.7").truncate)
+ assert_equal(3.141, BigDecimal.new("3.14159").truncate(3))
+ assert_equal(13300.0, BigDecimal.new("13345.234").truncate(-2))
+ end
+
+ def test_floor
+ assert_equal(3, BigDecimal.new("3.14159").floor)
+ assert_equal(-10, BigDecimal.new("-9.1").floor)
+ assert_equal(3.141, BigDecimal.new("3.14159").floor(3))
+ assert_equal(13300.0, BigDecimal.new("13345.234").floor(-2))
+ end
+
+ def test_ceil
+ assert_equal(4, BigDecimal.new("3.14159").ceil)
+ assert_equal(-9, BigDecimal.new("-9.1").ceil)
+ assert_equal(3.142, BigDecimal.new("3.14159").ceil(3))
+ assert_equal(13400.0, BigDecimal.new("13345.234").ceil(-2))
+ end
+
+ def test_to_s
+ assert_equal('-123.45678 90123 45678 9', BigDecimal.new('-123.45678901234567890').to_s('5F'))
+ assert_equal('+123.45678901 23456789', BigDecimal.new('123.45678901234567890').to_s('+8F'))
+ assert_equal(' 123.4567890123456789', BigDecimal.new('123.45678901234567890').to_s(' F'))
+ assert_equal('0.1234567890123456789E3', BigDecimal.new('123.45678901234567890').to_s)
+ assert_equal('0.12345 67890 12345 6789E3', BigDecimal.new('123.45678901234567890').to_s(5))
+ end
+
+ def test_split
+ x = BigDecimal.new('-123.45678901234567890')
+ assert_equal([-1, "1234567890123456789", 10, 3], x.split)
+ assert_equal([1, "0", 10, 0], BigDecimal.new("0").split)
+ assert_equal([-1, "0", 10, 0], BigDecimal.new("-0").split)
+
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
+ assert_equal([0, "NaN", 10, 0], BigDecimal.new("NaN").split)
+ assert_equal([1, "Infinity", 10, 0], BigDecimal.new("Infinity").split)
+ assert_equal([-1, "Infinity", 10, 0], BigDecimal.new("-Infinity").split)
+ end
+
+ def test_exponent
+ x = BigDecimal.new('-123.45678901234567890')
+ assert_equal(3, x.exponent)
+ end
+
+ def test_inspect
+ x = BigDecimal.new("1234.5678")
+ prec, maxprec = x.precs
+ assert_match(/^#<BigDecimal:[0-9a-f]+,'0.12345678E4',#{prec}\(#{maxprec}\)>$/, x.inspect)
+ end
+
+ def test_power
+ x = BigDecimal.new("3")
+ assert_equal(81, x ** 4)
+ assert_equal(1.0/81, x ** -4)
+ assert_equal(1, x ** 0)
+ assert_raise(TypeError) { x ** x }
+ assert_equal(0, BigDecimal.new("0") ** 4)
+ assert_equal(1, BigDecimal.new("0") ** 0)
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+ assert_equal(BigDecimal.new("Infinity"), BigDecimal.new("0") ** -1)
+ assert_equal(BigDecimal.new("-Infinity"), BigDecimal.new("-0") ** -1)
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
+ assert_equal(true, (BigDecimal.new("NaN") ** 1).nan?)
+
+ assert_equal(BigDecimal::SIGN_POSITIVE_INFINITE, (BigDecimal.new("Infinity") ** 2).sign)
+ assert_equal(BigDecimal::SIGN_POSITIVE_INFINITE, (BigDecimal.new("Infinity") ** 1).sign)
+ assert_equal(1, BigDecimal.new("Infinity") ** 0)
+ assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, (BigDecimal.new("Infinity") ** -1).sign)
+ assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, (BigDecimal.new("Infinity") ** -2).sign)
+
+ assert_equal(BigDecimal::SIGN_POSITIVE_INFINITE, (BigDecimal.new("-Infinity") ** 2).sign)
+ assert_equal(BigDecimal::SIGN_NEGATIVE_INFINITE, (BigDecimal.new("-Infinity") ** 1).sign)
+ assert_equal(1, BigDecimal.new("-Infinity") ** 0)
+ assert_equal(BigDecimal::SIGN_NEGATIVE_ZERO, (BigDecimal.new("-Infinity") ** -1).sign)
+ assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, (BigDecimal.new("-Infinity") ** -2).sign)
+ end
+
+ def test_limit
+ BigDecimal.limit(1)
+ x = BigDecimal.new("3")
+ assert_equal(90, x ** 4) # OK? must it be 80?
+ # 3 * 3 * 3 * 3 = 10 * 3 * 3 = 30 * 3 = 90 ???
+ assert_raise(ArgumentError) { BigDecimal.limit(-1) }
+ end
+
+ def test_sign
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
+
+ assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, BigDecimal.new("0").sign)
+ assert_equal(BigDecimal::SIGN_NEGATIVE_ZERO, BigDecimal.new("-0").sign)
+ assert_equal(BigDecimal::SIGN_POSITIVE_FINITE, BigDecimal.new("1").sign)
+ assert_equal(BigDecimal::SIGN_NEGATIVE_FINITE, BigDecimal.new("-1").sign)
+ assert_equal(BigDecimal::SIGN_POSITIVE_INFINITE, (BigDecimal.new("1") / 0).sign)
+ assert_equal(BigDecimal::SIGN_NEGATIVE_INFINITE, (BigDecimal.new("-1") / 0).sign)
+ assert_equal(BigDecimal::SIGN_NaN, (BigDecimal.new("0") / 0).sign)
+ end
+
+ def test_inf
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
+ inf = BigDecimal.new("Infinity")
+
+ assert_equal(inf, inf + inf)
+ assert_equal(true, (inf + (-inf)).nan?)
+ assert_equal(true, (inf - inf).nan?)
+ assert_equal(inf, inf - (-inf))
+ assert_equal(inf, inf * inf)
+ assert_equal(true, (inf / inf).nan?)
+
+ assert_equal(inf, inf + 1)
+ assert_equal(inf, inf - 1)
+ assert_equal(inf, inf * 1)
+ assert_equal(true, (inf * 0).nan?)
+ assert_equal(inf, inf / 1)
+
+ assert_equal(inf, 1 + inf)
+ assert_equal(-inf, 1 - inf)
+ assert_equal(inf, 1 * inf)
+ assert_equal(-inf, -1 * inf)
+ assert_equal(true, (0 * inf).nan?)
+ assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, (1 / inf).sign)
+ assert_equal(BigDecimal::SIGN_NEGATIVE_ZERO, (-1 / inf).sign)
+ end
+
+ def test_to_special_string
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
+ nan = BigDecimal.new("NaN")
+ assert_equal("NaN", nan.to_s)
+ inf = BigDecimal.new("Infinity")
+ assert_equal("Infinity", inf.to_s)
+ assert_equal(" Infinity", inf.to_s(" "))
+ assert_equal("+Infinity", inf.to_s("+"))
+ assert_equal("-Infinity", (-inf).to_s)
+ pzero = BigDecimal.new("0")
+ assert_equal("0.0", pzero.to_s)
+ assert_equal(" 0.0", pzero.to_s(" "))
+ assert_equal("+0.0", pzero.to_s("+"))
+ assert_equal("-0.0", (-pzero).to_s)
+ end
+
+ def test_to_string
+ assert_equal("0.01", BigDecimal("0.01").to_s("F"))
+ s = "0." + "0" * 100 + "1"
+ assert_equal(s, BigDecimal(s).to_s("F"))
+ s = "1" + "0" * 100 + ".0"
+ assert_equal(s, BigDecimal(s).to_s("F"))
+ end
+
+ def test_ctov
+ assert_equal(0.1, BigDecimal.new("1E-1"))
+ assert_equal(10, BigDecimal.new("1E+1"))
+ assert_equal(1, BigDecimal.new("+1"))
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+
+ assert_equal(BigDecimal::SIGN_POSITIVE_INFINITE, BigDecimal.new("1E1" + "0" * 10000).sign)
+ assert_equal(BigDecimal::SIGN_NEGATIVE_INFINITE, BigDecimal.new("-1E1" + "0" * 10000).sign)
+ assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, BigDecimal.new("1E-1" + "0" * 10000).sign)
+ assert_equal(BigDecimal::SIGN_NEGATIVE_ZERO, BigDecimal.new("-1E-1" + "0" * 10000).sign)
+ end
+end
diff --git a/test/cgi/test_cgi_cookie.rb b/test/cgi/test_cgi_cookie.rb
index f9950d1fb1..f9950d1fb1 100755..100644
--- a/test/cgi/test_cgi_cookie.rb
+++ b/test/cgi/test_cgi_cookie.rb
diff --git a/test/cgi/test_cgi_core.rb b/test/cgi/test_cgi_core.rb
index 36a3c3003c..97fda9d87c 100755..100644
--- a/test/cgi/test_cgi_core.rb
+++ b/test/cgi/test_cgi_core.rb
@@ -21,6 +21,19 @@ class CGICoreTest < Test::Unit::TestCase
$stdout = STDOUT
end
+ def test_cgi_parse_illegal_query
+ @environ = {
+ 'REQUEST_METHOD' => 'GET',
+ 'QUERY_STRING' => 'a=111&&b=222&c&d=',
+ 'HTTP_COOKIE' => '_session_id=12345; name1=val1&val2;',
+ 'SERVER_SOFTWARE' => 'Apache 2.2.0',
+ 'SERVER_PROTOCOL' => 'HTTP/1.1',
+ }
+ ENV.update(@environ)
+ cgi = CGI.new
+ assert_equal(["a","b","d"],cgi.keys.sort) if RUBY_VERSION>="1.9"
+ assert_equal("",cgi["d"])
+ end
def test_cgi_core_params_GET
@environ = {
@@ -99,6 +112,44 @@ class CGICoreTest < Test::Unit::TestCase
assert_equal([], cgi.params['*notfound*'])
end
+ def test_cgi_core_params_encoding_check
+ query_str = 'str=%BE%BE%B9%BE'
+ @environ = {
+ 'REQUEST_METHOD' => 'POST',
+ 'CONTENT_LENGTH' => query_str.length.to_s,
+ 'SERVER_SOFTWARE' => 'Apache 2.2.0',
+ 'SERVER_PROTOCOL' => 'HTTP/1.1',
+ }
+ ENV.update(@environ)
+ $stdin = StringIO.new
+ $stdin << query_str
+ $stdin.rewind
+ if RUBY_VERSION>="1.9.0"
+ hash={}
+ cgi = CGI.new(:accept_charset=>"UTF-8"){|key,val|hash[key]=val}
+ ## cgi[]
+ assert_equal("\xBE\xBE\xB9\xBE".force_encoding("UTF-8"), cgi['str'])
+ ## cgi.params
+ assert_equal(["\xBE\xBE\xB9\xBE".force_encoding("UTF-8")], cgi.params['str'])
+ ## accept-charset error
+ assert_equal({"str"=>"\xBE\xBE\xB9\xBE".force_encoding("UTF-8")},hash)
+
+ $stdin.rewind
+ assert_raise(CGI::InvalidEncoding) do
+ cgi = CGI.new(:accept_charset=>"UTF-8")
+ end
+
+ $stdin.rewind
+ cgi = CGI.new(:accept_charset=>"EUC-JP")
+ ## cgi[]
+ assert_equal("\xBE\xBE\xB9\xBE".force_encoding("EUC-JP"), cgi['str'])
+ ## cgi.params
+ assert_equal(["\xBE\xBE\xB9\xBE".force_encoding("EUC-JP")], cgi.params['str'])
+ else
+ assert(true)
+ end
+ end
+
def test_cgi_core_cookie
@environ = {
@@ -110,7 +161,7 @@ class CGICoreTest < Test::Unit::TestCase
}
ENV.update(@environ)
cgi = CGI.new
- assert_not_nil(cgi.cookies)
+ assert_not_equal(nil,cgi.cookies)
[ ['_session_id', ['12345'], ],
['name1', ['val1', 'val2'], ],
].each do |key, expected|
diff --git a/test/cgi/test_cgi_header.rb b/test/cgi/test_cgi_header.rb
index c92d01754a..58f82ba3bc 100755..100644
--- a/test/cgi/test_cgi_header.rb
+++ b/test/cgi/test_cgi_header.rb
@@ -71,7 +71,7 @@ class CGIHeaderTest < Test::Unit::TestCase
def test_cgi_header_argerr
cgi = CGI.new
#expected = NoMethodError # must be ArgumentError
- if defined?(CGI::RELEASE)
+ if RUBY_VERSION>="1.9.0"
expected = ArgumentError # for CGIAlt
else
expected = NoMethodError # for Ruby1.8
diff --git a/test/cgi/test_cgi_modruby.rb b/test/cgi/test_cgi_modruby.rb
index 4eb02fac56..4eb02fac56 100755..100644
--- a/test/cgi/test_cgi_modruby.rb
+++ b/test/cgi/test_cgi_modruby.rb
diff --git a/test/cgi/test_cgi_multipart.rb b/test/cgi/test_cgi_multipart.rb
index 18eb741d77..47a41f6488 100755..100644
--- a/test/cgi/test_cgi_multipart.rb
+++ b/test/cgi/test_cgi_multipart.rb
@@ -32,11 +32,11 @@ class MultiPart
def initialize(boundary=nil)
@boundary = boundary || create_boundary()
@buf = ''
+ @buf.force_encoding("ascii-8bit") if RUBY_VERSION>="1.9"
end
attr_reader :boundary
def append(name, value, filename=nil, content_type=nil)
- value.force_encoding("ASCII-8BIT") if RUBY_VERSION>="1.9"
content_type = detect_content_type(filename) if filename && content_type.nil?
s = filename ? "; filename=\"#{filename}\"" : ''
buf = @buf
@@ -44,7 +44,11 @@ class MultiPart
buf << "Content-Disposition: form-data: name=\"#{name}\"#{s}\r\n"
buf << "Content-Type: #{content_type}\r\n" if content_type
buf << "\r\n"
- buf << value
+ if RUBY_VERSION>="1.9"
+ buf << value.dup.force_encoding("ASCII-8BIT")
+ else
+ buf << value
+ end
buf << "\r\n"
return self
end
@@ -131,7 +135,11 @@ class CGIMultipartTest < Test::Unit::TestCase
ENV['CONTENT_LENGTH'] = input.length.to_s
ENV['REQUEST_METHOD'] = 'POST'
## set $stdin
- tmpfile = Tempfile.new(self.name)
+ tmpfile = if RUBY_VERSION >="1.9"
+ Tempfile.new(self.name, :binmode => true)
+ else
+ Tempfile.new(self.name)
+ end
tmpfile << input
tmpfile.rewind()
$stdin = tmpfile
@@ -142,17 +150,28 @@ class CGIMultipartTest < Test::Unit::TestCase
testname = $1
#$stderr.puts "*** debug: testname=#{testname.inspect}"
_prepare(@data)
- cgi = CGI.new
+ cgi = RUBY_VERSION>="1.9" ? CGI.new(:accept_charset=>"UTF-8") : CGI.new
expected_names = @data.collect{|hash| hash[:name] }.sort
assert_equal(expected_names, cgi.params.keys.sort)
threshold = 1024*10
@data.each do |hash|
name = hash[:name]
expected = hash[:value]
- expected_class = @expected_class || (hash[:value].length < threshold ? StringIO : Tempfile)
- assert_kind_of(expected_class, cgi[name]) if RUBY_VERSION<"1.9"
- assert_equal(expected, cgi[name].read()) if RUBY_VERSION<"1.9"
- assert_equal(hash[:filename] || '', cgi[name].original_filename) #if hash[:filename]
+ if RUBY_VERSION>="1.9"
+ if hash[:filename] #if file
+ expected_class = @expected_class || (hash[:value].length < threshold ? StringIO : Tempfile)
+ assert(cgi.files.keys.member?(hash[:name]))
+ else
+ expected_class = String
+ assert_equal(expected, cgi[name])
+ assert_equal(false,cgi.files.keys.member?(hash[:name]))
+ end
+ else
+ expected_class = @expected_class || (hash[:value].length < threshold ? StringIO : Tempfile)
+ end
+ assert_kind_of(expected_class, cgi[name])
+ assert_equal(expected, cgi[name].read())
+ assert_equal(hash[:filename] || '', cgi[name].original_filename) #if hash[:filename]
assert_equal(hash[:content_type] || '', cgi[name].content_type) #if hash[:content_type]
end
end
@@ -160,7 +179,12 @@ class CGIMultipartTest < Test::Unit::TestCase
def _read(basename)
filename = File.join(File.dirname(__FILE__), 'testdata', basename)
- s = File.open(filename, 'rb') {|f| f.read() }
+ if RUBY_VERSION>="1.9"
+ s = File.open(filename, 'r:ascii-8bit') {|f| f.read() }
+ else
+ s = File.open(filename, 'rb') {|f| f.read() }
+ end
+
return s
end
@@ -169,12 +193,13 @@ class CGIMultipartTest < Test::Unit::TestCase
@boundary = '----WebKitFormBoundaryAAfvAII+YL9102cX'
@data = [
{:name=>'hidden1', :value=>'foobar'},
- {:name=>'text1', :value=>"\202\240\202\242\202\244\202\246\202\250"},
+ {:name=>'text1', :value=>"\xE3\x81\x82\xE3\x81\x84\xE3\x81\x86\xE3\x81\x88\xE3\x81\x8A"},
{:name=>'file1', :value=>_read('file1.html'),
:filename=>'file1.html', :content_type=>'text/html'},
{:name=>'image1', :value=>_read('small.png'),
:filename=>'small.png', :content_type=>'image/png'}, # small image
]
+ @data[1][:value].force_encoding("UTF-8") if RUBY_VERSION>="1.9"
@expected_class = StringIO
_test_multipart()
end
@@ -184,12 +209,13 @@ class CGIMultipartTest < Test::Unit::TestCase
@boundary = '----WebKitFormBoundaryAAfvAII+YL9102cX'
@data = [
{:name=>'hidden1', :value=>'foobar'},
- {:name=>'text1', :value=>"\202\240\202\242\202\244\202\246\202\250"},
+ {:name=>'text1', :value=>"\xE3\x81\x82\xE3\x81\x84\xE3\x81\x86\xE3\x81\x88\xE3\x81\x8A"},
{:name=>'file1', :value=>_read('file1.html'),
:filename=>'file1.html', :content_type=>'text/html'},
{:name=>'image1', :value=>_read('large.png'),
:filename=>'large.png', :content_type=>'image/png'}, # large image
]
+ @data[1][:value].force_encoding("UTF-8") if RUBY_VERSION>="1.9"
@expected_class = Tempfile
_test_multipart()
end
@@ -254,7 +280,7 @@ class CGIMultipartTest < Test::Unit::TestCase
input2
end
ex = assert_raise(EOFError) do
- cgi = CGI.new
+ cgi = RUBY_VERSION>="1.9" ? CGI.new(:accept_charset=>"UTF-8") : CGI.new
end
assert_equal("bad boundary end of body part", ex.message)
#
@@ -265,7 +291,7 @@ class CGIMultipartTest < Test::Unit::TestCase
input2
end
ex = assert_raise(EOFError) do
- cgi = CGI.new
+ cgi = RUBY_VERSION>="1.9" ? CGI.new(:accept_charset=>"UTF-8") : CGI.new
end
assert_equal("bad content body", ex.message)
end
@@ -275,14 +301,15 @@ class CGIMultipartTest < Test::Unit::TestCase
@boundary = '(.|\n)*'
@data = [
{:name=>'hidden1', :value=>'foobar'},
- {:name=>'text1', :value=>"\202\240\202\242\202\244\202\246\202\250"},
+ {:name=>'text1', :value=>"\xE3\x81\x82\xE3\x81\x84\xE3\x81\x86\xE3\x81\x88\xE3\x81\x8A"},
{:name=>'file1', :value=>_read('file1.html'),
:filename=>'file1.html', :content_type=>'text/html'},
{:name=>'image1', :value=>_read('small.png'),
:filename=>'small.png', :content_type=>'image/png'}, # small image
]
+ @data[1][:value].force_encoding("UTF-8") if RUBY_VERSION>="1.9"
_prepare(@data)
- cgi = CGI.new
+ cgi = RUBY_VERSION>="1.9" ? CGI.new(:accept_charset=>"UTF-8") : CGI.new
assert_equal('file1.html', cgi['file1'].original_filename)
end
diff --git a/test/cgi/test_cgi_session.rb b/test/cgi/test_cgi_session.rb
new file mode 100644
index 0000000000..c041b9cf59
--- /dev/null
+++ b/test/cgi/test_cgi_session.rb
@@ -0,0 +1,98 @@
+require 'test/unit'
+require 'cgi'
+require 'cgi/session'
+require 'cgi/session/pstore'
+require 'stringio'
+
+class CGISessionTest < Test::Unit::TestCase
+
+
+ def setup
+ FileUtils.rm(Dir::glob(File.dirname(__FILE__)+"/session_dir/*"))
+ end
+
+
+ def teardown
+ @environ.each do |key, val| ENV.delete(key) end
+ $stdout = STDOUT
+# FileUtils.rm(Dir::glob(File.dirname(__FILE__)+"/session_dir/*"))
+ end
+
+ def test_cgi_session_filestore
+ @environ = {
+ 'REQUEST_METHOD' => 'GET',
+ # 'QUERY_STRING' => 'id=123&id=456&id=&str=%40h+%3D%7E+%2F%5E%24%2F',
+ # 'HTTP_COOKIE' => '_session_id=12345; name1=val1&val2;',
+ 'SERVER_SOFTWARE' => 'Apache 2.2.0',
+ 'SERVER_PROTOCOL' => 'HTTP/1.1',
+ }
+ value1="value1"
+ value2="\x8F\xBC\x8D]"
+ value2.force_encoding("SJIS") if RUBY_VERSION>="1.9"
+ ENV.update(@environ)
+ cgi = CGI.new
+ session = CGI::Session.new(cgi,"tmpdir"=>File.dirname(__FILE__)+"/session_dir")
+ session["key1"]=value1
+ session["key2"]=value2
+ assert_equal(value1,session["key1"])
+ assert_equal(value2,session["key2"])
+ session.close
+ $stdout = StringIO.new
+ cgi.out{""}
+
+ @environ = {
+ 'REQUEST_METHOD' => 'GET',
+ # 'HTTP_COOKIE' => "_session_id=#{session_id}",
+ 'QUERY_STRING' => "_session_id=#{session.session_id}",
+ 'SERVER_SOFTWARE' => 'Apache 2.2.0',
+ 'SERVER_PROTOCOL' => 'HTTP/1.1',
+ }
+ ENV.update(@environ)
+ cgi = CGI.new
+ session = CGI::Session.new(cgi,"tmpdir"=>File.dirname(__FILE__)+"/session_dir")
+ $stdout = StringIO.new
+ assert_equal(value1,session["key1"])
+ assert_equal(value2,session["key2"])
+ session.close
+
+ end
+ def test_cgi_session_pstore
+ @environ = {
+ 'REQUEST_METHOD' => 'GET',
+ # 'QUERY_STRING' => 'id=123&id=456&id=&str=%40h+%3D%7E+%2F%5E%24%2F',
+ # 'HTTP_COOKIE' => '_session_id=12345; name1=val1&val2;',
+ 'SERVER_SOFTWARE' => 'Apache 2.2.0',
+ 'SERVER_PROTOCOL' => 'HTTP/1.1',
+ }
+ value1="value1"
+ value2="\x8F\xBC\x8D]"
+ value2.force_encoding("SJIS") if RUBY_VERSION>="1.9"
+ ENV.update(@environ)
+ cgi = CGI.new
+ session = CGI::Session.new(cgi,"tmpdir"=>File.dirname(__FILE__)+"/session_dir","database_manager"=>CGI::Session::PStore)
+ session["key1"]=value1
+ session["key2"]=value2
+ assert_equal(value1,session["key1"])
+ assert_equal(value2,session["key2"])
+ session.close
+ $stdout = StringIO.new
+ cgi.out{""}
+
+ @environ = {
+ 'REQUEST_METHOD' => 'GET',
+ # 'HTTP_COOKIE' => "_session_id=#{session_id}",
+ 'QUERY_STRING' => "_session_id=#{session.session_id}",
+ 'SERVER_SOFTWARE' => 'Apache 2.2.0',
+ 'SERVER_PROTOCOL' => 'HTTP/1.1',
+ }
+ ENV.update(@environ)
+ cgi = CGI.new
+ session = CGI::Session.new(cgi,"tmpdir"=>File.dirname(__FILE__)+"/session_dir","database_manager"=>CGI::Session::PStore)
+ $stdout = StringIO.new
+ assert_equal(value1,session["key1"])
+ assert_equal(value2,session["key2"])
+ session.close
+
+
+ end
+end
diff --git a/test/cgi/test_cgi_tag_helper.rb b/test/cgi/test_cgi_tag_helper.rb
index 3ff2f54d42..6e726b93a3 100755..100644
--- a/test/cgi/test_cgi_tag_helper.rb
+++ b/test/cgi/test_cgi_tag_helper.rb
@@ -305,6 +305,26 @@ class CGITagHelperTest < Test::Unit::TestCase
assert_equal('<TH>foo</TH>',cgi.th{'foo'})
assert_equal('<TD>',cgi.td)
assert_equal('<TD>foo</TD>',cgi.td{'foo'})
+ str=cgi.checkbox_group("foo",["aa","bb"],["cc","dd"])
+ assert_match(/^<INPUT .*VALUE="aa".*>bb<INPUT .*VALUE="cc".*>dd$/,str)
+ assert_match(/^<INPUT .*TYPE="checkbox".*>bb<INPUT .*TYPE="checkbox".*>dd$/,str)
+ assert_match(/^<INPUT .*NAME="foo".*>bb<INPUT .*NAME="foo".*>dd$/,str)
+ str=cgi.radio_group("foo",["aa","bb"],["cc","dd"])
+ assert_match(/^<INPUT .*VALUE="aa".*>bb<INPUT .*VALUE="cc".*>dd$/,str)
+ assert_match(/^<INPUT .*TYPE="radio".*>bb<INPUT .*TYPE="radio".*>dd$/,str)
+ assert_match(/^<INPUT .*NAME="foo".*>bb<INPUT .*NAME="foo".*>dd$/,str)
+ str=cgi.checkbox_group("foo",["aa","bb"],["cc","dd",true])
+ assert_match(/^<INPUT .*VALUE="aa".*>bb<INPUT .*VALUE="cc".*>dd$/,str)
+ assert_match(/^<INPUT .*TYPE="checkbox".*>bb<INPUT .*TYPE="checkbox".*>dd$/,str)
+ assert_match(/^<INPUT .*NAME="foo".*>bb<INPUT .*NAME="foo".*>dd$/,str)
+ assert_match(/^<INPUT .*>bb<INPUT .*CHECKED.*>dd$/,str)
+ assert_match(/<INPUT .*TYPE="text".*>/,cgi.text_field(:name=>"name",:value=>"value")) if RUBY_VERSION>="1.9"
+ if RUBY_VERSION>="1.9"
+ str=cgi.radio_group("foo",["aa","bb"],["cc","dd",false])
+ assert_match(/^<INPUT .*VALUE="aa".*>bb<INPUT .*VALUE="cc".*>dd$/,str)
+ assert_match(/^<INPUT .*TYPE="radio".*>bb<INPUT .*TYPE="radio".*>dd$/,str)
+ assert_match(/^<INPUT .*NAME="foo".*>bb<INPUT .*NAME="foo".*>dd$/,str)
+ end
end
=begin
diff --git a/test/cgi/testdata/file1.html b/test/cgi/testdata/file1.html
index 2ceaf6bc39..2ceaf6bc39 100755..100644
--- a/test/cgi/testdata/file1.html
+++ b/test/cgi/testdata/file1.html
diff --git a/test/cgi/testdata/large.png b/test/cgi/testdata/large.png
index d716396fa3..d716396fa3 100755..100644
--- a/test/cgi/testdata/large.png
+++ b/test/cgi/testdata/large.png
Binary files differ
diff --git a/test/cgi/testdata/small.png b/test/cgi/testdata/small.png
index 753d58e3cb..753d58e3cb 100755..100644
--- a/test/cgi/testdata/small.png
+++ b/test/cgi/testdata/small.png
Binary files differ
diff --git a/test/csv/tc_csv_parsing.rb b/test/csv/test_csv_parsing.rb
index 965af929f3..e391687537 100644
--- a/test/csv/tc_csv_parsing.rb
+++ b/test/csv/test_csv_parsing.rb
@@ -1,4 +1,5 @@
-#!/usr/local/bin/ruby -w
+#!/usr/bin/env ruby -w
+# encoding: UTF-8
# tc_csv_parsing.rb
#
@@ -7,6 +8,7 @@
# under the terms of Ruby's license.
require "test/unit"
+require "timeout"
require "csv"
@@ -17,6 +19,8 @@ require "csv"
# separator <tt>$/</tt>.
#
class TestCSVParsing < Test::Unit::TestCase
+ BIG_DATA = "123456789\n" * 1024
+
def test_mastering_regex_example
ex = %Q{Ten Thousand,10000, 2710 ,,"10,000","It's ""10 Grand"", baby",10K}
assert_equal( [ "Ten Thousand", "10000", " 2710 ", nil, "10,000",
@@ -113,7 +117,7 @@ class TestCSVParsing < Test::Unit::TestCase
def test_malformed_csv
assert_raise(CSV::MalformedCSVError) do
- CSV.parse_line("1,2\r,3", :row_sep => "\n")
+ CSV.parse_line("1,2\r,3", row_sep: "\n")
end
bad_data = <<-END_DATA.gsub(/^ +/, "")
@@ -137,7 +141,7 @@ class TestCSVParsing < Test::Unit::TestCase
assert_equal( "Unquoted fields do not allow \\r or \\n (line 4).",
$!.message )
end
-
+
assert_raise(CSV::MalformedCSVError) { CSV.parse_line('1,2,"3...') }
bad_data = <<-END_DATA.gsub(/^ +/, "")
@@ -158,7 +162,31 @@ class TestCSVParsing < Test::Unit::TestCase
assert_send([csv.lineno, :<, 4])
end
rescue CSV::MalformedCSVError
- assert_equal("Unclosed quoted field on line 4.", $!.message)
+ assert_equal("Illegal quoting on line 4.", $!.message)
+ end
+ end
+
+ def test_the_parse_fails_fast_when_it_can_for_unquoted_fields
+ assert_parse_errors_out('valid,fields,bad start"' + BIG_DATA)
+ end
+
+ def test_the_parse_fails_fast_when_it_can_for_unescaped_quotes
+ assert_parse_errors_out('valid,fields,"bad start"unescaped' + BIG_DATA)
+ end
+
+ def test_field_size_limit_controls_lookahead
+ assert_parse_errors_out( 'valid,fields,"' + BIG_DATA + '"',
+ field_size_limit: 2048 )
+ end
+
+ private
+
+ def assert_parse_errors_out(*args)
+ assert_raise(CSV::MalformedCSVError) do
+ Timeout.timeout(0.2) do
+ CSV.parse(*args)
+ fail("Parse didn't error out")
+ end
end
end
end
diff --git a/test/csv/tc_csv_writing.rb b/test/csv/test_csv_writing.rb
index 4677284306..98e41fe9c4 100644
--- a/test/csv/tc_csv_writing.rb
+++ b/test/csv/test_csv_writing.rb
@@ -1,4 +1,5 @@
-#!/usr/local/bin/ruby -w
+#!/usr/bin/env ruby -w
+# encoding: UTF-8
# tc_csv_writing.rb
#
@@ -78,19 +79,19 @@ class TestCSVWriting < Test::Unit::TestCase
def test_col_sep
assert_equal( "a;b;;c\n", CSV.generate_line( ["a", "b", nil, "c"],
- :col_sep => ";" ) )
+ col_sep: ";" ) )
assert_equal( "a\tb\t\tc\n", CSV.generate_line( ["a", "b", nil, "c"],
- :col_sep => "\t" ) )
+ col_sep: "\t" ) )
end
def test_row_sep
assert_equal( "a,b,,c\r\n", CSV.generate_line( ["a", "b", nil, "c"],
- :row_sep => "\r\n" ) )
+ row_sep: "\r\n" ) )
end
def test_force_quotes
assert_equal( %Q{"1","b","","already ""quoted"""\n},
CSV.generate_line( [1, "b", nil, %Q{already "quoted"}],
- :force_quotes => true ) )
+ force_quotes: true ) )
end
end
diff --git a/test/csv/tc_data_converters.rb b/test/csv/test_data_converters.rb
index 24c6b6b76f..781450dc9e 100644
--- a/test/csv/tc_data_converters.rb
+++ b/test/csv/test_data_converters.rb
@@ -1,4 +1,5 @@
-#!/usr/local/bin/ruby -w
+#!/usr/bin/env ruby -w
+# encoding: UTF-8
# tc_data_converters.rb
#
@@ -158,7 +159,7 @@ class TestDataConverters < Test::Unit::TestCase
end
def test_convert_with_custom_code_using_field_info_header
- @parser = CSV.new(@data, :headers => %w{one two three four five})
+ @parser = CSV.new(@data, headers: %w{one two three four five})
# define custom converter that uses field header information...
assert_nothing_raised(Exception) do
@@ -174,13 +175,13 @@ class TestDataConverters < Test::Unit::TestCase
def test_shortcut_interface
assert_equal( ["Numbers", ":integer", 1, ":float", 3.015],
- CSV.parse_line(@data, :converters => :numeric) )
+ CSV.parse_line(@data, converters: :numeric) )
assert_equal( ["Numbers", ":integer", 1, ":float", 3.015],
- CSV.parse_line(@data, :converters => [:integer, :float]) )
+ CSV.parse_line(@data, converters: [:integer, :float]) )
assert_equal( ["Numbers", :integer, 1, :float, 3.015],
- CSV.parse_line(@data, :converters => [:numeric, @custom]) )
+ CSV.parse_line(@data, converters: [:numeric, @custom]) )
end
def test_unconverted_fields
@@ -191,8 +192,8 @@ class TestDataConverters < Test::Unit::TestCase
row = nil
assert_nothing_raised(Exception) do
row = CSV.parse_line( test,
- :converters => [:numeric, @custom],
- :unconverted_fields => true )
+ converters: [:numeric, @custom],
+ unconverted_fields: true )
end
assert_not_nil(row)
assert_equal(fields, row)
@@ -207,9 +208,9 @@ class TestDataConverters < Test::Unit::TestCase
row = nil
assert_nothing_raised(Exception) do
row = CSV.parse_line( data,
- :converters => :numeric,
- :unconverted_fields => true,
- :headers => :first_row )
+ converters: :numeric,
+ unconverted_fields: true,
+ headers: :first_row )
end
assert_not_nil(row)
assert_equal([["first", 1], ["second", 2], ["third", 3]], row.to_a)
@@ -218,10 +219,10 @@ class TestDataConverters < Test::Unit::TestCase
assert_nothing_raised(Exception) do
row = CSV.parse_line( data,
- :converters => :numeric,
- :unconverted_fields => true,
- :headers => :first_row,
- :return_headers => true )
+ converters: :numeric,
+ unconverted_fields: true,
+ headers: :first_row,
+ return_headers: true )
end
assert_not_nil(row)
assert_equal( [%w{first first}, %w{second second}, %w{third third}],
@@ -231,11 +232,11 @@ class TestDataConverters < Test::Unit::TestCase
assert_nothing_raised(Exception) do
row = CSV.parse_line( data,
- :converters => :numeric,
- :unconverted_fields => true,
- :headers => :first_row,
- :return_headers => true,
- :header_converters => :symbol )
+ converters: :numeric,
+ unconverted_fields: true,
+ headers: :first_row,
+ return_headers: true,
+ header_converters: :symbol )
end
assert_not_nil(row)
assert_equal( [[:first, "first"], [:second, "second"], [:third, "third"]],
@@ -245,11 +246,11 @@ class TestDataConverters < Test::Unit::TestCase
assert_nothing_raised(Exception) do
row = CSV.parse_line( data,
- :converters => :numeric,
- :unconverted_fields => true,
- :headers => %w{my new headers},
- :return_headers => true,
- :header_converters => :symbol )
+ converters: :numeric,
+ unconverted_fields: true,
+ headers: %w{my new headers},
+ return_headers: true,
+ header_converters: :symbol )
end
assert_not_nil(row)
assert_equal( [[:my, "my"], [:new, "new"], [:headers, "headers"]],
diff --git a/test/csv/test_encodings.rb b/test/csv/test_encodings.rb
new file mode 100644
index 0000000000..0a300af291
--- /dev/null
+++ b/test/csv/test_encodings.rb
@@ -0,0 +1,256 @@
+#!/usr/bin/env ruby -w
+# encoding: UTF-8
+
+# tc_encodings.rb
+#
+# Created by James Edward Gray II on 2008-09-13.
+# Copyright 2008 James Edward Gray II. You can redistribute or modify this code
+# under the terms of Ruby's license.
+
+require "test/unit"
+
+require "csv"
+
+class TestEncodings < Test::Unit::TestCase
+ def setup
+ @temp_csv_path = File.join(File.dirname(__FILE__), "temp.csv")
+ end
+
+ def teardown
+ File.unlink(@temp_csv_path) if File.exist? @temp_csv_path
+ end
+
+ ########################################
+ ### Hand Test Some Popular Encodings ###
+ ########################################
+
+ def test_parses_utf8_encoding
+ assert_parses( [ %w[ one two ],
+ %w[ 1 3 ],
+ %w[ 5 6 ] ], "UTF-8" )
+ end
+
+ def test_parses_latin1_encoding
+ assert_parses( [ %w[ one two R辿sum辿 ],
+ %w[ 1 R辿sum辿 3 ],
+ %w[ R辿sum辿 5 6 ] ], "ISO-8859-1" )
+ end
+
+ def test_parses_utf16be_encoding
+ assert_parses( [ %w[ one two ],
+ %w[ 1 3 ],
+ %w[ 5 6 ] ], "UTF-16BE" )
+ end
+
+ def test_parses_shift_jis_encoding
+ assert_parses( [ %w[ 筝 篋 筝 ],
+ %w[ 篋 ],
+ %w[ 筝 箙 ] ], "Shift_JIS" )
+ end
+
+ ###########################################################
+ ### Try Simple Reading for All Non-dummy Ruby Encodings ###
+ ###########################################################
+
+ def test_reading_with_most_encodings
+ each_encoding do |encoding|
+ begin
+ assert_parses( [ %w[ abc def ],
+ %w[ ghi jkl ] ], encoding )
+ rescue Encoding::ConverterNotFoundError
+ fail("Failed to support #{encoding.name}.")
+ end
+ end
+ end
+
+ def test_regular_expression_escaping
+ each_encoding do |encoding|
+ begin
+ assert_parses( [ %w[ abc def ],
+ %w[ ghi jkl ] ], encoding, col_sep: "|" )
+ rescue Encoding::ConverterNotFoundError
+ fail("Failed to properly escape #{encoding.name}.")
+ end
+ end
+ end
+
+ #######################################################################
+ ### Stress Test ASCII Compatible and Non-ASCII Compatible Encodings ###
+ #######################################################################
+
+ def test_auto_line_ending_detection
+ # arrange data to place a \r at the end of CSV's read ahead point
+ encode_for_tests([["a" * 509]], row_sep: "\r\n") do |data|
+ assert_equal("\r\n".encode(data.encoding), CSV.new(data).row_sep)
+ end
+ end
+
+ def test_csv_chars_are_transcoded
+ encode_for_tests([%w[abc def]]) do |data|
+ %w[col_sep row_sep quote_char].each do |csv_char|
+ assert_equal( "|".encode(data.encoding),
+ CSV.new(data, csv_char.to_sym => "|").send(csv_char) )
+ end
+ end
+ end
+
+ def test_parser_works_with_encoded_headers
+ encode_for_tests([%w[one two three], %w[1 2 3]]) do |data|
+ parsed = CSV.parse(data, headers: true)
+ assert( parsed.headers.all? { |h| h.encoding == data.encoding },
+ "Wrong data encoding." )
+ parsed.each do |row|
+ assert( row.fields.all? { |f| f.encoding == data.encoding },
+ "Wrong data encoding." )
+ end
+ end
+ end
+
+ def test_built_in_converters_transcode_to_utf_8_then_convert
+ encode_for_tests([%w[one two three], %w[1 2 3]]) do |data|
+ parsed = CSV.parse(data, converters: :integer)
+ assert( parsed[0].all? { |f| f.encoding == data.encoding },
+ "Wrong data encoding." )
+ assert_equal([1, 2, 3], parsed[1])
+ end
+ end
+
+ def test_built_in_header_converters_transcode_to_utf_8_then_convert
+ encode_for_tests([%w[one two three], %w[1 2 3]]) do |data|
+ parsed = CSV.parse( data, headers: true,
+ header_converters: :downcase )
+ assert( parsed.headers.all? { |h| h.encoding.name == "UTF-8" },
+ "Wrong data encoding." )
+ assert( parsed[0].fields.all? { |f| f.encoding == data.encoding },
+ "Wrong data encoding." )
+ end
+ end
+
+ def test_open_allows_you_to_set_encodings
+ encode_for_tests([%w[abc def]]) do |data|
+ # read and write in encoding
+ File.open(@temp_csv_path, "wb:#{data.encoding.name}") { |f| f << data }
+ CSV.open(@temp_csv_path, "rb:#{data.encoding.name}") do |csv|
+ csv.each do |row|
+ assert( row.all? { |f| f.encoding == data.encoding },
+ "Wrong data encoding." )
+ end
+ end
+
+ # read and write with transcoding
+ File.open(@temp_csv_path, "wb:UTF-32BE:#{data.encoding.name}") do |f|
+ f << data
+ end
+ CSV.open(@temp_csv_path, "rb:UTF-32BE:#{data.encoding.name}") do |csv|
+ csv.each do |row|
+ assert( row.all? { |f| f.encoding == data.encoding },
+ "Wrong data encoding." )
+ end
+ end
+ end
+ end
+
+ def test_foreach_allows_you_to_set_encodings
+ encode_for_tests([%w[abc def]]) do |data|
+ # read and write in encoding
+ File.open(@temp_csv_path, "wb:#{data.encoding.name}") { |f| f << data }
+ CSV.foreach(@temp_csv_path, encoding: data.encoding.name) do |row|
+ assert( row.all? { |f| f.encoding == data.encoding },
+ "Wrong data encoding." )
+ end
+
+ # read and write with transcoding
+ File.open(@temp_csv_path, "wb:UTF-32BE:#{data.encoding.name}") do |f|
+ f << data
+ end
+ CSV.foreach( @temp_csv_path,
+ encoding: "UTF-32BE:#{data.encoding.name}" ) do |row|
+ assert( row.all? { |f| f.encoding == data.encoding },
+ "Wrong data encoding." )
+ end
+ end
+ end
+
+ def test_read_allows_you_to_set_encodings
+ encode_for_tests([%w[abc def]]) do |data|
+ # read and write in encoding
+ File.open(@temp_csv_path, "wb:#{data.encoding.name}") { |f| f << data }
+ rows = CSV.read(@temp_csv_path, encoding: data.encoding.name)
+ assert( rows.flatten.all? { |f| f.encoding == data.encoding },
+ "Wrong data encoding." )
+
+ # read and write with transcoding
+ File.open(@temp_csv_path, "wb:UTF-32BE:#{data.encoding.name}") do |f|
+ f << data
+ end
+ rows = CSV.read( @temp_csv_path,
+ encoding: "UTF-32BE:#{data.encoding.name}" )
+ assert( rows.flatten.all? { |f| f.encoding == data.encoding },
+ "Wrong data encoding." )
+ end
+ end
+
+ #################################
+ ### Write CSV in any Encoding ###
+ #################################
+
+ def test_can_write_csv_in_any_encoding
+ each_encoding do |encoding|
+ # test generate_line with encoding hint
+ csv = %w[abc d|ef].map { |f| f.encode(encoding) }.
+ to_csv(col_sep: "|", encoding: encoding.name)
+ assert_equal(encoding, csv.encoding)
+
+ # test generate_line with encoding guessing from fields
+ csv = %w[abc d|ef].map { |f| f.encode(encoding) }.to_csv(col_sep: "|")
+ assert_equal(encoding, csv.encoding)
+
+ # writing to files
+ data = encode_ary([%w[abc d,ef], %w[123 456 ]], encoding)
+ CSV.open(@temp_csv_path, "wb:#{encoding.name}") do |f|
+ data.each { |row| f << row }
+ end
+ assert_equal(data, CSV.read(@temp_csv_path, encoding: encoding.name))
+ end
+ end
+
+ private
+
+ def assert_parses(fields, encoding, options = { })
+ encoding = Encoding.find(encoding) unless encoding.is_a? Encoding
+ fields = encode_ary(fields, encoding)
+ parsed = CSV.parse(ary_to_data(fields, options), options)
+ assert_equal(fields, parsed)
+ parsed.flatten.each_with_index do |field, i|
+ assert_equal(encoding, field.encoding, "Field[#{i + 1}] was transcoded.")
+ end
+ end
+
+ def encode_ary(ary, encoding)
+ ary.map { |row| row.map { |field| field.encode(encoding) } }
+ end
+
+ def ary_to_data(ary, options = { })
+ encoding = ary.flatten.first.encoding
+ quote_char = (options[:quote_char] || '"').encode(encoding)
+ col_sep = (options[:col_sep] || ",").encode(encoding)
+ row_sep = (options[:row_sep] || "\n").encode(encoding)
+ ary.map { |row|
+ row.map { |field|
+ [quote_char, field.encode(encoding), quote_char].join
+ }.join(col_sep) + row_sep
+ }.join.encode(encoding)
+ end
+
+ def encode_for_tests(data, options = { })
+ yield ary_to_data(encode_ary(data, "UTF-8"), options)
+ yield ary_to_data(encode_ary(data, "UTF-16BE"), options)
+ end
+
+ def each_encoding
+ Encoding.list.each do |encoding|
+ next if encoding.dummy? # skip "dummy" encodings
+ yield encoding
+ end
+ end
+end
diff --git a/test/csv/tc_features.rb b/test/csv/test_features.rb
index ae5a8a451b..9ed3f98191 100644
--- a/test/csv/tc_features.rb
+++ b/test/csv/test_features.rb
@@ -1,4 +1,5 @@
-#!/usr/local/bin/ruby -w
+#!/usr/bin/env ruby -w
+# encoding: UTF-8
# tc_features.rb
#
@@ -45,40 +46,47 @@ class TestCSVFeatures < Test::Unit::TestCase
TEST_CASES.each do |test_case|
assert_equal( test_case.last.map { |t| t.tr(",", sep) unless t.nil? },
CSV.parse_line( test_case.first.tr(",", sep),
- :col_sep => sep ) )
+ col_sep: sep ) )
end
end
- assert_equal([",,,", nil], CSV.parse_line(",,,;", :col_sep => ";"))
+ assert_equal([",,,", nil], CSV.parse_line(",,,;", col_sep: ";"))
end
def test_row_sep
assert_raise(CSV::MalformedCSVError) do
- CSV.parse_line("1,2,3\n,4,5\r\n", :row_sep => "\r\n")
+ CSV.parse_line("1,2,3\n,4,5\r\n", row_sep: "\r\n")
end
assert_equal( ["1", "2", "3\n", "4", "5"],
- CSV.parse_line(%Q{1,2,"3\n",4,5\r\n}, :row_sep => "\r\n"))
+ CSV.parse_line(%Q{1,2,"3\n",4,5\r\n}, row_sep: "\r\n"))
end
def test_quote_char
TEST_CASES.each do |test_case|
assert_equal( test_case.last.map { |t| t.tr('"', "'") unless t.nil? },
CSV.parse_line( test_case.first.tr('"', "'"),
- :quote_char => "'" ) )
+ quote_char: "'" ) )
+ end
+ end
+
+ def test_csv_char_readers
+ %w[col_sep row_sep quote_char].each do |reader|
+ csv = CSV.new("abc,def", reader.to_sym => "|")
+ assert_equal("|", csv.send(reader))
end
end
def test_row_sep_auto_discovery
["\r\n", "\n", "\r"].each do |line_end|
data = "1,2,3#{line_end}4,5#{line_end}"
- discovered = CSV.new(data).instance_eval { @row_sep }
+ discovered = CSV.new(data).row_sep
assert_equal(line_end, discovered)
end
- assert_equal("\n", CSV.new("\n\r\n\r").instance_eval { @row_sep })
+ assert_equal("\n", CSV.new("\n\r\n\r").row_sep)
- assert_equal($/, CSV.new("").instance_eval { @row_sep })
+ assert_equal($/, CSV.new("").row_sep)
- assert_equal($/, CSV.new(STDERR).instance_eval { @row_sep })
+ assert_equal($/, CSV.new(STDERR).row_sep)
end
def test_lineno
@@ -101,13 +109,13 @@ class TestCSVFeatures < Test::Unit::TestCase
end
def test_unknown_options
- assert_raise(ArgumentError) { CSV.new(String.new, :unknown => :error) }
+ assert_raise(ArgumentError) { CSV.new(String.new, unknown: :error) }
end
def test_skip_blanks
assert_equal(4, @csv.to_a.size)
- @csv = CSV.new(@sample_data, :skip_blanks => true)
+ @csv = CSV.new(@sample_data, skip_blanks: true)
count = 0
@csv.each do |row|
@@ -117,14 +125,59 @@ class TestCSVFeatures < Test::Unit::TestCase
assert_equal(3, count)
end
+ def test_csv_behavior_readers
+ %w[ unconverted_fields return_headers write_headers
+ skip_blanks force_quotes ].each do |behavior|
+ assert( !CSV.new("abc,def").send("#{behavior}?"),
+ "Behavior defaulted to on." )
+ csv = CSV.new("abc,def", behavior.to_sym => true)
+ assert(csv.send("#{behavior}?"), "Behavior change now registered.")
+ end
+ end
+
+ def test_converters_reader
+ # no change
+ assert_equal( [:integer],
+ CSV.new("abc,def", converters: [:integer]).converters )
+
+ # just one
+ assert_equal( [:integer],
+ CSV.new("abc,def", converters: :integer).converters )
+
+ # expanded
+ assert_equal( [:integer, :float],
+ CSV.new("abc,def", converters: :numeric).converters )
+
+ # custom
+ csv = CSV.new("abc,def", converters: [:integer, lambda { }])
+ assert_equal(2, csv.converters.size)
+ assert_equal(:integer, csv.converters.first)
+ assert_instance_of(Proc, csv.converters.last)
+ end
+
+ def test_header_converters_reader
+ # no change
+ hc = :header_converters
+ assert_equal([:downcase], CSV.new("abc,def", hc => [:downcase]).send(hc))
+
+ # just one
+ assert_equal([:downcase], CSV.new("abc,def", hc => :downcase).send(hc))
+
+ # custom
+ csv = CSV.new("abc,def", hc => [:symbol, lambda { }])
+ assert_equal(2, csv.send(hc).size)
+ assert_equal(:symbol, csv.send(hc).first)
+ assert_instance_of(Proc, csv.send(hc).last)
+ end
+
# reported by Kev Jackson
def test_failing_to_escape_col_sep_bug_fix
- assert_nothing_raised(Exception) { CSV.new(String.new, :col_sep => "|") }
+ assert_nothing_raised(Exception) { CSV.new(String.new, col_sep: "|") }
end
# reported by Chris Roos
def test_failing_to_reset_headers_in_rewind_bug_fix
- csv = CSV.new("forename,surname", :headers => true, :return_headers => true)
+ csv = CSV.new("forename,surname", headers: true, return_headers: true)
csv.each { |row| assert row.header_row? }
csv.rewind
csv.each { |row| assert row.header_row? }
@@ -136,7 +189,7 @@ class TestCSVFeatures < Test::Unit::TestCase
<=><=>A<=>B<=>C
1<=>2<=>3
END_DATA
- parsed = CSV.parse(data, :col_sep => "<=>")
+ parsed = CSV.parse(data, col_sep: "<=>")
assert_equal([[nil, nil, "A", "B", "C"], ["1", "2", "3"]], parsed)
end
@@ -149,7 +202,7 @@ class TestCSVFeatures < Test::Unit::TestCase
)
)
end
- assert_equal("\r\n", zipped.instance_eval { @row_sep })
+ assert_equal("\r\n", zipped.row_sep)
end
def test_gzip_writer_bug_fix
@@ -168,6 +221,43 @@ class TestCSVFeatures < Test::Unit::TestCase
File.unlink(file)
end
+ def test_inspect_is_smart_about_io_types
+ str = CSV.new("string,data").inspect
+ assert(str.include?("io_type:StringIO"), "IO type not detected.")
+
+ str = CSV.new($stderr).inspect
+ assert(str.include?("io_type:$stderr"), "IO type not detected.")
+
+ path = File.join(File.dirname(__FILE__), "temp.csv")
+ File.open(path, "w") { |csv| csv << "one,two,three\n1,2,3\n" }
+ str = CSV.open(path) { |csv| csv.inspect }
+ assert(str.include?("io_type:File"), "IO type not detected.")
+ File.unlink(path)
+ end
+
+ def test_inspect_shows_key_attributes
+ str = @csv.inspect
+ %w[lineno col_sep row_sep quote_char].each do |attr_name|
+ assert_match(/\b#{attr_name}:[^\s>]+/, str)
+ end
+ end
+
+ def test_inspect_shows_headers_when_available
+ CSV.new("one,two,three\n1,2,3\n", headers: true) do |csv|
+ assert(csv.inspect.include?("headers:true"), "Header hint not shown.")
+ csv.shift # load headers
+ assert_match(/headers:\[[^\]]+\]/, csv.inspect)
+ end
+ end
+
+ def test_inspect_encoding_is_ascii_compatible
+ CSV.new("one,two,three\n1,2,3\n".encode("UTF-16BE")) do |csv|
+ assert( Encoding.compatible?( Encoding.find("US-ASCII"),
+ csv.inspect.encoding ),
+ "inspect() was not ASCII compatible." )
+ end
+ end
+
def test_version
assert_not_nil(CSV::VERSION)
assert_instance_of(String, CSV::VERSION)
diff --git a/test/csv/tc_headers.rb b/test/csv/test_headers.rb
index 74e2f54ad4..6ce5675816 100644
--- a/test/csv/tc_headers.rb
+++ b/test/csv/test_headers.rb
@@ -1,4 +1,5 @@
-#!/usr/local/bin/ruby -w
+#!/usr/bin/env ruby -w
+# encoding: UTF-8
# tc_headers.rb
#
@@ -24,7 +25,7 @@ class TestCSVHeaders < Test::Unit::TestCase
# activate headers
csv = nil
assert_nothing_raised(Exception) do
- csv = CSV.parse(@data, :headers => setting)
+ csv = CSV.parse(@data, headers: setting)
end
# first data row - skipping headers
@@ -48,7 +49,7 @@ class TestCSVHeaders < Test::Unit::TestCase
# activate headers
csv = nil
assert_nothing_raised(Exception) do
- csv = CSV.parse(@data, :headers => [:my, :new, :headers])
+ csv = CSV.parse(@data, headers: [:my, :new, :headers])
end
# first data row - skipping headers
@@ -75,9 +76,9 @@ class TestCSVHeaders < Test::Unit::TestCase
# with return and convert
assert_nothing_raised(Exception) do
- csv = CSV.parse(@data, :headers => [:my, :new, :headers],
- :return_headers => true,
- :header_converters => lambda { |h| h.to_s } )
+ csv = CSV.parse( @data, headers: [:my, :new, :headers],
+ return_headers: true,
+ header_converters: lambda { |h| h.to_s } )
end
row = csv[0]
assert_not_nil(row)
@@ -91,7 +92,7 @@ class TestCSVHeaders < Test::Unit::TestCase
# activate headers
csv = nil
assert_nothing_raised(Exception) do
- csv = CSV.parse(@data, :headers => "my,new,headers")
+ csv = CSV.parse(@data, headers: "my,new,headers")
end
# first data row - skipping headers
@@ -117,9 +118,9 @@ class TestCSVHeaders < Test::Unit::TestCase
# with return and convert
assert_nothing_raised(Exception) do
- csv = CSV.parse(@data, :headers => "my,new,headers",
- :return_headers => true,
- :header_converters => :symbol )
+ csv = CSV.parse( @data, headers: "my,new,headers",
+ return_headers: true,
+ header_converters: :symbol )
end
row = csv[0]
assert_not_nil(row)
@@ -129,11 +130,26 @@ class TestCSVHeaders < Test::Unit::TestCase
assert(!row.field_row?)
end
+ def test_csv_header_string_inherits_separators
+ # parse with custom col_sep
+ csv = nil
+ assert_nothing_raised(Exception) do
+ csv = CSV.parse( @data.tr(",", "|"), col_sep: "|",
+ headers: "my|new|headers" )
+ end
+
+ # verify headers were recognized
+ row = csv[0]
+ assert_not_nil(row)
+ assert_instance_of(CSV::Row, row)
+ assert_equal([%w{my first}, %w{new second}, %w{headers third}], row.to_a)
+ end
+
def test_return_headers
# activate headers and request they are returned
csv = nil
assert_nothing_raised(Exception) do
- csv = CSV.parse(@data, :headers => true, :return_headers => true)
+ csv = CSV.parse(@data, headers: true, return_headers: true)
end
# header row
@@ -173,19 +189,19 @@ class TestCSVHeaders < Test::Unit::TestCase
END_MATCHING_CSV
# normal converters do not affect headers
- csv = CSV.parse( data, :headers => true,
- :return_headers => true,
- :converters => :numeric )
+ csv = CSV.parse( data, headers: true,
+ return_headers: true,
+ converters: :numeric )
assert_equal([%w{1 1}, %w{2 2}, %w{3 3}], csv[0].to_a)
assert_equal([["1", 1], ["2", 2], ["3", 3]], csv[1].to_a)
assert_nil(csv[2])
# header converters do affect headers (only)
assert_nothing_raised(Exception) do
- csv = CSV.parse( data, :headers => true,
- :return_headers => true,
- :converters => :numeric,
- :header_converters => :symbol )
+ csv = CSV.parse( data, headers: true,
+ return_headers: true,
+ converters: :numeric,
+ header_converters: :symbol )
end
assert_equal([[:"1", "1"], [:"2", "2"], [:"3", "3"]], csv[0].to_a)
assert_equal([[:"1", 1], [:"2", 2], [:"3", 3]], csv[1].to_a)
@@ -193,32 +209,32 @@ class TestCSVHeaders < Test::Unit::TestCase
end
def test_builtin_downcase_converter
- csv = CSV.parse( "One,TWO Three", :headers => true,
- :return_headers => true,
- :header_converters => :downcase )
+ csv = CSV.parse( "One,TWO Three", headers: true,
+ return_headers: true,
+ header_converters: :downcase )
assert_equal(%w{one two\ three}, csv.headers)
end
def test_builtin_symbol_converter
- csv = CSV.parse( "One,TWO Three", :headers => true,
- :return_headers => true,
- :header_converters => :symbol )
+ csv = CSV.parse( "One,TWO Three", headers: true,
+ return_headers: true,
+ header_converters: :symbol )
assert_equal([:one, :two_three], csv.headers)
end
def test_custom_converter
converter = lambda { |header| header.tr(" ", "_") }
csv = CSV.parse( "One,TWO Three",
- :headers => true,
- :return_headers => true,
- :header_converters => converter )
+ headers: true,
+ return_headers: true,
+ header_converters: converter )
assert_equal(%w{One TWO_Three}, csv.headers)
end
def test_table_support
csv = nil
assert_nothing_raised(Exception) do
- csv = CSV.parse(@data, :headers => true)
+ csv = CSV.parse(@data, headers: true)
end
assert_instance_of(CSV::Table, csv)
@@ -237,24 +253,35 @@ class TestCSVHeaders < Test::Unit::TestCase
END_CSV
expected = [%w[1 2 3]]
- CSV.parse(@data, :headers => true, :skip_blanks => true) do |row|
+ CSV.parse(@data, headers: true, skip_blanks: true) do |row|
assert_equal(expected.shift, row.fields)
end
expected = [%w[A B C], %w[1 2 3]]
CSV.parse( @data,
- :headers => true,
- :return_headers => true,
- :skip_blanks => true ) do |row|
+ headers: true,
+ return_headers: true,
+ skip_blanks: true ) do |row|
assert_equal(expected.shift, row.fields)
end
end
+ def test_headers_reader
+ # no headers
+ assert_nil(CSV.new(@data).headers)
+
+ # headers
+ csv = CSV.new(@data, headers: true)
+ assert_equal(true, csv.headers) # before headers are read
+ csv.shift # set headers
+ assert_equal(%w[first second third], csv.headers) # after headers are read
+ end
+
def test_blank_row_bug_fix
@data += "\n#{@data}" # add a blank row
# ensure that everything returned is a Row object
- CSV.parse(@data, :headers => true) do |row|
+ CSV.parse(@data, headers: true) do |row|
assert_instance_of(CSV::Row, row)
end
end
diff --git a/test/csv/tc_interface.rb b/test/csv/test_interface.rb
index e8cc920f9d..b9e634a559 100644
--- a/test/csv/tc_interface.rb
+++ b/test/csv/test_interface.rb
@@ -1,4 +1,5 @@
-#!/usr/local/bin/ruby -w
+#!/usr/bin/env ruby -w
+# encoding: UTF-8
# tc_interface.rb
#
@@ -29,21 +30,22 @@ class TestCSVInterface < Test::Unit::TestCase
### Test Read Interface ###
def test_foreach
- CSV.foreach(@path, :col_sep => "\t", :row_sep => "\r\n") do |row|
+ CSV.foreach(@path, col_sep: "\t", row_sep: "\r\n") do |row|
assert_equal(@expected.shift, row)
end
end
def test_open_and_close
- csv = CSV.open(@path, "r+", :col_sep => "\t", :row_sep => "\r\n")
+ csv = CSV.open(@path, "r+", col_sep: "\t", row_sep: "\r\n")
assert_not_nil(csv)
assert_instance_of(CSV, csv)
assert_equal(false, csv.closed?)
csv.close
assert(csv.closed?)
- ret = CSV.open(@path) do |csv|
- assert_instance_of(CSV, csv)
+ ret = CSV.open(@path) do |new_csv|
+ csv = new_csv
+ assert_instance_of(CSV, new_csv)
"Return value."
end
assert(csv.closed?)
@@ -53,21 +55,21 @@ class TestCSVInterface < Test::Unit::TestCase
def test_parse
data = File.read(@path)
assert_equal( @expected,
- CSV.parse(data, :col_sep => "\t", :row_sep => "\r\n") )
+ CSV.parse(data, col_sep: "\t", row_sep: "\r\n") )
- CSV.parse(data, :col_sep => "\t", :row_sep => "\r\n") do |row|
+ CSV.parse(data, col_sep: "\t", row_sep: "\r\n") do |row|
assert_equal(@expected.shift, row)
end
end
def test_parse_line
- row = CSV.parse_line("1;2;3", :col_sep => ";")
+ row = CSV.parse_line("1;2;3", col_sep: ";")
assert_not_nil(row)
assert_instance_of(Array, row)
assert_equal(%w{1 2 3}, row)
# shortcut interface
- row = "1;2;3".parse_csv(:col_sep => ";")
+ row = "1;2;3".parse_csv(col_sep: ";")
assert_not_nil(row)
assert_instance_of(Array, row)
assert_equal(%w{1 2 3}, row)
@@ -75,29 +77,29 @@ class TestCSVInterface < Test::Unit::TestCase
def test_read_and_readlines
assert_equal( @expected,
- CSV.read(@path, :col_sep => "\t", :row_sep => "\r\n") )
+ CSV.read(@path, col_sep: "\t", row_sep: "\r\n") )
assert_equal( @expected,
- CSV.readlines(@path, :col_sep => "\t", :row_sep => "\r\n") )
+ CSV.readlines(@path, col_sep: "\t", row_sep: "\r\n") )
- data = CSV.open(@path, :col_sep => "\t", :row_sep => "\r\n") do |csv|
+ data = CSV.open(@path, col_sep: "\t", row_sep: "\r\n") do |csv|
csv.read
end
assert_equal(@expected, data)
- data = CSV.open(@path, :col_sep => "\t", :row_sep => "\r\n") do |csv|
+ data = CSV.open(@path, col_sep: "\t", row_sep: "\r\n") do |csv|
csv.readlines
end
assert_equal(@expected, data)
end
def test_table
- table = CSV.table(@path, :col_sep => "\t", :row_sep => "\r\n")
+ table = CSV.table(@path, col_sep: "\t", row_sep: "\r\n")
assert_instance_of(CSV::Table, table)
assert_equal([[:"1", :"2", :"3"], [4, 5, nil]], table.to_a)
end
def test_shift # aliased as gets() and readline()
- CSV.open(@path, "r+", :col_sep => "\t", :row_sep => "\r\n") do |csv|
+ CSV.open(@path, "r+", col_sep: "\t", row_sep: "\r\n") do |csv|
assert_equal(@expected.shift, csv.shift)
assert_equal(@expected.shift, csv.shift)
assert_equal(nil, csv.shift)
@@ -123,13 +125,13 @@ class TestCSVInterface < Test::Unit::TestCase
end
def test_generate_line
- line = CSV.generate_line(%w{1 2 3}, :col_sep => ";")
+ line = CSV.generate_line(%w{1 2 3}, col_sep: ";")
assert_not_nil(line)
assert_instance_of(String, line)
assert_equal("1;2;3\n", line)
# shortcut interface
- line = %w{1 2 3}.to_csv(:col_sep => ";")
+ line = %w{1 2 3}.to_csv(col_sep: ";")
assert_not_nil(line)
assert_instance_of(String, line)
assert_equal("1;2;3\n", line)
@@ -139,7 +141,7 @@ class TestCSVInterface < Test::Unit::TestCase
File.unlink(@path)
headers = %w{a b c}
- CSV.open(@path, "w", :headers => true) do |csv|
+ CSV.open(@path, "w", headers: true) do |csv|
csv << headers
csv << %w{1 2 3}
assert_equal(headers, csv.instance_variable_get(:@headers))
@@ -159,16 +161,83 @@ class TestCSVInterface < Test::Unit::TestCase
def test_write_hash
File.unlink(@path)
- lines = [{:a => 1, :b => 2, :c => 3}, {:a => 4, :b => 5, :c => 6}]
- CSV.open( @path, "w", :headers => true,
- :converters => :all,
- :header_converters => :symbol ) do |csv|
+ lines = [{a: 1, b: 2, c: 3}, {a: 4, b: 5, c: 6}]
+ CSV.open( @path, "w", headers: true,
+ header_converters: :symbol ) do |csv|
csv << lines.first.keys
lines.each { |line| csv << line }
end
- CSV.open( @path, "w", :headers => true,
- :converters => :all,
- :header_converters => :symbol ) do |csv|
+ CSV.open( @path, "w", headers: true,
+ converters: :all,
+ header_converters: :symbol ) do |csv|
+ csv.each { |line| assert_equal(lines.shift, line.to_hash) }
+ end
+ end
+
+ def test_write_hash_with_headers_array
+ File.unlink(@path)
+
+ lines = [{a: 1, b: 2, c: 3}, {a: 4, b: 5, c: 6}]
+ CSV.open(@path, "w", headers: [:b, :a, :c]) do |csv|
+ lines.each { |line| csv << line }
+ end
+
+ # test writing fields in the correct order
+ File.open(@path, "r") do |f|
+ assert_equal("2,1,3", f.gets.strip)
+ assert_equal("5,4,6", f.gets.strip)
+ end
+
+ # test reading CSV with headers
+ CSV.open( @path, "r", headers: [:b, :a, :c],
+ converters: :all ) do |csv|
+ csv.each { |line| assert_equal(lines.shift, line.to_hash) }
+ end
+ end
+
+ def test_write_hash_with_headers_string
+ File.unlink(@path)
+
+ lines = [{"a" => 1, "b" => 2, "c" => 3}, {"a" => 4, "b" => 5, "c" => 6}]
+ CSV.open(@path, "w", headers: "b|a|c", col_sep: "|") do |csv|
+ lines.each { |line| csv << line }
+ end
+
+ # test writing fields in the correct order
+ File.open(@path, "r") do |f|
+ assert_equal("2|1|3", f.gets.strip)
+ assert_equal("5|4|6", f.gets.strip)
+ end
+
+ # test reading CSV with headers
+ CSV.open( @path, "r", headers: "b|a|c",
+ col_sep: "|",
+ converters: :all ) do |csv|
+ csv.each { |line| assert_equal(lines.shift, line.to_hash) }
+ end
+ end
+
+ def test_write_headers
+ File.unlink(@path)
+
+ lines = [{"a" => 1, "b" => 2, "c" => 3}, {"a" => 4, "b" => 5, "c" => 6}]
+ CSV.open( @path, "w", headers: "b|a|c",
+ write_headers: true,
+ col_sep: "|" ) do |csv|
+ lines.each { |line| csv << line }
+ end
+
+ # test writing fields in the correct order
+ File.open(@path, "r") do |f|
+ assert_equal("b|a|c", f.gets.strip)
+ assert_equal("2|1|3", f.gets.strip)
+ assert_equal("5|4|6", f.gets.strip)
+ end
+
+ # test reading CSV with headers
+ CSV.open( @path, "r", headers: true,
+ col_sep: "|",
+ converters: :all ) do |csv|
csv.each { |line| assert_equal(lines.shift, line.to_hash) }
end
end
@@ -176,7 +245,7 @@ class TestCSVInterface < Test::Unit::TestCase
def test_append # aliased add_row() and puts()
File.unlink(@path)
- CSV.open(@path, "w", :col_sep => "\t", :row_sep => "\r\n") do |csv|
+ CSV.open(@path, "w", col_sep: "\t", row_sep: "\r\n") do |csv|
@expected.each { |row| csv << row }
end
@@ -185,7 +254,7 @@ class TestCSVInterface < Test::Unit::TestCase
# same thing using CSV::Row objects
File.unlink(@path)
- CSV.open(@path, "w", :col_sep => "\t", :row_sep => "\r\n") do |csv|
+ CSV.open(@path, "w", col_sep: "\t", row_sep: "\r\n") do |csv|
@expected.each { |row| csv << CSV::Row.new(Array.new, row) }
end
@@ -199,8 +268,8 @@ class TestCSVInterface < Test::Unit::TestCase
expected = [[1, 2, 3], [4, 5]]
CSV.filter( "1;2;3\n4;5\n", (result = String.new),
- :in_col_sep => ";", :out_col_sep => ",",
- :converters => :all ) do |row|
+ in_col_sep: ";", out_col_sep: ",",
+ converters: :all ) do |row|
assert_equal(row, expected.shift)
row.map! { |n| n * 2 }
row << "Added\r"
@@ -213,7 +282,7 @@ class TestCSVInterface < Test::Unit::TestCase
first = nil
assert_nothing_raised(Exception) do
- first = CSV.instance(csv, :col_sep => ";")
+ first = CSV.instance(csv, col_sep: ";")
first << %w{a b c}
end
@@ -221,7 +290,7 @@ class TestCSVInterface < Test::Unit::TestCase
second = nil
assert_nothing_raised(Exception) do
- second = CSV.instance(csv, :col_sep => ";")
+ second = CSV.instance(csv, col_sep: ";")
second << [1, 2, 3]
end
@@ -230,6 +299,6 @@ class TestCSVInterface < Test::Unit::TestCase
# shortcuts
assert_equal(STDOUT, CSV.instance.instance_eval { @io })
- assert_equal(STDOUT, CSV { |csv| csv.instance_eval { @io } })
+ assert_equal(STDOUT, CSV { |new_csv| new_csv.instance_eval { @io } })
end
end
diff --git a/test/csv/tc_row.rb b/test/csv/test_row.rb
index a9b7f042b2..d0b0cdc406 100644
--- a/test/csv/tc_row.rb
+++ b/test/csv/test_row.rb
@@ -1,4 +1,5 @@
-#!/usr/local/bin/ruby -w
+#!/usr/bin/env ruby -w
+# encoding: UTF-8
# tc_row.rb
#
@@ -144,7 +145,7 @@ class TestCSVRow < Test::Unit::TestCase
%w{Header Field} ], @row.to_a )
# a pair with Hash syntax
- assert_equal(@row, @row << {:key => :value})
+ assert_equal(@row, @row << {key: :value})
assert_equal( [ ["A", 1],
["B", 2],
["C", 3],
@@ -278,7 +279,7 @@ class TestCSVRow < Test::Unit::TestCase
# with options
assert_equal( "1|2|3|4|\r\n",
- @row.to_csv(:col_sep => "|", :row_sep => "\r\n") )
+ @row.to_csv(col_sep: "|", row_sep: "\r\n") )
end
def test_array_delegation
@@ -286,4 +287,26 @@ class TestCSVRow < Test::Unit::TestCase
assert_equal([@row.headers.size, @row.fields.size].max, @row.size)
end
+
+ def test_inspect_shows_header_field_pairs
+ str = @row.inspect
+ @row.each do |header, field|
+ assert( str.include?("#{header.inspect}:#{field.inspect}"),
+ "Header field pair not found." )
+ end
+ end
+
+ def test_inspect_encoding_is_ascii_compatible
+ assert( Encoding.compatible?( Encoding.find("US-ASCII"),
+ @row.inspect.encoding ),
+ "inspect() was not ASCII compatible." )
+ end
+
+ def test_inspect_shows_symbol_headers_as_bare_attributes
+ str = CSV::Row.new(@row.headers.map { |h| h.to_sym }, @row.fields).inspect
+ @row.each do |header, field|
+ assert( str.include?("#{header}:#{field.inspect}"),
+ "Header field pair not found." )
+ end
+ end
end
diff --git a/test/csv/tc_serialization.rb b/test/csv/test_serialization.rb
index d9c37fde21..878619f58a 100644
--- a/test/csv/tc_serialization.rb
+++ b/test/csv/test_serialization.rb
@@ -1,4 +1,5 @@
-#!/usr/local/bin/ruby -w
+#!/usr/bin/env ruby -w
+# encoding: UTF-8
# tc_serialization.rb
#
@@ -149,7 +150,7 @@ class TestSerialization < Test::Unit::TestCase
end
def test_custom_dump_and_load
- obj = {1 => "simple", :test => Hash}
+ obj = {1 => "simple", test: Hash}
assert_equal(obj, CSV.load(CSV.dump([obj])).first)
end
end
diff --git a/test/csv/tc_table.rb b/test/csv/test_table.rb
index 028274d97f..d0b4d10103 100644
--- a/test/csv/tc_table.rb
+++ b/test/csv/test_table.rb
@@ -1,4 +1,5 @@
-#!/usr/local/bin/ruby -w
+#!/usr/bin/env ruby -w
+# encoding: UTF-8
# tc_table.rb
#
@@ -251,7 +252,7 @@ class TestCSVTable < Test::Unit::TestCase
# with options
assert_equal( csv.gsub(",", "|").gsub("\n", "\r\n"),
- @table.to_csv(:col_sep => "|", :row_sep => "\r\n") )
+ @table.to_csv(col_sep: "|", row_sep: "\r\n") )
# with headers
assert_equal(csv, @header_table.to_csv)
@@ -389,4 +390,19 @@ class TestCSVTable < Test::Unit::TestCase
assert_equal(@rows.size, @table.size)
end
+
+ def test_inspect_shows_current_mode
+ str = @table.inspect
+ assert(str.include?("mode:#{@table.mode}"), "Mode not shown.")
+
+ @table.by_col!
+ str = @table.inspect
+ assert(str.include?("mode:#{@table.mode}"), "Mode not shown.")
+ end
+
+ def test_inspect_encoding_is_ascii_compatible
+ assert( Encoding.compatible?( Encoding.find("US-ASCII"),
+ @table.inspect.encoding ),
+ "inspect() was not ASCII compatible." )
+ end
end
diff --git a/test/csv/ts_all.rb b/test/csv/ts_all.rb
index c930523757..4fadbb46e9 100644
--- a/test/csv/ts_all.rb
+++ b/test/csv/ts_all.rb
@@ -1,4 +1,5 @@
-#!/usr/local/bin/ruby -w
+#!/usr/bin/env ruby -w
+# encoding: UTF-8
# ts_all.rb
#
@@ -8,12 +9,13 @@
require "test/unit"
-require "tc_csv_parsing"
-require "tc_features"
-require "tc_interface"
-require "tc_csv_writing"
-require "tc_data_converters"
-require "tc_row"
-require "tc_table"
-require "tc_headers"
-require "tc_serialization"
+require "test_csv_parsing"
+require "test_features"
+require "test_interface"
+require "test_csv_writing"
+require "test_data_converters"
+require "test_row"
+require "test_table"
+require "test_headers"
+require "test_serialization"
+require "test_encodings"
diff --git a/test/date/test_date.rb b/test/date/test_date.rb
new file mode 100644
index 0000000000..de7e4838c3
--- /dev/null
+++ b/test/date/test_date.rb
@@ -0,0 +1,144 @@
+require 'test/unit'
+require 'date'
+
+class DateSub < Date; end
+class DateTimeSub < DateTime; end
+
+class TestDate < Test::Unit::TestCase
+
+ def test__const
+ assert_nil(Date::MONTHNAMES[0])
+ assert_equal('January', Date::MONTHNAMES[1])
+ assert_equal(13, Date::MONTHNAMES.size)
+ assert_equal('Sunday', Date::DAYNAMES[0])
+ assert_equal(7, Date::DAYNAMES.size)
+
+ assert_nil(Date::ABBR_MONTHNAMES[0])
+ assert_equal('Jan', Date::ABBR_MONTHNAMES[1])
+ assert_equal(13, Date::ABBR_MONTHNAMES.size)
+ assert_equal('Sun', Date::ABBR_DAYNAMES[0])
+ assert_equal(7, Date::ABBR_DAYNAMES.size)
+
+ assert(Date::MONTHNAMES.frozen?)
+ assert(!Date::MONTHNAMES[0].frozen?)
+ assert(Date::MONTHNAMES[1].frozen?)
+ assert(Date::DAYNAMES.frozen?)
+ assert(Date::DAYNAMES[0].frozen?)
+
+ assert(Date::ABBR_MONTHNAMES.frozen?)
+ assert(Date::ABBR_MONTHNAMES[1].frozen?)
+ assert(Date::ABBR_DAYNAMES.frozen?)
+ assert(Date::ABBR_DAYNAMES[0].frozen?)
+ end
+
+ def test_sub
+ d = DateSub.new
+ dt = DateTimeSub.new
+
+ assert_instance_of(DateSub, d)
+ assert_instance_of(DateTimeSub, dt)
+
+ assert_instance_of(DateSub, DateSub.today)
+ assert_instance_of(DateTimeSub, DateTimeSub.now)
+
+ assert_equal('#<DateSub: -1/2,0,2299161>', d.inspect)
+ assert_equal('-4712-01-01', d.to_s)
+ assert_equal('#<DateTimeSub: -1/2,0,2299161>', dt.inspect)
+ assert_equal('-4712-01-01T00:00:00+00:00', dt.to_s)
+
+ d2 = d + 1
+ assert_instance_of(DateSub, d2)
+ d2 = d - 1
+ assert_instance_of(DateSub, d2)
+ d2 = d >> 1
+ assert_instance_of(DateSub, d2)
+ d2 = d << 1
+ assert_instance_of(DateSub, d2)
+ d2 = d.succ
+ assert_instance_of(DateSub, d2)
+ d2 = d.next
+ assert_instance_of(DateSub, d2)
+ d2 = d.italy
+ assert_instance_of(DateSub, d2)
+ d2 = d.england
+ assert_instance_of(DateSub, d2)
+ d2 = d.julian
+ assert_instance_of(DateSub, d2)
+ d2 = d.gregorian
+ assert_instance_of(DateSub, d2)
+ s = Marshal.dump(d)
+ d2 = Marshal.load(s)
+ assert_equal(d2, d)
+ assert_instance_of(DateSub, d2)
+
+ dt2 = dt + 1
+ assert_instance_of(DateTimeSub, dt2)
+ dt2 = dt - 1
+ assert_instance_of(DateTimeSub, dt2)
+ dt2 = dt >> 1
+ assert_instance_of(DateTimeSub, dt2)
+ dt2 = dt << 1
+ assert_instance_of(DateTimeSub, dt2)
+ dt2 = dt.succ
+ assert_instance_of(DateTimeSub, dt2)
+ dt2 = dt.next
+ assert_instance_of(DateTimeSub, dt2)
+ dt2 = dt.italy
+ assert_instance_of(DateTimeSub, dt2)
+ dt2 = dt.england
+ assert_instance_of(DateTimeSub, dt2)
+ dt2 = dt.julian
+ assert_instance_of(DateTimeSub, dt2)
+ dt2 = dt.gregorian
+ assert_instance_of(DateTimeSub, dt2)
+ s = Marshal.dump(dt)
+ dt2 = Marshal.load(s)
+ assert_equal(dt2, dt)
+ assert_instance_of(DateTimeSub, dt2)
+ end
+
+ def test_eql_p
+ d = Date.jd(0)
+ d2 = Date.jd(0)
+ dt = DateTime.jd(0)
+ dt2 = DateTime.jd(0)
+
+ assert_equal(d, d2)
+ assert_not_equal(d, 0)
+
+ assert_equal(dt, dt2)
+ assert_not_equal(dt, 0)
+
+ assert_equal(d, dt)
+ assert_equal(d2, dt2)
+ end
+
+ def test_hash
+ h = {}
+ h[Date.new(1999,5,23)] = 0
+ h[Date.new(1999,5,24)] = 1
+ h[Date.new(1999,5,25)] = 2
+ h[Date.new(1999,5,25)] = 9
+ assert_equal(3, h.size)
+ assert_equal(9, h[Date.new(1999,5,25)])
+ assert_equal(9, h[DateTime.new(1999,5,25)])
+
+ h = {}
+ h[DateTime.new(1999,5,23)] = 0
+ h[DateTime.new(1999,5,24)] = 1
+ h[DateTime.new(1999,5,25)] = 2
+ h[DateTime.new(1999,5,25)] = 9
+ assert_equal(3, h.size)
+ assert_equal(9, h[Date.new(1999,5,25)])
+ assert_equal(9, h[DateTime.new(1999,5,25)])
+ end
+
+ def test_freeze
+ d = Date.new
+ d.freeze
+ assert_equal(true, d.frozen?)
+ assert_instance_of(Fixnum, d.yday)
+ assert_instance_of(String, d.to_s)
+ end
+
+end
diff --git a/test/date/test_date_arith.rb b/test/date/test_date_arith.rb
new file mode 100644
index 0000000000..745ddbd16c
--- /dev/null
+++ b/test/date/test_date_arith.rb
@@ -0,0 +1,286 @@
+require 'test/unit'
+require 'date'
+
+class TestDateArith < Test::Unit::TestCase
+
+ def new_offset
+ d = DateTime.new(2002, 3, 14)
+ assert_equal(Rational(9, 24), d.new_offset(Rational(9, 24)).offset)
+ assert_equal(Rational(9, 24), d.new_offset('+0900').offset)
+ end
+
+ def test__plus
+ d = Date.new(2000,2,29) + -1
+ assert_equal([2000, 2, 28], [d.year, d.mon, d.mday])
+ d = Date.new(2000,2,29) + 0
+ assert_equal([2000, 2, 29], [d.year, d.mon, d.mday])
+ d = Date.new(2000,2,29) + 1
+ assert_equal([2000, 3, 1], [d.year, d.mon, d.mday])
+
+ d = DateTime.new(2000,2,29) + 1.to_r/2
+ assert_equal([2000, 2, 29, 12, 0, 0],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec])
+ end
+
+ def test__plus__ex
+ e = TypeError
+ assert_raise(e) do
+ Date.new(2000,2,29) + 'foo'
+ end
+ assert_raise(e) do
+ DateTime.new(2000,2,29) + 'foo'
+ end
+ assert_raise(e) do
+ Date.new(2000,2,29) + Time.mktime(2000,2,29)
+ end
+ assert_raise(e) do
+ DateTime.new(2000,2,29) + Time.mktime(2000,2,29)
+ end
+ end
+
+ def test__minus
+ d = Date.new(2000,3,1) - -1
+ assert_equal([2000, 3, 2], [d.year, d.mon, d.mday])
+ d = Date.new(2000,3,1) - 0
+ assert_equal([2000, 3, 1], [d.year, d.mon, d.mday])
+ d = Date.new(2000,3,1) - 1
+ assert_equal([2000, 2, 29], [d.year, d.mon, d.mday])
+
+ d = Date.new(2000,3,1) - Date.new(2000,2,29)
+ assert_equal(1, d)
+ d = Date.new(2000,2,29) - Date.new(2000,3,1)
+ assert_equal(-1, d)
+
+ d = DateTime.new(2000,3,1) - 1.to_r/2
+ assert_equal([2000, 2, 29, 12, 0, 0],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec])
+ end
+
+ def test__minus__ex
+ e = TypeError
+ assert_raise(e) do
+ Date.new(2000,2,29) - 'foo'
+ end
+ assert_raise(e) do
+ DateTime.new(2000,2,29) - 'foo'
+ end
+ assert_raise(e) do
+ Date.new(2000,2,29) - Time.mktime(2000,2,29)
+ end
+ assert_raise(e) do
+ DateTime.new(2000,2,29) - Time.mktime(2000,2,29)
+ end
+ end
+
+ def test__compare
+ assert_equal(0, (Date.new(2000,1,1) <=> Date.new(2000,1,1)))
+ assert_equal(-1, (Date.new(2000,1,1) <=> Date.new(2000,1,2)))
+ assert_equal(1, (Date.new(2000,1,2) <=> Date.new(2000,1,1)))
+ assert_equal(0, (Date.new(2001,1,4,Date::JULIAN) <=>
+ Date.new(2001,1,17, Date::GREGORIAN)))
+ assert_equal(0, (DateTime.new(2001,1,4,0,0,0,0,Date::JULIAN) <=>
+ DateTime.new(2001,1,17,0,0,0,0,Date::GREGORIAN)))
+ end
+
+ def test_prev
+ d = Date.new(2000,1,1)
+ assert_raise(NoMethodError) do
+ d.prev
+ end
+ end
+
+ def test_prev_day
+ d = Date.new(2001,1,1).prev_day
+ assert_equal([2000, 12, 31], [d.year, d.mon, d.mday])
+ d = Date.new(2001,1,1).prev_day(2)
+ assert_equal([2000, 12, 30], [d.year, d.mon, d.mday])
+ d = Date.new(2000,12,31).prev_day(-2)
+ assert_equal([2001, 1, 2], [d.year, d.mon, d.mday])
+
+ d = DateTime.new(2000,3,1).prev_day(1.to_r/2)
+ assert_equal([2000, 2, 29, 12, 0, 0], [d.year, d.mon, d.mday, d.hour, d.min, d.sec])
+ end
+
+ def test_prev_month
+ d = Date.new(2000,1,31) << -1
+ assert_equal([2000, 2, 29], [d.year, d.mon, d.mday])
+ d = Date.new(2000,1,31) << 1
+ assert_equal([1999, 12, 31], [d.year, d.mon, d.mday])
+ d = Date.new(2000,1,31) << 12
+ assert_equal([1999, 1, 31], [d.year, d.mon, d.mday])
+ d = Date.new(2000,1,31) << 14
+ assert_equal([1998, 11, 30], [d.year, d.mon, d.mday])
+
+ end
+
+ def test_prev_month__2
+ d = Date.new(2000,1,31).prev_month(-1)
+ assert_equal([2000, 2, 29], [d.year, d.mon, d.mday])
+ d = Date.new(2000,1,31).prev_month
+ assert_equal([1999, 12, 31], [d.year, d.mon, d.mday])
+ d = Date.new(2000,1,31).prev_month(12)
+ assert_equal([1999, 1, 31], [d.year, d.mon, d.mday])
+ d = Date.new(2000,1,31).prev_month(14)
+ assert_equal([1998, 11, 30], [d.year, d.mon, d.mday])
+ end
+
+ def test_prev_year
+ d = Date.new(2000,1,31).prev_year(-1)
+ assert_equal([2001, 1, 31], [d.year, d.mon, d.mday])
+ d = Date.new(2000,1,31).prev_year
+ assert_equal([1999, 1, 31], [d.year, d.mon, d.mday])
+ d = Date.new(2000,1,31).prev_year(10)
+ assert_equal([1990, 1, 31], [d.year, d.mon, d.mday])
+ d = Date.new(2000,1,31).prev_year(100)
+ assert_equal([1900, 1, 31], [d.year, d.mon, d.mday])
+ end
+
+ def test_next
+ d = Date.new(2000,12,31).next
+ assert_equal([2001, 1, 1], [d.year, d.mon, d.mday])
+ d = Date.new(2000,12,31).succ
+ assert_equal([2001, 1, 1], [d.year, d.mon, d.mday])
+
+ d = Date.today
+ d2 = d.next
+ assert_equal(d, (d2 - 1))
+ d = Date.today
+ d2 = d.succ
+ assert_equal(d, (d2 - 1))
+
+ d = DateTime.now
+ d2 = d.next
+ assert_equal(d, (d2 - 1))
+ d = DateTime.now
+ d2 = d.succ
+ assert_equal(d, (d2 - 1))
+ end
+
+ def test_next_day
+ d = Date.new(2000,12,31).next_day
+ assert_equal([2001, 1, 1], [d.year, d.mon, d.mday])
+ d = Date.new(2000,12,31).next_day(2)
+ assert_equal([2001, 1, 2], [d.year, d.mon, d.mday])
+ d = Date.new(2001,1,1).next_day(-2)
+ assert_equal([2000, 12, 30], [d.year, d.mon, d.mday])
+
+ d = DateTime.new(2000,2,29).next_day(1.to_r/2)
+ assert_equal([2000, 2, 29, 12, 0, 0], [d.year, d.mon, d.mday, d.hour, d.min, d.sec])
+ end
+
+ def test_next_month
+ d = Date.new(2000,1,31) >> -1
+ assert_equal([1999, 12, 31], [d.year, d.mon, d.mday])
+ d = Date.new(2000,1,31) >> 1
+ assert_equal([2000, 2, 29], [d.year, d.mon, d.mday])
+ d = Date.new(2000,1,31) >> 12
+ assert_equal([2001, 1, 31], [d.year, d.mon, d.mday])
+ d = Date.new(2000,1,31) >> 13
+ assert_equal([2001, 2, 28], [d.year, d.mon, d.mday])
+ end
+
+ def test_next_month__2
+ d = Date.new(2000,1,31).next_month(-1)
+ assert_equal([1999, 12, 31], [d.year, d.mon, d.mday])
+ d = Date.new(2000,1,31).next_month
+ assert_equal([2000, 2, 29], [d.year, d.mon, d.mday])
+ d = Date.new(2000,1,31).next_month(12)
+ assert_equal([2001, 1, 31], [d.year, d.mon, d.mday])
+ d = Date.new(2000,1,31).next_month(13)
+ assert_equal([2001, 2, 28], [d.year, d.mon, d.mday])
+ end
+
+ def test_next_year
+ d = Date.new(2000,1,31).next_year(-1)
+ assert_equal([1999, 1, 31], [d.year, d.mon, d.mday])
+ d = Date.new(2000,1,31).next_year
+ assert_equal([2001, 1, 31], [d.year, d.mon, d.mday])
+ d = Date.new(2000,1,31).next_year(10)
+ assert_equal([2010, 1, 31], [d.year, d.mon, d.mday])
+ d = Date.new(2000,1,31).next_year(100)
+ assert_equal([2100, 1, 31], [d.year, d.mon, d.mday])
+ end
+
+ def test_downto
+ p = Date.new(2001,1,14)
+ q = Date.new(2001,1,7)
+ i = 0
+ p.downto(q) do |d|
+ i += 1
+ end
+ assert_equal(8, i)
+ end
+
+ def test_downto__noblock
+ p = Date.new(2001,1,14)
+ q = Date.new(2001,1,7)
+ e = p.downto(q)
+ assert_equal(8, e.to_a.size)
+ end
+
+ def test_upto
+ p = Date.new(2001,1,14)
+ q = Date.new(2001,1,21)
+ i = 0
+ p.upto(q) do |d|
+ i += 1
+ end
+ assert_equal(8, i)
+ end
+
+ def test_upto__noblock
+ p = Date.new(2001,1,14)
+ q = Date.new(2001,1,21)
+ e = p.upto(q)
+ assert_equal(8, e.to_a.size)
+ end
+
+ def test_step
+ p = Date.new(2001,1,14)
+ q = Date.new(2001,1,21)
+ i = 0
+ p.step(q, 2) do |d|
+ i += 1
+ end
+ assert_equal(4, i)
+
+ i = 0
+ p.step(q) do |d|
+ i += 1
+ end
+ assert_equal(8, i)
+ end
+
+ def test_step__noblock
+ p = Date.new(2001,1,14)
+ q = Date.new(2001,1,21)
+ e = p.step(q, 2)
+ assert_equal(4, e.to_a.size)
+
+ e = p.step(q)
+ assert_equal(8, e.to_a.size)
+ end
+
+=begin
+ def test_step__inf
+ p = Date.new(2001,1,14)
+ q = Date.new(2001,1,21)
+ inf = 1.0/0
+
+ if inf.infinite?
+ [p, q].each do |a|
+ [p, q].each do |b|
+ [inf, -inf].each do |c|
+ i = 0
+ a.step(b, c) do |d|
+ i += 1
+ end
+ assert_equal(0, i)
+ end
+ end
+ end
+ end
+ end
+=end
+
+end
diff --git a/test/date/test_date_attr.rb b/test/date/test_date_attr.rb
new file mode 100644
index 0000000000..2e71b5f501
--- /dev/null
+++ b/test/date/test_date_attr.rb
@@ -0,0 +1,109 @@
+require 'test/unit'
+require 'date'
+
+class TestDateAttr < Test::Unit::TestCase
+
+ def test__attr
+ date = Date.new(1965, 5, 23)
+ datetime = DateTime.new(1965, 5, 23, 22, 31, 59)
+
+ [date, datetime].each_with_index do |d, i|
+ if i == 0
+ assert_match(/\#<Date\d?: 4877807\/2,0,2299161>/,
+ d.inspect)
+ else
+ assert_match(/\#<DateTime\d?: 210721343519\/86400,0,2299161>/,
+ d.inspect)
+ end
+
+ if i == 0
+ assert_equal('1965-05-23', d.to_s)
+ else
+ assert_equal('1965-05-23T22:31:59+00:00', d.to_s)
+ end
+
+ assert_equal('', d.inspect.gsub!(/./,''))
+ assert_equal('', d.to_s.gsub!(/./,''))
+
+ assert_equal(2438904, d.jd)
+
+ if i == 0
+ assert_equal(0, d.day_fraction)
+ else
+ assert_equal(22.to_r/24 + 31.to_r/1440 + 59.to_r/86400, d.day_fraction)
+ end
+
+ assert_equal(38903, d.mjd)
+ assert_equal(139744, d.ld)
+
+ assert_equal(1965, d.year)
+ assert_equal(143, d.yday)
+ assert_equal(5, d.mon)
+ assert_equal(d.mon, d.month)
+ assert_equal(23, d.mday)
+ assert_equal(d.mday, d.day)
+
+ if i == 0
+ assert_equal(false, d.respond_to?(:hour))
+ assert_equal(false, d.respond_to?(:min))
+ assert_equal(false, d.respond_to?(:sec))
+ assert_equal(false, d.respond_to?(:sec_fraction))
+ assert_equal(false, d.respond_to?(:zone))
+ assert_equal(false, d.respond_to?(:offset))
+ else
+ assert_equal(22, d.hour)
+ assert_equal(31, d.min)
+ assert_equal(59, d.sec)
+ assert_equal(0, d.sec_fraction)
+ assert_equal('+00:00', d.zone)
+ assert_equal(0, d.offset)
+ end
+
+ assert_equal(1965, d.cwyear)
+ assert_equal(20, d.cweek)
+ assert_equal(7, d.cwday)
+
+ assert_equal(0, d.wday)
+ assert_equal(false, d.leap?)
+ assert_equal(false, d.julian?)
+ assert_equal(true, d.gregorian?)
+
+ assert_equal(Date::ITALY, d.start)
+ assert_equal(d.start, d.start)
+ end
+
+ d = DateTime.new(1965, 5, 23, 22, 31, 59) + 1.to_r/(86400*2)
+ assert_equal(1.to_r/2, d.sec_fraction)
+ end
+
+ def test__wday_predicate
+ d = Date.new(2005, 10, 23)
+ assert_equal(true, d.sunday?)
+ assert_equal(false, d.monday?)
+ assert_equal(false, d.tuesday?)
+ assert_equal(false, d.wednesday?)
+ assert_equal(false, d.thursday?)
+ assert_equal(false, d.friday?)
+ assert_equal(false, d.saturday?)
+
+ d = Date.new(2005, 10, 30)
+ 14.times do |i|
+ assert((d + i).__send__(%w(sunday? monday? tuesday? wednesday?
+ thursday? friday? saturday?)[i % 7]))
+ end
+ end
+
+ def test_nth_kday
+ assert_equal(false, Date.new(2001,1,14).__send__(:nth_kday?, 1,0))
+ assert_equal(true, Date.new(2001,1,14).__send__(:nth_kday?, 2,0))
+ assert_equal(false, Date.new(2001,1,14).__send__(:nth_kday?, 3,0))
+ assert_equal(false, Date.new(2001,1,14).__send__(:nth_kday?, 4,0))
+ assert_equal(false, Date.new(2001,1,14).__send__(:nth_kday?, 5,0))
+ assert_equal(false, Date.new(2001,1,14).__send__(:nth_kday?, -1,0))
+ assert_equal(false, Date.new(2001,1,14).__send__(:nth_kday?, -2,0))
+ assert_equal(true, Date.new(2001,1,14).__send__(:nth_kday?, -3,0))
+ assert_equal(false, Date.new(2001,1,14).__send__(:nth_kday?, -4,0))
+ assert_equal(false, Date.new(2001,1,14).__send__(:nth_kday?, -5,0))
+ end
+
+end
diff --git a/test/date/test_date_base.rb b/test/date/test_date_base.rb
new file mode 100644
index 0000000000..4b9bcf2aa4
--- /dev/null
+++ b/test/date/test_date_base.rb
@@ -0,0 +1,435 @@
+require 'test/unit'
+require 'date'
+
+begin
+ require 'calendar'
+ include Calendar
+rescue LoadError
+end
+
+class TestDateBase < Test::Unit::TestCase
+
+ def setup
+ if defined?(Calendar)
+ @from ||= julian_day_number_from_absolute(absolute_from_julian(1, 1, 1601))
+ @to ||= julian_day_number_from_absolute(absolute_from_julian(12, 31, 2400))
+ @from4t ||= julian_day_number_from_absolute(absolute_from_julian(1, 1, 1970))
+ @to4t ||= julian_day_number_from_absolute(absolute_from_julian(12, 31, 2037))
+ end
+ end
+
+ def test__inf
+ assert_equal(0, Date::Infinity.new(-1) <=> Date::Infinity.new(-1))
+ assert_equal(-1, Date::Infinity.new(-1) <=> Date::Infinity.new(+1))
+ assert_equal(-1, Date::Infinity.new(-1) <=> 0)
+
+ assert_equal(1, Date::Infinity.new(+1) <=> Date::Infinity.new(-1))
+ assert_equal(0, Date::Infinity.new(+1) <=> Date::Infinity.new(+1))
+ assert_equal(1, Date::Infinity.new(+1) <=> 0)
+
+ assert_equal(1, 0 <=> Date::Infinity.new(-1))
+ assert_equal(-1, 0 <=> Date::Infinity.new(+1))
+ assert_equal(0, 0 <=> 0)
+
+ assert_equal(0, Date::ITALY <=> Date::ITALY)
+ assert_equal(-1, Date::ITALY <=> Date::ENGLAND)
+ assert_equal(-1, Date::ITALY <=> Date::JULIAN)
+ assert_equal(1, Date::ITALY <=> Date::GREGORIAN)
+
+ assert_equal(1, Date::ENGLAND <=> Date::ITALY)
+ assert_equal(0, Date::ENGLAND <=> Date::ENGLAND)
+ assert_equal(-1, Date::ENGLAND <=> Date::JULIAN)
+ assert_equal(1, Date::ENGLAND <=> Date::GREGORIAN)
+
+ assert_equal(1, Date::JULIAN <=> Date::ITALY)
+ assert_equal(1, Date::JULIAN <=> Date::ENGLAND)
+ assert_equal(0, Date::JULIAN <=> Date::JULIAN)
+ assert_equal(1, Date::JULIAN <=> Date::GREGORIAN)
+
+ assert_equal(-1, Date::GREGORIAN <=> Date::ITALY)
+ assert_equal(-1, Date::GREGORIAN <=> Date::ENGLAND)
+ assert_equal(-1, Date::GREGORIAN <=> Date::JULIAN)
+ assert_equal(0, Date::GREGORIAN <=> Date::GREGORIAN)
+ end
+
+ def test_ordinal__julian
+ unless defined?(Calendar)
+ return
+ end
+ for j in @from..@to
+ m, d, y = julian_from_absolute(absolute_from_julian_day_number(j))
+ j0 = julian_day_number_from_absolute(absolute_from_julian(12, 31, y - 1))
+ j2 = julian_day_number_from_absolute(absolute_from_julian(m, d, y))
+ assert_equal(j, j2)
+ oy, od = Date.__send__(:jd_to_ordinal, j, Date::JULIAN)
+ assert_equal(y, oy)
+ assert_equal(j2 - j0, od)
+ oj = Date.__send__(:ordinal_to_jd, oy, od, Date::JULIAN)
+ assert_equal(j, oj)
+ end
+ end
+
+ def test_ordinal__gregorian
+ unless defined?(Calendar)
+ return
+ end
+ for j in @from..@to
+ m, d, y = gregorian_from_absolute(absolute_from_julian_day_number(j))
+ j0 =
+ julian_day_number_from_absolute(absolute_from_gregorian(12, 31, y - 1))
+ j2 = julian_day_number_from_absolute(absolute_from_gregorian(m, d, y))
+ assert_equal(j, j2)
+ oy, od = Date.__send__(:jd_to_ordinal, j, Date::GREGORIAN)
+ assert_equal(y, oy)
+ assert_equal(j2 - j0, od)
+ oj = Date.__send__(:ordinal_to_jd, oy, od, Date::GREGORIAN)
+ assert_equal(j, oj)
+ end
+ end
+
+ def test_civil__julian
+ unless defined?(Calendar)
+ return
+ end
+ for j in @from..@to
+ m, d, y = julian_from_absolute(absolute_from_julian_day_number(j))
+ j2 = julian_day_number_from_absolute(absolute_from_julian(m, d, y))
+ assert_equal(j2, j)
+ cy, cm, cd = Date.__send__(:jd_to_civil, j, Date::JULIAN)
+ assert_equal(y, cy)
+ assert_equal(m, cm)
+ assert_equal(d, cd)
+ cj = Date.__send__(:civil_to_jd, cy, cm, cd, Date::JULIAN)
+ assert_equal(j, cj)
+ end
+ end
+
+ def test_civil__gregorian
+ unless defined?(Calendar)
+ return
+ end
+ for j in @from..@to
+ m, d, y = gregorian_from_absolute(absolute_from_julian_day_number(j))
+ j2 = julian_day_number_from_absolute(absolute_from_gregorian(m, d, y))
+ assert_equal(j2, j)
+ cy, cm, cd = Date.__send__(:jd_to_civil, j, Date::GREGORIAN)
+ assert_equal(y, cy)
+ assert_equal(m, cm)
+ assert_equal(d, cd)
+ cj = Date.__send__(:civil_to_jd, cy, cm, cd, Date::GREGORIAN)
+ assert_equal(j, cj)
+ end
+ end
+
+ def test_commercial__gregorian
+ unless defined?(Calendar)
+ return
+ end
+ for j in @from..@to
+ w, d, y = iso_from_absolute(absolute_from_julian_day_number(j))
+ j2 = julian_day_number_from_absolute(absolute_from_iso(w, d, y))
+ assert_equal(j2, j)
+ cy, cw, cd = Date.__send__(:jd_to_commercial, j, Date::GREGORIAN)
+ assert_equal(y, cy)
+ assert_equal(w, cw)
+ assert_equal(d, cd)
+ cj = Date.__send__(:commercial_to_jd, cy, cw, cd, Date::GREGORIAN)
+ assert_equal(j, cj)
+ end
+ end
+
+ def test_weeknum
+ unless defined?(Calendar)
+ return
+ end
+ for j in @from..@to
+ for k in 0..1
+ wy, ww, wd = Date.__send__(:jd_to_weeknum, j, k, Date::GREGORIAN)
+ wj = Date.__send__(:weeknum_to_jd, wy, ww, wd, k, Date::GREGORIAN)
+ assert_equal(j, wj)
+ end
+ end
+ end
+
+ def test_weeknum__2
+ unless defined?(Calendar)
+ return
+ end
+ for j in @from4t..@to4t
+ d = Date.jd(j)
+ t = Time.mktime(d.year, d.mon, d.mday)
+ [
+ '%Y %U %w',
+ '%Y %U %u',
+ '%Y %W %w',
+ '%Y %W %u'
+ ].each do |fmt|
+ s = t.strftime(fmt)
+ d2 = Date.strptime(s, fmt)
+ assert_equal(j, d2.jd)
+ end
+ end
+ end
+
+ def test_nth_kday
+ unless defined?(Calendar)
+ return
+ end
+ for y in 1601..2401
+ for m in 1..12
+ for n in -5..5
+ next if n == 0
+ for k in 0..6
+ j = julian_day_number_from_absolute(Nth_Kday(n, k, m, y))
+ j2 = Date.__send__(:nth_kday_to_jd, y, m, n, k, Date::GREGORIAN)
+ assert_equal(j, j2)
+
+ d1 = Date.__send__(:jd_to_nth_kday, j2, Date::GREGORIAN)
+ j3 = Date.__send__(:nth_kday_to_jd, *d1)
+ assert_equal(j, j3)
+ end
+ end
+ end
+ end
+ end
+
+ def test_mjd
+ jd = Date.__send__(:mjd_to_jd, 51321)
+ mjd = Date.__send__(:jd_to_mjd, jd)
+ assert_equal(51321, mjd)
+ end
+
+ def test_ld
+ jd = Date.__send__(:ld_to_jd, 152162)
+ ld = Date.__send__(:jd_to_ld, jd)
+ assert_equal(152162, ld)
+ end
+
+ def test_wday
+ assert_equal(4, Date.__send__(:jd_to_wday, 3))
+ assert_equal(3, Date.__send__(:jd_to_wday, 2))
+ assert_equal(2, Date.__send__(:jd_to_wday, 1))
+ assert_equal(1, Date.__send__(:jd_to_wday, 0))
+ assert_equal(0, Date.__send__(:jd_to_wday, -1))
+ assert_equal(6, Date.__send__(:jd_to_wday, -2))
+ assert_equal(5, Date.__send__(:jd_to_wday, -3))
+ end
+
+ def test_leap?
+ assert_equal(true, Date.julian_leap?(1900))
+ assert_equal(false, Date.julian_leap?(1999))
+ assert_equal(true, Date.julian_leap?(2000))
+
+ assert_equal(false, Date.gregorian_leap?(1900))
+ assert_equal(false, Date.gregorian_leap?(1999))
+ assert_equal(true, Date.gregorian_leap?(2000))
+
+ assert_equal(Date.leap?(1990), Date.gregorian_leap?(1900))
+ assert_equal(Date.leap?(1999), Date.gregorian_leap?(1999))
+ assert_equal(Date.leap?(2000), Date.gregorian_leap?(2000))
+ end
+
+ def test_valid_jd
+ valid_jd_p = :_valid_jd?
+ assert_equal(-1, Date.__send__(valid_jd_p, -1))
+ assert_equal(0, Date.__send__(valid_jd_p, 0))
+ assert_equal(1, Date.__send__(valid_jd_p, 1))
+ assert_equal(2452348, Date.__send__(valid_jd_p, 2452348))
+ end
+
+ def test_valid_ordinal
+ valid_ordinal_p = :_valid_ordinal?
+ assert_nil(Date.__send__(valid_ordinal_p, 1999,366))
+ assert_equal(2451910, Date.__send__(valid_ordinal_p, 2000,366))
+ assert_nil(Date.__send__(valid_ordinal_p, 1999,-366))
+ assert_equal(2451545, Date.__send__(valid_ordinal_p, 2000,-366))
+ assert_equal(2452275, Date.__send__(valid_ordinal_p, 2001,365))
+ assert_nil(Date.__send__(valid_ordinal_p, 2001,366))
+ assert_equal(Date.__send__(valid_ordinal_p, 2001,1),
+ Date.__send__(valid_ordinal_p, 2001,-365))
+ assert_nil(Date.__send__(valid_ordinal_p, 2001,-366))
+ assert_equal(2452348, Date.__send__(valid_ordinal_p, 2002,73))
+ end
+
+ def test_valid_ordinal__edge
+ valid_ordinal_p = :_valid_ordinal?
+ (1601..2400).each do |y|
+ d = if Date.leap?(y) then 366 else 365 end
+ assert_not_nil(Date.__send__(valid_ordinal_p, y,d))
+ assert_nil(Date.__send__(valid_ordinal_p, y,d + 1))
+ assert_not_nil(Date.__send__(valid_ordinal_p, y,-d))
+ assert_nil(Date.__send__(valid_ordinal_p, y,-(d + 1)))
+ end
+ end
+
+ # October 1582
+ # S M Tu W Th F S
+ # 274 275 276 277 288 289
+ # 290 291 292 293 294 295 296
+ # 297 298 299 300 301 302 303
+ # 304
+
+ # October 1582
+ # S M Tu W Th F S
+ # -92 -91 -90 -89 -78 -77
+ # -76 -75 -74 -73 -72 -71 -70
+ # -69 -68 -67 -66 -65 -64 -63
+ # -62
+
+ def test_valid_ordinal__italy
+ valid_ordinal_p = :_valid_ordinal?
+ (1..355).each do |d|
+ assert_not_nil(Date.__send__(valid_ordinal_p, 1582,d,Date::ITALY))
+ end
+ (356..365).each do |d|
+ assert_nil(Date.__send__(valid_ordinal_p, 1582,d,Date::ITALY))
+ end
+ end
+
+ # September 1752
+ # S M Tu W Th F S
+ # 245 246 258 259 260
+ # 261 262 263 264 265 266 267
+ # 268 269 270 271 272 273 274
+
+ def test_valid_ordinal__england
+ valid_ordinal_p = :_valid_ordinal?
+ (1..355).each do |d|
+ assert_not_nil(Date.__send__(valid_ordinal_p, 1752,d,Date::ENGLAND))
+ end
+ (356..366).each do |d|
+ assert_nil(Date.__send__(valid_ordinal_p, 1752,d,Date::ENGLAND))
+ end
+ end
+
+ def test_valid_civil
+ valid_civil_p = :_valid_civil?
+ assert_nil(Date.__send__(valid_civil_p, 1999,2,29))
+ assert_equal(2451604, Date.__send__(valid_civil_p, 2000,2,29))
+ assert_nil(Date.__send__(valid_civil_p, 1999,2,-29))
+ assert_equal(2451576, Date.__send__(valid_civil_p, 2000,2,-29))
+ assert_equal(2451941, Date.__send__(valid_civil_p, 2001,1,31))
+ assert_nil(Date.__send__(valid_civil_p, 2001,1,32))
+ assert_equal(Date.__send__(valid_civil_p, 2001,1,1),
+ Date.__send__(valid_civil_p, 2001,1,-31))
+ assert_nil(Date.__send__(valid_civil_p, 2001,1,-32))
+ assert_equal(2452348, Date.__send__(valid_civil_p, 2002,3,14))
+ end
+
+ def test_valid_civil__edge
+ valid_civil_p = :_valid_civil?
+ (1601..2400).each do |y|
+ d = if Date.leap?(y) then 29 else 28 end
+ assert_not_nil(Date.__send__(valid_civil_p, y,2,d))
+ assert_nil(Date.__send__(valid_civil_p, y,2,d + 1))
+ assert_not_nil(Date.__send__(valid_civil_p, y,2,-d))
+ assert_nil(Date.__send__(valid_civil_p, y,2,-(d + 1)))
+ end
+ end
+
+ # October 1582
+ # S M Tu W Th F S
+ # 1 2 3 4 15 16
+ # 17 18 19 20 21 22 23
+ # 24 25 26 27 28 29 30
+ # 31
+
+ def test_valid_civil__italy
+ valid_civil_p = :_valid_civil?
+ (1..4).each do |d|
+ assert_not_nil(Date.__send__(valid_civil_p, 1582,10,d,Date::ITALY))
+ end
+ (5..14).each do |d|
+ assert_nil(Date.__send__(valid_civil_p, 1582,10,d,Date::ITALY))
+ end
+ (15..31).each do |d|
+ assert_not_nil(Date.__send__(valid_civil_p, 1582,10,d,Date::ITALY))
+ end
+ (32..100).each do |d|
+ assert_nil(Date.__send__(valid_civil_p, 1582,10,d,Date::ITALY))
+ end
+ (-31..-22).each do |d|
+ assert_nil(Date.__send__(valid_civil_p, 1582,10,d,Date::ITALY))
+ end
+ (-21..-1).each do |d|
+ assert_not_nil(Date.__send__(valid_civil_p, 1582,10,d,Date::ITALY))
+ end
+ end
+
+ # September 1752
+ # S M Tu W Th F S
+ # 1 2 14 15 16
+ # 17 18 19 20 21 22 23
+ # 24 25 26 27 28 29 30
+
+ def test_valid_civil__england
+ valid_civil_p = :_valid_civil?
+ (1..2).each do |d|
+ assert_not_nil(Date.__send__(valid_civil_p, 1752,9,d,Date::ENGLAND))
+ end
+ (3..13).each do |d|
+ assert_nil(Date.__send__(valid_civil_p, 1752,9,d,Date::ENGLAND))
+ end
+ (14..30).each do |d|
+ assert_not_nil(Date.__send__(valid_civil_p, 1752,9,d,Date::ENGLAND))
+ end
+ (31..100).each do |d|
+ assert_nil(Date.__send__(valid_civil_p, 1752,9,d,Date::ENGLAND))
+ end
+ (-31..-20).each do |d|
+ assert_nil(Date.__send__(valid_civil_p, 1752,9,d,Date::ENGLAND))
+ end
+ (-19..-1).each do |d|
+ assert_not_nil(Date.__send__(valid_civil_p, 1752,9,d,Date::ENGLAND))
+ end
+ end
+
+ def test_valid_commercial
+ valid_commercial_p = :_valid_commercial?
+ assert_nil(Date.__send__(valid_commercial_p, 1999,53,1))
+ assert_equal(2453367, Date.__send__(valid_commercial_p, 2004,53,1))
+ assert_nil(Date.__send__(valid_commercial_p, 1999,-53,-1))
+ assert_equal(2453009, Date.__send__(valid_commercial_p, 2004,-53,-1))
+ assert_equal(2452348, Date.__send__(valid_commercial_p, 2002,11,4))
+ end
+
+ def test_valid_weeknum
+ valid_weeknum_p = :_valid_weeknum?
+ assert_nil(Date.__send__(valid_weeknum_p, 1999,53,0, 0))
+ assert_equal(2454101, Date.__send__(valid_weeknum_p, 2006,53,0, 0))
+ assert_nil(Date.__send__(valid_weeknum_p, 1999,-53,-1, 0))
+ assert_equal(2453743, Date.__send__(valid_weeknum_p, 2006,-53,-1, 0))
+ assert_equal(2452355, Date.__send__(valid_weeknum_p, 2002,11,4, 0))
+ assert_nil(Date.__send__(valid_weeknum_p, 1999,53,0, 1))
+ assert_equal(2454101, Date.__send__(valid_weeknum_p, 2006,52,6, 1))
+ assert_nil(Date.__send__(valid_weeknum_p, 1999,-53,-1, 1))
+ assert_equal(2453743, Date.__send__(valid_weeknum_p, 2006,-52,-2, 1))
+ assert_equal(2452355, Date.__send__(valid_weeknum_p, 2002,11,3, 1))
+ end
+
+ def test_valid_nth_kday
+ valid_nth_kday_p = :_valid_nth_kday?
+ assert_nil(Date.__send__(valid_nth_kday_p, 1992,2, 5,0))
+ assert_equal(2448682, Date.__send__(valid_nth_kday_p, 1992,2, 5,6))
+ assert_equal(2448682, Date.__send__(valid_nth_kday_p, 1992,2, 5,-1))
+ assert_equal(2448682, Date.__send__(valid_nth_kday_p, 1992,2, -1,6))
+ assert_equal(2448682, Date.__send__(valid_nth_kday_p, 1992,2, -1,-1))
+ end
+
+ def test_valid_time
+ valid_time_p = :_valid_time?
+ assert_equal(Rational(0), DateTime.__send__(valid_time_p, 0,0,0))
+ assert_nil(DateTime.__send__(valid_time_p, 25,59,59))
+ assert_nil(DateTime.__send__(valid_time_p, 23,60,59))
+ assert_nil(DateTime.__send__(valid_time_p, 23,59,60))
+ assert_equal(Rational(86399, 86400),
+ DateTime.__send__(valid_time_p, 23,59,59))
+ assert_equal(Rational(86399, 86400),
+ DateTime.__send__(valid_time_p, -1,-1,-1))
+ assert_equal(Rational(1), DateTime.__send__(valid_time_p, 24,0,0))
+ assert_nil(DateTime.__send__(valid_time_p, 24,0,1))
+ assert_nil(DateTime.__send__(valid_time_p, 24,1,0))
+ assert_nil(DateTime.__send__(valid_time_p, 24,1,1))
+ end
+
+end
diff --git a/test/date/test_date_compat.rb b/test/date/test_date_compat.rb
new file mode 100644
index 0000000000..8284007407
--- /dev/null
+++ b/test/date/test_date_compat.rb
@@ -0,0 +1,21 @@
+require 'test/unit'
+require 'date'
+
+class TestDateCompat < Test::Unit::TestCase
+
+ def test_compat
+ assert_equal(DateTime.new, Date.new)
+ assert_equal(DateTime.new(2002,3,19), Date.new(2002,3,19))
+ assert_equal(DateTime.new(2002,3,19, 0,0,0), Date.new(2002,3,19))
+ assert_equal(DateTime.new(2002,3,19, 0,0,0, 0), Date.new(2002,3,19))
+ assert_equal(DateTime.new(2002,3,19, 0,0,0, 0.to_r), Date.new(2002,3,19))
+ assert_equal(DateTime.new(2002,3,19, 0,0,0, 0, Date::GREGORIAN), Date.new(2002,3,19, Date::GREGORIAN))
+ assert_equal(DateTime.new(2002,3,19, 0,0,0, 0, Date::JULIAN), Date.new(2002,3,19, Date::JULIAN))
+
+ assert(Date.new(2002,3,19) != DateTime.new(2002,3,19, 12,0,0))
+ assert(Date.new(2002,3,19) != DateTime.new(2002,3,19, 0,0,1))
+ assert(Date.new(2002,3,19) === DateTime.new(2002,3,19, 12,0,0))
+ assert(Date.new(2002,3,19) === DateTime.new(2002,3,19, 0,0,1))
+ end
+
+end
diff --git a/test/date/test_date_conv.rb b/test/date/test_date_conv.rb
new file mode 100644
index 0000000000..5565ca8e5e
--- /dev/null
+++ b/test/date/test_date_conv.rb
@@ -0,0 +1,130 @@
+require 'test/unit'
+require 'date'
+
+class TestDateConv < Test::Unit::TestCase
+
+ def test_to_class
+ [Time.now, Date.today, DateTime.now].each do |o|
+ assert_instance_of(Time, o.to_time)
+ assert_instance_of(Date, o.to_date)
+ assert_instance_of(DateTime, o.to_datetime)
+ end
+ end
+
+ def test_to_time__from_time
+ t = Time.mktime(2004, 9, 19, 1, 2, 3, 456789)
+ t2 = t.to_time
+ assert_equal([2004, 9, 19, 1, 2, 3, 456789],
+ [t2.year, t2.mon, t2.mday, t2.hour, t2.min, t2.sec, t2.usec])
+
+ t = Time.utc(2004, 9, 19, 1, 2, 3, 456789)
+ t2 = t.to_time.utc
+ assert_equal([2004, 9, 19, 1, 2, 3, 456789],
+ [t2.year, t2.mon, t2.mday, t2.hour, t2.min, t2.sec, t2.usec])
+ end
+
+ def test_to_time__from_date
+ d = Date.new(2004, 9, 19)
+ t = d.to_time
+ assert_equal([2004, 9, 19, 0, 0, 0, 0],
+ [t.year, t.mon, t.mday, t.hour, t.min, t.sec, t.usec])
+ end
+
+ def test_to_time__from_datetime
+ d = DateTime.new(2004, 9, 19, 1, 2, 3, 9.to_r/24) + 456789.to_r/86400000000
+ t = d.to_time
+ if t.utc_offset == 9*60*60
+ assert_equal([2004, 9, 19, 1, 2, 3, 456789],
+ [t.year, t.mon, t.mday, t.hour, t.min, t.sec, t.usec])
+ end
+
+ d = DateTime.new(2004, 9, 19, 1, 2, 3, 0) + 456789.to_r/86400000000
+ t = d.to_time.utc
+ assert_equal([2004, 9, 19, 1, 2, 3, 456789],
+ [t.year, t.mon, t.mday, t.hour, t.min, t.sec, t.usec])
+
+ if Time.allocate.respond_to?(:nsec)
+ d = DateTime.new(2004, 9, 19, 1, 2, 3, 0) + 456789123.to_r/86400000000000
+ t = d.to_time.utc
+ assert_equal([2004, 9, 19, 1, 2, 3, 456789123],
+ [t.year, t.mon, t.mday, t.hour, t.min, t.sec, t.nsec])
+ end
+ end
+
+ def test_to_date__from_time
+ t = Time.mktime(2004, 9, 19, 1, 2, 3, 456789)
+ d = t.to_date
+ assert_equal([2004, 9, 19, 0], [d.year, d.mon, d.mday, d.day_fraction])
+
+ t = Time.utc(2004, 9, 19, 1, 2, 3, 456789)
+ d = t.to_date
+ assert_equal([2004, 9, 19, 0], [d.year, d.mon, d.mday, d.day_fraction])
+ end
+
+ def test_to_date__from_date
+ d = Date.new(2004, 9, 19) + 1.to_r/2
+ d2 = d.to_date
+ assert_equal([2004, 9, 19, 1.to_r/2],
+ [d2.year, d2.mon, d2.mday, d2.day_fraction])
+ end
+
+ def test_to_date__from_datetime
+ d = DateTime.new(2004, 9, 19, 1, 2, 3, 9.to_r/24) + 456789.to_r/86400000000
+ d2 = d.to_date
+ assert_equal([2004, 9, 19, 0], [d2.year, d2.mon, d2.mday, d2.day_fraction])
+
+ d = DateTime.new(2004, 9, 19, 1, 2, 3, 0) + 456789.to_r/86400000000
+ d2 = d.to_date
+ assert_equal([2004, 9, 19, 0], [d2.year, d2.mon, d2.mday, d2.day_fraction])
+ end
+
+ def test_to_datetime__from_time
+ t = Time.mktime(2004, 9, 19, 1, 2, 3, 456789)
+ d = t.to_datetime
+ assert_equal([2004, 9, 19, 1, 2, 3,
+ 456789.to_r/1000000,
+ t.utc_offset.to_r/86400],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec,
+ d.sec_fraction, d.offset])
+
+ t = Time.utc(2004, 9, 19, 1, 2, 3, 456789)
+ d = t.to_datetime
+ assert_equal([2004, 9, 19, 1, 2, 3,
+ 456789.to_r/1000000,
+ 0],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec,
+ d.sec_fraction, d.offset])
+
+ t = Time.now
+ d = t.to_datetime
+ require 'time'
+ assert_equal(t.iso8601(10), d.iso8601(10))
+ end
+
+ def test_to_datetime__from_date
+ d = Date.new(2004, 9, 19) + 1.to_r/2
+ d2 = d.to_datetime
+ assert_equal([2004, 9, 19, 0, 0, 0, 0, 0],
+ [d2.year, d2.mon, d2.mday, d2.hour, d2.min, d2.sec,
+ d2.sec_fraction, d2.offset])
+ end
+
+ def test_to_datetime__from_datetime
+ d = DateTime.new(2004, 9, 19, 1, 2, 3, 9.to_r/24) + 456789.to_r/86400000000
+ d2 = d.to_datetime
+ assert_equal([2004, 9, 19, 1, 2, 3,
+ 456789.to_r/1000000,
+ 9.to_r/24],
+ [d2.year, d2.mon, d2.mday, d2.hour, d2.min, d2.sec,
+ d2.sec_fraction, d2.offset])
+
+ d = DateTime.new(2004, 9, 19, 1, 2, 3, 0) + 456789.to_r/86400000000
+ d2 = d.to_datetime
+ assert_equal([2004, 9, 19, 1, 2, 3,
+ 456789.to_r/1000000,
+ 0],
+ [d2.year, d2.mon, d2.mday, d2.hour, d2.min, d2.sec,
+ d2.sec_fraction, d2.offset])
+ end
+
+end
diff --git a/test/date/test_date_marshal.rb b/test/date/test_date_marshal.rb
new file mode 100644
index 0000000000..2f86a8c8c2
--- /dev/null
+++ b/test/date/test_date_marshal.rb
@@ -0,0 +1,29 @@
+require 'test/unit'
+require 'date'
+
+class TestDateMarshal < Test::Unit::TestCase
+
+ def test_marshal
+ d = Date.new
+ m = Marshal.dump(d)
+ d2 = Marshal.load(m)
+ assert_equal(d, d2)
+ assert_equal(d.start, d2.start)
+ assert_instance_of(String, d2.to_s)
+
+ d = Date.today
+ m = Marshal.dump(d)
+ d2 = Marshal.load(m)
+ assert_equal(d, d2)
+ assert_equal(d.start, d2.start)
+ assert_instance_of(String, d2.to_s)
+
+ d = DateTime.now
+ m = Marshal.dump(d)
+ d2 = Marshal.load(m)
+ assert_equal(d, d2)
+ assert_equal(d.start, d2.start)
+ assert_instance_of(String, d2.to_s)
+ end
+
+end
diff --git a/test/date/test_date_new.rb b/test/date/test_date_new.rb
new file mode 100644
index 0000000000..14ff247294
--- /dev/null
+++ b/test/date/test_date_new.rb
@@ -0,0 +1,278 @@
+require 'test/unit'
+require 'date'
+
+class TestDateNew < Test::Unit::TestCase
+
+ def test_jd
+ d = Date.jd
+ dt = DateTime.jd
+ assert_equal([-4712, 1, 1], [d.year, d.mon, d.mday])
+ assert_equal([-4712, 1, 1], [dt.year, dt.mon, dt.mday])
+ assert_equal([0, 0, 0], [dt.hour, dt.min, dt.sec])
+
+ d2 = Date.jd
+ dt2 = DateTime.jd
+ assert_equal(d, d2)
+ assert_equal(dt, dt2)
+
+ d = Date.jd(0)
+ assert_equal([-4712, 1, 1], [d.year, d.mon, d.mday])
+ d = DateTime.jd(0, 0,0,0, 0)
+ assert_equal([-4712, 1, 1, 0, 0, 0, 0],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec, d.offset])
+ d = DateTime.jd(0, 0,0,0, '+0900')
+ assert_equal([-4712, 1, 1, 0, 0, 0, 9.to_r/24],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec, d.offset])
+ end
+
+ def test_jd__ex
+ assert_raise(ArgumentError) do
+ DateTime.jd(0, 23,59,60,0)
+ end
+ end
+
+ def test_ordinal
+ d = Date.ordinal
+ dt = DateTime.ordinal
+ assert_equal([-4712, 1, 1], [d.year, d.mon, d.mday])
+ assert_equal([-4712, 1, 1], [dt.year, dt.mon, dt.mday])
+ assert_equal([0, 0, 0], [dt.hour, dt.min, dt.sec])
+
+ d2 = Date.ordinal
+ dt2 = DateTime.ordinal
+ assert_equal(d, d2)
+ assert_equal(dt, dt2)
+
+ d = Date.ordinal(-4712,1)
+ assert_equal([-4712, 1, 1], [d.year, d.mon, d.mday])
+
+ d = Date.ordinal(-4712,1.0)
+ assert_equal([-4712, 1, 1], [d.year, d.mon, d.mday])
+
+ d = DateTime.ordinal(-4712,1, 0,0,0, 0)
+ assert_equal([-4712, 1, 1, 0, 0, 0, 0],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec, d.offset])
+ d = DateTime.ordinal(-4712,1, 0,0,0, '+0900')
+ assert_equal([-4712, 1, 1, 0, 0, 0, 9.to_r/24],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec, d.offset])
+ end
+
+ def test_ordinal__neg
+ d = Date.ordinal(-1,-1)
+ assert_equal([-1, 365], [d.year, d.yday])
+
+ d = DateTime.ordinal(-1,-1, -1,-1,-1, 0)
+ assert_equal([-1, 365, 23, 59, 59, 0],
+ [d.year, d.yday, d.hour, d.min, d.sec, d.offset])
+ end
+
+ def test_ordinal__ex
+ assert_raise(ArgumentError) do
+ Date.ordinal(2001,1.1)
+ end
+ assert_raise(ArgumentError) do
+ Date.ordinal(2001,366)
+ end
+ assert_raise(ArgumentError) do
+ DateTime.ordinal(2001,365, 23,59,60, 0)
+ end
+ end
+
+ def test_civil
+ d = Date.civil
+ dt = DateTime.civil
+ assert_equal([-4712, 1, 1], [d.year, d.mon, d.mday])
+ assert_equal([-4712, 1, 1], [dt.year, dt.mon, dt.mday])
+ assert_equal([0, 0, 0], [dt.hour, dt.min, dt.sec])
+
+ d2 = Date.civil
+ dt2 = DateTime.civil
+ assert_equal(d, d2)
+ assert_equal(dt, dt2)
+
+ d = Date.civil(-4712,1,1)
+ assert_equal([-4712, 1, 1], [d.year, d.mon, d.mday])
+
+ d = Date.civil(-4712,1,1.0)
+ assert_equal([-4712, 1, 1], [d.year, d.mon, d.mday])
+
+ d = DateTime.civil(-4712,1,1, 0,0,0, 0)
+ assert_equal([-4712, 1, 1, 0, 0, 0, 0],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec, d.offset])
+ d = DateTime.civil(-4712,1,1, 0,0,0, '+0900')
+ assert_equal([-4712, 1, 1, 0, 0, 0, 9.to_r/24],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec, d.offset])
+
+
+ d = DateTime.civil(2001,2,3 + 1.to_r/2)
+ assert_equal([2001, 2, 3, 12, 0, 0, 0],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec, d.offset])
+ d = DateTime.civil(2001,2,3, 4 + 1.to_r/2)
+ assert_equal([2001, 2, 3, 4, 30, 0, 0],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec, d.offset])
+ d = DateTime.civil(2001,2,3, 4,5 + 1.to_r/2)
+ assert_equal([2001, 2, 3, 4, 5, 30, 0],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec, d.offset])
+ d = DateTime.civil(2001,2,3, 4,5,6 + 1.to_r/2)
+ assert_equal([2001, 2, 3, 4, 5, 6, 0],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec, d.offset])
+ assert_equal(1.to_r/2, d.sec_fraction)
+ end
+
+ def test_civil__neg
+ d = Date.civil(-1,-1,-1)
+ assert_equal([-1, 12, 31], [d.year, d.mon, d.mday])
+
+ d = DateTime.civil(-1,-1,-1, -1,-1,-1, 0)
+ assert_equal([-1, 12, 31, 23, 59, 59, 0],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec, d.offset])
+ end
+
+ def test_civil__ex
+ assert_raise(ArgumentError) do
+ Date.civil(2001,2,1.1)
+ end
+ assert_raise(ArgumentError) do
+ Date.civil(2001,2,29)
+ end
+ assert_raise(ArgumentError) do
+ DateTime.civil(2001,2,28, 23,59,60, 0)
+ end
+ assert_raise(ArgumentError) do
+ DateTime.civil(2001,2,28, 24,59,59, 0)
+ end
+ end
+
+ def test_civil__reform
+ d = Date.jd(Date::ENGLAND, Date::ENGLAND)
+ dt = DateTime.jd(Date::ENGLAND, 0,0,0,0, Date::ENGLAND)
+ assert_equal([1752, 9, 14], [d.year, d.mon, d.mday])
+ assert_equal([1752, 9, 14], [dt.year, dt.mon, dt.mday])
+ d -= 1
+ dt -= 1
+ assert_equal([1752, 9, 2], [d.year, d.mon, d.mday])
+ assert_equal([1752, 9, 2], [dt.year, dt.mon, dt.mday])
+
+ d = Date.jd(Date::ITALY, Date::ITALY)
+ dt = DateTime.jd(Date::ITALY, 0,0,0,0, Date::ITALY)
+ assert_equal([1582, 10, 15], [d.year, d.mon, d.mday])
+ assert_equal([1582, 10, 15], [dt.year, dt.mon, dt.mday])
+ d -= 1
+ dt -= 1
+ assert_equal([1582, 10, 4], [d.year, d.mon, d.mday])
+ assert_equal([1582, 10, 4], [dt.year, dt.mon, dt.mday])
+ end
+
+ def test_commercial
+ d = Date.commercial
+ dt = DateTime.commercial
+ assert_equal([-4712, 1, 1], [d.year, d.mon, d.mday])
+ assert_equal([-4712, 1, 1], [dt.year, dt.mon, dt.mday])
+ assert_equal([0, 0, 0], [dt.hour, dt.min, dt.sec])
+
+ d2 = Date.commercial
+ dt2 = DateTime.commercial
+ assert_equal(d, d2)
+ assert_equal(dt, dt2)
+
+ d = Date.commercial(1582,40,5)
+ assert_equal([1582, 10, 15], [d.year, d.mon, d.mday])
+
+ d = Date.commercial(1582,40,5.0)
+ assert_equal([1582, 10, 15], [d.year, d.mon, d.mday])
+
+ d = DateTime.commercial(1582,40,5, 0,0,0, 0)
+ assert_equal([1582, 10, 15, 0, 0, 0, 0],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec, d.offset])
+ d = DateTime.commercial(1582,40,5, 0,0,0, '+0900')
+ assert_equal([1582, 10, 15, 0, 0, 0, 9.to_r/24],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec, d.offset])
+ end
+
+ def test_commercial__neg
+ d = Date.commercial(1998,-1,-1)
+ assert_equal([1999, 1, 3], [d.year, d.mon, d.mday])
+
+ d = DateTime.commercial(1998,-1,-1, -1,-1,-1, 0)
+ assert_equal([1999, 1, 3, 23, 59, 59, 0],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec, d.offset])
+ end
+
+ def test_commercial__ex
+ assert_raise(ArgumentError) do
+ Date.commercial(1997,1,1.1)
+ end
+ assert_raise(ArgumentError) do
+ Date.commercial(1997,53,1)
+ end
+ assert_raise(ArgumentError) do
+ DateTime.commercial(1997,52,1, 23,59,60, 0)
+ end
+ end
+
+ def test_weeknum
+ d = Date.__send__(:weeknum)
+ dt = DateTime.__send__(:weeknum)
+ assert_equal([-4712, 1, 1], [d.year, d.mon, d.mday])
+ assert_equal([-4712, 1, 1], [dt.year, dt.mon, dt.mday])
+ assert_equal([0, 0, 0], [dt.hour, dt.min, dt.sec])
+
+ d = Date.__send__(:weeknum, 2002,11,4, 0)
+ assert_equal(2452355, d.jd)
+
+ d = DateTime.__send__(:weeknum, 2002,11,4, 0, 11,22,33)
+ assert_equal(2452355, d.jd)
+ assert_equal([11,22,33], [d.hour, d.min, d.sec])
+
+ assert_raise(ArgumentError) do
+ Date.__send__(:weeknum, 1999,53,0, 0)
+ end
+ assert_raise(ArgumentError) do
+ Date.__send__(:weeknum, 1999,-53,-1, 0)
+ end
+ end
+
+ def test_nth_kday
+ d = Date.__send__(:nth_kday)
+ dt = DateTime.__send__(:nth_kday)
+ assert_equal([-4712, 1, 1], [d.year, d.mon, d.mday])
+ assert_equal([-4712, 1, 1], [dt.year, dt.mon, dt.mday])
+ assert_equal([0, 0, 0], [dt.hour, dt.min, dt.sec])
+
+ d = Date.__send__(:nth_kday, 1992,2, 5,6)
+ assert_equal(2448682, d.jd)
+
+ d = DateTime.__send__(:nth_kday, 1992,2, 5,6, 11,22,33)
+ assert_equal(2448682, d.jd)
+ assert_equal([11,22,33], [d.hour, d.min, d.sec])
+
+ assert_raise(ArgumentError) do
+ Date.__send__(:nth_kday, 2006,5, 5,0)
+ end
+ assert_raise(ArgumentError) do
+ Date.__send__(:nth_kday, 2006,5, -5,0)
+ end
+ end
+
+ def test_today
+ z = Time.now
+ d = Date.today
+ t = Time.now
+ t2 = Time.utc(t.year, t.mon, t.mday)
+ t3 = Time.utc(d.year, d.mon, d.mday)
+ assert_in_delta(t2, t3, t - z + 2)
+
+ assert_equal(false, DateTime.respond_to?(:today))
+ end
+
+ def test_now
+ assert_equal(false, Date.respond_to?(:now))
+
+ z = Time.now
+ d = DateTime.now
+ t = Time.now
+ t2 = Time.local(d.year, d.mon, d.mday, d.hour, d.min, d.sec)
+ assert_in_delta(t, t2, t - z + 2)
+ end
+
+end
diff --git a/test/date/test_date_parse.rb b/test/date/test_date_parse.rb
new file mode 100644
index 0000000000..c44523fd98
--- /dev/null
+++ b/test/date/test_date_parse.rb
@@ -0,0 +1,973 @@
+require 'test/unit'
+require 'date'
+
+class TestDateParse < Test::Unit::TestCase
+
+ def test__parse
+ [
+ # ctime(3), asctime(3)
+ [['Sat Aug 28 02:55:50 1999',false],[1999,8,28,2,55,50,nil,nil,6]],
+ [['Sat Aug 28 02:55:50 02',false],[2,8,28,2,55,50,nil,nil,6]],
+ [['Sat Aug 28 02:55:50 02',true],[2002,8,28,2,55,50,nil,nil,6]],
+ [['Sat Aug 28 02:55:50 0002',false],[2,8,28,2,55,50,nil,nil,6]],
+ [['Sat Aug 28 02:55:50 0002',true],[2,8,28,2,55,50,nil,nil,6]],
+
+ # date(1)
+ [['Sat Aug 28 02:29:34 JST 1999',false],[1999,8,28,2,29,34,'JST',9*3600,6]],
+ [['Sat Aug 28 02:29:34 MET DST 1999',false],[1999,8,28,2,29,34,'MET DST',2*3600,6]],
+ [['Sat Aug 28 02:29:34 AMT 1999',false],[1999,8,28,2,29,34,'AMT',nil,6]],
+ [['Sat Aug 28 02:29:34 PMT 1999',false],[1999,8,28,2,29,34,'PMT',nil,6]],
+ [['Sat Aug 28 02:29:34 PMT -1999',false],[-1999,8,28,2,29,34,'PMT',nil,6]],
+
+ [['Sat Aug 28 02:29:34 JST 02',false],[2,8,28,2,29,34,'JST',9*3600,6]],
+ [['Sat Aug 28 02:29:34 JST 02',true],[2002,8,28,2,29,34,'JST',9*3600,6]],
+ [['Sat Aug 28 02:29:34 JST 0002',false],[2,8,28,2,29,34,'JST',9*3600,6]],
+ [['Sat Aug 28 02:29:34 JST 0002',true],[2,8,28,2,29,34,'JST',9*3600,6]],
+
+ [['Sat Aug 28 02:29:34 GMT+09 0002',false],[2,8,28,2,29,34,'GMT+09',9*3600,6]],
+ [['Sat Aug 28 02:29:34 GMT+0900 0002',false],[2,8,28,2,29,34,'GMT+0900',9*3600,6]],
+ [['Sat Aug 28 02:29:34 GMT+09:00 0002',false],[2,8,28,2,29,34,'GMT+09:00',9*3600,6]],
+ [['Sat Aug 28 02:29:34 GMT-09 0002',false],[2,8,28,2,29,34,'GMT-09',-9*3600,6]],
+ [['Sat Aug 28 02:29:34 GMT-0900 0002',false],[2,8,28,2,29,34,'GMT-0900',-9*3600,6]],
+ [['Sat Aug 28 02:29:34 GMT-09:00 0002',false],[2,8,28,2,29,34,'GMT-09:00',-9*3600,6]],
+ [['Sat Aug 28 02:29:34 GMT-090102 0002',false],[2,8,28,2,29,34,'GMT-090102',-9*3600-60-2,6]],
+ [['Sat Aug 28 02:29:34 GMT-09:01:02 0002',false],[2,8,28,2,29,34,'GMT-09:01:02',-9*3600-60-2,6]],
+
+ [['Sat Aug 28 02:29:34 GMT Standard Time 2000',false],[2000,8,28,2,29,34,'GMT Standard Time',0*3600,6]],
+ [['Sat Aug 28 02:29:34 Mountain Standard Time 2000',false],[2000,8,28,2,29,34,'Mountain Standard Time',-7*3600,6]],
+ [['Sat Aug 28 02:29:34 Mountain Daylight Time 2000',false],[2000,8,28,2,29,34,'Mountain Daylight Time',-6*3600,6]],
+ [['Sat Aug 28 02:29:34 Mexico Standard Time 2000',false],[2000,8,28,2,29,34,'Mexico Standard Time',-6*3600,6]],
+# [['Sat Aug 28 02:29:34 Mexico Standard Time 2 2000',false],[2000,8,28,2,29,34,'Mexico Standard Time 2',-7*3600,6]], # cp
+ [['Sat Aug 28 02:29:34 E. Australia Standard Time 2000',false],[2000,8,28,2,29,34,'E. Australia Standard Time',10*3600,6]],
+
+ # part of iso 8601
+ [['1999-05-23 23:55:21',false],[1999,5,23,23,55,21,nil,nil,nil]],
+ [['1999-05-23 23:55:21+0900',false],[1999,5,23,23,55,21,'+0900',9*3600,nil]],
+ [['1999-05-23 23:55:21-0900',false],[1999,5,23,23,55,21,'-0900',-9*3600,nil]],
+ [['1999-05-23 23:55:21+09:00',false],[1999,5,23,23,55,21,'+09:00',9*3600,nil]],
+ [['1999-05-23T23:55:21-09:00',false],[1999,5,23,23,55,21,'-09:00',-9*3600,nil]],
+ [['1999-05-23 23:55:21Z',false],[1999,5,23,23,55,21,'Z',0,nil]],
+ [['1999-05-23T23:55:21Z',false],[1999,5,23,23,55,21,'Z',0,nil]],
+ [['-1999-05-23T23:55:21Z',false],[-1999,5,23,23,55,21,'Z',0,nil]],
+ [['-1999-05-23T23:55:21Z',true],[-1999,5,23,23,55,21,'Z',0,nil]],
+ [['19990523T23:55:21Z',false],[1999,5,23,23,55,21,'Z',0,nil]],
+
+ [['+011985-04-12',false],[11985,4,12,nil,nil,nil,nil,nil,nil]],
+ [['+011985-04-12T10:15:30',false],[11985,4,12,10,15,30,nil,nil,nil]],
+ [['-011985-04-12',false],[-11985,4,12,nil,nil,nil,nil,nil,nil]],
+ [['-011985-04-12T10:15:30',false],[-11985,4,12,10,15,30,nil,nil,nil]],
+
+ [['02-04-12',false],[2,4,12,nil,nil,nil,nil,nil,nil]],
+ [['02-04-12',true],[2002,4,12,nil,nil,nil,nil,nil,nil]],
+ [['0002-04-12',false],[2,4,12,nil,nil,nil,nil,nil,nil]],
+ [['0002-04-12',true],[2,4,12,nil,nil,nil,nil,nil,nil]],
+
+ [['19990523',true],[1999,5,23,nil,nil,nil,nil,nil,nil]],
+ [['-19990523',true],[-1999,5,23,nil,nil,nil,nil,nil,nil]],
+ [['990523',true],[1999,5,23,nil,nil,nil,nil,nil,nil]],
+ [['0523',false],[nil,5,23,nil,nil,nil,nil,nil,nil]],
+ [['23',false],[nil,nil,23,nil,nil,nil,nil,nil,nil]],
+
+ [['19990523 235521',true],[1999,5,23,23,55,21,nil,nil,nil]],
+ [['990523 235521',true],[1999,5,23,23,55,21,nil,nil,nil]],
+ [['0523 2355',false],[nil,5,23,23,55,nil,nil,nil,nil]],
+ [['23 2355',false],[nil,nil,23,23,55,nil,nil,nil,nil]],
+
+ [['19990523T235521',true],[1999,5,23,23,55,21,nil,nil,nil]],
+ [['990523T235521',true],[1999,5,23,23,55,21,nil,nil,nil]],
+ [['19990523T235521.99',true],[1999,5,23,23,55,21,nil,nil,nil]],
+ [['990523T235521.99',true],[1999,5,23,23,55,21,nil,nil,nil]],
+ [['0523T2355',false],[nil,5,23,23,55,nil,nil,nil,nil]],
+
+ [['19990523T235521+0900',true],[1999,5,23,23,55,21,'+0900',9*3600,nil]],
+ [['990523T235521-0900',true],[1999,5,23,23,55,21,'-0900',-9*3600,nil]],
+ [['19990523T235521.99+0900',true],[1999,5,23,23,55,21,'+0900',9*3600,nil]],
+ [['990523T235521.99-0900',true],[1999,5,23,23,55,21,'-0900',-9*3600,nil]],
+ [['0523T2355Z',false],[nil,5,23,23,55,nil,'Z',0,nil]],
+
+ [['19990523235521.123456+0900',true],[1999,5,23,23,55,21,'+0900',9*3600,nil]],
+ [['19990523235521.123456-0900',true],[1999,5,23,23,55,21,'-0900',-9*3600,nil]],
+ [['19990523235521,123456+0900',true],[1999,5,23,23,55,21,'+0900',9*3600,nil]],
+ [['19990523235521,123456-0900',true],[1999,5,23,23,55,21,'-0900',-9*3600,nil]],
+
+ [['990523235521,123456-0900',false],[99,5,23,23,55,21,'-0900',-9*3600,nil]],
+ [['0523235521,123456-0900',false],[nil,5,23,23,55,21,'-0900',-9*3600,nil]],
+ [['23235521,123456-0900',false],[nil,nil,23,23,55,21,'-0900',-9*3600,nil]],
+ [['235521,123456-0900',false],[nil,nil,nil,23,55,21,'-0900',-9*3600,nil]],
+ [['5521,123456-0900',false],[nil,nil,nil,nil,55,21,'-0900',-9*3600,nil]],
+ [['21,123456-0900',false],[nil,nil,nil,nil,nil,21,'-0900',-9*3600,nil]],
+
+ [['3235521,123456-0900',false],[nil,nil,3,23,55,21,'-0900',-9*3600,nil]],
+ [['35521,123456-0900',false],[nil,nil,nil,3,55,21,'-0900',-9*3600,nil]],
+ [['521,123456-0900',false],[nil,nil,nil,nil,5,21,'-0900',-9*3600,nil]],
+
+ # reversed iso 8601 (?)
+ [['23-05-1999',false],[1999,5,23,nil,nil,nil,nil,nil,nil]],
+ [['23-05-1999 23:55:21',false],[1999,5,23,23,55,21,nil,nil,nil]],
+ [['23-05--1999 23:55:21',false],[-1999,5,23,23,55,21,nil,nil,nil]],
+ [["23-05-'99",false],[99,5,23,nil,nil,nil,nil,nil,nil]],
+ [["23-05-'99",true],[1999,5,23,nil,nil,nil,nil,nil,nil]],
+
+ # broken iso 8601 (?)
+# [['1999-05-23T235521Z',false],[1999,5,23,23,55,21,'Z',0,nil]], # cp
+ [['19990523T23:55:21Z',false],[1999,5,23,23,55,21,'Z',0,nil]],
+ [['19990523235521.1234-100',true],[1999,5,23,23,55,21,'-100',-1*3600,nil]],
+ [['19990523235521.1234-10',true],[1999,5,23,23,55,21,'-10',-10*3600,nil]],
+
+ # part of jis x0301
+ [['M11.05.23',false],[1878,5,23,nil,nil,nil,nil,nil,nil]],
+ [['T11.05.23 23:55:21+0900',false],[1922,5,23,23,55,21,'+0900',9*3600,nil]],
+ [['S11.05.23 23:55:21-0900',false],[1936,5,23,23,55,21,'-0900',-9*3600,nil]],
+ [['S40.05.23 23:55:21+09:00',false],[1965,5,23,23,55,21,'+09:00',9*3600,nil]],
+ [['S40.05.23T23:55:21-09:00',false],[1965,5,23,23,55,21,'-09:00',-9*3600,nil]],
+ [['H11.05.23 23:55:21Z',false],[1999,5,23,23,55,21,'Z',0,nil]],
+ [['H11.05.23T23:55:21Z',false],[1999,5,23,23,55,21,'Z',0,nil]],
+
+ # ofx date
+ [['19990523235521',false],[1999,5,23,23,55,21,nil,nil,nil]],
+ [['19990523235521.123',false],[1999,5,23,23,55,21,nil,nil,nil]],
+ [['19990523235521.123[-9]',false],[1999,5,23,23,55,21,'-9',-(9*3600),nil]],
+ [['19990523235521.123[+9]',false],[1999,5,23,23,55,21,'+9',+(9*3600),nil]],
+ [['19990523235521.123[9]',false],[1999,5,23,23,55,21,'9',+(9*3600),nil]],
+ [['19990523235521.123[-9.50]',false],[1999,5,23,23,55,21,'-9.50',-(9*3600+30*60),nil]],
+ [['19990523235521.123[+9.50]',false],[1999,5,23,23,55,21,'+9.50',+(9*3600+30*60),nil]],
+ [['19990523235521.123[-5:EST]',false],[1999,5,23,23,55,21,'EST',-5*3600,nil]],
+ [['19990523235521.123[+9:JST]',false],[1999,5,23,23,55,21,'JST',9*3600,nil]],
+ [['19990523235521.123[+12:XXX YYY ZZZ]',false],[1999,5,23,23,55,21,'XXX YYY ZZZ',12*3600,nil]],
+# [['235521',false],[nil,nil,nil,23,55,21,nil,nil,nil]], # cp
+ [['235521.123',false],[nil,nil,nil,23,55,21,nil,nil,nil]],
+ [['235521.123[-9]',false],[nil,nil,nil,23,55,21,'-9',-9*3600,nil]],
+ [['235521.123[+9]',false],[nil,nil,nil,23,55,21,'+9',+9*3600,nil]],
+ [['235521.123[-5:EST]',false],[nil,nil,nil,23,55,21,'EST',-5*3600,nil]],
+ [['235521.123[+9:JST]',false],[nil,nil,nil,23,55,21,'JST',+9*3600,nil]],
+
+ # rfc 2822
+ [['Sun, 22 Aug 1999 00:45:29 -0400',false],[1999,8,22,0,45,29,'-0400',-4*3600,0]],
+ [['Sun, 22 Aug 1999 00:45:29 -9959',false],[1999,8,22,0,45,29,'-9959',-(99*3600+59*60),0]],
+ [['Sun, 22 Aug 1999 00:45:29 +9959',false],[1999,8,22,0,45,29,'+9959',+(99*3600+59*60),0]],
+ [['Sun, 22 Aug 05 00:45:29 -0400',true],[2005,8,22,0,45,29,'-0400',-4*3600,0]],
+ [['Sun, 22 Aug 49 00:45:29 -0400',true],[2049,8,22,0,45,29,'-0400',-4*3600,0]],
+# [['Sun, 22 Aug 50 00:45:29 -0400',true],[1950,8,22,0,45,29,'-0400',-4*3600,0]],
+# [['Sun, 22 Aug 111 00:45:29 -0400',true],[2011,8,22,0,45,29,'-0400',-4*3600,0]],
+ [['Sun, 22 Aug 1999 00:45:29 GMT',false],[1999,8,22,0,45,29,'GMT',0,0]],
+ [["Sun,\00022\r\nAug\r\n1999\r\n00:45:29\r\nGMT",false],[1999,8,22,0,45,29,'GMT',0,0]],
+ [['Sun, 22 Aug 1999 00:45 GMT',false],[1999,8,22,0,45,nil,'GMT',0,0]],
+ [['Sun, 22 Aug -1999 00:45 GMT',false],[-1999,8,22,0,45,nil,'GMT',0,0]],
+ [['Sun, 22 Aug 99 00:45:29 UT',true],[1999,8,22,0,45,29,'UT',0,0]],
+ [['Sun, 22 Aug 0099 00:45:29 UT',true],[99,8,22,0,45,29,'UT',0,0]],
+
+ # rfc 850, obsoleted by rfc 1036
+ [['Tuesday, 02-Mar-99 11:20:32 GMT',true],[1999,3,2,11,20,32,'GMT',0,2]],
+
+ # W3C Working Draft - XForms - 4.8 Time
+ [['2000-01-31 13:20:00-5',false],[2000,1,31,13,20,0,'-5',-5*3600,nil]],
+
+ # [-+]\d+.\d+
+ [['2000-01-31 13:20:00-5.5',false],[2000,1,31,13,20,0,'-5.5',-5*3600-30*60,nil]],
+ [['2000-01-31 13:20:00-5,5',false],[2000,1,31,13,20,0,'-5,5',-5*3600-30*60,nil]],
+ [['2000-01-31 13:20:00+3.5',false],[2000,1,31,13,20,0,'+3.5',3*3600+30*60,nil]],
+ [['2000-01-31 13:20:00+3,5',false],[2000,1,31,13,20,0,'+3,5',3*3600+30*60,nil]],
+
+ # mil
+ [['2000-01-31 13:20:00 Z',false],[2000,1,31,13,20,0,'Z',0*3600,nil]],
+ [['2000-01-31 13:20:00 H',false],[2000,1,31,13,20,0,'H',8*3600,nil]],
+ [['2000-01-31 13:20:00 M',false],[2000,1,31,13,20,0,'M',12*3600,nil]],
+ [['2000-01-31 13:20 M',false],[2000,1,31,13,20,nil,'M',12*3600,nil]],
+ [['2000-01-31 13:20:00 S',false],[2000,1,31,13,20,0,'S',-6*3600,nil]],
+ [['2000-01-31 13:20:00 A',false],[2000,1,31,13,20,0,'A',1*3600,nil]],
+ [['2000-01-31 13:20:00 P',false],[2000,1,31,13,20,0,'P',-3*3600,nil]],
+
+ # dot
+ [['1999.5.2',false],[1999,5,2,nil,nil,nil,nil,nil,nil]],
+ [['1999.05.02',false],[1999,5,2,nil,nil,nil,nil,nil,nil]],
+ [['-1999.05.02',false],[-1999,5,2,nil,nil,nil,nil,nil,nil]],
+# [['05.02',false],[nil,5,2,nil,nil,nil,nil,nil,nil]], # not support
+# [[' 5. 2',false],[nil,5,2,nil,nil,nil,nil,nil,nil]], # not support
+
+ [['0099.5.2',false],[99,5,2,nil,nil,nil,nil,nil,nil]],
+ [['0099.5.2',true],[99,5,2,nil,nil,nil,nil,nil,nil]],
+
+ [["'99.5.2",false],[99,5,2,nil,nil,nil,nil,nil,nil]],
+ [["'99.5.2",true],[1999,5,2,nil,nil,nil,nil,nil,nil]],
+
+ # reversed dot
+ [['2.5.1999',false],[1999,5,2,nil,nil,nil,nil,nil,nil]],
+ [['02.05.1999',false],[1999,5,2,nil,nil,nil,nil,nil,nil]],
+ [['02.05.-1999',false],[-1999,5,2,nil,nil,nil,nil,nil,nil]],
+
+ [['2.5.0099',false],[99,5,2,nil,nil,nil,nil,nil,nil]],
+ [['2.5.0099',true],[99,5,2,nil,nil,nil,nil,nil,nil]],
+
+ [["2.5.'99",false],[99,5,2,nil,nil,nil,nil,nil,nil]],
+ [["2.5.'99",true],[1999,5,2,nil,nil,nil,nil,nil,nil]],
+
+ # vms
+ [['08-DEC-1988',false],[1988,12,8,nil,nil,nil,nil,nil,nil]],
+ [['31-JAN-1999',false],[1999,1,31,nil,nil,nil,nil,nil,nil]],
+ [['31-JAN--1999',false],[-1999,1,31,nil,nil,nil,nil,nil,nil]],
+
+ [['08-DEC-88',false],[88,12,8,nil,nil,nil,nil,nil,nil]],
+ [['08-DEC-88',true],[1988,12,8,nil,nil,nil,nil,nil,nil]],
+ [['08-DEC-0088',false],[88,12,8,nil,nil,nil,nil,nil,nil]],
+ [['08-DEC-0088',true],[88,12,8,nil,nil,nil,nil,nil,nil]],
+
+ # swaped vms
+ [['DEC-08-1988',false],[1988,12,8,nil,nil,nil,nil,nil,nil]],
+ [['JAN-31-1999',false],[1999,1,31,nil,nil,nil,nil,nil,nil]],
+ [['JAN-31--1999',false],[-1999,1,31,nil,nil,nil,nil,nil,nil]],
+ [['JAN-1999',false],[1999,1,nil,nil,nil,nil,nil,nil,nil]],
+ [['JAN--1999',false],[-1999,1,nil,nil,nil,nil,nil,nil,nil]],
+
+ # reversed vms
+ [['1988-DEC-08',false],[1988,12,8,nil,nil,nil,nil,nil,nil]],
+ [['1999-JAN-31',false],[1999,1,31,nil,nil,nil,nil,nil,nil]],
+ [['-1999-JAN-31',false],[-1999,1,31,nil,nil,nil,nil,nil,nil]],
+
+ [['0088-DEC-08',false],[88,12,8,nil,nil,nil,nil,nil,nil]],
+ [['0088-DEC-08',true],[88,12,8,nil,nil,nil,nil,nil,nil]],
+
+ [["'88/12/8",false],[88,12,8,nil,nil,nil,nil,nil,nil]],
+ [["'88/12/8",true],[1988,12,8,nil,nil,nil,nil,nil,nil]],
+
+ # non-spaced eu
+ [['08/dec/1988',false],[1988,12,8,nil,nil,nil,nil,nil,nil]],
+ [['31/jan/1999',false],[1999,1,31,nil,nil,nil,nil,nil,nil]],
+ [['31/jan/-1999',false],[-1999,1,31,nil,nil,nil,nil,nil,nil]],
+ [['08.dec.1988',false],[1988,12,8,nil,nil,nil,nil,nil,nil]],
+ [['31.jan.1999',false],[1999,1,31,nil,nil,nil,nil,nil,nil]],
+ [['31.jan.-1999',false],[-1999,1,31,nil,nil,nil,nil,nil,nil]],
+
+ # non-spaced us
+ [['dec/08/1988',false],[1988,12,8,nil,nil,nil,nil,nil,nil]],
+ [['jan/31/1999',false],[1999,1,31,nil,nil,nil,nil,nil,nil]],
+ [['jan/31/-1999',false],[-1999,1,31,nil,nil,nil,nil,nil,nil]],
+ [['jan/31',false],[nil,1,31,nil,nil,nil,nil,nil,nil]],
+ [['jan/1988',false],[1988,1,nil,nil,nil,nil,nil,nil,nil]],
+ [['dec.08.1988',false],[1988,12,8,nil,nil,nil,nil,nil,nil]],
+ [['jan.31.1999',false],[1999,1,31,nil,nil,nil,nil,nil,nil]],
+ [['jan.31.-1999',false],[-1999,1,31,nil,nil,nil,nil,nil,nil]],
+ [['jan.31',false],[nil,1,31,nil,nil,nil,nil,nil,nil]],
+ [['jan.1988',false],[1988,1,nil,nil,nil,nil,nil,nil,nil]],
+
+ # month and day of month
+ [['Jan 1',false],[nil,1,1,nil,nil,nil,nil,nil,nil]],
+ [['Jul 11',false],[nil,7,11,nil,nil,nil,nil,nil,nil]],
+ [['July 11',false],[nil,7,11,nil,nil,nil,nil,nil,nil]],
+ [['Sept 23',false],[nil,9,23,nil,nil,nil,nil,nil,nil]],
+ [['Sep. 23',false],[nil,9,23,nil,nil,nil,nil,nil,nil]],
+ [['Sept. 23',false],[nil,9,23,nil,nil,nil,nil,nil,nil]],
+ [['September 23',false],[nil,9,23,nil,nil,nil,nil,nil,nil]],
+ [['October 1st',false],[nil,10,1,nil,nil,nil,nil,nil,nil]],
+ [['October 23rd',false],[nil,10,23,nil,nil,nil,nil,nil,nil]],
+ [['October 25th 1999',false],[1999,10,25,nil,nil,nil,nil,nil,nil]],
+ [['October 25th -1999',false],[-1999,10,25,nil,nil,nil,nil,nil,nil]],
+ [['october 25th 1999',false],[1999,10,25,nil,nil,nil,nil,nil,nil]],
+ [['OCTOBER 25th 1999',false],[1999,10,25,nil,nil,nil,nil,nil,nil]],
+ [['oCtoBer 25th 1999',false],[1999,10,25,nil,nil,nil,nil,nil,nil]],
+ [['aSep 23',false],[nil,nil,23,nil,nil,nil,nil,nil,nil]],
+
+ # month and year
+ [['Sept 1990',false],[1990,9,nil,nil,nil,nil,nil,nil,nil]],
+ [["Sept '90",false],[90,9,nil,nil,nil,nil,nil,nil,nil]],
+ [["Sept '90",true],[1990,9,nil,nil,nil,nil,nil,nil,nil]],
+ [['1990/09',false],[1990,9,nil,nil,nil,nil,nil,nil,nil]],
+ [['09/1990',false],[1990,9,nil,nil,nil,nil,nil,nil,nil]],
+ [["aSep '90",false],[90,nil,nil,nil,nil,nil,nil,nil,nil]],
+
+ # year
+ [["'90",false],[90,nil,nil,nil,nil,nil,nil,nil,nil]],
+ [["'90",true],[1990,nil,nil,nil,nil,nil,nil,nil,nil]],
+
+ # month
+ [['Jun',false],[nil,6,nil,nil,nil,nil,nil,nil,nil]],
+ [['June',false],[nil,6,nil,nil,nil,nil,nil,nil,nil]],
+ [['Sep',false],[nil,9,nil,nil,nil,nil,nil,nil,nil]],
+ [['Sept',false],[nil,9,nil,nil,nil,nil,nil,nil,nil]],
+ [['September',false],[nil,9,nil,nil,nil,nil,nil,nil,nil]],
+ [['aSep',false],[nil,nil,nil,nil,nil,nil,nil,nil,nil]],
+
+ # day of month
+ [['1st',false],[nil,nil,1,nil,nil,nil,nil,nil,nil]],
+ [['2nd',false],[nil,nil,2,nil,nil,nil,nil,nil,nil]],
+ [['3rd',false],[nil,nil,3,nil,nil,nil,nil,nil,nil]],
+ [['4th',false],[nil,nil,4,nil,nil,nil,nil,nil,nil]],
+ [['29th',false],[nil,nil,29,nil,nil,nil,nil,nil,nil]],
+ [['31st',false],[nil,nil,31,nil,nil,nil,nil,nil,nil]],
+ [['1sta',false],[nil,nil,nil,nil,nil,nil,nil,nil,nil]],
+
+ # era
+ [['Sat Aug 28 02:29:34 GMT CE 2000',false],[2000,8,28,2,29,34,'GMT',0,6]],
+ [['Sat Aug 28 02:29:34 GMT C.E. 2000',false],[2000,8,28,2,29,34,'GMT',0,6]],
+ [['Sat Aug 28 02:29:34 GMT BCE 2000',false],[-1999,8,28,2,29,34,'GMT',0,6]],
+ [['Sat Aug 28 02:29:34 GMT B.C.E. 2000',false],[-1999,8,28,2,29,34,'GMT',0,6]],
+ [['Sat Aug 28 02:29:34 GMT AD 2000',false],[2000,8,28,2,29,34,'GMT',0,6]],
+ [['Sat Aug 28 02:29:34 GMT A.D. 2000',false],[2000,8,28,2,29,34,'GMT',0,6]],
+ [['Sat Aug 28 02:29:34 GMT BC 2000',false],[-1999,8,28,2,29,34,'GMT',0,6]],
+ [['Sat Aug 28 02:29:34 GMT B.C. 2000',false],[-1999,8,28,2,29,34,'GMT',0,6]],
+ [['Sat Aug 28 02:29:34 GMT 2000 BC',false],[-1999,8,28,2,29,34,'GMT',0,6]],
+ [['Sat Aug 28 02:29:34 GMT 2000 BCE',false],[-1999,8,28,2,29,34,'GMT',0,6]],
+ [['Sat Aug 28 02:29:34 GMT 2000 B.C.',false],[-1999,8,28,2,29,34,'GMT',0,6]],
+ [['Sat Aug 28 02:29:34 GMT 2000 B.C.E.',false],[-1999,8,28,2,29,34,'GMT',0,6]],
+
+ # collection
+# [['le ler juillet 1982',false],[1982,7,1,nil,nil,nil,nil,nil,nil]], # bih 1982
+# [['30 June 1982 , 23h 59m 59s',false],[1982,6,30,23,59,59,nil,nil,nil]], # bih 1982
+ [['Tuesday, May 18, 1999 Published at 13:36 GMT 14:36 UK',false],[1999,5,18,13,36,nil,'GMT',0,2]], # bbc.co.uk
+ [['July 20, 2000 Web posted at: 3:37 p.m. EDT (1937 GMT)',false],[2000,7,20,15,37,nil,'EDT',-4*3600,nil]], # cnn.com
+ [['12:54 p.m. EDT, September 11, 2006',false],[2006,9,11,12,54,nil,'EDT',-4*3600,nil]], # cnn.com
+ [['February 04, 2001 at 10:59 AM PST',false],[2001,2,4,10,59,nil,'PST',-8*3600,nil]], # old amazon.com
+ [['Monday May 08, @01:55PM',false],[nil,5,8,13,55,nil,nil,nil,1]], # slashdot.org
+ [['06.June 2005',false],[2005,6,6,nil,nil,nil,nil,nil,nil]], # dhl.com
+
+ # etc.
+ [['8:00 pm lt',false],[nil,nil,nil,20,0,nil,'lt',nil,nil]],
+ [['4:00 AM, Jan. 12, 1990',false],[1990,1,12,4,0,nil,nil,nil,nil]],
+ [['Jan. 12 4:00 AM 1990',false],[1990,1,12,4,0,nil,nil,nil,nil]],
+# [['Jan. 12 4:00 -1990',false],[-1990,1,12,4,0,nil,nil,nil,nil]], # cp
+ [['1990-01-12 04:00:00+00',false],[1990,1,12,4,0,0,'+00',0,nil]],
+ [['1990-01-11 20:00:00-08',false],[1990,1,11,20,0,0,'-08',-8*3600,nil]],
+ [['1990/01/12 04:00:00',false],[1990,1,12,4,0,0,nil,nil,nil]],
+# [['Thu Jan 11 20:00:00 1990 LT',false], [1990,1,11,20,0,0,'LT',nil,4]], # cp
+ [['Thu Jan 11 20:00:00 PST 1990',false],[1990,1,11,20,0,0,'PST',-8*3600,4]],
+ [['Fri Jan 12 04:00:00 GMT 1990',false],[1990,1,12,4,0,0,'GMT',0,5]],
+ [['Thu, 11 Jan 1990 20:00:00 -0800',false],[1990,1,11,20,0,0,'-0800',-8*3600,4]],
+ [['12-January-1990, 04:00 WET',false],[1990,1,12,4,0,nil,'WET',0*3600,nil]],
+ [['jan 2 3 am +4 5',false],[5,1,2,3,nil,nil,'+4',4*3600,nil]],
+ [['jan 2 3 am +4 5',true],[2005,1,2,3,nil,nil,'+4',4*3600,nil]],
+ [['fri1feb3bc4pm+5',false],[-2,2,1,16,nil,nil,'+5',5*3600,5]],
+ [['fri1feb3bc4pm+5',true],[-2,2,1,16,nil,nil,'+5',5*3600,5]],
+ [['03 feb 1st',false],[03,2,1,nil,nil,nil,nil,nil,nil]],
+
+ # apostrophe
+ [["July 4, '79",true],[1979,7,4,nil,nil,nil,nil,nil,nil]],
+ [["4th July '79",true],[1979,7,4,nil,nil,nil,nil,nil,nil]],
+
+ # day of week
+ [['Sunday',false],[nil,nil,nil,nil,nil,nil,nil,nil,0]],
+ [['Mon',false],[nil,nil,nil,nil,nil,nil,nil,nil,1]],
+ [['Tue',false],[nil,nil,nil,nil,nil,nil,nil,nil,2]],
+ [['Wed',false],[nil,nil,nil,nil,nil,nil,nil,nil,3]],
+ [['Thurs',false],[nil,nil,nil,nil,nil,nil,nil,nil,4]],
+ [['Friday',false],[nil,nil,nil,nil,nil,nil,nil,nil,5]],
+ [['Sat.',false],[nil,nil,nil,nil,nil,nil,nil,nil,6]],
+ [['sat.',false],[nil,nil,nil,nil,nil,nil,nil,nil,6]],
+ [['SAT.',false],[nil,nil,nil,nil,nil,nil,nil,nil,6]],
+ [['sAt.',false],[nil,nil,nil,nil,nil,nil,nil,nil,6]],
+# [['su',false],[nil,nil,nil,nil,nil,nil,nil,nil,0]],
+# [['mo',false],[nil,nil,nil,nil,nil,nil,nil,nil,1]],
+
+ # time
+ [['09:55',false],[nil,nil,nil,9,55,nil,nil,nil,nil]],
+ [['09:55:30',false],[nil,nil,nil,9,55,30,nil,nil,nil]],
+ [['09:55:30am',false],[nil,nil,nil,9,55,30,nil,nil,nil]],
+ [['09:55:30pm',false],[nil,nil,nil,21,55,30,nil,nil,nil]],
+ [['09:55:30a.m.',false],[nil,nil,nil,9,55,30,nil,nil,nil]],
+ [['09:55:30p.m.',false],[nil,nil,nil,21,55,30,nil,nil,nil]],
+ [['09:55:30pm GMT',false],[nil,nil,nil,21,55,30,'GMT',0,nil]],
+ [['09:55:30p.m. GMT',false],[nil,nil,nil,21,55,30,'GMT',0,nil]],
+ [['09:55+0900',false],[nil,nil,nil,9,55,nil,'+0900',9*3600,nil]],
+ [['09 AM',false],[nil,nil,nil,9,nil,nil,nil,nil,nil]],
+ [['09am',false],[nil,nil,nil,9,nil,nil,nil,nil,nil]],
+ [['09 A.M.',false],[nil,nil,nil,9,nil,nil,nil,nil,nil]],
+ [['09 PM',false],[nil,nil,nil,21,nil,nil,nil,nil,nil]],
+ [['09pm',false],[nil,nil,nil,21,nil,nil,nil,nil,nil]],
+ [['09 P.M.',false],[nil,nil,nil,21,nil,nil,nil,nil,nil]],
+
+ [['9h22m23s',false],[nil,nil,nil,9,22,23,nil,nil,nil]],
+ [['9h 22m 23s',false],[nil,nil,nil,9,22,23,nil,nil,nil]],
+ [['9h22m',false],[nil,nil,nil,9,22,nil,nil,nil,nil]],
+ [['9h 22m',false],[nil,nil,nil,9,22,nil,nil,nil,nil]],
+ [['9h',false],[nil,nil,nil,9,nil,nil,nil,nil,nil]],
+ [['9h 22m 23s am',false],[nil,nil,nil,9,22,23,nil,nil,nil]],
+ [['9h 22m 23s pm',false],[nil,nil,nil,21,22,23,nil,nil,nil]],
+ [['9h 22m am',false],[nil,nil,nil,9,22,nil,nil,nil,nil]],
+ [['9h 22m pm',false],[nil,nil,nil,21,22,nil,nil,nil,nil]],
+ [['9h am',false],[nil,nil,nil,9,nil,nil,nil,nil,nil]],
+ [['9h pm',false],[nil,nil,nil,21,nil,nil,nil,nil,nil]],
+
+ [['00:00',false],[nil,nil,nil,0,0,nil,nil,nil,nil]],
+ [['01:00',false],[nil,nil,nil,1,0,nil,nil,nil,nil]],
+ [['11:00',false],[nil,nil,nil,11,0,nil,nil,nil,nil]],
+ [['12:00',false],[nil,nil,nil,12,0,nil,nil,nil,nil]],
+ [['13:00',false],[nil,nil,nil,13,0,nil,nil,nil,nil]],
+ [['23:00',false],[nil,nil,nil,23,0,nil,nil,nil,nil]],
+ [['24:00',false],[nil,nil,nil,24,0,nil,nil,nil,nil]],
+
+ [['00:00 AM',false],[nil,nil,nil,0,0,nil,nil,nil,nil]],
+ [['12:00 AM',false],[nil,nil,nil,0,0,nil,nil,nil,nil]],
+ [['01:00 AM',false],[nil,nil,nil,1,0,nil,nil,nil,nil]],
+ [['11:00 AM',false],[nil,nil,nil,11,0,nil,nil,nil,nil]],
+ [['00:00 PM',false],[nil,nil,nil,12,0,nil,nil,nil,nil]],
+ [['12:00 PM',false],[nil,nil,nil,12,0,nil,nil,nil,nil]],
+ [['01:00 PM',false],[nil,nil,nil,13,0,nil,nil,nil,nil]],
+ [['11:00 PM',false],[nil,nil,nil,23,0,nil,nil,nil,nil]],
+
+ # pick up the rest
+ [['2000-01-02 1',false],[2000,1,2,1,nil,nil,nil,nil,nil]],
+ [['2000-01-02 23',false],[2000,1,2,23,nil,nil,nil,nil,nil]],
+ [['2000-01-02 24',false],[2000,1,2,24,nil,nil,nil,nil,nil]],
+ [['1 03:04:05',false],[nil,nil,1,3,4,5,nil,nil,nil]],
+ [['02 03:04:05',false],[nil,nil,2,3,4,5,nil,nil,nil]],
+ [['31 03:04:05',false],[nil,nil,31,3,4,5,nil,nil,nil]],
+
+ # null, space
+ [['',false],[nil,nil,nil,nil,nil,nil,nil,nil,nil]],
+ [["\s",false],[nil,nil,nil,nil,nil,nil,nil,nil,nil]],
+ [["\s" * 10, true],[nil,nil,nil,nil,nil,nil,nil,nil,nil]],
+ [["\t",false],[nil,nil,nil,nil,nil,nil,nil,nil,nil]],
+ [["\n",false],[nil,nil,nil,nil,nil,nil,nil,nil,nil]],
+ [["\v",false],[nil,nil,nil,nil,nil,nil,nil,nil,nil]],
+ [["\f",false],[nil,nil,nil,nil,nil,nil,nil,nil,nil]],
+ [["\r",false],[nil,nil,nil,nil,nil,nil,nil,nil,nil]],
+ [["\t\n\v\f\r\s",false],[nil,nil,nil,nil,nil,nil,nil,nil,nil]],
+ [["1999-05-23\t\n\v\f\r\s21:34:56",false],[1999,5,23,21,34,56,nil,nil,nil]],
+ [["1999-05-23\n\n\n\n\n\n21:34:56",false],[1999,5,23,21,34,56,nil,nil,nil]],
+ ].each do |x,y|
+ h = Date._parse(*x)
+ a = h.values_at(:year,:mon,:mday,:hour,:min,:sec,:zone,:offset,:wday)
+ if y[1] == -1
+ a[1] = -1
+ a[2] = h[:yday]
+ end
+ assert_equal(y, a, [x, y, a].inspect)
+ end
+ end
+
+ def test__parse_slash_exp
+ [
+ # little
+ [['2/5/1999',false],[1999,5,2,nil,nil,nil,nil,nil,nil]],
+ [['02/05/1999',false],[1999,5,2,nil,nil,nil,nil,nil,nil]],
+ [['02/05/-1999',false],[-1999,5,2,nil,nil,nil,nil,nil,nil]],
+ [['05/02',false],[nil,5,2,nil,nil,nil,nil,nil,nil]],
+ [[' 5/ 2',false],[nil,5,2,nil,nil,nil,nil,nil,nil]],
+
+ [["2/5/'99",true],[1999,5,2,nil,nil,nil,nil,nil,nil]],
+ [['2/5/0099',false],[99,5,2,nil,nil,nil,nil,nil,nil]],
+ [['2/5/0099',true],[99,5,2,nil,nil,nil,nil,nil,nil]],
+
+ [['2/5 1999',false],[1999,5,2,nil,nil,nil,nil,nil,nil]],
+ [['2/5-1999',false],[1999,5,2,nil,nil,nil,nil,nil,nil]],
+ [['2/5--1999',false],[-1999,5,2,nil,nil,nil,nil,nil,nil]],
+
+ # big
+ [['99/5/2',false],[99,5,2,nil,nil,nil,nil,nil,nil]],
+ [['99/5/2',true],[1999,5,2,nil,nil,nil,nil,nil,nil]],
+
+ [['1999/5/2',false],[1999,5,2,nil,nil,nil,nil,nil,nil]],
+ [['1999/05/02',false],[1999,5,2,nil,nil,nil,nil,nil,nil]],
+ [['-1999/05/02',false],[-1999,5,2,nil,nil,nil,nil,nil,nil]],
+
+ [['0099/5/2',false],[99,5,2,nil,nil,nil,nil,nil,nil]],
+ [['0099/5/2',true],[99,5,2,nil,nil,nil,nil,nil,nil]],
+
+ [["'99/5/2",false],[99,5,2,nil,nil,nil,nil,nil,nil]],
+ [["'99/5/2",true],[1999,5,2,nil,nil,nil,nil,nil,nil]],
+ ].each do |x,y|
+ h = Date._parse(*x)
+ a = h.values_at(:year,:mon,:mday,:hour,:min,:sec,:zone,:offset,:wday)
+ if y[1] == -1
+ a[1] = -1
+ a[2] = h[:yday]
+ end
+ assert_equal(y, a, [x, y, a].inspect)
+ end
+ end
+
+ def test__parse__2
+ h = Date._parse('22:45:59.5')
+ assert_equal([22, 45, 59, 5.to_r/10**1], h.values_at(:hour, :min, :sec, :sec_fraction))
+ h = Date._parse('22:45:59.05')
+ assert_equal([22, 45, 59, 5.to_r/10**2], h.values_at(:hour, :min, :sec, :sec_fraction))
+ h = Date._parse('22:45:59.005')
+ assert_equal([22, 45, 59, 5.to_r/10**3], h.values_at(:hour, :min, :sec, :sec_fraction))
+ h = Date._parse('22:45:59.0123')
+ assert_equal([22, 45, 59, 123.to_r/10**4], h.values_at(:hour, :min, :sec, :sec_fraction))
+
+ h = Date._parse('224559.5')
+ assert_equal([22, 45, 59, 5.to_r/10**1], h.values_at(:hour, :min, :sec, :sec_fraction))
+ h = Date._parse('224559.05')
+ assert_equal([22, 45, 59, 5.to_r/10**2], h.values_at(:hour, :min, :sec, :sec_fraction))
+ h = Date._parse('224559.005')
+ assert_equal([22, 45, 59, 5.to_r/10**3], h.values_at(:hour, :min, :sec, :sec_fraction))
+ h = Date._parse('224559.0123')
+ assert_equal([22, 45, 59, 123.to_r/10**4], h.values_at(:hour, :min, :sec, :sec_fraction))
+
+ h = Date._parse('2006-w15-5')
+ assert_equal([2006, 15, 5], h.values_at(:cwyear, :cweek, :cwday))
+ h = Date._parse('2006w155')
+ assert_equal([2006, 15, 5], h.values_at(:cwyear, :cweek, :cwday))
+ h = Date._parse('06w155', false)
+ assert_equal([6, 15, 5], h.values_at(:cwyear, :cweek, :cwday))
+ h = Date._parse('06w155', true)
+ assert_equal([2006, 15, 5], h.values_at(:cwyear, :cweek, :cwday))
+
+ h = Date._parse('2006-w15')
+ assert_equal([2006, 15, nil], h.values_at(:cwyear, :cweek, :cwday))
+ h = Date._parse('2006w15')
+ assert_equal([2006, 15, nil], h.values_at(:cwyear, :cweek, :cwday))
+
+ h = Date._parse('-w15-5')
+ assert_equal([nil, 15, 5], h.values_at(:cwyear, :cweek, :cwday))
+ h = Date._parse('-w155')
+ assert_equal([nil, 15, 5], h.values_at(:cwyear, :cweek, :cwday))
+
+ h = Date._parse('-w15')
+ assert_equal([nil, 15, nil], h.values_at(:cwyear, :cweek, :cwday))
+ h = Date._parse('-w15')
+ assert_equal([nil, 15, nil], h.values_at(:cwyear, :cweek, :cwday))
+
+ h = Date._parse('-w-5')
+ assert_equal([nil, nil, 5], h.values_at(:cwyear, :cweek, :cwday))
+
+ h = Date._parse('--11-29')
+ assert_equal([nil, 11, 29], h.values_at(:year, :mon, :mday))
+ h = Date._parse('--1129')
+ assert_equal([nil, 11, 29], h.values_at(:year, :mon, :mday))
+ h = Date._parse('--11')
+ assert_equal([nil, 11, nil], h.values_at(:year, :mon, :mday))
+ h = Date._parse('---29')
+ assert_equal([nil, nil, 29], h.values_at(:year, :mon, :mday))
+ h = Date._parse('-333')
+ assert_equal([nil, 333], h.values_at(:year, :yday))
+
+ h = Date._parse('2006-333')
+ assert_equal([2006, 333], h.values_at(:year, :yday))
+ h = Date._parse('2006333')
+ assert_equal([2006, 333], h.values_at(:year, :yday))
+ h = Date._parse('06333', false)
+ assert_equal([6, 333], h.values_at(:year, :yday))
+ h = Date._parse('06333', true)
+ assert_equal([2006, 333], h.values_at(:year, :yday))
+ h = Date._parse('333')
+ assert_equal([nil, 333], h.values_at(:year, :yday))
+ end
+
+ def test_parse
+ assert_equal(Date.new, Date.parse)
+ assert_equal(Date.new(2002,3,14), Date.parse('2002-03-14'))
+
+ assert_equal(DateTime.new(2002,3,14,11,22,33, 0),
+ DateTime.parse('2002-03-14T11:22:33Z'))
+ assert_equal(DateTime.new(2002,3,14,11,22,33, 9.to_r/24),
+ DateTime.parse('2002-03-14T11:22:33+09:00'))
+ assert_equal(DateTime.new(2002,3,14,11,22,33, -9.to_r/24),
+ DateTime.parse('2002-03-14T11:22:33-09:00'))
+ assert_equal(DateTime.new(2002,3,14,11,22,33, -9.to_r/24) + 123456789.to_r/1000000000/86400,
+ DateTime.parse('2002-03-14T11:22:33.123456789-09:00'))
+ end
+
+ def test_parse__2
+ d1 = DateTime.parse('2004-03-13T22:45:59.5')
+ d2 = DateTime.parse('2004-03-13T22:45:59')
+ assert_equal(d2 + 5.to_r/10**1/86400, d1)
+ d1 = DateTime.parse('2004-03-13T22:45:59.05')
+ d2 = DateTime.parse('2004-03-13T22:45:59')
+ assert_equal(d2 + 5.to_r/10**2/86400, d1)
+ d1 = DateTime.parse('2004-03-13T22:45:59.005')
+ d2 = DateTime.parse('2004-03-13T22:45:59')
+ assert_equal(d2 + 5.to_r/10**3/86400, d1)
+ d1 = DateTime.parse('2004-03-13T22:45:59.0123')
+ d2 = DateTime.parse('2004-03-13T22:45:59')
+ assert_equal(d2 + 123.to_r/10**4/86400, d1)
+ d1 = DateTime.parse('2004-03-13T22:45:59.5')
+ d1 += 1.to_r/2/86400
+ d2 = DateTime.parse('2004-03-13T22:46:00')
+ assert_equal(d2, d1)
+ end
+
+ require 'time'
+
+ def test_parse__time
+ methods = [:to_s, :asctime, :iso8601, :rfc2822, :httpdate, :xmlschema]
+
+ t = Time.utc(2001,2,3,4,5,6)
+ methods.each do |m|
+ d = DateTime.parse(t.__send__(m))
+ assert_equal([2001, 2, 3, 4, 5, 6],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec],
+ [m, t.__send__(m)].inspect)
+ end
+
+ t = Time.mktime(2001,2,3,4,5,6)
+ methods.each do |m|
+ next if m == :httpdate
+ d = DateTime.parse(t.__send__(m))
+ assert_equal([2001, 2, 3, 4, 5, 6],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec],
+ [m, t.__send__(m)].inspect)
+ end
+ end
+
+ def test_parse__comp
+ n = DateTime.now
+
+ d = DateTime.parse('073')
+ assert_equal([n.year, 73, 0, 0, 0],
+ [d.year, d.yday, d.hour, d.min, d.sec])
+ d = DateTime.parse('13')
+ assert_equal([n.year, n.mon, 13, 0, 0, 0],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec])
+
+ d = DateTime.parse('Mar 13')
+ assert_equal([n.year, 3, 13, 0, 0, 0],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec])
+ d = DateTime.parse('Mar 2004')
+ assert_equal([2004, 3, 1, 0, 0, 0],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec])
+ d = DateTime.parse('23:55')
+ assert_equal([n.year, n.mon, n.mday, 23, 55, 0],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec])
+ d = DateTime.parse('23:55:30')
+ assert_equal([n.year, n.mon, n.mday, 23, 55, 30],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec])
+
+ d = DateTime.parse('Sun 23:55')
+ d2 = d - d.wday
+ assert_equal([d2.year, d2.mon, d2.mday, 23, 55, 0],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec])
+ d = DateTime.parse('Aug 23:55')
+ assert_equal([n.year, 8, 1, 23, 55, 0],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec])
+ end
+
+ def test_parse__d_to_s
+ d = Date.new(2002,3,14)
+ assert_equal(d, Date.parse(d.to_s))
+
+ d = DateTime.new(2002,3,14,11,22,33, 9.to_r/24)
+ assert_equal(d, DateTime.parse(d.to_s))
+ end
+
+ def test_parse__ex
+ assert_raise(ArgumentError) do
+ Date.parse('')
+ end
+ assert_raise(ArgumentError) do
+ Date.parse('2001-02-29')
+ end
+ assert_raise(ArgumentError) do
+ DateTime.parse('2001-02-29T23:59:60')
+ end
+ assert_raise(ArgumentError) do
+ Date.parse('23:55')
+ end
+ end
+
+ def test__iso8601
+ h = Date._iso8601('01-02-03')
+ assert_equal([2001, 2, 3, nil, nil, nil, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._iso8601('2001-02-03')
+ assert_equal([2001, 2, 3, nil, nil, nil, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._iso8601('--02-03')
+ assert_equal([nil, 2, 3, nil, nil, nil, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+
+ h = Date._iso8601('2001-02-03T04:05')
+ assert_equal([2001, 2, 3, 4, 5, nil, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._iso8601('2001-02-03T04:05:06')
+ assert_equal([2001, 2, 3, 4, 5, 6, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._iso8601('2001-02-03T04:05:06,07')
+ assert_equal([2001, 2, 3, 4, 5, 6, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._iso8601('2001-02-03T04:05:06Z')
+ assert_equal([2001, 2, 3, 4, 5, 6, 0],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._iso8601('2001-02-03T04:05:06.07+01:00')
+ assert_equal([2001, 2, 3, 4, 5, 6, 3600],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+
+ h = Date._iso8601('010203')
+ assert_equal([2001, 2, 3, nil, nil, nil, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._iso8601('20010203')
+ assert_equal([2001, 2, 3, nil, nil, nil, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._iso8601('--0203')
+ assert_equal([nil, 2, 3, nil, nil, nil, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+
+ h = Date._iso8601('010203T0405')
+ assert_equal([2001, 2, 3, 4, 5, nil, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._iso8601('20010203T0405')
+ assert_equal([2001, 2, 3, 4, 5, nil, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._iso8601('20010203T040506')
+ assert_equal([2001, 2, 3, 4, 5, 6, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._iso8601('20010203T040506,07')
+ assert_equal([2001, 2, 3, 4, 5, 6, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._iso8601('20010203T040506Z')
+ assert_equal([2001, 2, 3, 4, 5, 6, 0],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._iso8601('20010203T040506.07+0100')
+ assert_equal([2001, 2, 3, 4, 5, 6, 3600],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+
+ h = Date._iso8601('200102030405')
+ assert_equal([2001, 2, 3, 4, 5, nil, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._iso8601('20010203040506')
+ assert_equal([2001, 2, 3, 4, 5, 6, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._iso8601('20010203040506,07')
+ assert_equal([2001, 2, 3, 4, 5, 6, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._iso8601('20010203040506Z')
+ assert_equal([2001, 2, 3, 4, 5, 6, 0],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._iso8601('20010203040506.07+0100')
+ assert_equal([2001, 2, 3, 4, 5, 6, 3600],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+
+ h = Date._iso8601('01-023')
+ assert_equal([2001, 23, nil, nil, nil, nil],
+ h.values_at(:year, :yday, :hour, :min, :sec, :offset))
+ h = Date._iso8601('2001-023')
+ assert_equal([2001, 23, nil, nil, nil, nil],
+ h.values_at(:year, :yday, :hour, :min, :sec, :offset))
+ h = Date._iso8601('-023')
+ assert_equal([nil, 23, nil, nil, nil, nil],
+ h.values_at(:year, :yday, :hour, :min, :sec, :offset))
+
+ h = Date._iso8601('04:05')
+ assert_equal([nil, nil, nil, 4, 5, nil, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._iso8601('04:05:06')
+ assert_equal([nil, nil, nil, 4, 5, 6, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._iso8601('04:05:06,07')
+ assert_equal([nil, nil, nil, 4, 5, 6, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._iso8601('04:05:06Z')
+ assert_equal([nil, nil, nil, 4, 5, 6, 0],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._iso8601('04:05:06.07+01:00')
+ assert_equal([nil, nil, nil, 4, 5, 6, 3600],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+
+ h = Date._iso8601('040506,07')
+ assert_equal([nil, nil, nil, 4, 5, 6, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._iso8601('040506.07+0100')
+ assert_equal([nil, nil, nil, 4, 5, 6, 3600],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+
+ h = Date._iso8601('01-w02-3')
+ assert_equal([2001, 2, 3, nil, nil, nil, nil],
+ h.values_at(:cwyear, :cweek, :cwday, :hour, :min, :sec, :offset))
+ h = Date._iso8601('2001-w02-3')
+ assert_equal([2001, 2, 3, nil, nil, nil, nil],
+ h.values_at(:cwyear, :cweek, :cwday, :hour, :min, :sec, :offset))
+ h = Date._iso8601('2001w023')
+ assert_equal([2001, 2, 3, nil, nil, nil, nil],
+ h.values_at(:cwyear, :cweek, :cwday, :hour, :min, :sec, :offset))
+ h = Date._iso8601('-w02-3')
+ assert_equal([nil, 2, 3, nil, nil, nil, nil],
+ h.values_at(:cwyear, :cweek, :cwday, :hour, :min, :sec, :offset))
+ h = Date._iso8601('-w-3')
+ assert_equal([nil, nil, 3, nil, nil, nil, nil],
+ h.values_at(:cwyear, :cweek, :cwday, :hour, :min, :sec, :offset))
+ end
+
+ def test__rfc3339
+ h = Date._rfc3339('2001-02-03T04:05:06Z')
+ assert_equal([2001, 2, 3, 4, 5, 6, 0],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._rfc3339('2001-02-03 04:05:06Z')
+ assert_equal([2001, 2, 3, 4, 5, 6, 0],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._rfc3339('2001-02-03T04:05:06.07+01:00')
+ assert_equal([2001, 2, 3, 4, 5, 6, 3600],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ end
+
+ def test__xmlschema
+ h = Date._xmlschema('2001-02-03')
+ assert_equal([2001, 2, 3, nil, nil, nil, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._xmlschema('2001-02-03Z')
+ assert_equal([2001, 2, 3, nil, nil, nil, 0],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._xmlschema('2001-02-03+01:00')
+ assert_equal([2001, 2, 3, nil, nil, nil, 3600],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+
+ h = Date._xmlschema('2001-02-03T04:05:06')
+ assert_equal([2001, 2, 3, 4, 5, 6, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._xmlschema('2001-02-03T04:05:06.07')
+ assert_equal([2001, 2, 3, 4, 5, 6, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._xmlschema('2001-02-03T04:05:06.07Z')
+ assert_equal([2001, 2, 3, 4, 5, 6, 0],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._xmlschema('2001-02-03T04:05:06.07+01:00')
+ assert_equal([2001, 2, 3, 4, 5, 6, 3600],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+
+ h = Date._xmlschema('04:05:06')
+ assert_equal([nil, nil, nil, 4, 5, 6, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._xmlschema('04:05:06Z')
+ assert_equal([nil, nil, nil, 4, 5, 6, 0],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._xmlschema('04:05:06+01:00')
+ assert_equal([nil, nil, nil, 4, 5, 6, 3600],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+
+ h = Date._xmlschema('2001-02')
+ assert_equal([2001, 2, nil, nil, nil, nil, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._xmlschema('2001-02Z')
+ assert_equal([2001, 2, nil, nil, nil, nil, 0],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._xmlschema('2001-02+01:00')
+ assert_equal([2001, 2, nil, nil, nil, nil, 3600],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._xmlschema('2001-02-01:00')
+ assert_equal([2001, 2, nil, nil, nil, nil, -3600],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+
+ h = Date._xmlschema('2001')
+ assert_equal([2001, nil, nil, nil, nil, nil, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._xmlschema('2001Z')
+ assert_equal([2001, nil, nil, nil, nil, nil, 0],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._xmlschema('2001+01:00')
+ assert_equal([2001, nil, nil, nil, nil, nil, 3600],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._xmlschema('2001-01:00')
+ assert_equal([2001, nil, nil, nil, nil, nil, -3600],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+
+ h = Date._xmlschema('--02')
+ assert_equal([nil, 2, nil, nil, nil, nil, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._xmlschema('--02Z')
+ assert_equal([nil, 2, nil, nil, nil, nil, 0],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._xmlschema('--02+01:00')
+ assert_equal([nil, 2, nil, nil, nil, nil, 3600],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+
+ h = Date._xmlschema('92001-02-03T04:05:06.07+01:00')
+ assert_equal([92001, 2, 3, 4, 5, 6, 3600],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+
+ h = Date._xmlschema('-92001-02-03T04:05:06.07+01:00')
+ assert_equal([-92001, 2, 3, 4, 5, 6, 3600],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ end
+
+ def test__rfc2822
+ h = Date._rfc2822('Sat, 3 Feb 2001 04:05:06 UT')
+ assert_equal([2001, 2, 3, 4, 5, 6, 0],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._rfc2822('Sat, 3 Feb 2001 04:05:06 EST')
+ assert_equal([2001, 2, 3, 4, 5, 6, -5*3600],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._rfc2822('Sat, 3 Feb 2001 04:05:06 +0000')
+ assert_equal([2001, 2, 3, 4, 5, 6, 0],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._rfc2822('Sat, 3 Feb 2001 04:05:06 +0100')
+ assert_equal([2001, 2, 3, 4, 5, 6, 3600],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+
+ h = Date._rfc2822('Sat, 03 Feb 50 04:05:06 +0100')
+ assert_equal([1950, 2, 3, 4, 5, 6, 3600],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._rfc2822('Sat, 03 Feb 49 04:05:06 +0100')
+ assert_equal([2049, 2, 3, 4, 5, 6, 3600],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._rfc2822('Sat, 03 Feb 100 04:05:06 +0100')
+ assert_equal([2000, 2, 3, 4, 5, 6, 3600],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+
+ h1 = Date._rfc2822('Sat, 3 Feb 2001 04:05:06 UT')
+ h2 = Date._rfc822('Sat, 3 Feb 2001 04:05:06 UT')
+ assert_equal(h1, h2)
+ end
+
+ def test__httpdate
+ h = Date._httpdate('Sat, 03 Feb 2001 04:05:06 GMT')
+ assert_equal([2001, 2, 3, 4, 5, 6, 0],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+
+ h = Date._httpdate('Saturday, 03-Feb-01 04:05:06 GMT')
+ assert_equal([2001, 2, 3, 4, 5, 6, 0],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+
+ h = Date._httpdate('Sat Feb 3 04:05:06 2001')
+ assert_equal([2001, 2, 3, 4, 5, 6, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._httpdate('Sat Feb 03 04:05:06 2001')
+ assert_equal([2001, 2, 3, 4, 5, 6, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ end
+
+ def test__jisx0301
+ h = Date._jisx0301('13.02.03')
+ assert_equal([2001, 2, 3, nil, nil, nil, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._jisx0301('H13.02.03')
+ assert_equal([2001, 2, 3, nil, nil, nil, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._jisx0301('S63.02.03')
+ assert_equal([1988, 2, 3, nil, nil, nil, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+
+ h = Date._jisx0301('H13.02.03T04:05:06')
+ assert_equal([2001, 2, 3, 4, 5, 6, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._jisx0301('H13.02.03T04:05:06,07')
+ assert_equal([2001, 2, 3, 4, 5, 6, nil],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._jisx0301('H13.02.03T04:05:06Z')
+ assert_equal([2001, 2, 3, 4, 5, 6, 0],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ h = Date._jisx0301('H13.02.03T04:05:06.07+0100')
+ assert_equal([2001, 2, 3, 4, 5, 6, 3600],
+ h.values_at(:year, :mon, :mday, :hour, :min, :sec, :offset))
+ end
+
+ def test_iso8601
+ assert_instance_of(Date, Date.iso8601)
+ assert_instance_of(DateTime, DateTime.iso8601)
+ end
+
+ def test_rfc3339
+ assert_instance_of(Date, Date.rfc3339)
+ assert_instance_of(DateTime, DateTime.rfc3339)
+ end
+
+ def test_xmlschema
+ assert_instance_of(Date, Date.xmlschema)
+ assert_instance_of(DateTime, DateTime.xmlschema)
+ end
+
+ def test_rfc2822
+ assert_instance_of(Date, Date.rfc2822)
+ assert_instance_of(DateTime, DateTime.rfc2822)
+ assert_instance_of(Date, Date.rfc822)
+ assert_instance_of(DateTime, DateTime.rfc822)
+ end
+
+ def test_httpdate
+ assert_instance_of(Date, Date.httpdate)
+ assert_instance_of(DateTime, DateTime.httpdate)
+ end
+
+ def test_jisx0301
+ assert_instance_of(Date, Date.jisx0301)
+ assert_instance_of(DateTime, DateTime.jisx0301)
+ end
+
+end
diff --git a/test/date/test_date_strftime.rb b/test/date/test_date_strftime.rb
new file mode 100644
index 0000000000..1a190f21cc
--- /dev/null
+++ b/test/date/test_date_strftime.rb
@@ -0,0 +1,370 @@
+require 'test/unit'
+require 'date'
+
+class TestDateStrftime < Test::Unit::TestCase
+
+ STRFTIME_2001_02_03 = {
+ '%A'=>['Saturday',{:wday=>6}],
+ '%a'=>['Sat',{:wday=>6}],
+ '%B'=>['February',{:mon=>2}],
+ '%b'=>['Feb',{:mon=>2}],
+ '%c'=>['Sat Feb 3 00:00:00 2001',
+ {:wday=>6,:mon=>2,:mday=>3,:hour=>0,:min=>0,:sec=>0,:year=>2001}],
+ '%d'=>['03',{:mday=>3}],
+ '%e'=>[' 3',{:mday=>3}],
+ '%H'=>['00',{:hour=>0}],
+ '%I'=>['12',{:hour=>0}],
+ '%j'=>['034',{:yday=>34}],
+ '%M'=>['00',{:min=>0}],
+ '%m'=>['02',{:mon=>2}],
+ '%p'=>['AM',{}],
+ '%S'=>['00',{:sec=>0}],
+ '%U'=>['04',{:wnum0=>4}],
+ '%W'=>['05',{:wnum1=>5}],
+ '%X'=>['00:00:00',{:hour=>0,:min=>0,:sec=>0}],
+ '%x'=>['02/03/01',{:mon=>2,:mday=>3,:year=>2001}],
+ '%Y'=>['2001',{:year=>2001}],
+ '%y'=>['01',{:year=>2001}],
+ '%Z'=>['+00:00',{:zone=>'+00:00',:offset=>0}],
+ '%%'=>['%',{}],
+ '%C'=>['20',{}],
+ '%D'=>['02/03/01',{:mon=>2,:mday=>3,:year=>2001}],
+ '%F'=>['2001-02-03',{:year=>2001,:mon=>2,:mday=>3}],
+ '%G'=>['2001',{:cwyear=>2001}],
+ '%g'=>['01',{:cwyear=>2001}],
+ '%h'=>['Feb',{:mon=>2}],
+ '%k'=>[' 0',{:hour=>0}],
+ '%L'=>['000',{:sec_fraction=>0}],
+ '%l'=>['12',{:hour=>0}],
+ '%N'=>['000000000',{:sec_fraction=>0}],
+ '%n'=>["\n",{}],
+ '%P'=>['am',{}],
+ '%Q'=>['981158400000',{:seconds=>981158400.to_r}],
+ '%R'=>['00:00',{:hour=>0,:min=>0}],
+ '%r'=>['12:00:00 AM',{:hour=>0,:min=>0,:sec=>0}],
+ '%s'=>['981158400',{:seconds=>981158400}],
+ '%T'=>['00:00:00',{:hour=>0,:min=>0,:sec=>0}],
+ '%t'=>["\t",{}],
+ '%u'=>['6',{:cwday=>6}],
+ '%V'=>['05',{:cweek=>5}],
+ '%v'=>[' 3-Feb-2001',{:mday=>3,:mon=>2,:year=>2001}],
+ '%z'=>['+0000',{:zone=>'+0000',:offset=>0}],
+ '%+'=>['Sat Feb 3 00:00:00 +00:00 2001',
+ {:wday=>6,:mon=>2,:mday=>3,
+ :hour=>0,:min=>0,:sec=>0,:zone=>'+00:00',:offset=>0,:year=>2001}],
+ }
+
+ STRFTIME_2001_02_03_CVS19 = {
+ }
+
+ STRFTIME_2001_02_03_GNUext = {
+ '%:z'=>['+00:00',{:zone=>'+00:00',:offset=>0}],
+ '%::z'=>['+00:00:00',{:zone=>'+00:00:00',:offset=>0}],
+ '%:::z'=>['+00',{:zone=>'+00',:offset=>0}],
+ }
+
+ STRFTIME_2001_02_03.update(STRFTIME_2001_02_03_CVS19)
+ STRFTIME_2001_02_03.update(STRFTIME_2001_02_03_GNUext)
+
+ def test_strftime
+ d = Date.new(2001,2,3)
+ STRFTIME_2001_02_03.each do |f, s|
+ assert_equal(s[0], d.strftime(f), [f, s].inspect)
+ case f[-1,1]
+ when 'c', 'C', 'x', 'X', 'y', 'Y'
+ f2 = f.sub(/\A%/, '%E')
+ assert_equal(s[0], d.strftime(f2), [f2, s].inspect)
+ else
+ f2 = f.sub(/\A%/, '%E')
+ assert_equal(f2, d.strftime(f2), [f2, s].inspect)
+ end
+ case f[-1,1]
+ when 'd', 'e', 'H', 'I', 'm', 'M', 'S', 'u', 'U', 'V', 'w', 'W', 'y'
+ f2 = f.sub(/\A%/, '%O')
+ assert_equal(s[0], d.strftime(f2), [f2, s].inspect)
+ else
+ f2 = f.sub(/\A%/, '%O')
+ assert_equal(f2, d.strftime(f2), [f2, s].inspect)
+ end
+ end
+ end
+
+ def test_strftime__2
+ d = Date.new(2001,2,3)
+ assert_equal('2001-02-03', d.strftime)
+
+ d = DateTime.new(2001,2,3)
+ assert_equal('2001-02-03T00:00:00+00:00', d.strftime)
+
+ assert_equal('', d.strftime(''))
+ assert_equal("\s"*3, d.strftime("\s"*3))
+ assert_equal("\tfoo\n\000\r", d.strftime("\tfoo\n\000\r"))
+ assert_equal("%\n", d.strftime("%\n")) # gnu
+ assert_equal('Saturday'*1024 + ',', d.strftime('%A'*1024 + ','))
+ assert_equal('%%', d.strftime('%%%'))
+ assert_equal('Anton von Webern', d.strftime('Anton von Webern'))
+
+ d = DateTime.new(2001,2,3, 1,2,3)
+ assert_equal('2001-02-03T01:02:03+00:00', d.strftime)
+ assert_equal('AM', d.strftime('%p'))
+ assert_equal('am', d.strftime('%P'))
+ d = DateTime.new(2001,2,3, 13,14,15)
+ assert_equal('2001-02-03T13:14:15+00:00', d.strftime)
+ assert_equal('PM', d.strftime('%p'))
+ assert_equal('pm', d.strftime('%P'))
+ end
+
+ def test_strftime__3_1
+ (Date.new(1970,1,1)..Date.new(2037,12,31)).each do |d|
+ t = Time.utc(d.year,d.mon,d.mday)
+ assert_equal(t.strftime('%U'), d.strftime('%U'))
+ assert_equal(t.strftime('%W'), d.strftime('%W'))
+ end
+ end
+
+ def test_strftime__3_2
+ s = Time.now.strftime('%G')
+ if s.empty? || s == '%G'
+ return
+ end
+ (Date.new(1970,1,1)..Date.new(2037,12,31)).each do |d|
+ t = Time.utc(d.year,d.mon,d.mday)
+ assert_equal(t.strftime('%G'), d.strftime('%G'))
+ assert_equal(t.strftime('%g'), d.strftime('%g'))
+ assert_equal(t.strftime('%V'), d.strftime('%V'))
+ assert_equal(t.strftime('%u'), d.strftime('%u'))
+ end
+ end
+
+ def test_strftime__4
+ s = '2006-08-08T23:15:33.123456789'
+ f = '%FT%T.%N'
+ d = DateTime.parse(s)
+ assert_equal(s, d.strftime(f))
+ d = DateTime.strptime(s, f)
+ assert_equal(s, d.strftime(f))
+
+ s = '2006-08-08T23:15:33.123456789'
+ f = '%FT%T.%N'
+ d = DateTime.parse(s + '123456789')
+ assert_equal(s, d.strftime(f))
+ d = DateTime.strptime(s + '123456789', f)
+ assert_equal(s, d.strftime(f))
+
+ si = '2006-08-08T23:15:33.9'
+ so = '2006-08-08T23:15:33.900000000'
+ f = '%FT%T.%N'
+ d = DateTime.parse(si)
+ assert_equal(so, d.strftime(f))
+ d = DateTime.strptime(si, f)
+ assert_equal(so, d.strftime(f))
+
+ s = '2006-08-08T23:15:33.123'
+ f = '%FT%T.%L'
+ d = DateTime.parse(s)
+ assert_equal(s, d.strftime(f))
+ d = DateTime.strptime(s, f)
+ assert_equal(s, d.strftime(f))
+
+ s = '2006-08-08T23:15:33.123'
+ f = '%FT%T.%L'
+ d = DateTime.parse(s + '123')
+ assert_equal(s, d.strftime(f))
+ d = DateTime.strptime(s + '123', f)
+ assert_equal(s, d.strftime(f))
+
+ si = '2006-08-08T23:15:33.9'
+ so = '2006-08-08T23:15:33.900'
+ f = '%FT%T.%L'
+ d = DateTime.parse(si)
+ assert_equal(so, d.strftime(f))
+ d = DateTime.strptime(si, f)
+ assert_equal(so, d.strftime(f))
+ end
+
+ def test_strftime__offset
+ s = '2006-08-08T23:15:33'
+ (-24..24).collect{|x| '%+.2d' % x}.each do |hh|
+ %w(00 30).each do |mm|
+ d = DateTime.parse(s + hh + mm)
+ assert_equal(hh + mm, d.strftime('%z'))
+ end
+ end
+ end
+
+ def test_strftime__minus
+ d = DateTime.new(1969, 12, 31, 23, 59, 59)
+ assert_equal('-1', d.strftime('%s'))
+ assert_equal('-1000', d.strftime('%Q'))
+ end
+
+ def test_strftime__gnuext # coreutils
+ d = DateTime.new(2006,8,8,23,15,33,9.to_r/24)
+
+ assert_equal('2006', d.strftime('%-Y'))
+ assert_equal('2006', d.strftime('%-5Y'))
+ assert_equal('02006', d.strftime('%5Y'))
+ assert_equal('2006', d.strftime('%_Y'))
+ assert_equal(' 2006', d.strftime('%_5Y'))
+ assert_equal('02006', d.strftime('%05Y'))
+
+ assert_equal('8', d.strftime('%-d'))
+ assert_equal('8', d.strftime('%-3d'))
+ assert_equal('008', d.strftime('%3d'))
+ assert_equal(' 8', d.strftime('%_d'))
+ assert_equal(' 8', d.strftime('%_3d'))
+ assert_equal('008', d.strftime('%03d'))
+
+ assert_equal('8', d.strftime('%-e'))
+ assert_equal('8', d.strftime('%-3e'))
+ assert_equal(' 8', d.strftime('%3e'))
+ assert_equal(' 8', d.strftime('%_e'))
+ assert_equal(' 8', d.strftime('%_3e'))
+ assert_equal('008', d.strftime('%03e'))
+
+ assert_equal('Tuesday', d.strftime('%-10A'))
+ assert_equal(' Tuesday', d.strftime('%10A'))
+ assert_equal(' Tuesday', d.strftime('%_10A'))
+ assert_equal('000Tuesday', d.strftime('%010A'))
+ assert_equal('TUESDAY', d.strftime('%^A'))
+ assert_equal('TUESDAY', d.strftime('%#A'))
+
+ assert_equal('Tue', d.strftime('%-6a'))
+ assert_equal(' Tue', d.strftime('%6a'))
+ assert_equal(' Tue', d.strftime('%_6a'))
+ assert_equal('000Tue', d.strftime('%06a'))
+ assert_equal('TUE', d.strftime('%^a'))
+ assert_equal('TUE', d.strftime('%#a'))
+ assert_equal(' TUE', d.strftime('%#6a'))
+
+ assert_equal('August', d.strftime('%-10B'))
+ assert_equal(' August', d.strftime('%10B'))
+ assert_equal(' August', d.strftime('%_10B'))
+ assert_equal('0000August', d.strftime('%010B'))
+ assert_equal('AUGUST', d.strftime('%^B'))
+ assert_equal('AUGUST', d.strftime('%#B'))
+
+ assert_equal('Aug', d.strftime('%-6b'))
+ assert_equal(' Aug', d.strftime('%6b'))
+ assert_equal(' Aug', d.strftime('%_6b'))
+ assert_equal('000Aug', d.strftime('%06b'))
+ assert_equal('AUG', d.strftime('%^b'))
+ assert_equal('AUG', d.strftime('%#b'))
+ assert_equal(' AUG', d.strftime('%#6b'))
+
+ assert_equal('Aug', d.strftime('%-6h'))
+ assert_equal(' Aug', d.strftime('%6h'))
+ assert_equal(' Aug', d.strftime('%_6h'))
+ assert_equal('000Aug', d.strftime('%06h'))
+ assert_equal('AUG', d.strftime('%^h'))
+ assert_equal('AUG', d.strftime('%#h'))
+ assert_equal(' AUG', d.strftime('%#6h'))
+
+ assert_equal('PM', d.strftime('%^p'))
+ assert_equal('pm', d.strftime('%#p'))
+ assert_equal('PM', d.strftime('%^P'))
+ assert_equal('PM', d.strftime('%#P'))
+
+ assert_equal('+000900', d.strftime('%7z'))
+ assert_equal(' +900', d.strftime('%_7z'))
+ assert_equal('+09:00', d.strftime('%:z'))
+ assert_equal('+0009:00', d.strftime('%8:z'))
+ assert_equal(' +9:00', d.strftime('%_8:z'))
+ assert_equal('+09:00:00', d.strftime('%::z'))
+ assert_equal('+0009:00:00', d.strftime('%11::z'))
+ assert_equal(' +9:00:00', d.strftime('%_11::z'))
+ assert_equal('+09', d.strftime('%:::z'))
+ assert_equal('+0009', d.strftime('%5:::z'))
+ assert_equal(' +9', d.strftime('%_5:::z'))
+ assert_equal('+9', d.strftime('%-:::z'))
+
+ d = DateTime.new(-200,8,8,23,15,33,9.to_r/24)
+
+ assert_equal('-0200', d.strftime('%Y'))
+ assert_equal('-200', d.strftime('%-Y'))
+ assert_equal('-200', d.strftime('%-5Y'))
+ assert_equal('-0200', d.strftime('%5Y'))
+ assert_equal(' -200', d.strftime('%_Y'))
+ assert_equal(' -200', d.strftime('%_5Y'))
+ assert_equal('-0200', d.strftime('%05Y'))
+
+ d = DateTime.new(-2000,8,8,23,15,33,9.to_r/24)
+
+ assert_equal('-2000', d.strftime('%Y'))
+ assert_equal('-2000', d.strftime('%-Y'))
+ assert_equal('-2000', d.strftime('%-5Y'))
+ assert_equal('-2000', d.strftime('%5Y'))
+ assert_equal('-2000', d.strftime('%_Y'))
+ assert_equal('-2000', d.strftime('%_5Y'))
+ assert_equal('-2000', d.strftime('%05Y'))
+ end
+
+ def test_strftime__gnuext_z # coreutils
+ d = DateTime.parse('2006-08-08T23:15:33+09:08:07')
+ assert_equal('+0908', d.strftime('%z'))
+ assert_equal('+09:08', d.strftime('%:z'))
+ assert_equal('+09:08:07', d.strftime('%::z'))
+ assert_equal('+09:08:07', d.strftime('%:::z'))
+ end
+
+ def test__different_format
+ d = Date.new(2001,2,3)
+
+ assert_equal('Sat Feb 3 00:00:00 2001', d.ctime)
+ assert_equal(d.ctime, d.asctime)
+
+ assert_equal('2001-02-03', d.iso8601)
+ assert_equal(d.rfc3339, d.iso8601)
+ assert_equal(d.xmlschema, d.iso8601)
+ assert_equal('Sat, 3 Feb 2001 00:00:00 +0000', d.rfc2822)
+ assert_equal(d.rfc822, d.rfc2822)
+ assert_equal('Sat, 03 Feb 2001 00:00:00 GMT', d.httpdate)
+ assert_equal('H13.02.03', d.jisx0301)
+
+ d = DateTime.new(2001,2,3)
+
+ assert_equal('Sat Feb 3 00:00:00 2001', d.ctime)
+ assert_equal(d.ctime, d.asctime)
+
+ assert_equal('2001-02-03T00:00:00+00:00', d.iso8601)
+ assert_equal(d.rfc3339, d.iso8601)
+ assert_equal(d.xmlschema, d.iso8601)
+ assert_equal('Sat, 3 Feb 2001 00:00:00 +0000', d.rfc2822)
+ assert_equal(d.rfc822, d.rfc2822)
+ assert_equal('Sat, 03 Feb 2001 00:00:00 GMT', d.httpdate)
+ assert_equal('H13.02.03T00:00:00+00:00', d.jisx0301)
+
+ d2 = DateTime.parse('2001-02-03T04:05:06.123456')
+ assert_equal('2001-02-03T04:05:06.123+00:00', d2.iso8601(3))
+ assert_equal('2001-02-03T04:05:06.123+00:00', d2.rfc3339(3))
+ assert_equal('H13.02.03T04:05:06.123+00:00', d2.jisx0301(3))
+ assert_equal('2001-02-03T04:05:06.123456000+00:00', d2.iso8601(9))
+ assert_equal('2001-02-03T04:05:06.123456000+00:00', d2.rfc3339(9))
+ assert_equal('H13.02.03T04:05:06.123456000+00:00', d2.jisx0301(9))
+
+ assert_equal('1868-01-25', Date.parse('1868-01-25').jisx0301)
+ assert_equal('1872-12-31', Date.parse('1872-12-31').jisx0301)
+
+ assert_equal('M06.01.01', Date.parse('1873-01-01').jisx0301)
+ assert_equal('M45.07.29', Date.parse('1912-07-29').jisx0301)
+ assert_equal('T01.07.30', Date.parse('1912-07-30').jisx0301)
+ assert_equal('T15.12.24', Date.parse('1926-12-24').jisx0301)
+ assert_equal('S01.12.25', Date.parse('1926-12-25').jisx0301)
+ assert_equal('S64.01.07', Date.parse('1989-01-07').jisx0301)
+ assert_equal('H01.01.08', Date.parse('1989-01-08').jisx0301)
+ assert_equal('H18.09.01', Date.parse('2006-09-01').jisx0301)
+
+ %w(M06.01.01
+ M45.07.29
+ T01.07.30
+ T15.12.24
+ S01.12.25
+ S64.01.07
+ H01.01.08
+ H18.09.01).each do |s|
+ assert_equal(s, Date.parse(s).jisx0301)
+ end
+
+ end
+
+end
diff --git a/test/date/test_date_strptime.rb b/test/date/test_date_strptime.rb
new file mode 100644
index 0000000000..572d1ea42a
--- /dev/null
+++ b/test/date/test_date_strptime.rb
@@ -0,0 +1,469 @@
+require 'test/unit'
+require 'date'
+
+class TestDateStrptime < Test::Unit::TestCase
+
+ STRFTIME_2001_02_03 = {
+ '%A'=>['Saturday',{:wday=>6}],
+ '%a'=>['Sat',{:wday=>6}],
+ '%B'=>['February',{:mon=>2}],
+ '%b'=>['Feb',{:mon=>2}],
+ '%c'=>['Sat Feb 3 00:00:00 2001',
+ {:wday=>6,:mon=>2,:mday=>3,:hour=>0,:min=>0,:sec=>0,:year=>2001}],
+ '%d'=>['03',{:mday=>3}],
+ '%e'=>[' 3',{:mday=>3}],
+ '%H'=>['00',{:hour=>0}],
+ '%I'=>['12',{:hour=>0}],
+ '%j'=>['034',{:yday=>34}],
+ '%M'=>['00',{:min=>0}],
+ '%m'=>['02',{:mon=>2}],
+ '%p'=>['AM',{}],
+ '%S'=>['00',{:sec=>0}],
+ '%U'=>['04',{:wnum0=>4}],
+ '%W'=>['05',{:wnum1=>5}],
+ '%X'=>['00:00:00',{:hour=>0,:min=>0,:sec=>0}],
+ '%x'=>['02/03/01',{:mon=>2,:mday=>3,:year=>2001}],
+ '%Y'=>['2001',{:year=>2001}],
+ '%y'=>['01',{:year=>2001}],
+ '%Z'=>['+00:00',{:zone=>'+00:00',:offset=>0}],
+ '%%'=>['%',{}],
+ '%C'=>['20',{}],
+ '%D'=>['02/03/01',{:mon=>2,:mday=>3,:year=>2001}],
+ '%F'=>['2001-02-03',{:year=>2001,:mon=>2,:mday=>3}],
+ '%G'=>['2001',{:cwyear=>2001}],
+ '%g'=>['01',{:cwyear=>2001}],
+ '%h'=>['Feb',{:mon=>2}],
+ '%k'=>[' 0',{:hour=>0}],
+ '%L'=>['000',{:sec_fraction=>0}],
+ '%l'=>['12',{:hour=>0}],
+ '%N'=>['000000000',{:sec_fraction=>0}],
+ '%n'=>["\n",{}],
+ '%P'=>['am',{}],
+ '%Q'=>['981158400000',{:seconds=>981158400.to_r}],
+ '%R'=>['00:00',{:hour=>0,:min=>0}],
+ '%r'=>['12:00:00 AM',{:hour=>0,:min=>0,:sec=>0}],
+ '%s'=>['981158400',{:seconds=>981158400}],
+ '%T'=>['00:00:00',{:hour=>0,:min=>0,:sec=>0}],
+ '%t'=>["\t",{}],
+ '%u'=>['6',{:cwday=>6}],
+ '%V'=>['05',{:cweek=>5}],
+ '%v'=>[' 3-Feb-2001',{:mday=>3,:mon=>2,:year=>2001}],
+ '%z'=>['+0000',{:zone=>'+0000',:offset=>0}],
+ '%+'=>['Sat Feb 3 00:00:00 +00:00 2001',
+ {:wday=>6,:mon=>2,:mday=>3,
+ :hour=>0,:min=>0,:sec=>0,:zone=>'+00:00',:offset=>0,:year=>2001}],
+ }
+
+ STRFTIME_2001_02_03_CVS19 = {
+ }
+
+ STRFTIME_2001_02_03_GNUext = {
+ '%:z'=>['+00:00',{:zone=>'+00:00',:offset=>0}],
+ '%::z'=>['+00:00:00',{:zone=>'+00:00:00',:offset=>0}],
+ '%:::z'=>['+00',{:zone=>'+00',:offset=>0}],
+ }
+
+ STRFTIME_2001_02_03.update(STRFTIME_2001_02_03_CVS19)
+ STRFTIME_2001_02_03.update(STRFTIME_2001_02_03_GNUext)
+
+ def test__strptime
+ STRFTIME_2001_02_03.each do |f, s|
+ if (f == '%I' and s[0] == '12') or
+ (f == '%l' and s[0] == '12') # hour w/o merid
+ s[1][:hour] = 12
+ end
+ assert_equal(s[1], Date._strptime(s[0], f), [f, s].inspect)
+ case f[-1,1]
+ when 'c', 'C', 'x', 'X', 'y', 'Y'
+ f2 = f.sub(/\A%/, '%E')
+ assert_equal(s[1], Date._strptime(s[0], f2), [f2, s].inspect)
+ else
+ f2 = f.sub(/\A%/, '%E')
+ assert_equal(nil, Date._strptime(s[0], f2), [f2, s].inspect)
+ assert_equal({}, Date._strptime(f2, f2), [f2, s].inspect)
+ end
+ case f[-1,1]
+ when 'd', 'e', 'H', 'I', 'm', 'M', 'S', 'u', 'U', 'V', 'w', 'W', 'y'
+ f2 = f.sub(/\A%/, '%O')
+ assert_equal(s[1], Date._strptime(s[0], f2), [f2, s].inspect)
+ else
+ f2 = f.sub(/\A%/, '%O')
+ assert_equal(nil, Date._strptime(s[0], f2), [f2, s].inspect)
+ assert_equal({}, Date._strptime(f2, f2), [f2, s].inspect)
+ end
+ end
+ end
+
+ def test__strptime__2
+ h = Date._strptime('2001-02-03')
+ assert_equal([2001,2,3], h.values_at(:year,:mon,:mday))
+
+ h = DateTime._strptime('2001-02-03T12:13:14Z')
+ assert_equal([2001,2,3,12,13,14],
+ h.values_at(:year,:mon,:mday,:hour,:min,:sec))
+
+ assert_equal({}, Date._strptime('', ''))
+ assert_equal({:leftover=>"\s"*3}, Date._strptime("\s"*3, ''))
+ assert_equal({:leftover=>'x'}, Date._strptime("\nx", "\n"))
+ assert_equal({}, Date._strptime('', "\s"*3))
+ assert_equal({}, Date._strptime("\s"*3, "\s"*3))
+ assert_equal({}, Date._strptime("\tfoo\n\000\r", "\tfoo\n\000\r"))
+ assert_equal({}, Date._strptime("foo\n\nbar", "foo\sbar"))
+ assert_equal({}, Date._strptime("%\n", "%\n")) # gnu
+ assert_equal({}, Date._strptime('%%', '%%%'))
+ assert_equal({:wday=>6}, Date._strptime('Saturday'*1024 + ',', '%A'*1024 + ','))
+ assert_equal({:wday=>6}, Date._strptime('Saturday'*1024 + ',', '%a'*1024 + ','))
+ assert_equal({}, Date._strptime('Anton von Webern', 'Anton von Webern'))
+ end
+
+ def test__strptime__3
+ [
+ # iso8601
+ [['2001-02-03', '%Y-%m-%d'], [2001,2,3,nil,nil,nil,nil,nil,nil]],
+ [['2001-02-03T23:59:60', '%Y-%m-%dT%H:%M:%S'], [2001,2,3,23,59,60,nil,nil,nil]],
+ [['2001-02-03T23:59:60+09:00', '%Y-%m-%dT%H:%M:%S%Z'], [2001,2,3,23,59,60,'+09:00',9*3600,nil]],
+ [['-2001-02-03T23:59:60+09:00', '%Y-%m-%dT%H:%M:%S%Z'], [-2001,2,3,23,59,60,'+09:00',9*3600,nil]],
+ [['+012345-02-03T23:59:60+09:00', '%Y-%m-%dT%H:%M:%S%Z'], [12345,2,3,23,59,60,'+09:00',9*3600,nil]],
+ [['-012345-02-03T23:59:60+09:00', '%Y-%m-%dT%H:%M:%S%Z'], [-12345,2,3,23,59,60,'+09:00',9*3600,nil]],
+
+ # ctime(3), asctime(3)
+ [['Thu Jul 29 14:47:19 1999', '%c'], [1999,7,29,14,47,19,nil,nil,4]],
+ [['Thu Jul 29 14:47:19 -1999', '%c'], [-1999,7,29,14,47,19,nil,nil,4]],
+
+ # date(1)
+ [['Thu Jul 29 16:39:41 EST 1999', '%a %b %d %H:%M:%S %Z %Y'], [1999,7,29,16,39,41,'EST',-5*3600,4]],
+ [['Thu Jul 29 16:39:41 MET DST 1999', '%a %b %d %H:%M:%S %Z %Y'], [1999,7,29,16,39,41,'MET DST',2*3600,4]],
+ [['Thu Jul 29 16:39:41 AMT 1999', '%a %b %d %H:%M:%S %Z %Y'], [1999,7,29,16,39,41,'AMT',nil,4]],
+ [['Thu Jul 29 16:39:41 AMT -1999', '%a %b %d %H:%M:%S %Z %Y'], [-1999,7,29,16,39,41,'AMT',nil,4]],
+ [['Thu Jul 29 16:39:41 GMT+09 1999', '%a %b %d %H:%M:%S %Z %Y'], [1999,7,29,16,39,41,'GMT+09',9*3600,4]],
+ [['Thu Jul 29 16:39:41 GMT+0908 1999', '%a %b %d %H:%M:%S %Z %Y'], [1999,7,29,16,39,41,'GMT+0908',9*3600+8*60,4]],
+ [['Thu Jul 29 16:39:41 GMT+090807 1999', '%a %b %d %H:%M:%S %Z %Y'], [1999,7,29,16,39,41,'GMT+090807',9*3600+8*60+7,4]],
+ [['Thu Jul 29 16:39:41 GMT-09 1999', '%a %b %d %H:%M:%S %Z %Y'], [1999,7,29,16,39,41,'GMT-09',-9*3600,4]],
+ [['Thu Jul 29 16:39:41 GMT-09:08 1999', '%a %b %d %H:%M:%S %Z %Y'], [1999,7,29,16,39,41,'GMT-09:08',-9*3600-8*60,4]],
+ [['Thu Jul 29 16:39:41 GMT-09:08:07 1999', '%a %b %d %H:%M:%S %Z %Y'], [1999,7,29,16,39,41,'GMT-09:08:07',-9*3600-8*60-7,4]],
+ [['Thu Jul 29 16:39:41 GMT-3.5 1999', '%a %b %d %H:%M:%S %Z %Y'], [1999,7,29,16,39,41,'GMT-3.5',-3*3600-30*60,4]],
+ [['Thu Jul 29 16:39:41 GMT-3,5 1999', '%a %b %d %H:%M:%S %Z %Y'], [1999,7,29,16,39,41,'GMT-3,5',-3*3600-30*60,4]],
+ [['Thu Jul 29 16:39:41 Mountain Daylight Time 1999', '%a %b %d %H:%M:%S %Z %Y'], [1999,7,29,16,39,41,'Mountain Daylight Time',-6*3600,4]],
+ [['Thu Jul 29 16:39:41 E. Australia Standard Time 1999', '%a %b %d %H:%M:%S %Z %Y'], [1999,7,29,16,39,41,'E. Australia Standard Time',10*3600,4]],
+
+ # rfc822
+ [['Thu, 29 Jul 1999 09:54:21 UT', '%a, %d %b %Y %H:%M:%S %Z'], [1999,7,29,9,54,21,'UT',0,4]],
+ [['Thu, 29 Jul 1999 09:54:21 GMT', '%a, %d %b %Y %H:%M:%S %Z'], [1999,7,29,9,54,21,'GMT',0,4]],
+ [['Thu, 29 Jul 1999 09:54:21 PDT', '%a, %d %b %Y %H:%M:%S %Z'], [1999,7,29,9,54,21,'PDT',-7*3600,4]],
+ [['Thu, 29 Jul 1999 09:54:21 z', '%a, %d %b %Y %H:%M:%S %Z'], [1999,7,29,9,54,21,'z',0,4]],
+ [['Thu, 29 Jul 1999 09:54:21 +0900', '%a, %d %b %Y %H:%M:%S %Z'], [1999,7,29,9,54,21,'+0900',9*3600,4]],
+ [['Thu, 29 Jul 1999 09:54:21 +0430', '%a, %d %b %Y %H:%M:%S %Z'], [1999,7,29,9,54,21,'+0430',4*3600+30*60,4]],
+ [['Thu, 29 Jul 1999 09:54:21 -0430', '%a, %d %b %Y %H:%M:%S %Z'], [1999,7,29,9,54,21,'-0430',-4*3600-30*60,4]],
+ [['Thu, 29 Jul -1999 09:54:21 -0430', '%a, %d %b %Y %H:%M:%S %Z'], [-1999,7,29,9,54,21,'-0430',-4*3600-30*60,4]],
+
+ # etc
+ [['06-DEC-99', '%d-%b-%y'], [1999,12,6,nil,nil,nil,nil,nil,nil]],
+ [['sUnDay oCtoBer 31 01', '%A %B %d %y'], [2001,10,31,nil,nil,nil,nil,nil,0]],
+ [["October\t\n\v\f\r 15,\t\n\v\f\r99", '%B %d, %y'], [1999,10,15,nil,nil,nil,nil,nil,nil]],
+ [["October\t\n\v\f\r 15,\t\n\v\f\r99", '%B%t%d,%n%y'], [1999,10,15,nil,nil,nil,nil,nil,nil]],
+
+ [['09:02:11 AM', '%I:%M:%S %p'], [nil,nil,nil,9,2,11,nil,nil,nil]],
+ [['09:02:11 A.M.', '%I:%M:%S %p'], [nil,nil,nil,9,2,11,nil,nil,nil]],
+ [['09:02:11 PM', '%I:%M:%S %p'], [nil,nil,nil,21,2,11,nil,nil,nil]],
+ [['09:02:11 P.M.', '%I:%M:%S %p'], [nil,nil,nil,21,2,11,nil,nil,nil]],
+
+ [['12:33:44 AM', '%r'], [nil,nil,nil,0,33,44,nil,nil,nil]],
+ [['01:33:44 AM', '%r'], [nil,nil,nil,1,33,44,nil,nil,nil]],
+ [['11:33:44 AM', '%r'], [nil,nil,nil,11,33,44,nil,nil,nil]],
+ [['12:33:44 PM', '%r'], [nil,nil,nil,12,33,44,nil,nil,nil]],
+ [['01:33:44 PM', '%r'], [nil,nil,nil,13,33,44,nil,nil,nil]],
+ [['11:33:44 PM', '%r'], [nil,nil,nil,23,33,44,nil,nil,nil]],
+
+ [['11:33:44 PM AMT', '%I:%M:%S %p %Z'], [nil,nil,nil,23,33,44,'AMT',nil,nil]],
+ [['11:33:44 P.M. AMT', '%I:%M:%S %p %Z'], [nil,nil,nil,23,33,44,'AMT',nil,nil]],
+
+ [['fri1feb034pm+5', '%a%d%b%y%H%p%Z'], [2003,2,1,16,nil,nil,'+5',5*3600,5]]
+ ].each do |x, y|
+ h = Date._strptime(*x)
+ a = h.values_at(:year,:mon,:mday,:hour,:min,:sec,:zone,:offset,:wday)
+ if y[1] == -1
+ a[1] = -1
+ a[2] = h[:yday]
+ end
+ assert_equal(y, a, [x, y, a].inspect)
+ end
+ end
+
+ def test__strptime__width
+ [
+ [['99', '%y'], [1999,nil,nil,nil,nil,nil,nil,nil,nil]],
+ [['01', '%y'], [2001,nil,nil,nil,nil,nil,nil,nil,nil]],
+ [['19 99', '%C %y'], [1999,nil,nil,nil,nil,nil,nil,nil,nil]],
+ [['20 01', '%C %y'], [2001,nil,nil,nil,nil,nil,nil,nil,nil]],
+ [['1999', '%C%y'], [1999,nil,nil,nil,nil,nil,nil,nil,nil]],
+ [['2001', '%C%y'], [2001,nil,nil,nil,nil,nil,nil,nil,nil]],
+
+ [['20060806', '%Y'], [20060806,nil,nil,nil,nil,nil,nil,nil,nil]],
+ [['20060806', "%Y\s"], [20060806,nil,nil,nil,nil,nil,nil,nil,nil]],
+ [['20060806', '%Y%m%d'], [2006,8,6,nil,nil,nil,nil,nil,nil]],
+ [['2006908906', '%Y9%m9%d'], [2006,8,6,nil,nil,nil,nil,nil,nil]],
+ [['12006 08 06', '%Y %m %d'], [12006,8,6,nil,nil,nil,nil,nil,nil]],
+ [['12006-08-06', '%Y-%m-%d'], [12006,8,6,nil,nil,nil,nil,nil,nil]],
+ [['200608 6', '%Y%m%e'], [2006,8,6,nil,nil,nil,nil,nil,nil]],
+
+ [['2006333', '%Y%j'], [2006,-1,333,nil,nil,nil,nil,nil,nil]],
+ [['20069333', '%Y9%j'], [2006,-1,333,nil,nil,nil,nil,nil,nil]],
+ [['12006 333', '%Y %j'], [12006,-1,333,nil,nil,nil,nil,nil,nil]],
+ [['12006-333', '%Y-%j'], [12006,-1,333,nil,nil,nil,nil,nil,nil]],
+
+ [['232425', '%H%M%S'], [nil,nil,nil,23,24,25,nil,nil,nil]],
+ [['23924925', '%H9%M9%S'], [nil,nil,nil,23,24,25,nil,nil,nil]],
+ [['23 24 25', '%H %M %S'], [nil,nil,nil,23,24,25,nil,nil,nil]],
+ [['23:24:25', '%H:%M:%S'], [nil,nil,nil,23,24,25,nil,nil,nil]],
+ [[' 32425', '%k%M%S'], [nil,nil,nil,3,24,25,nil,nil,nil]],
+ [[' 32425', '%l%M%S'], [nil,nil,nil,3,24,25,nil,nil,nil]],
+
+ [['FriAug', '%a%b'], [nil,8,nil,nil,nil,nil,nil,nil,5]],
+ [['FriAug', '%A%B'], [nil,8,nil,nil,nil,nil,nil,nil,5]],
+ [['FridayAugust', '%A%B'], [nil,8,nil,nil,nil,nil,nil,nil,5]],
+ [['FridayAugust', '%a%b'], [nil,8,nil,nil,nil,nil,nil,nil,5]]
+ ].each do |x, y|
+ h = Date._strptime(*x)
+ a = h.values_at(:year,:mon,:mday,:hour,:min,:sec,:zone,:offset,:wday)
+ if y[1] == -1
+ a[1] = -1
+ a[2] = h[:yday]
+ end
+ assert_equal(y, a, [x, y, a].inspect)
+ end
+ end
+
+ def test__strptime__fail
+ assert_not_nil(Date._strptime('2001.', '%Y.'))
+ assert_not_nil(Date._strptime("2001.\s", '%Y.'))
+ assert_not_nil(Date._strptime('2001.', "%Y.\s"))
+ assert_not_nil(Date._strptime("2001.\s", "%Y.\s"))
+
+ assert_nil(Date._strptime('2001', '%Y.'))
+ assert_nil(Date._strptime("2001\s", '%Y.'))
+ assert_nil(Date._strptime('2001', "%Y.\s"))
+ assert_nil(Date._strptime("2001\s", "%Y.\s"))
+
+ assert_nil(Date._strptime('2001-13-31', '%Y-%m-%d'))
+ assert_nil(Date._strptime('2001-12-00', '%Y-%m-%d'))
+ assert_nil(Date._strptime('2001-12-32', '%Y-%m-%d'))
+ assert_nil(Date._strptime('2001-12-00', '%Y-%m-%e'))
+ assert_nil(Date._strptime('2001-12-32', '%Y-%m-%e'))
+ assert_nil(Date._strptime('2001-12-31', '%y-%m-%d'))
+
+ assert_nil(Date._strptime('2004-000', '%Y-%j'))
+ assert_nil(Date._strptime('2004-367', '%Y-%j'))
+ assert_nil(Date._strptime('2004-366', '%y-%j'))
+
+ assert_not_nil(Date._strptime('24:59:59', '%H:%M:%S'))
+ assert_not_nil(Date._strptime('24:59:59', '%k:%M:%S'))
+ assert_not_nil(Date._strptime('24:59:60', '%H:%M:%S'))
+ assert_not_nil(Date._strptime('24:59:60', '%k:%M:%S'))
+
+ assert_nil(Date._strptime('24:60:59', '%H:%M:%S'))
+ assert_nil(Date._strptime('24:60:59', '%k:%M:%S'))
+ assert_nil(Date._strptime('24:59:61', '%H:%M:%S'))
+ assert_nil(Date._strptime('24:59:61', '%k:%M:%S'))
+ assert_nil(Date._strptime('00:59:59', '%I:%M:%S'))
+ assert_nil(Date._strptime('13:59:59', '%I:%M:%S'))
+ assert_nil(Date._strptime('00:59:59', '%l:%M:%S'))
+ assert_nil(Date._strptime('13:59:59', '%l:%M:%S'))
+
+ assert_not_nil(Date._strptime('0', '%U'))
+ assert_nil(Date._strptime('54', '%U'))
+ assert_not_nil(Date._strptime('0', '%W'))
+ assert_nil(Date._strptime('54', '%W'))
+ assert_nil(Date._strptime('0', '%V'))
+ assert_nil(Date._strptime('54', '%V'))
+ assert_nil(Date._strptime('0', '%u'))
+ assert_not_nil(Date._strptime('7', '%u'))
+ assert_not_nil(Date._strptime('0', '%w'))
+ assert_nil(Date._strptime('7', '%w'))
+
+ assert_nil(Date._strptime('Sanday', '%A'))
+ assert_nil(Date._strptime('Jenuary', '%B'))
+ assert_not_nil(Date._strptime('Sundai', '%A'))
+ assert_not_nil(Date._strptime('Januari', '%B'))
+ assert_nil(Date._strptime('Sundai,', '%A,'))
+ assert_nil(Date._strptime('Januari,', '%B,'))
+ end
+
+ def test_strptime
+ assert_equal(Date.new, Date.strptime)
+ d = Date.new(2002,3,14)
+ assert_equal(d, Date.strptime(d.to_s))
+ assert_equal(Date.new(2002,3,14), Date.strptime('2002-03-14'))
+
+ d = DateTime.new(2002,3,14,11,22,33, 0)
+ assert_equal(d, DateTime.strptime(d.to_s))
+ assert_equal(DateTime.new(2002,3,14,11,22,33, 0),
+ DateTime.strptime('2002-03-14T11:22:33Z'))
+ assert_equal(DateTime.new(2002,3,14,11,22,33, 0),
+ DateTime.strptime('2002-03-14T11:22:33Z', '%Y-%m-%dT%H:%M:%S%Z'))
+ assert_equal(DateTime.new(2002,3,14,11,22,33, 9.to_r/24),
+ DateTime.strptime('2002-03-14T11:22:33+09:00', '%Y-%m-%dT%H:%M:%S%Z'))
+ assert_equal(DateTime.new(2002,3,14,11,22,33, -9.to_r/24),
+ DateTime.strptime('2002-03-14T11:22:33-09:00', '%FT%T%Z'))
+ assert_equal(DateTime.new(2002,3,14,11,22,33, -9.to_r/24) + 123456789.to_r/1000000000/86400,
+ DateTime.strptime('2002-03-14T11:22:33.123456789-09:00', '%FT%T.%N%Z'))
+ end
+
+ def test_strptime__2
+ n = 10**9
+ (Date.new(2006,6,1)..Date.new(2007,6,1)).each do |d|
+ [
+ '%Y %m %d',
+ '%C %y %m %d',
+
+ '%Y %j',
+ '%C %y %j',
+
+ '%G %V %w',
+ '%G %V %u',
+ '%C %g %V %w',
+ '%C %g %V %u',
+
+ '%Y %U %w',
+ '%Y %U %u',
+ '%Y %W %w',
+ '%Y %W %u',
+ '%C %y %U %w',
+ '%C %y %U %u',
+ '%C %y %W %w',
+ '%C %y %W %u',
+ ].each do |fmt|
+ s = d.strftime(fmt)
+ d2 = Date.strptime(s, fmt)
+ assert_equal(d, d2, [fmt, d.to_s, d2.to_s].inspect)
+ end
+
+ [
+ '%Y %m %d %H %M %S',
+ '%Y %m %d %H %M %S %N',
+ '%C %y %m %d %H %M %S',
+ '%C %y %m %d %H %M %S %N',
+
+ '%Y %j %H %M %S',
+ '%Y %j %H %M %S %N',
+ '%C %y %j %H %M %S',
+ '%C %y %j %H %M %S %N',
+
+ '%s',
+ '%s %N',
+ '%Q',
+ '%Q %N',
+ ].each do |fmt|
+ s = d.strftime(fmt)
+ d2 = DateTime.strptime(s, fmt)
+ assert_equal(d, d2, [fmt, d.to_s, d2.to_s].inspect)
+ end
+ end
+ end
+
+ def test_strptime__minus
+ d = DateTime.strptime('-1', '%s')
+ assert_equal([1969, 12, 31, 23, 59, 59],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec])
+ d = DateTime.strptime('-86400', '%s')
+ assert_equal([1969, 12, 31, 0, 0, 0],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec])
+
+ d = DateTime.strptime('-999', '%Q')
+ assert_equal([1969, 12, 31, 23, 59, 59, 1.to_r/10**3],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec, d.sec_fraction])
+ d = DateTime.strptime('-1000', '%Q')
+ assert_equal([1969, 12, 31, 23, 59, 59, 0],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec, d.sec_fraction])
+ end
+
+ def test_strptime__comp
+ n = DateTime.now
+
+ d = DateTime.strptime('073', '%j')
+ assert_equal([n.year, 73, 0, 0, 0],
+ [d.year, d.yday, d.hour, d.min, d.sec])
+ d = DateTime.strptime('13', '%d')
+ assert_equal([n.year, n.mon, 13, 0, 0, 0],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec])
+
+ d = DateTime.strptime('Mar', '%b')
+ assert_equal([n.year, 3, 1, 0, 0, 0],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec])
+ d = DateTime.strptime('2004', '%Y')
+ assert_equal([2004, 1, 1, 0, 0, 0],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec])
+
+ d = DateTime.strptime('Mar 13', '%b %d')
+ assert_equal([n.year, 3, 13, 0, 0, 0],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec])
+ d = DateTime.strptime('Mar 2004', '%b %Y')
+ assert_equal([2004, 3, 1, 0, 0, 0],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec])
+ d = DateTime.strptime('23:55', '%H:%M')
+ assert_equal([n.year, n.mon, n.mday, 23, 55, 0],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec])
+ d = DateTime.strptime('23:55:30', '%H:%M:%S')
+ assert_equal([n.year, n.mon, n.mday, 23, 55, 30],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec])
+
+ d = DateTime.strptime('Sun 23:55', '%a %H:%M')
+ d2 = d - d.wday
+ assert_equal([d2.year, d2.mon, d2.mday, 23, 55, 0],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec])
+ d = DateTime.strptime('Aug 23:55', '%b %H:%M')
+ assert_equal([n.year, 8, 1, 23, 55, 0],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec])
+
+ d = DateTime.strptime('2004', '%G')
+ assert_equal([2004, 1, 1, 0, 0, 0],
+ [d.cwyear, d.cweek, d.cwday, d.hour, d.min, d.sec])
+ d = DateTime.strptime('11', '%V')
+ assert_equal([n.cwyear, 11, 1, 0, 0, 0],
+ [d.cwyear, d.cweek, d.cwday, d.hour, d.min, d.sec])
+ d = DateTime.strptime('6', '%u')
+ assert_equal([n.cwyear, n.cweek, 6, 0, 0, 0],
+ [d.cwyear, d.cweek, d.cwday, d.hour, d.min, d.sec])
+
+ d = DateTime.strptime('11-6', '%V-%u')
+ assert_equal([n.cwyear, 11, 6, 0, 0, 0],
+ [d.cwyear, d.cweek, d.cwday, d.hour, d.min, d.sec])
+ d = DateTime.strptime('2004-11', '%G-%V')
+ assert_equal([2004, 11, 1, 0, 0, 0],
+ [d.cwyear, d.cweek, d.cwday, d.hour, d.min, d.sec])
+
+ d = DateTime.strptime('11-6', '%U-%w')
+ assert_equal([n.year, 11, 6, 0, 0, 0],
+ [d.year, d.strftime('%U').to_i, d.wday, d.hour, d.min, d.sec])
+ d = DateTime.strptime('2004-11', '%Y-%U')
+ assert_equal([2004, 11, 0, 0, 0, 0],
+ [d.year, d.strftime('%U').to_i, d.wday, d.hour, d.min, d.sec])
+
+ d = DateTime.strptime('11-6', '%W-%w')
+ assert_equal([n.year, 11, 6, 0, 0, 0],
+ [d.year, d.strftime('%W').to_i, d.wday, d.hour, d.min, d.sec])
+ d = DateTime.strptime('2004-11', '%Y-%W')
+ assert_equal([2004, 11, 0, 0, 0, 0],
+ [d.year, d.strftime('%W').to_i, d.wday, d.hour, d.min, d.sec])
+ end
+
+ def test_strptime__d_to_s
+ d = Date.new(2002,3,14)
+ assert_equal(d, Date.strptime(d.to_s))
+
+ d = DateTime.new(2002,3,14,11,22,33, 9.to_r/24)
+ assert_equal(d, DateTime.strptime(d.to_s))
+ end
+
+ def test_strptime__ex
+ assert_raise(ArgumentError) do
+ Date.strptime('2001-02-29', '%F')
+ end
+ assert_raise(ArgumentError) do
+ DateTime.strptime('2001-02-29T23:59:60', '%FT%T')
+ end
+ assert_raise(ArgumentError) do
+ Date.strptime('23:55', '%H:%M')
+ end
+ end
+
+end
diff --git a/test/dbm/test_dbm.rb b/test/dbm/test_dbm.rb
index 159ab43f35..1845a6db55 100644
--- a/test/dbm/test_dbm.rb
+++ b/test/dbm/test_dbm.rb
@@ -160,9 +160,9 @@ if defined? DBM
}
end
- def test_index
+ def test_key
assert_equal('bar', @dbm['foo'] = 'bar')
- assert_equal('foo', @dbm.index('bar'))
+ assert_equal('foo', @dbm.key('bar'))
assert_nil(@dbm['bar'])
end
@@ -238,7 +238,7 @@ if defined? DBM
n = 0
ret = @dbm.each_value {|val|
- assert_not_nil(key = @dbm.index(val))
+ assert_not_nil(key = @dbm.key(val))
assert_not_nil(i = keys.index(key))
assert_equal(val, values[i])
@@ -334,14 +334,11 @@ if defined? DBM
def test_delete_with_block
key = 'no called block'
@dbm[key] = 'foo'
- assert_equal('foo', @dbm.delete(key) {|k| k.replace 'called block'})
- assert_equal('no called block', key)
+ assert_equal('foo', @dbm.delete(key) {|k| k.replace 'called block'; :blockval})
assert_equal(0, @dbm.size)
key = 'no called block'
- assert_equal(:blockval,
- @dbm.delete(key) {|k| k.replace 'called block'; :blockval})
- assert_equal('called block', key)
+ assert_equal(:blockval, @dbm.delete(key) {|k| k.replace 'called block'; :blockval})
assert_equal(0, @dbm.size)
end
@@ -534,7 +531,7 @@ if defined? DBM
v = DBM.open("#{@tmproot}/a", nil, DBM::READER) {|d|
# Errno::EPERM is raised on Solaris which use ndbm.
# DBMError is raised on Debian which use gdbm.
- assert_raises(Errno::EPERM, DBMError) { d["k"] = "v" }
+ assert_raise(Errno::EPERM, DBMError) { d["k"] = "v" }
true
}
assert(v)
@@ -555,7 +552,7 @@ if defined? DBM
def test_freeze
DBM.open("#{@tmproot}/a") {|d|
d.freeze
- assert_raises(RuntimeError) { d["k"] = "v" }
+ assert_raise(RuntimeError) { d["k"] = "v" }
}
end
end
diff --git a/test/drb/drbtest.rb b/test/drb/drbtest.rb
index 143d856a1e..e06139a9d6 100644
--- a/test/drb/drbtest.rb
+++ b/test/drb/drbtest.rb
@@ -127,23 +127,23 @@ module DRbCore
assert_equal('DRbEx', obj.name)
end
- assert_raises(DRb::DRbUnknownError) do
+ assert_raise(DRb::DRbUnknownError) do
@there.unknown_error
end
onecky = FailOnecky.new('3')
- assert_raises(FailOnecky::OneckyError) do
+ assert_raise(FailOnecky::OneckyError) do
@there.sample(onecky, 1, 2)
end
end
def test_03
assert_equal(8, @there.sum(1, 1, 1, 1, 1, 1, 1, 1))
- assert_raises(ArgumentError) do
+ assert_raise(ArgumentError) do
@there.sum(1, 1, 1, 1, 1, 1, 1, 1, 1)
end
- assert_raises(DRb::DRbConnError) do
+ assert_raise(DRb::DRbConnError) do
@there.sum('1' * 4096)
end
end
@@ -168,10 +168,10 @@ module DRbCore
def test_06_timeout
ten = Onecky.new(10)
- assert_raises(TimeoutError) do
+ assert_raise(TimeoutError) do
@there.do_timeout(ten)
end
- assert_raises(TimeoutError) do
+ assert_raise(TimeoutError) do
@there.do_timeout(ten)
end
end
@@ -208,7 +208,7 @@ module DRbCore
assert_match(/^undefined method \`undefined_method_test\'/, $!.message)
end
}
- assert_raises(DRb::DRbConnError) do
+ assert_raise(DRb::DRbConnError) do
@there.method_missing(:__send__, :to_s)
end
assert_equal(true, @there.missing)
@@ -261,7 +261,7 @@ module DRbCore
end
def test_11_remote_no_method_error
- assert_raises(DRb::DRbRemoteError) do
+ assert_raise(DRb::DRbRemoteError) do
@there.remote_no_method_error
end
begin
diff --git a/test/drb/test_drb.rb b/test/drb/test_drb.rb
index 106e958d9a..57cf7175d7 100644
--- a/test/drb/test_drb.rb
+++ b/test/drb/test_drb.rb
@@ -219,21 +219,21 @@ class TestDRbEval # < Test::Unit::TestCase
end
def test_01_safe1_safe4_eval
- assert_raises(SecurityError) do
+ assert_raise(SecurityError) do
@there.method_missing(:instance_eval, 'ENV.inspect')
end
- assert_raises(SecurityError) do
+ assert_raise(SecurityError) do
@there.method_missing(:send, :eval, 'ENV.inspect')
end
remote_class = @there.remote_class
- assert_raises(SecurityError) do
+ assert_raise(SecurityError) do
remote_class.class_eval('ENV.inspect')
end
- assert_raises(SecurityError) do
+ assert_raise(SecurityError) do
remote_class.module_eval('ENV.inspect')
end
@@ -246,11 +246,11 @@ class TestDRbEval # < Test::Unit::TestCase
assert_equal(1, remote_class.module_eval('1'))
- assert_raises(SecurityError) do
+ assert_raise(SecurityError) do
remote_class.class_eval('ENV = {}')
end
- assert_raises(SecurityError) do
+ assert_raise(SecurityError) do
remote_class.module_eval('ENV = {}')
end
end
@@ -283,7 +283,7 @@ class TestDRbLarge < Test::Unit::TestCase
end
def test_04_many_arg
- assert_raises(ArgumentError) {
+ assert_raise(ArgumentError) {
@there.arg_test(1, 2, 3, 4, 5, 6, 7, 8, 9, 0)
}
end
diff --git a/test/fileutils/fileasserts.rb b/test/fileutils/fileasserts.rb
index 41469a6ac6..d784544555 100644
--- a/test/fileutils/fileasserts.rb
+++ b/test/fileutils/fileasserts.rb
@@ -4,6 +4,10 @@ module Test
module Unit
module Assertions # redefine
+ def _wrap_assertion
+ yield
+ end
+
def assert_same_file(from, to)
_wrap_assertion {
assert_block("file #{from} != #{to}") {
diff --git a/test/fileutils/test_fileutils.rb b/test/fileutils/test_fileutils.rb
index b4ddee0239..3117193385 100644
--- a/test/fileutils/test_fileutils.rb
+++ b/test/fileutils/test_fileutils.rb
@@ -16,11 +16,11 @@ Dir.mkdir tmproot unless File.directory?(tmproot)
Dir.chdir tmproot
def have_drive_letter?
- /djgpp|mswin(?!ce)|mingw|bcc|emx/ =~ RUBY_PLATFORM
+ /mswin(?!ce)|mingw|bcc|emx/ =~ RUBY_PLATFORM
end
def have_file_perm?
- /djgpp|mswin|mingw|bcc|wince|emx/ !~ RUBY_PLATFORM
+ /mswin|mingw|bcc|emx/ !~ RUBY_PLATFORM
end
$fileutils_rb_have_symlink = nil
@@ -192,7 +192,7 @@ end
TARGETS.each do |fname|
assert cmp(fname, fname), 'not same?'
end
- assert_raises(ArgumentError) {
+ assert_raise(ArgumentError) {
cmp TARGETS[0], TARGETS[0], :undefinedoption => true
}
@@ -225,21 +225,21 @@ end
# src==dest (1) same path
touch 'tmp/cptmp'
- assert_raises(ArgumentError) {
+ assert_raise(ArgumentError) {
cp 'tmp/cptmp', 'tmp/cptmp'
}
if have_symlink?
# src==dest (2) symlink and its target
File.symlink 'cptmp', 'tmp/cptmp_symlink'
- assert_raises(ArgumentError) {
+ assert_raise(ArgumentError) {
cp 'tmp/cptmp', 'tmp/cptmp_symlink'
}
- assert_raises(ArgumentError) {
+ assert_raise(ArgumentError) {
cp 'tmp/cptmp_symlink', 'tmp/cptmp'
}
# src==dest (3) looped symlink
File.symlink 'symlink', 'tmp/symlink'
- assert_raises(Errno::ELOOP) {
+ assert_raise(Errno::ELOOP) {
cp 'tmp/symlink', 'tmp/symlink'
}
end
@@ -328,31 +328,31 @@ end
mkdir 'tmp/tmpdir'
mkdir_p 'tmp/dest2/tmpdir'
- assert_raises(Errno::EEXIST) {
+ assert_raise(Errno::EEXIST) {
mv 'tmp/tmpdir', 'tmp/dest2'
}
mkdir 'tmp/dest2/tmpdir/junk'
- assert_raises(Errno::EEXIST, "[ruby-talk:124368]") {
+ assert_raise(Errno::EEXIST, "[ruby-talk:124368]") {
mv 'tmp/tmpdir', 'tmp/dest2'
}
# src==dest (1) same path
touch 'tmp/cptmp'
- assert_raises(ArgumentError) {
+ assert_raise(ArgumentError) {
mv 'tmp/cptmp', 'tmp/cptmp'
}
if have_symlink?
# src==dest (2) symlink and its target
File.symlink 'cptmp', 'tmp/cptmp_symlink'
- assert_raises(ArgumentError) {
+ assert_raise(ArgumentError) {
mv 'tmp/cptmp', 'tmp/cptmp_symlink'
}
- assert_raises(ArgumentError) {
+ assert_raise(ArgumentError) {
mv 'tmp/cptmp_symlink', 'tmp/cptmp'
}
# src==dest (3) looped symlink
File.symlink 'symlink', 'tmp/symlink'
- assert_raises(Errno::ELOOP) {
+ assert_raise(Errno::ELOOP) {
mv 'tmp/symlink', 'tmp/symlink'
}
end
@@ -589,16 +589,16 @@ if have_hardlink?
# src==dest (1) same path
touch 'tmp/cptmp'
- assert_raises(Errno::EEXIST) {
+ assert_raise(Errno::EEXIST) {
ln 'tmp/cptmp', 'tmp/cptmp'
}
if have_symlink?
# src==dest (2) symlink and its target
File.symlink 'cptmp', 'tmp/symlink'
- assert_raises(Errno::EEXIST) {
+ assert_raise(Errno::EEXIST) {
ln 'tmp/cptmp', 'tmp/symlink' # normal file -> symlink
}
- assert_raises(Errno::EEXIST) {
+ assert_raise(Errno::EEXIST) {
ln 'tmp/symlink', 'tmp/cptmp' # symlink -> normal file
}
# src==dest (3) looped symlink
@@ -796,21 +796,21 @@ end
# src==dest (1) same path
touch 'tmp/cptmp'
- assert_raises(ArgumentError) {
+ assert_raise(ArgumentError) {
install 'tmp/cptmp', 'tmp/cptmp'
}
if have_symlink?
# src==dest (2) symlink and its target
File.symlink 'cptmp', 'tmp/cptmp_symlink'
- assert_raises(ArgumentError) {
+ assert_raise(ArgumentError) {
install 'tmp/cptmp', 'tmp/cptmp_symlink'
}
- assert_raises(ArgumentError) {
+ assert_raise(ArgumentError) {
install 'tmp/cptmp_symlink', 'tmp/cptmp'
}
# src==dest (3) looped symlink
File.symlink 'symlink', 'tmp/symlink'
- assert_raises(Errno::ELOOP) {
+ assert_raise(Errno::ELOOP) {
# File#install invokes open(2), always ELOOP must be raised
install 'tmp/symlink', 'tmp/symlink'
}
diff --git a/test/gdbm/test_gdbm.rb b/test/gdbm/test_gdbm.rb
index 6033a7640b..7e28d5121d 100644
--- a/test/gdbm/test_gdbm.rb
+++ b/test/gdbm/test_gdbm.rb
@@ -276,9 +276,9 @@ if defined? GDBM
}
end
- def test_index
+ def test_key
assert_equal('bar', @gdbm['foo'] = 'bar')
- assert_equal('foo', @gdbm.index('bar'))
+ assert_equal('foo', @gdbm.key('bar'))
assert_nil(@gdbm['bar'])
end
@@ -354,7 +354,7 @@ if defined? GDBM
n = 0
ret = @gdbm.each_value {|val|
- assert_not_nil(key = @gdbm.index(val))
+ assert_not_nil(key = @gdbm.key(val))
assert_not_nil(i = keys.index(key))
assert_equal(val, values[i])
@@ -687,7 +687,7 @@ if defined? GDBM
def test_reader_open
GDBM.open("#{@tmproot}/a.dbm") {} # create a db.
v = GDBM.open("#{@tmproot}/a.dbm", nil, GDBM::READER) {|d|
- assert_raises(GDBMError) { d["k"] = "v" }
+ assert_raise(GDBMError) { d["k"] = "v" }
true
}
assert(v)
@@ -708,7 +708,7 @@ if defined? GDBM
def test_freeze
GDBM.open("#{@tmproot}/a.dbm") {|d|
d.freeze
- assert_raises(RuntimeError) { d["k"] = "v" }
+ assert_raise(RuntimeError) { d["k"] = "v" }
}
end
end
diff --git a/test/iconv/test_basic.rb b/test/iconv/test_basic.rb
index ea564e91f1..394d271bc1 100644
--- a/test/iconv/test_basic.rb
+++ b/test/iconv/test_basic.rb
@@ -43,6 +43,13 @@ class TestIconv::Basic < TestIconv
assert_equal("#{SJIS_STR}\n"*2, output)
end
+ def test_invalid_arguments
+ assert_raise(TypeError) { Iconv.new(nil, 'Shift_JIS') }
+ assert_raise(TypeError) { Iconv.new('Shift_JIS', nil) }
+ assert_raise(TypeError) { Iconv.open(nil, 'Shift_JIS') }
+ assert_raise(TypeError) { Iconv.open('Shift_JIS', nil) }
+ end
+
def test_unknown_encoding
assert_raise(Iconv::InvalidEncoding) { Iconv.iconv("utf-8", "X-UKNOWN", "heh") }
end
diff --git a/test/json/fixtures/fail18.json b/test/json/fixtures/fail18.json
index d61a345465..e2d130c6eb 100644
--- a/test/json/fixtures/fail18.json
+++ b/test/json/fixtures/fail18.json
@@ -1 +1 @@
-[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]] // No, we don't limit our depth: Moved to pass...
+[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]
diff --git a/test/json/runner.rb b/test/json/runner.rb
index 91bc12a594..9ad04485bf 100755
--- a/test/json/runner.rb
+++ b/test/json/runner.rb
@@ -23,4 +23,3 @@ class TS_AllTests
end
end
Test::Unit::UI::Console::TestRunner.run(TS_AllTests)
- # vim: set et sw=2 ts=2:
diff --git a/test/json/test_json.rb b/test/json/test_json.rb
index 257b8e0f63..02da6d4e7a 100755
--- a/test/json/test_json.rb
+++ b/test/json/test_json.rb
@@ -3,6 +3,7 @@
require 'test/unit'
require 'json'
+require 'stringio'
class TC_JSON < Test::Unit::TestCase
include JSON
@@ -28,7 +29,6 @@ class TC_JSON < Test::Unit::TestCase
@json = '{"a":2,"b":3.141,"c":"c","d":[1,"b",3.14],"e":{"foo":"bar"},' +
'"g":"\\"\\u0000\\u001f","h":1.0E3,"i":1.0E-3}'
end
- suite << TC_JSON.suite
def test_construction
parser = JSON::Parser.new('test')
@@ -49,10 +49,10 @@ class TC_JSON < Test::Unit::TestCase
assert_equal([23], parse('[23]'))
assert_equal([0.23], parse('[0.23]'))
assert_equal([0.0], parse('[0e0]'))
- assert_raises(JSON::ParserError) { parse('[+23.2]') }
- assert_raises(JSON::ParserError) { parse('[+23]') }
- assert_raises(JSON::ParserError) { parse('[.23]') }
- assert_raises(JSON::ParserError) { parse('[023]') }
+ assert_raise(JSON::ParserError) { parse('[+23.2]') }
+ assert_raise(JSON::ParserError) { parse('[+23]') }
+ assert_raise(JSON::ParserError) { parse('[.23]') }
+ assert_raise(JSON::ParserError) { parse('[023]') }
assert_equal_float [3.141], parse('[3.141]')
assert_equal_float [-3.141], parse('[-3.141]')
assert_equal_float [3.141], parse('[3141e-3]')
@@ -61,6 +61,12 @@ class TC_JSON < Test::Unit::TestCase
assert_equal_float [3.141], parse('[3141.0E-3]')
assert_equal_float [-3.141], parse('[-3141.0e-3]')
assert_equal_float [-3.141], parse('[-3141e-3]')
+ assert_raise(ParserError) { parse('[NaN]') }
+ assert parse('[NaN]', :allow_nan => true).first.nan?
+ assert_raise(ParserError) { parse('[Infinity]') }
+ assert_equal [1.0/0], parse('[Infinity]', :allow_nan => true)
+ assert_raise(ParserError) { parse('[-Infinity]') }
+ assert_equal [-1.0/0], parse('[-Infinity]', :allow_nan => true)
assert_equal([""], parse('[""]'))
assert_equal(["foobar"], parse('["foobar"]'))
assert_equal([{}], parse('[{}]'))
@@ -73,7 +79,7 @@ class TC_JSON < Test::Unit::TestCase
assert_equal({ "a" => nil }, parse('{"a":null}'))
assert_equal({ "a" => false }, parse('{ "a" : false } '))
assert_equal({ "a" => false }, parse('{"a":false}'))
- assert_raises(JSON::ParserError) { parse('{false}') }
+ assert_raise(JSON::ParserError) { parse('{false}') }
assert_equal({ "a" => true }, parse('{"a":true}'))
assert_equal({ "a" => true }, parse(' { "a" : true } '))
assert_equal({ "a" => -23 }, parse(' { "a" : -23 } '))
@@ -84,30 +90,22 @@ class TC_JSON < Test::Unit::TestCase
assert_equal({ "a" => 0.23 }, parse(' { "a" : 0.23 } '))
end
- begin
- require 'permutation'
- def test_parse_more_complex_arrays
- a = [ nil, false, true, "fobar", [ "nstd", true ], { "nested" => true, "nt丹2" => {} }]
- perms = Permutation.for a
- perms.each do |perm|
- orig_ary = perm.project
- json = pretty_generate(orig_ary)
- assert_equal orig_ary, parse(json)
- end
+ def test_parse_more_complex_arrays
+ a = [ nil, false, true, "fobar", [ "nstd", true ], { "nested" => true, "nt丹2" => {} }]
+ a.permutation do |orig_ary|
+ json = pretty_generate(orig_ary)
+ assert_equal orig_ary, parse(json)
end
+ end
- def test_parse_complex_objects
- a = [ nil, false, true, "fobar", [ "nstd", true ], { "nested" => true, "nt丹2" => {} }]
- perms = Permutation.for a
- perms.each do |perm|
- s = "a"
- orig_obj = perm.project.inject({}) { |h, x| h[s.dup] = x; s = s.succ; h }
- json = pretty_generate(orig_obj)
- assert_equal orig_obj, parse(json)
- end
+ def test_parse_complex_objects
+ a = [ nil, false, true, "fobar", [ "nstd", true ], { "nested" => true, "nt丹2" => {} }]
+ a.permutation do |orig_ary|
+ s = "a"
+ orig_obj = orig_ary.inject({}) { |h, x| h[s.dup] = x; s = s.succ; h }
+ json = pretty_generate(orig_obj)
+ assert_equal orig_obj, parse(json)
end
- rescue LoadError
- warn "Skipping permutation tests."
end
def test_parse_arrays
@@ -175,7 +173,7 @@ EOT
* comment */
}
EOT
- assert_raises(ParserError) { parse(json) }
+ assert_raise(ParserError) { parse(json) }
json = <<EOT
{
"key1":"value1" /* multi line
@@ -184,7 +182,7 @@ EOT
and again, throw an Error */
}
EOT
- assert_raises(ParserError) { parse(json) }
+ assert_raise(ParserError) { parse(json) }
json = <<EOT
{
"key1":"value1" /*/*/
@@ -220,36 +218,67 @@ EOT
end
def test_wrong_inputs
- assert_raises(ParserError) { JSON.parse('"foo"') }
- assert_raises(ParserError) { JSON.parse('123') }
- assert_raises(ParserError) { JSON.parse('[] bla') }
- assert_raises(ParserError) { JSON.parse('[] 1') }
- assert_raises(ParserError) { JSON.parse('[] []') }
- assert_raises(ParserError) { JSON.parse('[] {}') }
- assert_raises(ParserError) { JSON.parse('{} []') }
- assert_raises(ParserError) { JSON.parse('{} {}') }
- assert_raises(ParserError) { JSON.parse('[NULL]') }
- assert_raises(ParserError) { JSON.parse('[FALSE]') }
- assert_raises(ParserError) { JSON.parse('[TRUE]') }
- assert_raises(ParserError) { JSON.parse('[07] ') }
- assert_raises(ParserError) { JSON.parse('[0a]') }
- assert_raises(ParserError) { JSON.parse('[1.]') }
- assert_raises(ParserError) { JSON.parse(' ') }
+ assert_raise(ParserError) { JSON.parse('"foo"') }
+ assert_raise(ParserError) { JSON.parse('123') }
+ assert_raise(ParserError) { JSON.parse('[] bla') }
+ assert_raise(ParserError) { JSON.parse('[] 1') }
+ assert_raise(ParserError) { JSON.parse('[] []') }
+ assert_raise(ParserError) { JSON.parse('[] {}') }
+ assert_raise(ParserError) { JSON.parse('{} []') }
+ assert_raise(ParserError) { JSON.parse('{} {}') }
+ assert_raise(ParserError) { JSON.parse('[NULL]') }
+ assert_raise(ParserError) { JSON.parse('[FALSE]') }
+ assert_raise(ParserError) { JSON.parse('[TRUE]') }
+ assert_raise(ParserError) { JSON.parse('[07] ') }
+ assert_raise(ParserError) { JSON.parse('[0a]') }
+ assert_raise(ParserError) { JSON.parse('[1.]') }
+ assert_raise(ParserError) { JSON.parse(' ') }
end
def test_nesting
- to_deep = '[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]'
- assert_raises(JSON::NestingError) { JSON.parse to_deep }
- assert_raises(JSON::NestingError) { JSON.parser.new(to_deep).parse }
- assert_raises(JSON::NestingError) { JSON.parse to_deep, :max_nesting => 19 }
- ok = JSON.parse to_deep, :max_nesting => 20
- assert_kind_of Array, ok
- ok = JSON.parse to_deep, :max_nesting => nil
- assert_kind_of Array, ok
- ok = JSON.parse to_deep, :max_nesting => false
- assert_kind_of Array, ok
- ok = JSON.parse to_deep, :max_nesting => 0
- assert_kind_of Array, ok
+ assert_raise(JSON::NestingError) { JSON.parse '[[]]', :max_nesting => 1 }
+ assert_raise(JSON::NestingError) { JSON.parser.new('[[]]', :max_nesting => 1).parse }
+ assert_equal [[]], JSON.parse('[[]]', :max_nesting => 2)
+ too_deep = '[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]'
+ too_deep_ary = eval too_deep
+ assert_raise(JSON::NestingError) { JSON.parse too_deep }
+ assert_raise(JSON::NestingError) { JSON.parser.new(too_deep).parse }
+ assert_raise(JSON::NestingError) { JSON.parse too_deep, :max_nesting => 19 }
+ ok = JSON.parse too_deep, :max_nesting => 20
+ assert_equal too_deep_ary, ok
+ ok = JSON.parse too_deep, :max_nesting => nil
+ assert_equal too_deep_ary, ok
+ ok = JSON.parse too_deep, :max_nesting => false
+ assert_equal too_deep_ary, ok
+ ok = JSON.parse too_deep, :max_nesting => 0
+ assert_equal too_deep_ary, ok
+ assert_raise(JSON::NestingError) { JSON.generate [[]], :max_nesting => 1 }
+ assert_equal '[[]]', JSON.generate([[]], :max_nesting => 2)
+ assert_raise(JSON::NestingError) { JSON.generate too_deep_ary }
+ assert_raise(JSON::NestingError) { JSON.generate too_deep_ary, :max_nesting => 19 }
+ ok = JSON.generate too_deep_ary, :max_nesting => 20
+ assert_equal too_deep, ok
+ ok = JSON.generate too_deep_ary, :max_nesting => nil
+ assert_equal too_deep, ok
+ ok = JSON.generate too_deep_ary, :max_nesting => false
+ assert_equal too_deep, ok
+ ok = JSON.generate too_deep_ary, :max_nesting => 0
+ assert_equal too_deep, ok
+ end
+
+ def test_load_dump
+ too_deep = '[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]'
+ assert_equal too_deep, JSON.dump(eval(too_deep))
+ assert_kind_of String, Marshal.dump(eval(too_deep))
+ assert_raise(ArgumentError) { JSON.dump(eval(too_deep), 19) }
+ assert_raise(ArgumentError) { Marshal.dump(eval(too_deep), 19) }
+ assert_equal too_deep, JSON.dump(eval(too_deep), 20)
+ assert_kind_of String, Marshal.dump(eval(too_deep), 20)
+ output = StringIO.new
+ JSON.dump(eval(too_deep), output)
+ assert_equal too_deep, output.string
+ output = StringIO.new
+ JSON.dump(eval(too_deep), output, 20)
+ assert_equal too_deep, output.string
end
end
- # vim: set et sw=2 ts=2:
diff --git a/test/json/test_json_addition.rb b/test/json/test_json_addition.rb
index 04c690ce31..95b6166261 100755
--- a/test/json/test_json_addition.rb
+++ b/test/json/test_json_addition.rb
@@ -31,6 +31,10 @@ class TC_JSONAddition < Test::Unit::TestCase
end
class B
+ def self.json_creatable?
+ false
+ end
+
def to_json(*args)
{
'json_class' => self.class.name,
@@ -50,9 +54,6 @@ class TC_JSONAddition < Test::Unit::TestCase
end
end
- def setup
- end
-
def test_extended_json
a = A.new(666)
assert A.json_creatable?
@@ -77,18 +78,18 @@ class TC_JSONAddition < Test::Unit::TestCase
)
end
- def test_extended_json_fail
+ def test_extended_json_fail1
b = B.new
assert !B.json_creatable?
json = generate(b)
- assert_equal({ 'json_class' => B.name }, JSON.parse(json))
+ assert_equal({ "json_class"=>"TC_JSONAddition::B" }, JSON.parse(json))
end
- def test_extended_json_fail
+ def test_extended_json_fail2
c = C.new
assert !C.json_creatable?
json = generate(c)
- assert_raises(ArgumentError) { JSON.parse(json) }
+ assert_raise(ArgumentError) { JSON.parse(json) }
end
def test_raw_strings
@@ -111,9 +112,11 @@ EOT
assert_equal raw, raw_again
end
+ MyJsonStruct = Struct.new 'MyJsonStruct', :foo, :bar
+
def test_core
- t = Time.at(1198254128, 895990)
- assert_equal t, JSON(JSON(t))
+ t = Time.now
+ assert_equal t.inspect, JSON(JSON(t)).inspect
d = Date.today
assert_equal d, JSON(JSON(d))
d = DateTime.civil(2007, 6, 14, 14, 57, 10, Rational(1, 12), 2299161)
@@ -122,12 +125,11 @@ EOT
assert_equal 1...10, JSON(JSON(1...10))
assert_equal "a".."c", JSON(JSON("a".."c"))
assert_equal "a"..."c", JSON(JSON("a"..."c"))
- struct = Struct.new 'MyJsonStruct', :foo, :bar
- s = struct.new 4711, 'foot'
+ s = MyJsonStruct.new 4711, 'foot'
assert_equal s, JSON(JSON(s))
struct = Struct.new :foo, :bar
s = struct.new 4711, 'foot'
- assert_raises(JSONError) { JSON(s) }
+ assert_raise(JSONError) { JSON(s) }
begin
raise TypeError, "test me"
rescue TypeError => e
@@ -137,7 +139,19 @@ EOT
assert_equal e.message, e_again.message
assert_equal e.backtrace, e_again.backtrace
end
- assert_equal /foo/, JSON(JSON(/foo/))
- assert_equal /foo/i, JSON(JSON(/foo/i))
+ assert_equal(/foo/, JSON(JSON(/foo/)))
+ assert_equal(/foo/i, JSON(JSON(/foo/i)))
+ end
+
+ def test_utc_datetime
+ now = Time.now
+ d = DateTime.parse(now.to_s) # usual case
+ assert d, JSON.parse(d.to_json)
+ d = DateTime.parse(now.utc.to_s) # of = 0
+ assert d, JSON.parse(d.to_json)
+ d = DateTime.civil(2008, 6, 17, 11, 48, 32, 1) # of = 1 / 12 => 1/12
+ assert d, JSON.parse(d.to_json)
+ d = DateTime.civil(2008, 6, 17, 11, 48, 32, 12) # of = 12 / 12 => 12
+ assert d, JSON.parse(d.to_json)
end
end
diff --git a/test/json/test_json_fixtures.rb b/test/json/test_json_fixtures.rb
index 33573cd300..6cc1bfc6fa 100755
--- a/test/json/test_json_fixtures.rb
+++ b/test/json/test_json_fixtures.rb
@@ -20,7 +20,7 @@ class TC_JSONFixtures < Test::Unit::TestCase
def test_failing
for name, source in @failed
- assert_raises(JSON::ParserError, JSON::NestingError,
+ assert_raise(JSON::ParserError, JSON::NestingError,
"Did not fail for fixture '#{name}'") do
JSON.parse(source)
end
diff --git a/test/json/test_json_generate.rb b/test/json/test_json_generate.rb
index e720b2d862..8c55a409cd 100644
--- a/test/json/test_json_generate.rb
+++ b/test/json/test_json_generate.rb
@@ -70,11 +70,30 @@ EOT
#assert s.check_circular
h = { 1=>2 }
h[3] = h
- assert_raises(JSON::CircularDatastructure) { generate(h, s) }
+ assert_raise(JSON::CircularDatastructure) { generate(h) }
+ assert_raise(JSON::CircularDatastructure) { generate(h, s) }
s = JSON.state.new(:check_circular => true)
#assert s.check_circular
a = [ 1, 2 ]
a << a
- assert_raises(JSON::CircularDatastructure) { generate(a, s) }
+ assert_raise(JSON::CircularDatastructure) { generate(a, s) }
+ end
+
+ def test_allow_nan
+ assert_raise(GeneratorError) { generate([JSON::NaN]) }
+ assert_equal '[NaN]', generate([JSON::NaN], :allow_nan => true)
+ assert_equal '[NaN]', fast_generate([JSON::NaN])
+ assert_raise(GeneratorError) { pretty_generate([JSON::NaN]) }
+ assert_equal "[\n NaN\n]", pretty_generate([JSON::NaN], :allow_nan => true)
+ assert_raise(GeneratorError) { generate([JSON::Infinity]) }
+ assert_equal '[Infinity]', generate([JSON::Infinity], :allow_nan => true)
+ assert_equal '[Infinity]', fast_generate([JSON::Infinity])
+ assert_raise(GeneratorError) { pretty_generate([JSON::Infinity]) }
+ assert_equal "[\n Infinity\n]", pretty_generate([JSON::Infinity], :allow_nan => true)
+ assert_raise(GeneratorError) { generate([JSON::MinusInfinity]) }
+ assert_equal '[-Infinity]', generate([JSON::MinusInfinity], :allow_nan => true)
+ assert_equal '[-Infinity]', fast_generate([JSON::MinusInfinity])
+ assert_raise(GeneratorError) { pretty_generate([JSON::MinusInfinity]) }
+ assert_equal "[\n -Infinity\n]", pretty_generate([JSON::MinusInfinity], :allow_nan => true)
end
end
diff --git a/test/json/test_json_rails.rb b/test/json/test_json_rails.rb
index e44ea606e3..52dc29f388 100644
--- a/test/json/test_json_rails.rb
+++ b/test/json/test_json_rails.rb
@@ -31,6 +31,10 @@ class TC_JSONRails < Test::Unit::TestCase
end
class B
+ def self.json_creatable?
+ false
+ end
+
def to_json(*args)
{
'json_class' => self.class.name,
@@ -46,9 +50,6 @@ class TC_JSONRails < Test::Unit::TestCase
end
end
- def setup
- end
-
def test_extended_json
a = A.new(666)
assert A.json_creatable?
@@ -73,18 +74,18 @@ class TC_JSONRails < Test::Unit::TestCase
)
end
- def test_extended_json_fail
+ def test_extended_json_fail1
b = B.new
assert !B.json_creatable?
json = generate(b)
assert_equal({ 'json_class' => B.name }, JSON.parse(json))
end
- def test_extended_json_fail
+ def test_extended_json_fail2
c = C.new # with rails addition all objects are theoretically creatable
assert C.json_creatable?
json = generate(c)
- assert_raises(ArgumentError) { JSON.parse(json) }
+ assert_raise(ArgumentError) { JSON.parse(json) }
end
def test_raw_strings
diff --git a/test/json/test_json_unicode.rb b/test/json/test_json_unicode.rb
index cad93846b5..b8a37c8b8d 100755
--- a/test/json/test_json_unicode.rb
+++ b/test/json/test_json_unicode.rb
@@ -7,9 +7,6 @@ require 'json'
class TC_JSONUnicode < Test::Unit::TestCase
include JSON
- def setup
- end
-
def test_unicode
assert_equal '""', ''.to_json
assert_equal '"\\b"', "\b".to_json
@@ -53,8 +50,8 @@ class TC_JSONUnicode < Test::Unit::TestCase
assert_equal json, JSON.generate(["" << i])
end
end
- assert_raises(JSON::GeneratorError) do
- JSON.generate(["" << 0x80])
+ assert_raise(JSON::GeneratorError) do
+ JSON.generate(["\x80"])
end
assert_equal "\302\200", JSON.parse('["\u0080"]').first
end
diff --git a/test/logger/test_logger.rb b/test/logger/test_logger.rb
index 12728c608b..a6c132d0f3 100644
--- a/test/logger/test_logger.rb
+++ b/test/logger/test_logger.rb
@@ -23,6 +23,10 @@ class TestLogger < Test::Unit::TestCase
@logger = Logger.new(nil)
end
+ def test_const_progname
+ assert %r!\Alogger\.rb/\S+\z! === Logger::ProgName
+ end
+
class Log
attr_reader :label, :datetime, :pid, :severity, :progname, :msg
def initialize(line)
@@ -266,7 +270,7 @@ class TestLogDevice < Test::Unit::TestCase
logdev = d(STDERR)
assert_equal(STDERR, logdev.dev)
assert_nil(logdev.filename)
- assert_raises(TypeError) do
+ assert_raise(TypeError) do
d(nil)
end
#
diff --git a/test/matrix/test_matrix.rb b/test/matrix/test_matrix.rb
new file mode 100644
index 0000000000..0850117b86
--- /dev/null
+++ b/test/matrix/test_matrix.rb
@@ -0,0 +1,49 @@
+require 'test/unit'
+require 'matrix'
+
+class TestMatrix < Test::Unit::TestCase
+ def setup
+ @m1 = Matrix[[1,2,3], [4,5,6]]
+ @m2 = Matrix[[1,2,3], [4,5,6]]
+ @m3 = @m1.clone
+ @m4 = Matrix[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]
+ @n1 = Matrix[[2,3,4], [5,6,7]]
+ end
+
+ def test_identity
+ assert_same @m1, @m1
+ assert_not_same @m1, @m2
+ assert_not_same @m1, @m3
+ assert_not_same @m1, @m4
+ assert_not_same @m1, @n1
+ end
+
+ def test_equality
+ assert_equal @m1, @m1
+ assert_equal @m1, @m2
+ assert_equal @m1, @m3
+ assert_equal @m1, @m4
+ assert_not_equal @m1, @n1
+ end
+
+ def test_hash_equality
+ assert @m1.eql?(@m1)
+ assert @m1.eql?(@m2)
+ assert @m1.eql?(@m3)
+ assert !@m1.eql?(@m4)
+ assert !@m1.eql?(@n1)
+
+ hash = { @m1 => :value }
+ assert hash.key?(@m1)
+ assert hash.key?(@m2)
+ assert hash.key?(@m3)
+ assert !hash.key?(@m4)
+ assert !hash.key?(@n1)
+ end
+
+ def test_hash
+ assert_equal @m1.hash, @m1.hash
+ assert_equal @m1.hash, @m2.hash
+ assert_equal @m1.hash, @m3.hash
+ end
+end
diff --git a/test/matrix/test_vector.rb b/test/matrix/test_vector.rb
new file mode 100644
index 0000000000..95a39693fc
--- /dev/null
+++ b/test/matrix/test_vector.rb
@@ -0,0 +1,49 @@
+require 'test/unit'
+require 'matrix'
+
+class TestVector < Test::Unit::TestCase
+ def setup
+ @v1 = Vector[1,2,3]
+ @v2 = Vector[1,2,3]
+ @v3 = @v1.clone
+ @v4 = Vector[1.0, 2.0, 3.0]
+ @w1 = Vector[2,3,4]
+ end
+
+ def test_identity
+ assert_same @v1, @v1
+ assert_not_same @v1, @v2
+ assert_not_same @v1, @v3
+ assert_not_same @v1, @v4
+ assert_not_same @v1, @w1
+ end
+
+ def test_equality
+ assert_equal @v1, @v1
+ assert_equal @v1, @v2
+ assert_equal @v1, @v3
+ assert_equal @v1, @v4
+ assert_not_equal @v1, @w1
+ end
+
+ def test_hash_equality
+ assert @v1.eql?(@v1)
+ assert @v1.eql?(@v2)
+ assert @v1.eql?(@v3)
+ assert !@v1.eql?(@v4)
+ assert !@v1.eql?(@w1)
+
+ hash = { @v1 => :value }
+ assert hash.key?(@v1)
+ assert hash.key?(@v2)
+ assert hash.key?(@v3)
+ assert !hash.key?(@v4)
+ assert !hash.key?(@w1)
+ end
+
+ def test_hash
+ assert_equal @v1.hash, @v1.hash
+ assert_equal @v1.hash, @v2.hash
+ assert_equal @v1.hash, @v3.hash
+ end
+end
diff --git a/test/minitest/test_mini_mock.rb b/test/minitest/test_mini_mock.rb
new file mode 100644
index 0000000000..0f16ae930e
--- /dev/null
+++ b/test/minitest/test_mini_mock.rb
@@ -0,0 +1,83 @@
+############################################################
+# This file is imported from a different project.
+# DO NOT make modifications in this repo.
+# File a patch instead and assign it to Ryan Davis
+############################################################
+
+require 'minitest/mock'
+require 'minitest/unit'
+
+MiniTest::Unit.autorun
+
+class TestMiniMock < MiniTest::Unit::TestCase
+ def setup
+ @mock = MiniTest::Mock.new.expect(:foo, nil)
+ @mock.expect(:meaning_of_life, 42)
+ end
+
+ def test_should_create_stub_method
+ assert_nil @mock.foo
+ end
+
+ def test_should_allow_return_value_specification
+ assert_equal 42, @mock.meaning_of_life
+ end
+
+ def test_should_blow_up_if_not_called
+ @mock.foo
+
+ util_verify_bad
+ end
+
+ def test_should_not_blow_up_if_everything_called
+ @mock.foo
+ @mock.meaning_of_life
+
+ assert @mock.verify
+ end
+
+ def test_should_allow_expectations_to_be_added_after_creation
+ @mock.expect(:bar, true)
+ assert @mock.bar
+ end
+
+ def test_should_not_verify_if_new_expected_method_is_not_called
+ @mock.foo
+ @mock.meaning_of_life
+ @mock.expect(:bar, true)
+
+ util_verify_bad
+ end
+
+ def test_should_not_verify_if_unexpected_method_is_called
+ assert_raises NoMethodError do
+ @mock.unexpected
+ end
+ end
+
+ def test_should_blow_up_on_wrong_number_of_arguments
+ @mock.foo
+ @mock.meaning_of_life
+ @mock.expect(:sum, 3, [1, 2])
+
+ assert_raises ArgumentError do
+ @mock.sum
+ end
+ end
+
+ def test_should_blow_up_on_wrong_arguments
+ @mock.foo
+ @mock.meaning_of_life
+ @mock.expect(:sum, 3, [1, 2])
+
+ @mock.sum(2, 4)
+
+ util_verify_bad
+ end
+
+ def util_verify_bad
+ assert_raises MockExpectationError do
+ @mock.verify
+ end
+ end
+end
diff --git a/test/minitest/test_mini_spec.rb b/test/minitest/test_mini_spec.rb
new file mode 100644
index 0000000000..4fe5bad048
--- /dev/null
+++ b/test/minitest/test_mini_spec.rb
@@ -0,0 +1,156 @@
+############################################################
+# This file is imported from a different project.
+# DO NOT make modifications in this repo.
+# File a patch instead and assign it to Ryan Davis
+############################################################
+
+require 'minitest/spec'
+
+MiniTest::Unit.autorun
+
+describe MiniTest::Spec do
+ before do
+ @assertion_count = 4
+ end
+
+ after do
+ self._assertions.must_equal @assertion_count
+ end
+
+ it "needs to have all methods named well" do
+ @assertion_count = 2
+
+ methods = Object.public_instance_methods.find_all { |n| n =~ /^must|^wont/ }
+ methods.map! { |m| m.to_s } if Symbol === methods.first
+
+ musts, wonts = methods.sort.partition { |m| m =~ /^must/ }
+
+ expected_musts = %w(must_be
+ must_be_close_to
+ must_be_empty
+ must_be_instance_of
+ must_be_kind_of
+ must_be_nil
+ must_be_same_as
+ must_be_within_delta
+ must_be_within_epsilon
+ must_equal
+ must_include
+ must_match
+ must_raise
+ must_respond_to
+ must_send
+ must_throw)
+
+ expected_wonts = expected_musts.map { |m| m.sub(/^must/, 'wont') }
+ expected_wonts.reject! { |m| m =~ /wont_(not|raise|throw|send)/ }
+
+ musts.must_equal expected_musts
+ wonts.must_equal expected_wonts
+ end
+
+ it "needs to verify equality" do
+ (6 * 7).must_equal(42).must_equal true
+ proc { (6 * 9).must_equal(42) }.must_raise MiniTest::Assertion
+ end
+
+ it "needs to verify floats within a delta" do
+ (6.0 * 7).must_be_close_to(42.0).must_equal true
+ proc { 42.002.must_be_close_to 42.0 }.must_raise MiniTest::Assertion
+ end
+
+ it "needs to verify types of objects" do
+ (6 * 7).must_be_instance_of(Fixnum).must_equal true
+ proc { (6 * 7).must_be_instance_of String }.must_raise MiniTest::Assertion
+ end
+
+ it "needs to verify kinds of objects" do
+ @assertion_count = 6
+
+ (6 * 7).must_be_kind_of(Fixnum).must_equal true
+ (6 * 7).must_be_kind_of(Numeric).must_equal true
+ proc { (6 * 7).must_be_kind_of String }.must_raise MiniTest::Assertion
+ end
+
+ it "needs to verify regexp matches" do
+ @assertion_count = 6
+
+ "blah".must_match(/\w+/).must_equal true
+ proc { "blah".must_match(/\d+/) }.must_raise MiniTest::Assertion
+ end
+
+ it "needs to verify nil" do
+ nil.must_be_nil.must_equal true
+ proc { 42.must_be_nil }.must_raise MiniTest::Assertion
+ end
+
+ it "needs to verify using any operator" do
+ 41.must_be(:<, 42).must_equal true
+ proc { 42.must_be(:<, 41) }.must_raise MiniTest::Assertion
+ end
+
+ it "needs to catch an expected exception" do
+ @assertion_count = 2
+
+ proc { raise "blah" }.must_raise RuntimeError
+ proc { raise MiniTest::Assertion }.must_raise MiniTest::Assertion
+ end
+
+ it "needs to catch an unexpected exception" do
+ @assertion_count = 2
+
+ proc {
+ proc { raise MiniTest::Assertion }.must_raise(RuntimeError)
+ }.must_raise MiniTest::Assertion
+ end
+
+ it "needs raise if an expected exception is not raised" do
+ @assertion_count = 2
+
+ proc { proc { 42 }.must_raise(RuntimeError) }.must_raise MiniTest::Assertion
+ end
+
+ it "needs to be able to catch a MiniTest::Assertion exception" do
+ @assertion_count = 2
+
+ proc { 1.wont_equal 1 }.must_raise MiniTest::Assertion
+ end
+
+ it "needs to verify using respond_to" do
+ 42.must_respond_to(:+).must_equal true
+ proc { 42.must_respond_to(:clear) }.must_raise MiniTest::Assertion
+ end
+
+ it "needs to verify identity" do
+ 1.must_be_same_as(1).must_equal true
+ proc { 1.must_be_same_as 2 }.must_raise MiniTest::Assertion
+ end
+
+ it "needs to verify throw" do
+ @assertion_count = 6
+
+ proc { throw :blah }.must_throw(:blah).must_equal true
+ proc { proc { }.must_throw(:blah) }.must_raise MiniTest::Assertion
+ proc { proc { throw :xxx }.must_throw(:blah) }.must_raise MiniTest::Assertion
+ end
+
+ it "needs to verify inequality" do
+ 42.wont_equal(6 * 9).must_equal false
+ proc { 1.wont_equal 1 }.must_raise MiniTest::Assertion
+ end
+
+ it "needs to verify mismatch" do
+ "blah".wont_match(/\d+/).must_equal false
+ proc { "blah".wont_match(/\w+/) }.must_raise MiniTest::Assertion
+ end
+
+ it "needs to verify non-nil" do
+ 42.wont_be_nil.must_equal false
+ proc { nil.wont_be_nil }.must_raise MiniTest::Assertion
+ end
+
+ it "needs to verify non-identity" do
+ 1.wont_be_same_as(2).must_equal false
+ proc { 1.wont_be_same_as 1 }.must_raise MiniTest::Assertion
+ end
+end
diff --git a/test/minitest/test_mini_test.rb b/test/minitest/test_mini_test.rb
new file mode 100644
index 0000000000..2f30232074
--- /dev/null
+++ b/test/minitest/test_mini_test.rb
@@ -0,0 +1,866 @@
+############################################################
+# This file is imported from a different project.
+# DO NOT make modifications in this repo.
+# File a patch instead and assign it to Ryan Davis
+############################################################
+
+require 'stringio'
+require 'pathname'
+require 'minitest/unit'
+
+MiniTest::Unit.autorun
+
+module M; end
+class E < StandardError; include M; end
+
+class TestMiniTest < MiniTest::Unit::TestCase
+ def setup
+ srand 42
+ MiniTest::Unit::TestCase.reset
+ @tu = MiniTest::Unit.new
+ @output = StringIO.new("")
+ MiniTest::Unit.output = @output
+ assert_equal [0, 0], @tu.run_test_suites
+ end
+
+ def teardown
+ MiniTest::Unit.output = $stdout
+ Object.send :remove_const, :ATestCase if defined? ATestCase
+ end
+
+ pwd = Pathname.new(File.expand_path Dir.pwd)
+ basedir = Pathname.new(File.expand_path(MiniTest::MINI_DIR)) + 'mini'
+ basedir = basedir.relative_path_from(pwd).to_s
+ MINITEST_BASE_DIR = basedir[/\A\./] ? basedir : "./#{basedir}"
+ BT_MIDDLE = ["#{MINITEST_BASE_DIR}/test.rb:165:in `run_test_suites'",
+ "#{MINITEST_BASE_DIR}/test.rb:161:in `each'",
+ "#{MINITEST_BASE_DIR}/test.rb:161:in `run_test_suites'",
+ "#{MINITEST_BASE_DIR}/test.rb:158:in `each'",
+ "#{MINITEST_BASE_DIR}/test.rb:158:in `run_test_suites'",
+ "#{MINITEST_BASE_DIR}/test.rb:139:in `run'",
+ "#{MINITEST_BASE_DIR}/test.rb:106:in `run'"]
+
+ def test_filter_backtrace
+ # this is a semi-lame mix of relative paths.
+ # I cheated by making the autotest parts not have ./
+ bt = (["lib/autotest.rb:571:in `add_exception'",
+ "test/test_autotest.rb:62:in `test_add_exception'",
+ "#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] +
+ BT_MIDDLE +
+ ["#{MINITEST_BASE_DIR}/test.rb:29",
+ "test/test_autotest.rb:422"])
+ bt = util_expand_bt bt
+
+ ex = ["lib/autotest.rb:571:in `add_exception'",
+ "test/test_autotest.rb:62:in `test_add_exception'"]
+ ex = util_expand_bt ex
+
+ fu = MiniTest::filter_backtrace(bt)
+
+ assert_equal ex, fu
+ end
+
+ def util_expand_bt bt
+ if RUBY_VERSION =~ /^1\.9/ then
+ bt.map { |f| (f =~ /^\./) ? File.expand_path(f) : f }
+ else
+ bt
+ end
+ end
+
+ def test_filter_backtrace_all_unit
+ bt = (["./lib/mini/test.rb:165:in `__send__'"] +
+ BT_MIDDLE +
+ ["./lib/mini/test.rb:29"])
+ ex = bt.clone
+ fu = MiniTest::filter_backtrace(bt)
+ assert_equal ex, fu
+ end
+
+ def test_filter_backtrace_unit_starts
+ bt = (["#{MINITEST_BASE_DIR}/test.rb:165:in `__send__'"] +
+ BT_MIDDLE +
+ ["#{MINITEST_BASE_DIR}/mini/test.rb:29",
+ "-e:1"])
+
+ bt = util_expand_bt bt
+
+ ex = ["-e:1"]
+ fu = MiniTest::filter_backtrace(bt)
+ assert_equal ex, fu
+ end
+
+ def test_class_puke_with_assertion_failed
+ exception = MiniTest::Assertion.new "Oh no!"
+ exception.set_backtrace ["unhappy"]
+ assert_equal 'F', @tu.puke('SomeClass', 'method_name', exception)
+ assert_equal 1, @tu.failures
+ assert_match(/^Failure.*Oh no!/m, @tu.report.first)
+ end
+
+ def test_class_puke_with_failure_and_flunk_in_backtrace
+ exception = begin
+ MiniTest::Unit::TestCase.new('fake tc').flunk
+ rescue MiniTest::Assertion => failure
+ failure
+ end
+ assert_equal 'F', @tu.puke('SomeClass', 'method_name', exception)
+ refute @tu.report.any?{|line| line =~ /in .flunk/}
+ end
+
+ def test_class_puke_with_non_failure_exception
+ exception = Exception.new("Oh no again!")
+ assert_equal 'E', @tu.puke('SomeClass', 'method_name', exception)
+ assert_equal 1, @tu.errors
+ assert_match(/^Exception.*Oh no again!/m, @tu.report.first)
+ end
+
+ def test_class_run_test_suites
+ tc = Class.new(MiniTest::Unit::TestCase) do
+ def test_something
+ assert true
+ end
+ end
+
+ Object.const_set(:ATestCase, tc)
+
+ assert_equal [1, 1], @tu.run_test_suites
+ end
+
+ def test_run_failing # TODO: add error test
+ tc = Class.new(MiniTest::Unit::TestCase) do
+ def test_something
+ assert true
+ end
+
+ def test_failure
+ assert false
+ end
+ end
+
+ Object.const_set(:ATestCase, tc)
+
+ @tu.run
+
+ expected = "Loaded suite blah
+Started
+F.
+Finished in 0.00
+
+ 1) Failure:
+test_failure(ATestCase) [FILE:LINE]:
+Failed assertion, no message given.
+
+2 tests, 2 assertions, 1 failures, 0 errors, 0 skips
+"
+ util_assert_report expected
+ end
+
+ def test_run_error
+ tc = Class.new(MiniTest::Unit::TestCase) do
+ def test_something
+ assert true
+ end
+
+ def test_error
+ raise "unhandled exception"
+ end
+ end
+
+ Object.const_set(:ATestCase, tc)
+
+ @tu.run
+
+ expected = "Loaded suite blah
+Started
+E.
+Finished in 0.00
+
+ 1) Error:
+test_error(ATestCase):
+RuntimeError: unhandled exception
+ FILE:LINE:in `test_error'
+
+2 tests, 1 assertions, 0 failures, 1 errors, 0 skips
+"
+ util_assert_report expected
+ end
+
+ def test_run_error_teardown
+ tc = Class.new(MiniTest::Unit::TestCase) do
+ def test_something
+ assert true
+ end
+
+ def teardown
+ raise "unhandled exception"
+ end
+ end
+
+ Object.const_set(:ATestCase, tc)
+
+ @tu.run
+
+ expected = "Loaded suite blah
+Started
+E
+Finished in 0.00
+
+ 1) Error:
+test_something(ATestCase):
+RuntimeError: unhandled exception
+ FILE:LINE:in `teardown'
+
+1 tests, 1 assertions, 0 failures, 1 errors, 0 skips
+"
+ util_assert_report expected
+ end
+
+ def test_run_skip
+ tc = Class.new(MiniTest::Unit::TestCase) do
+ def test_something
+ assert true
+ end
+
+ def test_skip
+ skip "not yet"
+ end
+ end
+
+ Object.const_set(:ATestCase, tc)
+
+ @tu.run
+
+ expected = "Loaded suite blah
+Started
+S.
+Finished in 0.00
+
+ 1) Skipped:
+test_skip(ATestCase) [FILE:LINE]:
+not yet
+
+2 tests, 1 assertions, 0 failures, 0 errors, 1 skips
+"
+ util_assert_report expected
+ end
+
+ def util_assert_report expected = nil
+ expected ||= "Loaded suite blah
+Started
+.
+Finished in 0.00
+
+1 tests, 1 assertions, 0 failures, 0 errors, 0 skips
+"
+ output = @output.string.sub(/Finished in .*/, "Finished in 0.00")
+ output.sub!(/Loaded suite .*/, 'Loaded suite blah')
+ output.sub!(/^(\s+)(?:#{Regexp.union(__FILE__, File.expand_path(__FILE__))}):\d+:/o, '\1FILE:LINE:')
+ output.sub!(/\[(?:#{Regexp.union(__FILE__, File.expand_path(__FILE__))}):\d+\]/o, '[FILE:LINE]')
+ assert_equal(expected, output)
+ end
+ def test_run_failing_filtered
+ tc = Class.new(MiniTest::Unit::TestCase) do
+ def test_something
+ assert true
+ end
+
+ def test_failure
+ assert false
+ end
+ end
+
+ Object.const_set(:ATestCase, tc)
+
+ @tu.run(%w(-n /something/))
+
+ util_assert_report
+ end
+
+ def test_run_passing
+ tc = Class.new(MiniTest::Unit::TestCase) do
+ def test_something
+ assert true
+ end
+ end
+
+ Object.const_set(:ATestCase, tc)
+
+ @tu.run
+
+ util_assert_report
+ end
+end
+
+class TestMiniTestTestCase < MiniTest::Unit::TestCase
+ def setup
+ MiniTest::Unit::TestCase.reset
+
+ @tc = MiniTest::Unit::TestCase.new 'fake tc'
+ @zomg = "zomg ponies!"
+ @assertion_count = 1
+ end
+
+ def teardown
+ assert_equal(@assertion_count, @tc._assertions,
+ "expected #{@assertion_count} assertions to be fired during the test, not #{@tc._assertions}") if @tc._assertions
+ Object.send :remove_const, :ATestCase if defined? ATestCase
+ end
+
+ def test_class_inherited
+ @assertion_count = 0
+
+ Object.const_set(:ATestCase, Class.new(MiniTest::Unit::TestCase))
+
+ assert_equal [ATestCase], MiniTest::Unit::TestCase.test_suites
+ end
+
+ def test_class_test_suites
+ @assertion_count = 0
+
+ Object.const_set(:ATestCase, Class.new(MiniTest::Unit::TestCase))
+
+ assert_equal 1, MiniTest::Unit::TestCase.test_suites.size
+ assert_equal [ATestCase], MiniTest::Unit::TestCase.test_suites
+ end
+
+ def test_class_asserts_match_refutes
+ @assertion_count = 0
+
+ methods = MiniTest::Assertions.public_instance_methods
+ methods.map! { |m| m.to_s } if Symbol === methods.first
+
+ ignores = %w(assert_block assert_no_match assert_not_equal assert_not_nil
+ assert_not_same assert_nothing_thrown assert_raise
+ assert_nothing_raised assert_raises assert_throws assert_send)
+ asserts = methods.grep(/^assert/).sort - ignores
+ refutes = methods.grep(/^refute/).sort - ignores
+
+ assert_empty refutes.map { |n| n.sub(/^refute/, 'assert') } - asserts
+ assert_empty asserts.map { |n| n.sub(/^assert/, 'refute') } - refutes
+ end
+
+ def test_assert
+ @assertion_count = 2
+
+ @tc.assert_equal true, @tc.assert(true), "returns true on success"
+ end
+
+ def test_assert__triggered
+ util_assert_triggered "Failed assertion, no message given." do
+ @tc.assert false
+ end
+ end
+
+ def test_assert__triggered_message
+ util_assert_triggered @zomg do
+ @tc.assert false, @zomg
+ end
+ end
+
+ def test_assert_block
+ @tc.assert_block do
+ true
+ end
+ end
+
+ def test_assert_block_triggered
+ util_assert_triggered 'Expected block to return true value.' do
+ @tc.assert_block do
+ false
+ end
+ end
+ end
+
+ def test_assert_empty
+ @assertion_count = 2
+
+ @tc.assert_empty []
+ end
+
+ def test_assert_empty_triggered
+ @assertion_count = 2
+
+ util_assert_triggered "Expected [1] to be empty." do
+ @tc.assert_empty [1]
+ end
+ end
+
+ def test_assert_equal
+ @tc.assert_equal 1, 1
+ end
+
+ def test_assert_equal_different
+ util_assert_triggered "Expected 1, not 2." do
+ @tc.assert_equal 1, 2
+ end
+ end
+
+ def test_assert_in_delta
+ @tc.assert_in_delta 0.0, 1.0 / 1000, 0.1
+ end
+
+ def test_assert_in_delta_triggered
+ util_assert_triggered 'Expected 0.0 - 0.001 (0.001) to be < 1.0e-06.' do
+ @tc.assert_in_delta 0.0, 1.0 / 1000, 0.000001
+ end
+ end
+
+ def test_assert_in_epsilon
+ @assertion_count = 8
+
+ @tc.assert_in_epsilon 10000, 9991
+ @tc.assert_in_epsilon 9991, 10000
+ @tc.assert_in_epsilon 1.0, 1.001
+ @tc.assert_in_epsilon 1.001, 1.0
+
+ @tc.assert_in_epsilon 10000, 9999.1, 0.0001
+ @tc.assert_in_epsilon 9999.1, 10000, 0.0001
+ @tc.assert_in_epsilon 1.0, 1.0001, 0.0001
+ @tc.assert_in_epsilon 1.0001, 1.0, 0.0001
+ end
+
+ def test_assert_in_epsilon_triggered
+ util_assert_triggered 'Expected 10000 - 9990 (10) to be < 9.99.' do
+ @tc.assert_in_epsilon 10000, 9990
+ end
+ end
+
+ def test_assert_includes
+ @assertion_count = 2
+
+ @tc.assert_includes [true], true
+ end
+
+ def test_assert_includes_triggered
+ @assertion_count = 3
+
+ e = @tc.assert_raises MiniTest::Assertion do
+ @tc.assert_includes [true], false
+ end
+
+ expected = "Expected [true] to include false."
+ assert_equal expected, e.message
+ end
+
+ def test_assert_instance_of
+ @tc.assert_instance_of String, "blah"
+ end
+
+ def test_assert_instance_of_triggered
+ util_assert_triggered 'Expected "blah" to be an instance of Array, not String.' do
+ @tc.assert_instance_of Array, "blah"
+ end
+ end
+
+ def test_assert_kind_of
+ @tc.assert_kind_of String, "blah"
+ end
+
+ def test_assert_kind_of_triggered
+ util_assert_triggered 'Expected "blah" to be a kind of Array, not String.' do
+ @tc.assert_kind_of Array, "blah"
+ end
+ end
+
+ def test_assert_match
+ @assertion_count = 2
+ @tc.assert_match "blah blah blah", /\w+/
+ end
+
+ def test_assert_match_triggered
+ @assertion_count = 2
+ util_assert_triggered 'Expected /\d+/ to match "blah blah blah".' do
+ @tc.assert_match "blah blah blah", /\d+/
+ end
+ end
+
+ def test_assert_nil
+ @tc.assert_nil nil
+ end
+
+ def test_assert_nil_triggered
+ util_assert_triggered 'Expected 42 to be nil.' do
+ @tc.assert_nil 42
+ end
+ end
+
+ def test_assert_operator
+ @tc.assert_operator 2, :>, 1
+ end
+
+ def test_assert_operator_triggered
+ util_assert_triggered "Expected 2 to be < 1." do
+ @tc.assert_operator 2, :<, 1
+ end
+ end
+
+ def test_assert_raises
+ @tc.assert_raises RuntimeError do
+ raise "blah"
+ end
+ end
+
+ def test_assert_raises_module
+ @tc.assert_raises M do
+ raise E
+ end
+ end
+
+ def test_assert_raises_triggered_different
+ e = assert_raises MiniTest::Assertion do
+ @tc.assert_raises RuntimeError do
+ raise SyntaxError, "icky"
+ end
+ end
+
+ expected = "[RuntimeError] exception expected, not
+Class: <SyntaxError>
+Message: <\"icky\">
+---Backtrace---
+FILE:LINE:in `test_assert_raises_triggered_different'
+---------------"
+
+ actual = e.message.gsub(/^.+:\d+/, 'FILE:LINE')
+ actual.gsub!(/block \(\d+ levels\) in /, '') if RUBY_VERSION =~ /^1\.9/
+
+ assert_equal expected, actual
+ end
+
+ def test_assert_raises_triggered_none
+ e = assert_raises MiniTest::Assertion do
+ @tc.assert_raises MiniTest::Assertion do
+ # do nothing
+ end
+ end
+
+ expected = "MiniTest::Assertion expected but nothing was raised."
+
+ assert_equal expected, e.message
+ end
+
+ def test_assert_raises_triggered_subclass
+ e = assert_raises MiniTest::Assertion do
+ @tc.assert_raises StandardError do
+ raise E
+ end
+ end
+
+ expected = "[StandardError] exception expected, not
+Class: <E>
+Message: <\"E\">
+---Backtrace---
+FILE:LINE:in `test_assert_raises_triggered_subclass'
+---------------"
+
+ actual = e.message.gsub(/^.+:\d+/, 'FILE:LINE')
+ actual.gsub!(/block \(\d+ levels\) in /, '') if RUBY_VERSION =~ /^1\.9/
+
+ assert_equal expected, actual
+ end
+
+ def test_assert_respond_to
+ @tc.assert_respond_to "blah", :empty?
+ end
+
+ def test_assert_respond_to_triggered
+ util_assert_triggered 'Expected "blah" (String) to respond to #rawr!.' do
+ @tc.assert_respond_to "blah", :rawr!
+ end
+ end
+
+ def test_assert_same
+ @assertion_count = 3
+
+ o = "blah"
+ @tc.assert_same 1, 1
+ @tc.assert_same :blah, :blah
+ @tc.assert_same o, o
+ end
+
+ def test_assert_same_triggered
+ @assertion_count = 2
+
+ util_assert_triggered 'Expected 2 (0xXXX) to be the same as 1 (0xXXX).' do
+ @tc.assert_same 1, 2
+ end
+
+ s1 = "blah"
+ s2 = "blah"
+
+ util_assert_triggered 'Expected "blah" (0xXXX) to be the same as "blah" (0xXXX).' do
+ @tc.assert_same s1, s2
+ end
+ end
+
+ def test_assert_send
+ @tc.assert_send [1, :<, 2]
+ end
+
+ def test_assert_send_bad
+ util_assert_triggered "Expected 1.>(*[2]) to return true." do
+ @tc.assert_send [1, :>, 2]
+ end
+ end
+
+ def test_assert_throws
+ @tc.assert_throws(:blah) do
+ throw :blah
+ end
+ end
+
+ def test_assert_throws_different
+ util_assert_triggered 'Expected :blah to have been thrown, not :not_blah.' do
+ @tc.assert_throws(:blah) do
+ throw :not_blah
+ end
+ end
+ end
+
+ def test_assert_throws_unthrown
+ util_assert_triggered 'Expected :blah to have been thrown.' do
+ @tc.assert_throws(:blah) do
+ # do nothing
+ end
+ end
+ end
+
+ def test_capture_io
+ @assertion_count = 0
+
+ out, err = capture_io do
+ puts 'hi'
+ warn 'bye!'
+ end
+
+ assert_equal "hi\n", out
+ assert_equal "bye!\n", err
+ end
+
+ def test_flunk
+ util_assert_triggered 'Epic Fail!' do
+ @tc.flunk
+ end
+ end
+
+ def test_flunk_message
+ util_assert_triggered @zomg do
+ @tc.flunk @zomg
+ end
+ end
+
+ def test_message
+ @assertion_count = 0
+
+ assert_equal "blah2.", @tc.message { "blah2" }.call
+ assert_equal "blah2.", @tc.message("") { "blah2" }.call
+ assert_equal "blah1.\nblah2.", @tc.message("blah1") { "blah2" }.call
+ end
+
+ def test_pass
+ @tc.pass
+ end
+
+ def test_test_methods_sorted
+ @assertion_count = 0
+
+ sample_test_case = Class.new(MiniTest::Unit::TestCase)
+
+ class << sample_test_case
+ def test_order; :sorted end
+ end
+
+ sample_test_case.instance_eval do
+ define_method :test_test3 do assert "does not matter" end
+ define_method :test_test2 do assert "does not matter" end
+ define_method :test_test1 do assert "does not matter" end
+ end
+
+ expected = %w(test_test1 test_test2 test_test3)
+ assert_equal expected, sample_test_case.test_methods
+ end
+
+ def test_test_methods_random
+ @assertion_count = 0
+
+ sample_test_case = Class.new(MiniTest::Unit::TestCase)
+
+ class << sample_test_case
+ def test_order; :random end
+ end
+
+ sample_test_case.instance_eval do
+ define_method :test_test1 do assert "does not matter" end
+ define_method :test_test2 do assert "does not matter" end
+ define_method :test_test3 do assert "does not matter" end
+ end
+
+ srand 42
+ expected = %w(test_test1 test_test2 test_test3)
+ max = expected.size
+ expected = expected.sort_by { rand(max) }
+
+ srand 42
+ result = sample_test_case.test_methods
+
+ assert_equal expected, result
+ end
+
+ def test_refute
+ @assertion_count = 2
+
+ @tc.assert_equal false, @tc.refute(false), "returns false on success"
+ end
+
+ def test_refute_empty
+ @assertion_count = 2
+
+ @tc.refute_empty [1]
+ end
+
+ def test_refute_empty_triggered
+ @assertion_count = 2
+
+ util_assert_triggered "Expected [] to not be empty." do
+ @tc.refute_empty []
+ end
+ end
+
+ def test_refute_equal
+ @tc.refute_equal "blah", "yay"
+ end
+
+ def test_refute_equal_triggered
+ util_assert_triggered 'Expected "blah" to not be equal to "blah".' do
+ @tc.refute_equal "blah", "blah"
+ end
+ end
+
+ def test_refute_in_delta
+ @tc.refute_in_delta 0.0, 1.0 / 1000, 0.000001
+ end
+
+ def test_refute_in_delta_triggered
+ util_assert_triggered 'Expected 0.0 - 0.001 (0.001) to not be < 0.1.' do
+ @tc.refute_in_delta 0.0, 1.0 / 1000, 0.1
+ end
+ end
+
+ def test_refute_in_epsilon
+ @tc.refute_in_epsilon 10000, 9990
+ end
+
+ def test_refute_in_epsilon_triggered
+ util_assert_triggered 'Expected 10000 - 9991 (9) to not be < 10.0.' do
+ @tc.refute_in_epsilon 10000, 9991
+ fail
+ end
+ end
+
+ def test_refute_includes
+ @assertion_count = 2
+
+ @tc.refute_includes [true], false
+ end
+
+ def test_refute_includes_triggered
+ @assertion_count = 3
+
+ e = @tc.assert_raises MiniTest::Assertion do
+ @tc.refute_includes [true], true
+ end
+
+ expected = "Expected [true] to not include true."
+ assert_equal expected, e.message
+ end
+
+ def test_refute_instance_of
+ @tc.refute_instance_of Array, "blah"
+ end
+
+ def test_refute_instance_of_triggered
+ util_assert_triggered 'Expected "blah" to not be an instance of String.' do
+ @tc.refute_instance_of String, "blah"
+ end
+ end
+
+ def test_refute_kind_of
+ @tc.refute_kind_of Array, "blah"
+ end
+
+ def test_refute_kind_of_triggered
+ util_assert_triggered 'Expected "blah" to not be a kind of String.' do
+ @tc.refute_kind_of String, "blah"
+ end
+ end
+
+ def test_refute_match
+ @tc.refute_match "blah blah blah", /\d+/
+ end
+
+ def test_refute_match_triggered
+ util_assert_triggered 'Expected /\w+/ to not match "blah blah blah".' do
+ @tc.refute_match "blah blah blah", /\w+/
+ end
+ end
+
+ def test_refute_nil
+ @tc.refute_nil 42
+ end
+
+ def test_refute_nil_triggered
+ util_assert_triggered 'Expected nil to not be nil.' do
+ @tc.refute_nil nil
+ end
+ end
+
+ def test_refute_operator
+ @tc.refute_operator 2, :<, 1
+ end
+
+ def test_refute_operator_triggered
+ util_assert_triggered "Expected 2 to not be > 1." do
+ @tc.refute_operator 2, :>, 1
+ end
+ end
+
+ def test_refute_respond_to
+ @tc.refute_respond_to "blah", :rawr!
+ end
+
+ def test_refute_respond_to_triggered
+ util_assert_triggered 'Expected "blah" to not respond to empty?.' do
+ @tc.refute_respond_to "blah", :empty?
+ end
+ end
+
+ def test_refute_same
+ @tc.refute_same 1, 2
+ end
+
+ # TODO: "with id <id>" crap from assertions.rb
+ def test_refute_same_triggered
+ util_assert_triggered 'Expected 1 to not be the same as 1.' do
+ @tc.refute_same 1, 1
+ end
+ end
+
+ def test_skip
+ @assertion_count = 0
+
+ util_assert_triggered "haha!", MiniTest::Skip do
+ @tc.skip "haha!"
+ end
+ end
+
+ def util_assert_triggered expected, klass = MiniTest::Assertion
+ e = assert_raises(klass) do
+ yield
+ end
+
+ msg = e.message.sub(/(---Backtrace---).*/m, '\1')
+ msg.gsub!(/\(0x[0-9a-f]+\)/, '(0xXXX)')
+
+ assert_equal expected, msg
+ end
+end
diff --git a/test/net/http/test_httpheader.rb b/test/net/http/test_httpheader.rb
index 3ba1b217c0..379c9bd1ad 100644
--- a/test/net/http/test_httpheader.rb
+++ b/test/net/http/test_httpheader.rb
@@ -215,7 +215,7 @@ class HTTPHeaderTest < Test::Unit::TestCase
try_content_length 123, ' 123'
try_content_length 1, '1 23'
try_content_length 500, '(OK)500'
- assert_raises(Net::HTTPHeaderSyntaxError, 'here is no digit, but') {
+ assert_raise(Net::HTTPHeaderSyntaxError, 'here is no digit, but') {
@c['content-length'] = 'no digit'
@c.content_length
}
diff --git a/test/net/pop/test_pop.rb b/test/net/pop/test_pop.rb
new file mode 100644
index 0000000000..c8aa9a83a8
--- /dev/null
+++ b/test/net/pop/test_pop.rb
@@ -0,0 +1,132 @@
+require 'net/pop'
+require 'test/unit'
+require 'digest/md5'
+
+class TestPOP < Test::Unit::TestCase
+ def setup
+ @users = {'user' => 'pass' }
+ @ok_user = 'user'
+ @stamp_base = "#{$$}.#{Time.now.to_i}@localhost"
+ end
+
+ def test_pop_auth_ok
+ pop_test(false) do |pop|
+ assert_instance_of Net::POP3, pop
+ assert_nothing_raised do
+ pop.start(@ok_user, @users[@ok_user])
+ end
+ end
+ end
+
+ def test_pop_auth_ng
+ pop_test(false) do |pop|
+ assert_instance_of Net::POP3, pop
+ assert_raise Net::POPAuthenticationError do
+ pop.start(@ok_user, 'bad password')
+ end
+ end
+ end
+
+ def test_apop_ok
+ pop_test(@stamp_base) do |pop|
+ assert_instance_of Net::APOP, pop
+ assert_nothing_raised do
+ pop.start(@ok_user, @users[@ok_user])
+ end
+ end
+ end
+
+ def test_apop_ng
+ pop_test(@stamp_base) do |pop|
+ assert_instance_of Net::APOP, pop
+ assert_raise Net::POPAuthenticationError do
+ pop.start(@ok_user, 'bad password')
+ end
+ end
+ end
+
+ def test_apop_invalid
+ pop_test("\x80"+@stamp_base) do |pop|
+ assert_instance_of Net::APOP, pop
+ assert_raise Net::POPAuthenticationError do
+ pop.start(@ok_user, @users[@ok_user])
+ end
+ end
+ end
+
+ def test_apop_invalid_at
+ pop_test(@stamp_base.sub('@', '.')) do |pop|
+ assert_instance_of Net::APOP, pop
+ e = assert_raise Net::POPAuthenticationError do
+ pop.start(@ok_user, @users[@ok_user])
+ end
+ end
+ end
+
+ def pop_test(apop=false)
+ host = 'localhost'
+ server = TCPServer.new(host, 0)
+ port = server.addr[1]
+ thread = Thread.start do
+ sock = server.accept
+ begin
+ pop_server_loop(sock, apop)
+ ensure
+ sock.close
+ end
+ end
+ begin
+ pop = Net::POP3::APOP(apop).new(host, port)
+ #pop.set_debug_output $stderr
+ yield pop
+ ensure
+ begin
+ pop.finish
+ rescue IOError
+ raise unless $!.message == "POP session not yet started"
+ end
+ end
+ ensure
+ server.close
+ thread.value
+ end
+
+ def pop_server_loop(sock, apop)
+ if apop
+ sock.print "+OK ready <#{apop}>\r\n"
+ else
+ sock.print "+OK ready\r\n"
+ end
+ user = nil
+ while line = sock.gets
+ case line
+ when /^USER (.+)\r\n/
+ user = $1
+ if @users.key?(user)
+ sock.print "+OK\r\n"
+ else
+ sock.print "-ERR unknown user\r\n"
+ end
+ when /^PASS (.+)\r\n/
+ if @users[user] == $1
+ sock.print "+OK\r\n"
+ else
+ sock.print "-ERR invalid password\r\n"
+ end
+ when /^APOP (.+) (.+)\r\n/
+ user = $1
+ if apop && Digest::MD5.hexdigest("<#{apop}>#{@users[user]}") == $2
+ sock.print "+OK\r\n"
+ else
+ sock.print "-ERR authentication failed\r\n"
+ end
+ when /^QUIT/
+ sock.print "+OK bye\r\n"
+ return
+ else
+ sock.print "-ERR command not recognized\r\n"
+ return
+ end
+ end
+ end
+end
diff --git a/test/nkf/test_nkf.rb b/test/nkf/test_nkf.rb
index 279ad59e1a..2c6b964eb9 100644
--- a/test/nkf/test_nkf.rb
+++ b/test/nkf/test_nkf.rb
@@ -13,4 +13,10 @@ Ruby"
assert_equal(::NKF::EUC, NKF.guess(str_euc))
end
+ def test_ruby_dev_36909
+ assert_nothing_raised do
+ 1000.times { NKF.nkf("--oc=eucJP-nkf", "foo") }
+ end
+ end
+
end
diff --git a/test/openssl/test_cipher.rb b/test/openssl/test_cipher.rb
index d671908165..cc21e818ed 100644
--- a/test/openssl/test_cipher.rb
+++ b/test/openssl/test_cipher.rb
@@ -65,7 +65,7 @@ class OpenSSL::TestCipher < Test::Unit::TestCase
def test_empty_data
@c1.encrypt
- assert_raises(ArgumentError){ @c1.update("") }
+ assert_raise(ArgumentError){ @c1.update("") }
end
if OpenSSL::OPENSSL_VERSION_NUMBER > 0x00907000
diff --git a/test/openssl/test_ec.rb b/test/openssl/test_ec.rb
index 671901ca36..66dbf54b4d 100644
--- a/test/openssl/test_ec.rb
+++ b/test/openssl/test_ec.rb
@@ -89,7 +89,7 @@ class OpenSSL::TestEC < Test::Unit::TestCase
sig = key.dsa_sign_asn1(@data1)
assert_equal(key.dsa_verify_asn1(@data1, sig), true)
- assert_raises(OpenSSL::PKey::ECError) { key.dsa_sign_asn1(@data2) }
+ assert_raise(OpenSSL::PKey::ECError) { key.dsa_sign_asn1(@data2) }
end
end
diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb
index ea959892f3..44e79c9e24 100644
--- a/test/openssl/test_ssl.rb
+++ b/test/openssl/test_ssl.rb
@@ -236,7 +236,7 @@ class OpenSSL::TestSSL < Test::Unit::TestCase
def test_client_auth
vflag = OpenSSL::SSL::VERIFY_PEER|OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
start_server(PORT, vflag, true){|server, port|
- assert_raises(OpenSSL::SSL::SSLError){
+ assert_raise(OpenSSL::SSL::SSLError){
sock = TCPSocket.new("127.0.0.1", port)
ssl = OpenSSL::SSL::SSLSocket.new(sock)
ssl.connect
@@ -375,10 +375,10 @@ class OpenSSL::TestSSL < Test::Unit::TestCase
sock = TCPSocket.new("127.0.0.1", port)
ssl = OpenSSL::SSL::SSLSocket.new(sock)
ssl.connect
- assert_raises(sslerr){ssl.post_connection_check("localhost.localdomain")}
- assert_raises(sslerr){ssl.post_connection_check("127.0.0.1")}
+ assert_raise(sslerr){ssl.post_connection_check("localhost.localdomain")}
+ assert_raise(sslerr){ssl.post_connection_check("127.0.0.1")}
assert(ssl.post_connection_check("localhost"))
- assert_raises(sslerr){ssl.post_connection_check("foo.example.com")}
+ assert_raise(sslerr){ssl.post_connection_check("foo.example.com")}
cert = ssl.peer_cert
assert(!OpenSSL::SSL.verify_certificate_identity(cert, "localhost.localdomain"))
@@ -401,8 +401,8 @@ class OpenSSL::TestSSL < Test::Unit::TestCase
ssl.connect
assert(ssl.post_connection_check("localhost.localdomain"))
assert(ssl.post_connection_check("127.0.0.1"))
- assert_raises(sslerr){ssl.post_connection_check("localhost")}
- assert_raises(sslerr){ssl.post_connection_check("foo.example.com")}
+ assert_raise(sslerr){ssl.post_connection_check("localhost")}
+ assert_raise(sslerr){ssl.post_connection_check("foo.example.com")}
cert = ssl.peer_cert
assert(OpenSSL::SSL.verify_certificate_identity(cert, "localhost.localdomain"))
@@ -423,9 +423,9 @@ class OpenSSL::TestSSL < Test::Unit::TestCase
ssl = OpenSSL::SSL::SSLSocket.new(sock)
ssl.connect
assert(ssl.post_connection_check("localhost.localdomain"))
- assert_raises(sslerr){ssl.post_connection_check("127.0.0.1")}
- assert_raises(sslerr){ssl.post_connection_check("localhost")}
- assert_raises(sslerr){ssl.post_connection_check("foo.example.com")}
+ assert_raise(sslerr){ssl.post_connection_check("127.0.0.1")}
+ assert_raise(sslerr){ssl.post_connection_check("localhost")}
+ assert_raise(sslerr){ssl.post_connection_check("foo.example.com")}
cert = ssl.peer_cert
assert(OpenSSL::SSL.verify_certificate_identity(cert, "localhost.localdomain"))
assert(!OpenSSL::SSL.verify_certificate_identity(cert, "127.0.0.1"))
@@ -439,7 +439,10 @@ class OpenSSL::TestSSL < Test::Unit::TestCase
start_server(PORT, OpenSSL::SSL::VERIFY_NONE, true) do |server, port|
2.times do
sock = TCPSocket.new("127.0.0.1", port)
- ssl = OpenSSL::SSL::SSLSocket.new(sock)
+ # Debian's openssl 0.9.8g-13 failed at assert(ssl.session_reused?),
+ # when use default SSLContext. [ruby-dev:36167]
+ ctx = OpenSSL::SSL::SSLContext.new("TLSv1")
+ ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
ssl.sync_close = true
ssl.session = last_session if last_session
ssl.connect
diff --git a/test/openssl/test_x509cert.rb b/test/openssl/test_x509cert.rb
index a5a75ff1b6..c092ce5796 100644
--- a/test/openssl/test_x509cert.rb
+++ b/test/openssl/test_x509cert.rb
@@ -157,15 +157,15 @@ class OpenSSL::TestX509Certificate < Test::Unit::TestCase
cert.not_after = Time.now
assert_equal(false, cert.verify(@dsa512))
- assert_raises(OpenSSL::X509::CertificateError){
+ assert_raise(OpenSSL::X509::CertificateError){
cert = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, [],
nil, nil, OpenSSL::Digest::DSS1.new)
}
- assert_raises(OpenSSL::X509::CertificateError){
+ assert_raise(OpenSSL::X509::CertificateError){
cert = issue_cert(@ca, @dsa512, 1, Time.now, Time.now+3600, [],
nil, nil, OpenSSL::Digest::MD5.new)
}
- assert_raises(OpenSSL::X509::CertificateError){
+ assert_raise(OpenSSL::X509::CertificateError){
cert = issue_cert(@ca, @dsa512, 1, Time.now, Time.now+3600, [],
nil, nil, OpenSSL::Digest::SHA1.new)
}
diff --git a/test/openssl/test_x509store.rb b/test/openssl/test_x509store.rb
index b0fe597262..fc7c35e3dd 100644
--- a/test/openssl/test_x509store.rb
+++ b/test/openssl/test_x509store.rb
@@ -198,7 +198,7 @@ class OpenSSL::TestX509Store < Test::Unit::TestCase
nil, nil, OpenSSL::Digest::SHA1.new)
store = OpenSSL::X509::Store.new
store.add_cert(ca1_cert)
- assert_raises(OpenSSL::X509::StoreError){
+ assert_raise(OpenSSL::X509::StoreError){
store.add_cert(ca1_cert) # add same certificate twice
}
@@ -209,7 +209,7 @@ class OpenSSL::TestX509Store < Test::Unit::TestCase
crl2 = issue_crl(revoke_info, 2, now+1800, now+3600, [],
ca1_cert, @rsa2048, OpenSSL::Digest::SHA1.new)
store.add_crl(crl1)
- assert_raises(OpenSSL::X509::StoreError){
+ assert_raise(OpenSSL::X509::StoreError){
store.add_crl(crl2) # add CRL issued by same CA twice.
}
end
diff --git a/test/optparse/test_noarg.rb b/test/optparse/test_noarg.rb
index 28c469093d..329956a61a 100644
--- a/test/optparse/test_noarg.rb
+++ b/test/optparse/test_noarg.rb
@@ -18,7 +18,7 @@ module TestOptionParser::NoArg
end
def test_short
- assert_raises(OptionParser::InvalidOption) {@opt.parse!(%w"-xq")}
+ assert_raise(OptionParser::InvalidOption) {@opt.parse!(%w"-xq")}
assert_equal(%w"", no_error {@opt.parse!(%w"-x")})
assert_equal(true, @flag)
@flag = nil
@@ -27,11 +27,11 @@ module TestOptionParser::NoArg
end
def test_abbrev
- assert_raises(OptionParser::InvalidOption) {@opt.parse!(%w"-oq")}
+ assert_raise(OptionParser::InvalidOption) {@opt.parse!(%w"-oq")}
assert_equal(%w"", no_error {@opt.parse!(%w"-o")})
assert_equal(true, @flag)
@flag = nil
- assert_raises(OptionParser::InvalidOption) {@opt.parse!(%w"-O")}
+ assert_raise(OptionParser::InvalidOption) {@opt.parse!(%w"-O")}
assert_nil(@flag)
@flag = nil
assert_equal(%w"foo", no_error {@opt.parse!(%w"-o foo")})
@@ -39,7 +39,7 @@ module TestOptionParser::NoArg
end
def test_long
- assert_raises(OptionParser::NeedlessArgument) {@opt.parse!(%w"--option=x")}
+ assert_raise(OptionParser::NeedlessArgument) {@opt.parse!(%w"--option=x")}
assert_equal(%w"", no_error {@opt.parse!(%w"--opt")})
assert_equal(true, @flag)
@flag = nil
@@ -49,8 +49,8 @@ module TestOptionParser::NoArg
def test_ambiguous
@opt.def_option("--open") {|x|}
- assert_raises(OptionParser::AmbiguousOption) {@opt.parse!(%w"--op")}
- assert_raises(OptionParser::AmbiguousOption) {@opt.parse!(%w"-o")}
+ assert_raise(OptionParser::AmbiguousOption) {@opt.parse!(%w"--op")}
+ assert_raise(OptionParser::AmbiguousOption) {@opt.parse!(%w"-o")}
assert_equal(%w"", no_error {@opt.parse!(%w"--opt")})
assert_equal(true, @flag)
end
diff --git a/test/optparse/test_reqarg.rb b/test/optparse/test_reqarg.rb
index 0999e5e603..4ce9dd6292 100644
--- a/test/optparse/test_reqarg.rb
+++ b/test/optparse/test_reqarg.rb
@@ -32,7 +32,7 @@ module TestOptionParser::ReqArg
end
def test_short
- assert_raises(OptionParser::MissingArgument) {@opt.parse!(%w"-x")}
+ assert_raise(OptionParser::MissingArgument) {@opt.parse!(%w"-x")}
assert_equal(%w"", no_error {@opt.parse!(%w"-x foo")})
assert_equal("foo", @flag)
assert_equal(%w"", no_error {@opt.parse!(%w"-xbar")})
@@ -42,7 +42,7 @@ module TestOptionParser::ReqArg
end
def test_abbrev
- assert_raises(OptionParser::MissingArgument) {@opt.parse!(%w"-o")}
+ assert_raise(OptionParser::MissingArgument) {@opt.parse!(%w"-o")}
assert_equal(%w"", no_error {@opt.parse!(%w"-o foo")})
assert_equal("foo", @flag)
assert_equal(%w"", no_error {@opt.parse!(%w"-obar")})
@@ -52,7 +52,7 @@ module TestOptionParser::ReqArg
end
def test_long
- assert_raises(OptionParser::MissingArgument) {@opt.parse!(%w"--opt")}
+ assert_raise(OptionParser::MissingArgument) {@opt.parse!(%w"--opt")}
assert_equal(%w"", no_error {@opt.parse!(%w"--opt foo")})
assert_equal("foo", @flag)
assert_equal(%w"foo", no_error {@opt.parse!(%w"--opt= foo")})
diff --git a/test/pathname/test_pathname.rb b/test/pathname/test_pathname.rb
index 11c1bb7b2b..da12383bdd 100644
--- a/test/pathname/test_pathname.rb
+++ b/test/pathname/test_pathname.rb
@@ -481,6 +481,7 @@ class TestPathname < Test::Unit::TestCase
result = []
Pathname.new("/usr/bin/ruby").each_filename {|f| result << f }
assert_equal(%w[usr bin ruby], result)
+ assert_equal(%w[usr bin ruby], Pathname.new("/usr/bin/ruby").each_filename.to_a)
end
def test_kernel_pathname
diff --git a/test/rdoc/binary.dat b/test/rdoc/binary.dat
new file mode 100644
index 0000000000..371950efe6
--- /dev/null
+++ b/test/rdoc/binary.dat
Binary files differ
diff --git a/test/rdoc/rdoc_markup_to_html_crossref_reference.rb b/test/rdoc/rdoc_markup_to_html_crossref_reference.rb
new file mode 100644
index 0000000000..cbf6734b28
--- /dev/null
+++ b/test/rdoc/rdoc_markup_to_html_crossref_reference.rb
@@ -0,0 +1,31 @@
+#
+# This file is parsed by test_rdoc_markup_to_html_crossref.rb
+# during its tests.
+#
+class Ref_Class1
+end
+
+class Ref_Class2
+ class Ref_Class3
+ def method
+ end
+
+ class Helper1
+ def method?
+ end
+ end
+ end
+end
+
+class Ref_Class3
+ class Helper1
+ end
+
+ class Helper2
+ end
+end
+
+class Ref_Class4
+ class Ref_Class4
+ end
+end
diff --git a/test/rdoc/test_attribute_manager.rb b/test/rdoc/test_attribute_manager.rb
new file mode 100644
index 0000000000..ee45c0596f
--- /dev/null
+++ b/test/rdoc/test_attribute_manager.rb
@@ -0,0 +1,76 @@
+require 'rubygems'
+require 'minitest/unit'
+require 'rdoc/markup/attribute_manager'
+
+class TestAttributeManager < MiniTest::Unit::TestCase
+
+ def setup
+ @am = RDoc::Markup::AttributeManager.new
+ @klass = RDoc::Markup::AttributeManager
+ end
+
+ def teardown
+ silently do
+ @klass.const_set(:MATCHING_WORD_PAIRS, {})
+ @klass.const_set(:WORD_PAIR_MAP, {})
+ @klass.const_set(:HTML_TAGS, {})
+ end
+ end
+
+ def test_initial_word_pairs
+ word_pairs = @klass::MATCHING_WORD_PAIRS
+ assert word_pairs.is_a?(Hash)
+ assert_equal(3, word_pairs.size)
+ end
+
+ def test_initial_html
+ html_tags = @klass::HTML_TAGS
+ assert html_tags.is_a?(Hash)
+ assert_equal(5, html_tags.size)
+ end
+
+ def test_add_matching_word_pair
+ @am.add_word_pair("x","x", :TEST)
+ word_pairs = @klass::MATCHING_WORD_PAIRS
+ assert_equal(4,word_pairs.size)
+ assert(word_pairs.has_key?("x"))
+ end
+
+ def test_add_invalid_word_pair
+ assert_raises ArgumentError do
+ @am.add_word_pair("<", "<", :TEST)
+ end
+ end
+
+ def test_add_word_pair_map
+ @am.add_word_pair("x", "y", :TEST)
+ word_pair_map = @klass::WORD_PAIR_MAP
+ assert_equal(1,word_pair_map.size)
+ assert_equal(word_pair_map. keys.first.source, "(x)(\\S+)(y)")
+ end
+
+ def test_add_html_tag
+ @am.add_html("Test", :TEST)
+ tags = @klass::HTML_TAGS
+ assert_equal(6, tags.size)
+ assert(tags.has_key?("test"))
+ end
+
+ def test_add_special
+ @am.add_special("WikiWord", :WIKIWORD)
+ specials = @klass::SPECIAL
+ assert_equal(1,specials.size)
+ assert(specials.has_key?("WikiWord"))
+ end
+
+ def silently(&block)
+ warn_level = $VERBOSE
+ $VERBOSE = nil
+ result = block.call
+ $VERBOSE = warn_level
+ result
+ end
+
+end
+
+MiniTest::Unit.autorun
diff --git a/test/rdoc/test_rdoc_info_formatting.rb b/test/rdoc/test_rdoc_info_formatting.rb
index 6c024f7454..87147fb7cb 100644
--- a/test/rdoc/test_rdoc_info_formatting.rb
+++ b/test/rdoc/test_rdoc_info_formatting.rb
@@ -1,11 +1,12 @@
require 'fileutils'
require 'tmpdir'
-require 'test/unit'
+require 'rubygems'
+require 'minitest/unit'
require 'rdoc/generator/texinfo'
# From chapter 18 of the Pickaxe 3rd ed. and the TexInfo manual.
-class TestRdocInfoFormatting < Test::Unit::TestCase
+class TestRDocInfoFormatting < MiniTest::Unit::TestCase
def setup
@output_dir = File.join Dir.tmpdir, "test_rdoc_info_formatting_#{$$}"
@output_file = File.join @output_dir, 'rdoc.texinfo'
@@ -19,12 +20,13 @@ class TestRdocInfoFormatting < Test::Unit::TestCase
end
def teardown
- FileUtils.rm_rf @output_dir
+ # FileUtils.rm_rf @output_dir
end
# Make sure tags like *this* do not make HTML
def test_descriptions_are_not_html
- assert_no_match Regexp.new("\<b\>this\<\/b\>"), @text, "We had some HTML; icky!"
+ refute_match Regexp.new("\<b\>this\<\/b\>"), @text,
+ "We had some HTML; icky!"
end
# Ensure we get a reasonable amount
@@ -73,10 +75,10 @@ class TestRdocInfoFormatting < Test::Unit::TestCase
# === Everything deeper becomes a regular @heading
# ====== Regardless of its nesting level
def test_headings
- assert_match(/@majorheading\{Huge heading should be a @@majorheading\}/)
- assert_match(/@chapheading\{There is also @@chapheading\}/)
- assert_match(/@heading\{Everything deeper becomes a regular @@heading\}/)
- assert_match(/@heading\{Regardless of its nesting level\}/)
+ assert_match(/@majorheading Huge heading should be a @@majorheading/)
+ assert_match(/@chapheading There is also @@chapheading/)
+ assert_match(/@heading Everything deeper becomes a regular @@heading/)
+ assert_match(/@heading Regardless of its nesting level/)
end
# * list item
@@ -173,3 +175,5 @@ Second outer item.
assert string[regex] #, message
end
end
+
+MiniTest::Unit.autorun
diff --git a/test/rdoc/test_rdoc_info_sections.rb b/test/rdoc/test_rdoc_info_sections.rb
index cceba186c1..9571cd611e 100644
--- a/test/rdoc/test_rdoc_info_sections.rb
+++ b/test/rdoc/test_rdoc_info_sections.rb
@@ -1,15 +1,16 @@
require 'fileutils'
require 'tempfile'
-require 'test/unit'
+require 'rubygems'
+require 'minitest/unit'
require 'tmpdir'
require 'rdoc/generator/texinfo'
# give us access to check this stuff before it's rendered
-class RDoc::Generator::Texinfo; attr_reader :files, :classes; end
+class RDoc::Generator::TEXINFO; attr_reader :files, :classes; end
class RDoc::RDoc; attr_reader :options; attr_reader :gen; end
-class TestRdocInfoSections < Test::Unit::TestCase
+class TestRDocInfoSections < MiniTest::Unit::TestCase
def setup
@output_dir = File.join Dir.tmpdir, "test_rdoc_info_sections_#{$$}"
@@ -134,3 +135,5 @@ end
DOC
end
+
+MiniTest::Unit.autorun
diff --git a/test/rdoc/test_rdoc_markup.rb b/test/rdoc/test_rdoc_markup.rb
index d88743858a..7004fe50ec 100644
--- a/test/rdoc/test_rdoc_markup.rb
+++ b/test/rdoc/test_rdoc_markup.rb
@@ -1,8 +1,9 @@
-require 'test/unit'
+require 'rubygems'
+require 'minitest/unit'
require 'rdoc/markup'
require 'rdoc/markup/to_test'
-class TestRDocMarkup < Test::Unit::TestCase
+class TestRDocMarkup < MiniTest::Unit::TestCase
def basic_conv(str)
sm = RDoc::Markup.new
@@ -611,3 +612,4 @@ class TestRDocMarkup < Test::Unit::TestCase
end
+MiniTest::Unit.autorun
diff --git a/test/rdoc/test_rdoc_markup_attribute_manager.rb b/test/rdoc/test_rdoc_markup_attribute_manager.rb
index 8ba9d7440a..520470a8cc 100644
--- a/test/rdoc/test_rdoc_markup_attribute_manager.rb
+++ b/test/rdoc/test_rdoc_markup_attribute_manager.rb
@@ -1,9 +1,14 @@
-require "test/unit"
+require "rubygems"
+require "minitest/unit"
require "rdoc/markup/inline"
+require "rdoc/markup/to_html_crossref"
-class TestRDocMarkupAttributeManager < Test::Unit::TestCase
+class TestRDocMarkupAttributeManager < MiniTest::Unit::TestCase
def setup
+ @orig_special = RDoc::Markup::AttributeManager::SPECIAL
+ RDoc::Markup::AttributeManager::SPECIAL.replace Hash.new
+
@am = RDoc::Markup::AttributeManager.new
@bold_on = @am.changed_attribute_by_name([], [:BOLD])
@@ -27,6 +32,10 @@ class TestRDocMarkupAttributeManager < Test::Unit::TestCase
@wombat_off = @am.changed_attribute_by_name([:WOMBAT], [])
end
+ def teardown
+ RDoc::Markup::AttributeManager::SPECIAL.replace @orig_special
+ end
+
def crossref(text)
crossref_bitmap = RDoc::Markup::Attribute.bitmap_for(:_SPECIAL_) |
RDoc::Markup::Attribute.bitmap_for(:CROSSREF)
@@ -52,7 +61,7 @@ class TestRDocMarkupAttributeManager < Test::Unit::TestCase
end
def test_add_word_pair_angle
- e = assert_raise ArgumentError do
+ e = assert_raises ArgumentError do
@am.add_word_pair '<', '>', 'angles'
end
@@ -201,24 +210,25 @@ class TestRDocMarkupAttributeManager < Test::Unit::TestCase
end
def test_special
- # class names, variable names, file names, or instance variables
- @am.add_special(/(
- \b([A-Z]\w+(::\w+)*)
- | \#\w+[!?=]?
- | \b\w+([_\/\.]+\w+)+[!?=]?
- )/x,
- :CROSSREF)
+ @am.add_special(RDoc::Markup::ToHtmlCrossref::CROSSREF_REGEXP, :CROSSREF)
- assert_equal(["cat"], @am.flow("cat"))
+ #
+ # The apostrophes in "cats'" and "dogs'" suppress the flagging of these
+ # words as potential cross-references, which is necessary for the unit
+ # tests. Unfortunately, the markup engine right now does not actually
+ # check whether a cross-reference is valid before flagging it.
+ #
+ assert_equal(["cats'"], @am.flow("cats'"))
- assert_equal(["cat ", crossref("#fred"), " dog"].flatten,
- @am.flow("cat #fred dog"))
+ assert_equal(["cats' ", crossref("#fred"), " dogs'"].flatten,
+ @am.flow("cats' #fred dogs'"))
- assert_equal([crossref("#fred"), " dog"].flatten,
- @am.flow("#fred dog"))
+ assert_equal([crossref("#fred"), " dogs'"].flatten,
+ @am.flow("#fred dogs'"))
- assert_equal(["cat ", crossref("#fred")].flatten, @am.flow("cat #fred"))
+ assert_equal(["cats' ", crossref("#fred")].flatten, @am.flow("cats' #fred"))
end
end
+MiniTest::Unit.autorun
diff --git a/test/rdoc/test_rdoc_markup_to_html.rb b/test/rdoc/test_rdoc_markup_to_html.rb
index 463228cc4a..b611b768a3 100644
--- a/test/rdoc/test_rdoc_markup_to_html.rb
+++ b/test/rdoc/test_rdoc_markup_to_html.rb
@@ -1,8 +1,9 @@
-require 'test/unit'
+require 'rubygems'
+require 'minitest/unit'
require 'rdoc/markup'
require 'rdoc/markup/to_html'
-class TestRdocMarkupToHtml < Test::Unit::TestCase
+class TestRDocMarkupToHtml < MiniTest::Unit::TestCase
def setup
@am = RDoc::Markup::AttributeManager.new
@@ -10,11 +11,23 @@ class TestRdocMarkupToHtml < Test::Unit::TestCase
end
def test_tt_formatting
- assert_equal "<p>\n<tt>--</tt> &#8212; <tt>(c)</tt> &#169;\n</p>\n",
- util_format("<tt>--</tt> -- <tt>(c)</tt> (c)")
+ assert_equal "<p>\n<tt>--</tt> &#8212; <tt>cats'</tt> cats&#8217;\n</p>\n",
+ util_format("<tt>--</tt> -- <tt>cats'</tt> cats'")
assert_equal "<p>\n<b>&#8212;</b>\n</p>\n", util_format("<b>--</b>")
end
+ def test_convert_string_fancy
+ #
+ # The HTML typesetting is broken in a number of ways, but I have fixed
+ # the most glaring issues for single and double quotes. Note that
+ # "strange" symbols (periods or dashes) need to be at the end of the
+ # test case strings in order to suppress cross-references.
+ #
+ assert_equal "<p>\n&#8220;cats&#8221;.\n</p>\n", util_format("\"cats\".")
+ assert_equal "<p>\n&#8216;cats&#8217;.\n</p>\n", util_format("\'cats\'.")
+ assert_equal "<p>\ncat&#8217;s-\n</p>\n", util_format("cat\'s-")
+ end
+
def util_fragment(text)
RDoc::Markup::Fragment.new 0, nil, nil, text
end
@@ -28,3 +41,5 @@ class TestRdocMarkupToHtml < Test::Unit::TestCase
end
end
+
+MiniTest::Unit.autorun
diff --git a/test/rdoc/test_rdoc_markup_to_html_crossref.rb b/test/rdoc/test_rdoc_markup_to_html_crossref.rb
index ab4c3e7e9c..baacda8285 100644
--- a/test/rdoc/test_rdoc_markup_to_html_crossref.rb
+++ b/test/rdoc/test_rdoc_markup_to_html_crossref.rb
@@ -1,18 +1,294 @@
-require 'test/unit'
+require 'rubygems'
+require 'minitest/unit'
require 'rdoc/generator'
+require 'rdoc/stats'
+require 'rdoc/code_objects'
require 'rdoc/markup/to_html_crossref'
+require 'rdoc/parser/ruby'
-class TestRdocMarkupToHtmlCrossref < Test::Unit::TestCase
+require 'pathname'
- def setup
- @xref = RDoc::Markup::ToHtmlCrossref.new 'from_path', nil, nil
+class TestRDocMarkupToHtmlCrossref < MiniTest::Unit::TestCase
+
+ #
+ # This method parses a source file and returns a Hash mapping
+ # class names (Strings) to RDoc::Generator::Class instances
+ # (classes), which can be used to create RDoc::Markup::ToHtmlCrossref
+ # instances. The unit tests only test against classes starting with
+ # Ref_, so this method only includes such classes in the Hash.
+ #
+ def create_class_hash
+ # The relative gem would help here...
+ # @source_file_name must be cleaned because rdoc does not deal
+ # well with paths containing "." or "..".
+ curr_file = Pathname.new(__FILE__)
+ @source_file_name = curr_file.dirname + "rdoc_markup_to_html_crossref_reference.rb"
+ @source_file_name = @source_file_name.cleanpath.to_s
+
+ RDoc::TopLevel.reset
+
+ # Reset RDoc::Generator::Method so that the method sequence number starts
+ # at 1, making the method sequence numbers for the methods in the Ref_
+ # predicable.
+ RDoc::Generator::Method.reset
+ top_level = RDoc::TopLevel.new @source_file_name
+
+ options = RDoc::Options.new
+ options.quiet = true
+
+ # If this is false, then RDoc::Generator::Method will attempt to create
+ # an HTML file containing the method source code when being instantiated,
+ # which does not work in the context of this unit test.
+ #
+ # RDoc::Generator::Method needs to be refactored so that this does *not*
+ # happen as part of instantiation.
+ options.inline_source = true
+
+ stats = RDoc::Stats.new 0
+
+ parser = RDoc::Parser::Ruby.new(top_level,
+ @source_file_name,
+ IO.read(@source_file_name),
+ options,
+ stats)
+ top_levels = []
+ top_levels.push(parser.scan())
+
+ files, classes = RDoc::Generator::Context.build_indices(top_levels, options)
+
+ class_hash = {}
+ classes.each do |klass|
+ if(klass.name.include?("Ref_"))
+ class_hash[klass.name] = klass
+ end
+ end
+
+ return class_hash
end
- def test_handle_special_CROSSREF_no_underscore
- out = @xref.convert 'foo'
+ #
+ # This method uses xref to cross-reference String reference and
+ # asserts that xref.convert(reference) is equal
+ # to String expected_result.
+ #
+ def verify_convert(xref, reference, expected_result)
+ # Everything converted in the tests will be within paragraph markup, so
+ # add paragraph markup to the expected result.
+ actual_expected_result = "<p>\n#{expected_result}\n</p>\n"
+
+ result = xref.convert(reference)
+
+ # RDoc::Markup::ToHtml word-wraps lines. It is tricky to predict where
+ # a line will be wrapped except that it will happen on a space, so replace
+ # all newlines with spaces in order to not have to worry about this.
+ actual_expected_result.gsub!(/\n/, " ")
+ result.gsub!(/\n/, " ")
+
+ assert_equal actual_expected_result, result
+ end
+
+ #
+ # This method verifies that xref generates no cross-reference link for
+ # String reference.
+ #
+ def verify_no_crossref(xref, reference)
+ if(reference[0, 1] == "\\") # Remove the markup suppression character
+ expected_result = reference[1, reference.length() - 1]
+ else
+ expected_result = reference
+ end
+
+ verify_convert(xref, reference, expected_result)
+ end
+
+ #
+ # This method verifies that xref generates a cross-reference link to
+ # class_name (String) for String reference.
+ #
+ def verify_class_crossref(xref, reference, class_name)
+ class_file_name = class_name.gsub(/::/, "/")
+
+ result = "<a href=\"../classes/#{class_file_name}.html\">#{reference}</a>"
+
+ verify_convert xref, reference, result
+ end
+
+ #
+ # This method verifies that xref generates a cross-reference link to method
+ # method_seq (String, e.g, "M000001") in class_name (String) for
+ # String reference.
+ #
+ def verify_method_crossref(xref, reference, class_name, method_seq)
+ class_file_name = class_name.gsub(/::/, "/")
+
+ result = "<a href=\"../classes/#{class_file_name}.html##{method_seq}\">#{reference}</a>"
+
+ verify_convert xref, reference, result
+ end
+
+ #
+ # This method verifies that xref generates a cross-reference link to
+ # file_name (String) for String reference.
+ #
+ def verify_file_crossref(xref, reference, file_name)
+ generated_document_path = Pathname.new("../files/#{file_name.gsub(/\./, '_')}.html").cleanpath.to_s
+ result = "<a href=\"#{generated_document_path}\">#{reference}</a>"
+
+ verify_convert xref, reference, result
+ end
+
+ #
+ # This method verifies that several invariant cross-references are
+ # (or are not) generated.
+ #
+ def verify_invariant_crossrefs(xref)
+ # bogus does not exist and so no cross-reference should be generated.
+ verify_no_crossref xref, "bogus"
+ verify_no_crossref xref, "\\bogus"
+
+ # Ref_Class1 is in the top-level namespace, and so a cross-reference always
+ # should be generated, unless markup is suppressed.
+ verify_class_crossref xref, "Ref_Class1", "Ref_Class1"
+ verify_no_crossref xref, "\\Ref_Class1"
+
+ # Ref_Class2 is in the top-level namespace, and so a cross-reference always
+ # should be generated for it and for its nested classes.
+ verify_class_crossref xref, "Ref_Class2", "Ref_Class2"
+ verify_class_crossref xref, "Ref_Class2::Ref_Class3", "Ref_Class2::Ref_Class3"
+ verify_method_crossref xref, "Ref_Class2::Ref_Class3#method", "Ref_Class2::Ref_Class3", "M000001"
+ verify_method_crossref xref, "Ref_Class2::Ref_Class3#method()", "Ref_Class2::Ref_Class3", "M000001"
+ verify_method_crossref xref, "Ref_Class2::Ref_Class3.method()", "Ref_Class2::Ref_Class3", "M000001"
+ verify_method_crossref xref, "Ref_Class2::Ref_Class3.method(*)", "Ref_Class2::Ref_Class3", "M000001"
+ verify_class_crossref xref, "Ref_Class2::Ref_Class3::Helper1", "Ref_Class2::Ref_Class3::Helper1"
+ verify_method_crossref xref, "Ref_Class2::Ref_Class3::Helper1#method?", "Ref_Class2::Ref_Class3::Helper1", "M000002"
+
+ # The hyphen character is not a valid class/method separator character, so
+ # rdoc just generates a class cross-reference (perhaps it should not
+ # generate anything?).
+ result = "<a href=\"../classes/Ref_Class2/Ref_Class3.html\">Ref_Class2::Ref_Class3</a>;method(*)"
+ verify_convert xref, "Ref_Class2::Ref_Class3;method(*)", result
+
+ # There is one Ref_Class3 nested in Ref_Class2 and one defined in the
+ # top-level namespace; regardless, ::Ref_Class3 (Ref_Class3 relative
+ # to the top-level namespace) always should generate a link to the
+ # top-level Ref_Class3 (unless of course cross-references are suppressed).
+ verify_class_crossref xref, "::Ref_Class3", "Ref_Class3"
+ verify_no_crossref xref, "\\::Ref_Class3"
+ verify_class_crossref xref, "::Ref_Class3::Helper1", "Ref_Class3::Helper1"
+ verify_class_crossref xref, "::Ref_Class3::Helper2", "Ref_Class3::Helper2"
+
+ #
+ # Ref_Class3::Helper1 does not have method method.
+ #
+ verify_no_crossref xref, "::Ref_Class3::Helper1#method"
+ verify_no_crossref xref, "\\::Ref_Class3::Helper1#method"
+
+ # References to Ref_Class2 relative to the top-level namespace always should
+ # generate links to Ref_Class2.
+ verify_method_crossref xref, "::Ref_Class2::Ref_Class3#method", "Ref_Class2::Ref_Class3", "M000001"
+ verify_method_crossref xref, "::Ref_Class2::Ref_Class3#method()", "Ref_Class2::Ref_Class3", "M000001"
+ verify_method_crossref xref, "::Ref_Class2::Ref_Class3#method(*)", "Ref_Class2::Ref_Class3", "M000001"
+ verify_class_crossref xref, "::Ref_Class2::Ref_Class3::Helper1", "Ref_Class2::Ref_Class3::Helper1"
+ verify_no_crossref xref, "\\::Ref_Class2::Ref_Class3#method(*)"
+
+ # Suppressing cross-references always should suppress the generation of
+ # links.
+ verify_no_crossref xref, "\\#method"
+ verify_no_crossref xref, "\\#method()"
+ verify_no_crossref xref, "\\#method(*)"
- assert_equal "<p>\nfoo\n</p>\n", out
+ # Links never should be generated for words solely consisting of lowercase
+ # letters, because too many links would get generated by mistake (i.e., the
+ # word "new" always would be a link).
+ verify_no_crossref xref, "method"
+
+ # A link always should be generated for a file name.
+ verify_file_crossref xref, @source_file_name, @source_file_name
+
+ # References should be generated correctly for a class scoped within
+ # a class of the same name.
+ verify_class_crossref xref, "Ref_Class4::Ref_Class4", "Ref_Class4::Ref_Class4"
end
+ def test_handle_special_CROSSREF_no_underscore
+ class_hash = create_class_hash
+
+ # Note that we instruct the ToHtmlCrossref instance to show hashes so that
+ # an exception won't have to be made for words starting with a '#'.
+ # I'm also not convinced that the current behavior of the rdoc code
+ # is correct since, without this, it strips the leading # from all
+ # words, whether or not they end up as cross-references.
+ #
+ # After the behavior has been sorted out, this can be changed.
+ #
+ # Create a variety of RDoc::Markup::ToHtmlCrossref instances, for
+ # different classes, and test the cross-references generated by
+ # each.
+ klass = class_hash["Ref_Class1"]
+ xref = RDoc::Markup::ToHtmlCrossref.new 'from_path', klass, true
+ verify_invariant_crossrefs xref
+ verify_class_crossref xref, "Ref_Class3", "Ref_Class3"
+ verify_no_crossref xref, "Ref_Class3#method"
+ verify_no_crossref xref, "#method"
+ verify_class_crossref xref, "Ref_Class3::Helper1", "Ref_Class3::Helper1"
+ verify_class_crossref xref, "Ref_Class3::Helper2", "Ref_Class3::Helper2"
+ verify_no_crossref xref, "Helper1"
+ verify_class_crossref xref, "Ref_Class4", "Ref_Class4"
+
+ klass = class_hash["Ref_Class2"]
+ xref = RDoc::Markup::ToHtmlCrossref.new 'from_path', klass, true
+ verify_invariant_crossrefs xref
+ verify_class_crossref xref, "Ref_Class3", "Ref_Class2::Ref_Class3"
+ verify_method_crossref xref, "Ref_Class3#method", "Ref_Class2::Ref_Class3", "M000001"
+ verify_no_crossref xref, "#method"
+ verify_class_crossref xref, "Ref_Class3::Helper1", "Ref_Class2::Ref_Class3::Helper1"
+ verify_class_crossref xref, "Ref_Class4", "Ref_Class4"
+
+ # This one possibly is an rdoc bug...
+ # Ref_Class2 has a nested Ref_Class3, but
+ # Ref_Class2::Ref_Class3::Helper2 does not exist.
+ # On the other hand, there is a Ref_Class3::Helper2
+ # in the top-level namespace... Should rdoc stop
+ # looking if it finds one class match?
+ verify_no_crossref xref, "Ref_Class3::Helper2"
+ verify_no_crossref xref, "Helper1"
+
+ klass = class_hash["Ref_Class2::Ref_Class3"]
+ xref = RDoc::Markup::ToHtmlCrossref.new 'from_path', klass, true
+ verify_invariant_crossrefs xref
+ verify_class_crossref xref, "Ref_Class3", "Ref_Class2::Ref_Class3"
+ verify_method_crossref xref, "Ref_Class3#method", "Ref_Class2::Ref_Class3", "M000001"
+ verify_method_crossref xref, "#method", "Ref_Class2::Ref_Class3", "M000001"
+ verify_class_crossref xref, "Ref_Class3::Helper1", "Ref_Class2::Ref_Class3::Helper1"
+ verify_no_crossref xref, "Ref_Class3::Helper2"
+ verify_class_crossref xref, "Helper1", "Ref_Class2::Ref_Class3::Helper1"
+ verify_class_crossref xref, "Ref_Class4", "Ref_Class4"
+
+ klass = class_hash["Ref_Class3"]
+ xref = RDoc::Markup::ToHtmlCrossref.new 'from_path', klass, true
+ verify_invariant_crossrefs xref
+ verify_class_crossref xref, "Ref_Class3", "Ref_Class3"
+ verify_no_crossref xref, "Ref_Class3#method"
+ verify_no_crossref xref, "#method"
+ verify_class_crossref xref, "Ref_Class3::Helper1", "Ref_Class3::Helper1"
+ verify_class_crossref xref, "Ref_Class3::Helper2", "Ref_Class3::Helper2"
+ verify_class_crossref xref, "Helper1", "Ref_Class3::Helper1"
+ verify_class_crossref xref, "Ref_Class4", "Ref_Class4"
+
+ klass = class_hash["Ref_Class4"]
+ xref = RDoc::Markup::ToHtmlCrossref.new 'from_path', klass, true
+ verify_invariant_crossrefs xref
+ # A Ref_Class4 reference inside a Ref_Class4 class containing a
+ # Ref_Class4 class should resolve to the contained class.
+ verify_class_crossref xref, "Ref_Class4", "Ref_Class4::Ref_Class4"
+
+ klass = class_hash["Ref_Class4::Ref_Class4"]
+ xref = RDoc::Markup::ToHtmlCrossref.new 'from_path', klass, true
+ verify_invariant_crossrefs xref
+ # A Ref_Class4 reference inside a Ref_Class4 class contained within
+ # a Ref_Class4 class should resolve to the inner Ref_Class4 class.
+ verify_class_crossref xref, "Ref_Class4", "Ref_Class4::Ref_Class4"
+ end
end
+MiniTest::Unit.autorun
diff --git a/test/rdoc/test_rdoc_parser.rb b/test/rdoc/test_rdoc_parser.rb
new file mode 100644
index 0000000000..d6420d20f1
--- /dev/null
+++ b/test/rdoc/test_rdoc_parser.rb
@@ -0,0 +1,23 @@
+require 'rubygems'
+require 'minitest/unit'
+require 'rdoc/parser'
+require 'rdoc/parser/ruby'
+
+class TestRDocParser < MiniTest::Unit::TestCase
+ def test_can_parse
+ assert_equal(RDoc::Parser.can_parse(__FILE__), RDoc::Parser::Ruby)
+
+ readme_file_name = File.join(File.dirname(__FILE__), "..", "README.txt")
+
+ unless File.exist? readme_file_name then # HACK for tests in trunk :/
+ readme_file_name = File.join File.dirname(__FILE__), '..', '..', 'README'
+ end
+
+ assert_equal(RDoc::Parser.can_parse(readme_file_name), RDoc::Parser::Simple)
+
+ binary_file_name = File.join(File.dirname(__FILE__), "binary.dat")
+ assert_equal(RDoc::Parser.can_parse(binary_file_name), nil)
+ end
+end
+
+MiniTest::Unit.autorun
diff --git a/test/rdoc/test_rdoc_parser_c.rb b/test/rdoc/test_rdoc_parser_c.rb
index fd750070d8..ebf96594c8 100644
--- a/test/rdoc/test_rdoc_parser_c.rb
+++ b/test/rdoc/test_rdoc_parser_c.rb
@@ -1,6 +1,7 @@
require 'stringio'
require 'tempfile'
-require 'test/unit'
+require 'rubygems'
+require 'minitest/unit'
require 'rdoc/options'
require 'rdoc/parser/c'
@@ -10,7 +11,7 @@ class RDoc::Parser::C
public :do_classes, :do_constants
end
-class TestRdocParserC < Test::Unit::TestCase
+class TestRDocParserC < MiniTest::Unit::TestCase
def setup
@tempfile = Tempfile.new self.class.name
@@ -244,9 +245,36 @@ Init_Foo(void) {
assert_equal " \n a comment for class Foo on Init\n \n", klass.comment
end
+ def test_define_method
+ content = <<-EOF
+/*Method Comment! */
+static VALUE
+rb_io_s_read(argc, argv, io)
+ int argc;
+ VALUE *argv;
+ VALUE io;
+{
+}
+
+void
+Init_IO(void) {
+ /*
+ * a comment for class Foo on rb_define_class
+ */
+ VALUE rb_cIO = rb_define_class("IO", rb_cObject);
+ rb_define_singleton_method(rb_cIO, "read", rb_io_s_read, -1);
+}
+ EOF
+
+ klass = util_get_class content, 'rb_cIO'
+ read_method = klass.method_list.first
+ assert_equal "read", read_method.name
+ assert_equal " Method Comment! \n", read_method.comment
+ end
+
def util_get_class(content, name)
parser = util_parser content
- parser.do_classes
+ parser.scan
parser.classes[name]
end
@@ -256,3 +284,4 @@ Init_Foo(void) {
end
+MiniTest::Unit.autorun
diff --git a/test/rdoc/test_rdoc_parser_perl.rb b/test/rdoc/test_rdoc_parser_perl.rb
new file mode 100644
index 0000000000..165cadaa5d
--- /dev/null
+++ b/test/rdoc/test_rdoc_parser_perl.rb
@@ -0,0 +1,74 @@
+require 'stringio'
+require 'tempfile'
+require 'rubygems'
+require 'minitest/unit'
+require 'rdoc/options'
+require 'rdoc/parser/perl'
+
+class TestRdocParserPerlPOD < MiniTest::Unit::TestCase
+
+ def setup
+ @tempfile = Tempfile.new self.class.name
+ filename = @tempfile.path
+
+ @top_level = RDoc::TopLevel.new filename
+ @fn = filename
+ @options = RDoc::Options.new
+ @stats = RDoc::Stats.new 0
+ end
+
+ def teardown
+ @tempfile.close
+ end
+
+ def test_uncommented_perl
+ content = <<-EOF
+while (<>) {
+ tr/a-z/A-Z;
+ print
+}
+ EOF
+
+ comment = util_get_comment content
+ assert_equal "", comment
+ end
+
+ def test_perl_without_pod
+ content = <<-EOF
+#!/usr/local/bin/perl
+#
+#This is a pointless perl program because it does -p.
+#
+while(<>) {print;}:
+ EOF
+
+ comment = util_get_comment content
+ assert_equal "", comment
+ end
+
+ def test_simple_pod_no_structure
+ content = <<-EOF
+=begin pod
+
+This just contains plain old documentation
+
+=end
+ EOF
+ comment = util_get_comment content
+ assert_equal "\nThis just contains plain old documentation\n\n", comment
+ end
+
+ # Get the comment of the @top_level when it has processed the input.
+ def util_get_comment(content)
+ parser = util_parser content
+ parser.scan.comment
+ end
+
+ # create a new parser with the supplied content.
+ def util_parser(content)
+ RDoc::Parser::PerlPOD.new @top_level, @fn, content, @options, @stats
+ end
+
+end
+
+MiniTest::Unit.autorun
diff --git a/test/rdoc/test_rdoc_parser_ruby.rb b/test/rdoc/test_rdoc_parser_ruby.rb
index 77d8bd24fc..3845fb2907 100644
--- a/test/rdoc/test_rdoc_parser_ruby.rb
+++ b/test/rdoc/test_rdoc_parser_ruby.rb
@@ -1,17 +1,22 @@
require 'stringio'
require 'tempfile'
-require 'test/unit'
+require 'rubygems'
+require 'minitest/unit'
require 'rdoc/options'
require 'rdoc/parser/ruby'
require 'rdoc/stats'
-class TestRdocParserRuby < Test::Unit::TestCase
+class TestRDocParserRuby < MiniTest::Unit::TestCase
def setup
@tempfile = Tempfile.new self.class.name
@filename = @tempfile.path
+ # Some tests need two paths.
+ @tempfile2 = Tempfile.new self.class.name
+ @filename2 = @tempfile2.path
+
util_toplevel
@options = RDoc::Options.new
@options.quiet = true
@@ -20,6 +25,7 @@ class TestRdocParserRuby < Test::Unit::TestCase
def teardown
@tempfile.close
+ @tempfile2.close
end
def test_look_for_directives_in_commented
@@ -158,6 +164,105 @@ class TestRdocParserRuby < Test::Unit::TestCase
assert_equal 'Super', bar.superclass
end
+ def test_parse_module
+ comment = "##\n# my module\n"
+
+ util_parser 'module Foo; end'
+
+ tk = @parser.get_tk
+
+ @parser.parse_module @top_level, RDoc::Parser::Ruby::NORMAL, tk, comment
+
+ foo = @top_level.modules.first
+ assert_equal 'Foo', foo.full_name
+ assert_equal comment, foo.comment
+ end
+
+ def test_parse_class_mistaken_for_module
+#
+# The code below is not strictly legal Ruby (Foo must have been defined
+# before Foo::Bar is encountered), but RDoc might encounter Foo::Bar before
+# Foo if they live in different files.
+#
+ code = <<-EOF
+class Foo::Bar
+end
+
+module Foo::Baz
+end
+
+class Foo
+end
+EOF
+
+ util_parser code
+
+ @parser.scan()
+
+ assert(@top_level.modules.empty?)
+ foo = @top_level.classes.first
+ assert_equal 'Foo', foo.full_name
+
+ bar = foo.classes.first
+ assert_equal 'Foo::Bar', bar.full_name
+
+ baz = foo.modules.first
+ assert_equal 'Foo::Baz', baz.full_name
+ end
+
+ def test_parse_class_definition_encountered_after_class_reference
+#
+# The code below is not strictly legal Ruby (Foo must have been defined
+# before Foo.bar is encountered), but RDoc might encounter Foo.bar before
+# Foo if they live in different files.
+#
+ code = <<-EOF
+def Foo.bar
+end
+
+class Foo < IO
+end
+EOF
+
+ util_parser code
+
+ @parser.scan()
+
+ assert(@top_level.modules.empty?)
+
+ foo = @top_level.classes.first
+ assert_equal 'Foo', foo.full_name
+ assert_equal 'IO', foo.superclass
+
+ bar = foo.method_list.first
+ assert_equal 'bar', bar.name
+ end
+
+ def test_parse_module_relative_to_top_level_namespace
+ comment = <<-EOF
+#
+# Weirdly named module
+#
+EOF
+
+ code = comment + <<-EOF
+module ::Foo
+ class Helper
+ end
+end
+EOF
+
+ util_parser code
+ @parser.scan()
+
+ foo = @top_level.modules.first
+ assert_equal 'Foo', foo.full_name
+ assert_equal comment, foo.comment
+
+ helper = foo.classes.first
+ assert_equal 'Foo::Helper', helper.full_name
+ end
+
def test_parse_comment
content = <<-EOF
class Foo
@@ -416,9 +521,107 @@ end
@parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL, nil, ''
+ foo = @top_level.classes.first.method_list[0]
+ assert_equal 'foo', foo.name
+
foo2 = @top_level.classes.first.method_list.last
assert_equal 'foo2', foo2.name
assert_equal 'foo', foo2.is_alias_for.name
+ assert @top_level.classes.first.aliases.empty?
+ end
+
+ def test_parse_statements_identifier_alias_method_before_original_method
+ # This is not strictly legal Ruby code, but it simulates finding an alias
+ # for a method before finding the original method, which might happen
+ # to rdoc if the alias is in a different file than the original method
+ # and rdoc processes the alias' file first.
+ content = <<-EOF
+class Foo
+ alias_method :foo2, :foo
+
+ alias_method :foo3, :foo
+
+ def foo()
+ end
+
+ alias_method :foo4, :foo
+
+ alias_method :foo5, :unknown
+end
+EOF
+
+ util_parser content
+
+ @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL, nil, ''
+
+ foo = @top_level.classes.first.method_list[0]
+ assert_equal 'foo', foo.name
+
+ foo2 = @top_level.classes.first.method_list[1]
+ assert_equal 'foo2', foo2.name
+ assert_equal 'foo', foo2.is_alias_for.name
+
+ foo3 = @top_level.classes.first.method_list[2]
+ assert_equal 'foo3', foo3.name
+ assert_equal 'foo', foo3.is_alias_for.name
+
+ foo4 = @top_level.classes.first.method_list.last
+ assert_equal 'foo4', foo4.name
+ assert_equal 'foo', foo4.is_alias_for.name
+
+ assert_equal 'unknown', @top_level.classes.first.aliases[0].old_name
+ end
+
+ def test_parse_statements_identifier_constant
+ content = <<-EOF
+class Foo
+ FIRST_CONSTANT = 5
+
+ SECOND_CONSTANT = [
+ 1,
+ 2,
+ 3
+ ]
+
+ THIRD_CONSTANT = {
+ :foo => 'bar',
+ :x => 'y'
+ }
+
+ FOURTH_CONSTANT = SECOND_CONSTANT.map do |element|
+ element + 1
+ element + 2
+ end
+
+ FIFTH_CONSTANT = SECOND_CONSTANT.map { |element| element + 1 }
+end
+EOF
+
+ util_parser content
+
+ @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL, nil, ''
+
+ constants = @top_level.classes.first.constants
+
+ constant = constants[0]
+ assert_equal 'FIRST_CONSTANT', constant.name
+ assert_equal '5', constant.value
+
+ constant = constants[1]
+ assert_equal 'SECOND_CONSTANT', constant.name
+ assert_equal '[ 1, 2, 3 ]', constant.value
+
+ constant = constants[2]
+ assert_equal 'THIRD_CONSTANT', constant.name
+ assert_equal "{ :foo => 'bar', :x => 'y' }", constant.value
+
+ constant = constants[3]
+ assert_equal 'FOURTH_CONSTANT', constant.name
+ assert_equal 'SECOND_CONSTANT.map do |element| element + 1 element + 2 end', constant.value
+
+ constant = constants.last
+ assert_equal 'FIFTH_CONSTANT', constant.name
+ assert_equal 'SECOND_CONSTANT.map { |element| element + 1 }', constant.value
end
def test_parse_statements_identifier_attr
@@ -530,10 +733,19 @@ end
@stats
end
+ def util_two_parsers(first_file_content, second_file_content)
+ util_parser first_file_content
+
+ @parser2 = RDoc::Parser::Ruby.new @top_level2, @filename,
+ second_file_content, @options, @stats
+ end
+
def util_toplevel
RDoc::TopLevel.reset
@top_level = RDoc::TopLevel.new @filename
+ @top_level2 = RDoc::TopLevel.new @filename2
end
end
+MiniTest::Unit.autorun
diff --git a/test/rdoc/test_rdoc_ri_attribute_formatter.rb b/test/rdoc/test_rdoc_ri_attribute_formatter.rb
index d61a6f5cbc..a86312618b 100644
--- a/test/rdoc/test_rdoc_ri_attribute_formatter.rb
+++ b/test/rdoc/test_rdoc_ri_attribute_formatter.rb
@@ -1,8 +1,9 @@
require 'stringio'
-require 'test/unit'
+require 'rubygems'
+require 'minitest/unit'
require 'rdoc/ri/formatter'
-class TestRDocRIAttributeFormatter < Test::Unit::TestCase
+class TestRDocRIAttributeFormatter < MiniTest::Unit::TestCase
def setup
@output = StringIO.new
@@ -40,3 +41,4 @@ class TestRDocRIAttributeFormatter < Test::Unit::TestCase
end
+MiniTest::Unit.autorun
diff --git a/test/rdoc/test_rdoc_ri_default_display.rb b/test/rdoc/test_rdoc_ri_default_display.rb
index 97fa6c94ae..1182b046c3 100644
--- a/test/rdoc/test_rdoc_ri_default_display.rb
+++ b/test/rdoc/test_rdoc_ri_default_display.rb
@@ -1,10 +1,11 @@
require 'stringio'
-require 'test/unit'
+require 'rubygems'
+require 'minitest/unit'
require 'rdoc/ri/formatter'
require 'rdoc/ri/display'
require 'rdoc/ri/driver'
-class TestRdocRiDefaultDisplay < Test::Unit::TestCase
+class TestRDocRiDefaultDisplay < MiniTest::Unit::TestCase
def setup
@output = StringIO.new
@@ -27,7 +28,6 @@ class TestRdocRiDefaultDisplay < Test::Unit::TestCase
end
def test_display_class_info
- ri_reader = nil
klass = h \
'attributes' => [
{ 'name' => 'attribute', 'rw' => 'RW',
@@ -43,9 +43,9 @@ class TestRdocRiDefaultDisplay < Test::Unit::TestCase
],
'comment' => [RDoc::Markup::Flow::P.new('SomeClass comment')],
'constants' => [
- { 'name' => 'CONSTANT', 'value' => '"value"',
+ { 'name' => 'CONSTANT', 'value' => '"value1"',
'comment' => [RDoc::Markup::Flow::P.new('CONSTANT value')] },
- { 'name' => 'CONSTANT_NOCOMMENT', 'value' => '"value"',
+ { 'name' => 'CONSTANT_NOCOMMENT', 'value' => '"value2"',
'comment' => nil },
],
'display_name' => 'Class',
@@ -53,13 +53,14 @@ class TestRdocRiDefaultDisplay < Test::Unit::TestCase
'includes' => [],
'instance_methods' => [
{ 'name' => 'instance_method' },
+ { 'name' => 'instance_method2' },
],
'instance_method_extensions' => [
{ 'name' => 'instance_method_extension' },
],
- 'superclass_string' => 'Object'
+ 'superclass' => 'Object'
- @dd.display_class_info klass, ri_reader
+ @dd.display_class_info klass
expected = <<-EOF
---------------------------------------------------- Class: SomeClass < Object
@@ -71,10 +72,19 @@ class TestRdocRiDefaultDisplay < Test::Unit::TestCase
Constants:
----------
- CONSTANT:
+ CONSTANT = "value1"
CONSTANT value
- CONSTANT_NOCOMMENT
+ CONSTANT_NOCOMMENT = "value2"
+
+
+Attributes:
+-----------
+
+ attribute (RW):
+ attribute comment
+
+ attribute_no_comment (RW)
Class methods:
@@ -92,22 +102,13 @@ Class method extensions:
Instance methods:
-----------------
- instance_method
+ instance_method, instance_method2
Instance method extensions:
---------------------------
instance_method_extension
-
-
-Attributes:
------------
-
- attribute (RW):
- attribute comment
-
- attribute_no_comment (RW)
EOF
assert_equal expected, @output.string
@@ -140,7 +141,7 @@ Attributes:
-------------------------------------------------------- SomeClass#some_method
some_method(arg1, arg2) {|block_param| ...}
- Extension from /nonexistent
+ From /nonexistent
------------------------------------------------------------------------------
some comment
@@ -152,7 +153,7 @@ Attributes:
end
def test_display_method_info_singleton
- method = RDoc::RI::Driver::Hash.new.update \
+ method = RDoc::RI::Driver::OpenStructHash.new.update \
'aliases' => [],
'block_params' => nil,
'comment' => nil,
@@ -167,6 +168,8 @@ Attributes:
expected = <<-EOF
------------------------------------------------------- SomeClass::some_method
SomeClass::some_method(arg1, arg2)
+
+ From
------------------------------------------------------------------------------
[no description]
EOF
@@ -176,7 +179,7 @@ Attributes:
def test_display_method_list
methods = [
- RDoc::RI::Driver::Hash.new.update(
+ RDoc::RI::Driver::OpenStructHash.new.update(
"aliases" => [],
"block_params" => nil,
"comment" => nil,
@@ -186,7 +189,7 @@ Attributes:
"params" => "()",
"visibility" => "public"
),
- RDoc::RI::Driver::Hash.new.update(
+ RDoc::RI::Driver::OpenStructHash.new.update(
"aliases" => [],
"block_params" => nil,
"comment" => nil,
@@ -204,7 +207,8 @@ Attributes:
More than one method matched your request. You can refine your search by
asking for information on one of:
- SomeClass#some_method, SomeClass#some_other_method
+SomeClass#some_method []
+SomeClass#some_other_method []
EOF
assert_equal expected, @output.string
@@ -216,7 +220,7 @@ Attributes:
expected = <<-EOF
some_method(arg1, arg2) {|block_param| ...}
- Extension from /nonexistent
+ From /nonexistent
EOF
assert_equal expected, @output.string
@@ -234,7 +238,7 @@ some_method(start, length)
some_method(index)
some_method(start, length)
- Extension from /nonexistent
+ From /nonexistent
EOF
assert_equal expected, @output.string
@@ -249,7 +253,7 @@ some_method(start, length)
expected = <<-EOF
SomeClass::some_method(arg1, arg2) {|block_param| ...}
- Extension from /nonexistent
+ From /nonexistent
EOF
assert_equal expected, @output.string
@@ -289,8 +293,9 @@ install an additional package, or ask the packager to enable ri generation.
end
def h(hash)
- RDoc::RI::Driver::Hash.convert hash
+ RDoc::RI::Driver::OpenStructHash.convert hash
end
end
+MiniTest::Unit.autorun
diff --git a/test/rdoc/test_rdoc_ri_driver.rb b/test/rdoc/test_rdoc_ri_driver.rb
index cddd4e60d1..f160492057 100644
--- a/test/rdoc/test_rdoc_ri_driver.rb
+++ b/test/rdoc/test_rdoc_ri_driver.rb
@@ -1,8 +1,9 @@
-require 'test/unit'
+require 'rubygems'
+require 'minitest/unit'
require 'tmpdir'
require 'rdoc/ri/driver'
-class TestRDocRIDriver < Test::Unit::TestCase
+class TestRDocRIDriver < MiniTest::Unit::TestCase
def setup
@tmpdir = File.join Dir.tmpdir, "test_rdoc_ri_driver_#{$$}"
@@ -14,7 +15,7 @@ class TestRDocRIDriver < Test::Unit::TestCase
FileUtils.mkdir_p @home_ri
FileUtils.mkdir_p @cache_dir
- @driver = RDoc::RI::Driver.new
+ @driver = RDoc::RI::Driver.new(RDoc::RI::Driver.process_args([]))
@driver.homepath = @home_ri
end
@@ -90,3 +91,4 @@ class TestRDocRIDriver < Test::Unit::TestCase
end
+MiniTest::Unit.autorun
diff --git a/test/rdoc/test_rdoc_ri_formatter.rb b/test/rdoc/test_rdoc_ri_formatter.rb
index ed2ccba22d..a70f9dcba7 100644
--- a/test/rdoc/test_rdoc_ri_formatter.rb
+++ b/test/rdoc/test_rdoc_ri_formatter.rb
@@ -1,9 +1,10 @@
require 'stringio'
-require 'test/unit'
+require 'rubygems'
+require 'minitest/unit'
require 'rdoc/ri/formatter'
require 'rdoc/markup/to_flow'
-class TestRDocRIFormatter < Test::Unit::TestCase
+class TestRDocRIFormatter < MiniTest::Unit::TestCase
def setup
@output = StringIO.new
@@ -97,7 +98,7 @@ class TestRDocRIFormatter < Test::Unit::TestCase
end
def test_display_flow_item_unknown
- e = assert_raise RDoc::Error do
+ e = assert_raises RDoc::Error do
@f.display_flow_item Object.new
end
@@ -189,7 +190,7 @@ class TestRDocRIFormatter < Test::Unit::TestCase
list = RDoc::Markup::Flow::LIST.new :UNKNOWN
list << RDoc::Markup::Flow::LI.new(nil, 'a b c')
- e = assert_raise ArgumentError do
+ e = assert_raises ArgumentError do
@f.display_list list
end
@@ -245,7 +246,7 @@ class TestRDocRIFormatter < Test::Unit::TestCase
def test_raw_print_line
@f.raw_print_line 'a b c'
- assert_equal "a b c\n", @output.string
+ assert_equal "a b c", @output.string
end
def test_strip_attributes_b
@@ -316,3 +317,4 @@ class TestRDocRIFormatter < Test::Unit::TestCase
end
+MiniTest::Unit.autorun
diff --git a/test/rdoc/test_rdoc_ri_overstrike_formatter.rb b/test/rdoc/test_rdoc_ri_overstrike_formatter.rb
index 050e92a4fe..38b95414dd 100644
--- a/test/rdoc/test_rdoc_ri_overstrike_formatter.rb
+++ b/test/rdoc/test_rdoc_ri_overstrike_formatter.rb
@@ -1,10 +1,11 @@
require 'stringio'
-require 'test/unit'
+require 'rubygems'
+require 'minitest/unit'
require 'rdoc/ri/formatter'
require 'rdoc/markup/fragments'
require 'rdoc/markup/to_flow'
-class TestRDocRIOverstrikeFormatter < Test::Unit::TestCase
+class TestRDocRIOverstrikeFormatter < MiniTest::Unit::TestCase
def setup
@output = StringIO.new
@@ -67,3 +68,4 @@ class TestRDocRIOverstrikeFormatter < Test::Unit::TestCase
end
+MiniTest::Unit.autorun
diff --git a/test/readline/test_readline.rb b/test/readline/test_readline.rb
index 071accf68b..36aadd92d7 100644
--- a/test/readline/test_readline.rb
+++ b/test/readline/test_readline.rb
@@ -63,7 +63,7 @@ class TestReadline < Test::Unit::TestCase
["filename_quote_characters"],
]
method_args.each do |method_name, *args|
- assert_raises(SecurityError, NotImplementedError,
+ assert_raise(SecurityError, NotImplementedError,
"method=<#{method_name}>") do
Thread.start {
$SAFE = 4
@@ -90,7 +90,7 @@ class TestReadline < Test::Unit::TestCase
assert_equal("> ", stdout.read(2))
assert_equal(1, Readline::HISTORY.length)
assert_equal("hello", Readline::HISTORY[0])
- assert_raises(SecurityError) do
+ assert_raise(SecurityError) do
Thread.start {
$SAFE = 1
replace_stdio(stdin.path, stdout.path) do
@@ -98,7 +98,7 @@ class TestReadline < Test::Unit::TestCase
end
}.join
end
- assert_raises(SecurityError) do
+ assert_raise(SecurityError) do
Thread.start {
$SAFE = 4
replace_stdio(stdin.path, stdout.path) { Readline.readline("> ") }
diff --git a/test/readline/test_readline_history.rb b/test/readline/test_readline_history.rb
index 8033a9a827..0b55c114f6 100644
--- a/test/readline/test_readline_history.rb
+++ b/test/readline/test_readline_history.rb
@@ -53,7 +53,7 @@ class Readline::TestHistory < Test::Unit::TestCase
["clear", []],
]
method_args.each do |method_name, args|
- assert_raises(SecurityError, NotImplementedError,
+ assert_raise(SecurityError, NotImplementedError,
"method=<#{method_name}>") do
Thread.start {
$SAFE = 4
@@ -63,7 +63,7 @@ class Readline::TestHistory < Test::Unit::TestCase
end
end
- assert_raises(SecurityError, NotImplementedError,
+ assert_raise(SecurityError, NotImplementedError,
"method=<each>") do
Thread.start {
$SAFE = 4
@@ -123,14 +123,14 @@ class Readline::TestHistory < Test::Unit::TestCase
end
def test_set__out_of_range
- assert_raises(IndexError, NotImplementedError, "index=<0>") do
+ assert_raise(IndexError, NotImplementedError, "index=<0>") do
HISTORY[0] = "set: 0"
end
lines = push_history(5)
invalid_indexes = [5, 6, 100, -6, -7, -100]
invalid_indexes.each do |i|
- assert_raises(IndexError, NotImplementedError, "index=<#{i}>") do
+ assert_raise(IndexError, NotImplementedError, "index=<#{i}>") do
HISTORY[i] = "set: #{i}"
end
end
@@ -205,16 +205,18 @@ class Readline::TestHistory < Test::Unit::TestCase
end
def test_each
- HISTORY.each do |s|
+ e = HISTORY.each do |s|
assert(false) # not reachable
end
+ assert_equal(HISTORY, e)
lines = push_history(5)
i = 0
- HISTORY.each do |s|
+ e = HISTORY.each do |s|
assert_equal(HISTORY[i], s)
assert_equal(lines[i], s)
i += 1
end
+ assert_equal(HISTORY, e)
end
def test_each__enumerator
@@ -268,14 +270,14 @@ class Readline::TestHistory < Test::Unit::TestCase
end
def test_delete_at__out_of_range
- assert_raises(IndexError, NotImplementedError, "index=<0>") do
+ assert_raise(IndexError, NotImplementedError, "index=<0>") do
HISTORY.delete_at(0)
end
lines = push_history(5)
invalid_indexes = [5, 6, 100, -6, -7, -100]
invalid_indexes.each do |i|
- assert_raises(IndexError, NotImplementedError, "index=<#{i}>") do
+ assert_raise(IndexError, NotImplementedError, "index=<#{i}>") do
HISTORY.delete_at(i)
end
end
@@ -283,7 +285,7 @@ class Readline::TestHistory < Test::Unit::TestCase
invalid_indexes = [100_000_000_000_000_000_000,
-100_000_000_000_000_000_000]
invalid_indexes.each do |i|
- assert_raises(RangeError, NotImplementedError, "index=<#{i}>") do
+ assert_raise(RangeError, NotImplementedError, "index=<#{i}>") do
HISTORY.delete_at(i)
end
end
diff --git a/test/rexml/test_document.rb b/test/rexml/test_document.rb
index 9e9e58b7a0..0261e80b74 100644
--- a/test/rexml/test_document.rb
+++ b/test/rexml/test_document.rb
@@ -10,8 +10,7 @@ EOF
assert_equal("Hello world!", doc.root.children.first.value)
end
- def test_entity_expansion_limit
- xml = <<EOF
+ XML_WITH_NESTED_ENTITY = <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE member [
<!ENTITY a "&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;">
@@ -26,44 +25,17 @@ EOF
&a;
</member>
EOF
- doc = REXML::Document.new(xml)
- assert_raise(RuntimeError) do
- doc.root.children.first.value
- end
- REXML::Document.entity_expansion_limit = 100
- assert_equal(100, REXML::Document.entity_expansion_limit)
- doc = REXML::Document.new(xml)
- assert_raise(RuntimeError) do
- doc.root.children.first.value
- end
- assert_equal(101, doc.entity_expansion_count)
- end
-end
-require "rexml/document"
-require "test/unit"
-
-class REXML::TestDocument < Test::Unit::TestCase
- def test_new
- doc = REXML::Document.new(<<EOF)
-<?xml version="1.0" encoding="UTF-8"?>
-<message>Hello world!</message>
-EOF
- assert_equal("Hello world!", doc.root.children.first.value)
- end
- XML_WITH_NESTED_ENTITY = <<EOF
+ XML_WITH_4_ENTITY_EXPANSION = <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE member [
- <!ENTITY a "&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;">
- <!ENTITY b "&c;&c;&c;&c;&c;&c;&c;&c;&c;&c;">
- <!ENTITY c "&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;">
- <!ENTITY d "&e;&e;&e;&e;&e;&e;&e;&e;&e;&e;">
- <!ENTITY e "&f;&f;&f;&f;&f;&f;&f;&f;&f;&f;">
- <!ENTITY f "&g;&g;&g;&g;&g;&g;&g;&g;&g;&g;">
- <!ENTITY g "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx">
+ <!ENTITY a "a">
+ <!ENTITY a2 "&a; &a;">
]>
<member>
&a;
+&a2;
+&lt;
</member>
EOF
@@ -79,5 +51,16 @@ EOF
doc.root.children.first.value
end
assert_equal(101, doc.entity_expansion_count)
+
+ REXML::Document.entity_expansion_limit = 4
+ doc = REXML::Document.new(XML_WITH_4_ENTITY_EXPANSION)
+ assert_equal("\na\na a\n<\n", doc.root.children.first.value)
+ REXML::Document.entity_expansion_limit = 3
+ doc = REXML::Document.new(XML_WITH_4_ENTITY_EXPANSION)
+ assert_raise(RuntimeError) do
+ doc.root.children.first.value
+ end
+ ensure
+ REXML::Document.entity_expansion_limit = 10000
end
end
diff --git a/test/rinda/test_rinda.rb b/test/rinda/test_rinda.rb
index 14d3c31499..0b1c512bf1 100644
--- a/test/rinda/test_rinda.rb
+++ b/test/rinda/test_rinda.rb
@@ -149,7 +149,7 @@ module TupleSpaceTestModule
assert(!tmpl.match({"message"=>"Hi", "name"=>"Foo", "age"=>1}))
assert(!tmpl.match({"message"=>"Hello", "no_name"=>"Foo"}))
- assert_raises(Rinda::InvalidHashTupleKey) do
+ assert_raise(Rinda::InvalidHashTupleKey) do
tmpl = Rinda::Template.new({:message=>String, "name"=>String})
end
tmpl = Rinda::Template.new({"name"=>String})
@@ -182,7 +182,7 @@ module TupleSpaceTestModule
assert(!tmpl.match({"message"=>"Hi", "name"=>"Foo", "age"=>1}))
assert(!tmpl.match({"message"=>"Hello", "no_name"=>"Foo"}))
- assert_raises(Rinda::InvalidHashTupleKey) do
+ assert_raise(Rinda::InvalidHashTupleKey) do
@ts.write({:message=>String, "name"=>String})
end
@@ -193,7 +193,7 @@ module TupleSpaceTestModule
assert_equal({'1'=>1, '2'=>2, '3'=>3}, @ts.take({'1'=>1, '2'=>2, '3'=>3}))
entry = @ts.write(['1'=>1, '2'=>2, '3'=>3])
- assert_raises(Rinda::RequestExpiredError) do
+ assert_raise(Rinda::RequestExpiredError) do
assert_equal({'1'=>1, '2'=>2, '3'=>3}, @ts.read({'1'=>1}, 0))
end
entry.cancel
@@ -230,11 +230,11 @@ module TupleSpaceTestModule
end
def test_inp_rdp
- assert_raises(Rinda::RequestExpiredError) do
+ assert_raise(Rinda::RequestExpiredError) do
@ts.take([:empty], 0)
end
- assert_raises(Rinda::RequestExpiredError) do
+ assert_raise(Rinda::RequestExpiredError) do
@ts.read([:empty], 0)
end
end
@@ -242,13 +242,13 @@ module TupleSpaceTestModule
def test_ruby_talk_264062
th = Thread.new { @ts.take([:empty], 1) }
sleep(10)
- assert_raises(Rinda::RequestExpiredError) do
+ assert_raise(Rinda::RequestExpiredError) do
thread_join(th)
end
th = Thread.new { @ts.read([:empty], 1) }
sleep(10)
- assert_raises(Rinda::RequestExpiredError) do
+ assert_raise(Rinda::RequestExpiredError) do
thread_join(th)
end
end
@@ -317,8 +317,8 @@ module TupleSpaceTestModule
def test_core_03_notify
notify1 = @ts.notify(nil, [:req, Integer])
- notify2 = @ts.notify(nil, [:ans, Integer], 5)
- notify3 = @ts.notify(nil, {"message"=>String, "name"=>String}, 5)
+ notify2 = @ts.notify(nil, [:ans, Integer], 8)
+ notify3 = @ts.notify(nil, {"message"=>String, "name"=>String}, 8)
@ts.write({"message"=>"first", "name"=>"3"}, 3)
@ts.write({"message"=>"second", "name"=>"1"}, 1)
@@ -347,19 +347,18 @@ module TupleSpaceTestModule
result = nil
lv = 0
n = 0
- notify2.each do |ev|
+ notify2.each do |ev, tuple|
n += 1
- if ev[0] == 'write'
+ if ev == 'write'
lv = lv + 1
- elsif ev[0] == 'take'
+ elsif ev == 'take'
lv = lv - 1
- elsif ev[0] == 'close'
+ elsif ev == 'close'
result = [lv, n]
- else
break
end
assert(lv >= 0)
- assert_equal([:ans, 10], ev[1])
+ assert_equal([:ans, 10], tuple)
end
result
end
@@ -386,13 +385,15 @@ module TupleSpaceTestModule
sleep(4)
assert_equal(10, thread_join(taker))
+ # notify2 must not expire until this @ts.take.
+ # sleep(4) might be short enough for the timeout of notify2 (8 secs)
tuple = @ts.take([:ans, nil])
assert_equal(10, tuple[1])
assert_equal([], @ts.read_all([nil, nil]))
-
+
notify1.cancel
- sleep(3) # notify2 expired
-
+ sleep(7) # notify2 expired (sleep(4)+sleep(7) > 8)
+
assert_equal([0, 11], thread_join(listener1))
assert_equal([0, 3], thread_join(listener2))
@@ -429,7 +430,7 @@ module TupleSpaceTestModule
sleep(2)
- assert_raises(Rinda::RequestCanceledError) do
+ assert_raise(Rinda::RequestCanceledError) do
assert_nil(thread_join(taker))
end
@@ -458,7 +459,7 @@ module TupleSpaceTestModule
sleep(2)
- assert_raises(Rinda::RequestCanceledError) do
+ assert_raise(Rinda::RequestCanceledError) do
assert_nil(thread_join(reader))
end
diff --git a/test/rss/rss-assertions.rb b/test/rss/rss-assertions.rb
index 12e53f7cd5..0a84e4f16d 100644
--- a/test/rss/rss-assertions.rb
+++ b/test/rss/rss-assertions.rb
@@ -2,6 +2,10 @@ require 'erb'
module RSS
module Assertions
+ def _wrap_assertion
+ yield
+ end
+
def assert_parse(rss, assert_method, *args)
__send__("assert_#{assert_method}", *args) do
::RSS::Parser.parse(rss)
@@ -1460,7 +1464,7 @@ EOA
_assert_maker_atom_element(feed_type, maker_readers, feed_readers,
maker_extractor, feed_extractor,
&block)
- end
+ end
def assert_maker_atom_generator(feed_type, maker_readers, feed_readers,
not_set_error_name=nil, &block)
diff --git a/test/ruby/enc/test_euc_jp.rb b/test/ruby/enc/test_euc_jp.rb
index 82abe2116d..1ccc55ccb9 100644
--- a/test/ruby/enc/test_euc_jp.rb
+++ b/test/ruby/enc/test_euc_jp.rb
@@ -17,4 +17,8 @@ class TestEUC_JP < Test::Unit::TestCase
assert_no_match(/あ{0}\p{Katakana}{4}/, "漢字漢字")
assert_raise(RegexpError) { Regexp.new('あ{0}\p{foobarbaz}') }
end
+
+ def test_charboundary
+ assert_nil(/\xA2\xA2/ =~ "\xA1\xA2\xA2\xA3")
+ end
end
diff --git a/test/ruby/enc/test_utf16.rb b/test/ruby/enc/test_utf16.rb
index a7c735f436..c949c1e293 100644
--- a/test/ruby/enc/test_utf16.rb
+++ b/test/ruby/enc/test_utf16.rb
@@ -1,12 +1,19 @@
require 'test/unit'
class TestUTF16 < Test::Unit::TestCase
- def encdump(str)
- d = str.dump
- if /\.force_encoding\("[A-Za-z0-9.:_+-]*"\)\z/ =~ d
- d
+ def encdump(obj)
+ case obj
+ when String
+ d = obj.dump
+ if /\.force_encoding\("[A-Za-z0-9.:_+-]*"\)\z/ =~ d
+ d
+ else
+ "#{d}.force_encoding(#{obj.encoding.name.dump})"
+ end
+ when Regexp
+ "Regexp.new(#{encdump(obj.source)}, #{obj.options})"
else
- "#{d}.force_encoding(#{str.encoding.name.dump})"
+ raise Argument, "unexpected: #{obj.inspect}"
end
end
@@ -137,19 +144,19 @@ EOT
end
def test_hex
- assert_raise(EncodingCompatibilityError) {
+ assert_raise(Encoding::CompatibilityError) {
"ff".encode("utf-16le").hex
}
- assert_raise(EncodingCompatibilityError) {
+ assert_raise(Encoding::CompatibilityError) {
"ff".encode("utf-16be").hex
}
end
def test_oct
- assert_raise(EncodingCompatibilityError) {
+ assert_raise(Encoding::CompatibilityError) {
"77".encode("utf-16le").oct
}
- assert_raise(EncodingCompatibilityError) {
+ assert_raise(Encoding::CompatibilityError) {
"77".encode("utf-16be").oct
}
end
@@ -157,7 +164,7 @@ EOT
def test_count
s1 = "aa".force_encoding("utf-16be")
s2 = "aa"
- assert_raise(EncodingCompatibilityError, "#{encdump s1}.count(#{encdump s2})") {
+ assert_raise(Encoding::CompatibilityError, "#{encdump s1}.count(#{encdump s2})") {
s1.count(s2)
}
end
@@ -165,7 +172,7 @@ EOT
def test_plus
s1 = "a".force_encoding("us-ascii")
s2 = "aa".force_encoding("utf-16be")
- assert_raise(EncodingCompatibilityError, "#{encdump s1} + #{encdump s2}") {
+ assert_raise(Encoding::CompatibilityError, "#{encdump s1} + #{encdump s2}") {
s1 + s2
}
end
@@ -178,7 +185,7 @@ EOT
def test_interpolation
s = "aa".force_encoding("utf-16be")
- assert_raise(EncodingCompatibilityError, "\"a\#{#{encdump s}}\"") {
+ assert_raise(Encoding::CompatibilityError, "\"a\#{#{encdump s}}\"") {
"a#{s}"
}
end
@@ -206,7 +213,7 @@ EOT
def test_plus_nonempty
s1 = "aa"
s2 = "bb".force_encoding("utf-16be")
- assert_raise(EncodingCompatibilityError, "#{encdump s1} << #{encdump s2}") {
+ assert_raise(Encoding::CompatibilityError, "#{encdump s1} << #{encdump s2}") {
s1 + s2
}
end
@@ -230,7 +237,7 @@ EOT
def test_concat_nonempty
s1 = "aa"
s2 = "bb".force_encoding("utf-16be")
- assert_raise(EncodingCompatibilityError, "#{encdump s1} << #{encdump s2}") {
+ assert_raise(Encoding::CompatibilityError, "#{encdump s1} << #{encdump s2}") {
s1 << s2
}
end
@@ -272,7 +279,7 @@ EOT
s.gsub(Regexp.new(".".encode("utf-16be")), "xy")
}
s = "ab\0\ncd".force_encoding("utf-16be")
- assert_raise(EncodingCompatibilityError) {
+ assert_raise(Encoding::CompatibilityError) {
s.gsub(Regexp.new(".".encode("utf-16be")), "xy")
}
end
@@ -355,4 +362,23 @@ EOT
assert_equal("", sl.chop)
assert_equal("", sb.chop)
end
+
+ def test_regexp_escape
+ s = "\0*".force_encoding("UTF-16BE")
+ r = Regexp.new(Regexp.escape(s))
+ assert(r =~ s, "#{encdump(r)} =~ #{encdump(s)}")
+ end
+
+ def test_casecmp
+ assert_equal(0, "\0A".force_encoding("UTF-16BE").casecmp("\0a".force_encoding("UTF-16BE")))
+ assert_not_equal(0, "\0A".force_encoding("UTF-16LE").casecmp("\0a".force_encoding("UTF-16LE")))
+ assert_not_equal(0, "A\0".force_encoding("UTF-16BE").casecmp("a\0".force_encoding("UTF-16BE")))
+ assert_equal(0, "A\0".force_encoding("UTF-16LE").casecmp("a\0".force_encoding("UTF-16LE")))
+
+ ary = ["01".force_encoding("UTF-16LE"),
+ "10".force_encoding("UTF-16LE")]
+ e = ary.sort {|x,y| x <=> y }
+ a = ary.sort {|x,y| x.casecmp(y) }
+ assert_equal(e, a)
+ end
end
diff --git a/test/ruby/marshaltestlib.rb b/test/ruby/marshaltestlib.rb
index 0a70380d44..4486a78429 100644
--- a/test/ruby/marshaltestlib.rb
+++ b/test/ruby/marshaltestlib.rb
@@ -128,7 +128,7 @@ module MarshalTestLib
def test_hash_default_proc
h = Hash.new {}
- assert_raises(TypeError) { marshaltest(h) }
+ assert_raise(TypeError) { marshaltest(h) }
end
def test_hash_ivar
@@ -418,16 +418,16 @@ module MarshalTestLib
def test_singleton
o = Object.new
def o.m() end
- assert_raises(TypeError) { marshaltest(o) }
+ assert_raise(TypeError) { marshaltest(o) }
o = Object.new
c = class << o
@v = 1
class C; self; end
end
- assert_raises(TypeError) { marshaltest(o) }
- assert_raises(TypeError) { marshaltest(c) }
- assert_raises(TypeError) { marshaltest(ARGF) }
- assert_raises(TypeError) { marshaltest(ENV) }
+ assert_raise(TypeError) { marshaltest(o) }
+ assert_raise(TypeError) { marshaltest(c) }
+ assert_raise(TypeError) { marshaltest(ARGF) }
+ assert_raise(TypeError) { marshaltest(ENV) }
end
def test_extend
@@ -440,7 +440,7 @@ module MarshalTestLib
marshal_equal(o) {|obj| class << obj; ancestors end}
o = Object.new
o.extend Module.new
- assert_raises(TypeError) { marshaltest(o) }
+ assert_raise(TypeError) { marshaltest(o) }
end
def test_extend_string
@@ -453,16 +453,16 @@ module MarshalTestLib
marshal_equal(o) {|obj| class << obj; ancestors end}
o = ""
o.extend Module.new
- assert_raises(TypeError) { marshaltest(o) }
+ assert_raise(TypeError) { marshaltest(o) }
end
def test_anonymous
c = Class.new
- assert_raises(TypeError) { marshaltest(c) }
+ assert_raise(TypeError) { marshaltest(c) }
o = c.new
- assert_raises(TypeError) { marshaltest(o) }
+ assert_raise(TypeError) { marshaltest(o) }
m = Module.new
- assert_raises(TypeError) { marshaltest(m) }
+ assert_raise(TypeError) { marshaltest(m) }
end
def test_string_empty
diff --git a/test/ruby/test_argf.rb b/test/ruby/test_argf.rb
index eb5556b98a..9e18a80b40 100644
--- a/test/ruby/test_argf.rb
+++ b/test/ruby/test_argf.rb
@@ -55,7 +55,7 @@ class TestArgf < Test::Unit::TestCase
end
def test_argf
- ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+ src = <<-SRC
a = ARGF
b = a.dup
p [a.gets.chomp, a.lineno, b.gets.chomp, b.lineno] #=> ["1", 1, "1", 1]
@@ -72,23 +72,20 @@ class TestArgf < Test::Unit::TestCase
p [a.gets.chomp, a.lineno, b.gets.chomp, b.lineno] #=> ["5", 5, "5", 8]
p [a.gets.chomp, a.lineno, b.gets.chomp, b.lineno] #=> ["6", 6, "6", 9]
SRC
- a = f.read.split("\n")
- assert_equal('["1", 1, "1", 1]', a.shift)
- assert_equal('["2", 2, "2", 2]', a.shift)
- assert_equal('["1", 1, "1", 3]', a.shift)
- assert_equal('["2", 2, "2", 4]', a.shift)
- assert_equal('["3", 3, "3", 5]', a.shift)
- assert_equal('["4", 4, "4", 6]', a.shift)
- assert_equal('["5", 5, "5", 7]', a.shift)
- assert_equal('["5", 5, "5", 8]', a.shift)
- assert_equal('["6", 6, "6", 9]', a.shift)
+ expected = src.scan(/\#=> *(.*+)/).flatten
+ ruby('-e', src, @t1.path, @t2.path, @t3.path) do |f|
+ f.each_with_index do |a, i|
+ assert_equal(expected.shift, a.chomp, "[ruby-dev:34445]: line #{i}")
+ end
+
+ assert_empty(expected, "[ruby-dev:34445]: remained")
# is this test OK? [ruby-dev:34445]
end
end
def test_lineno
- ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+ src = <<-SRC
a = ARGF
a.gets; p $. #=> 1
a.gets; p $. #=> 2
@@ -105,12 +102,14 @@ class TestArgf < Test::Unit::TestCase
a.gets; p $. #=> 2001
a.gets; p $. #=> 2001
SRC
- assert_equal("1,2,3,3,3,4,4,3,1000,1001,1002,2001,2001", f.read.chomp.gsub("\n", ","))
+ expected = src.scan(/\#=> *(.*+)/).join(",")
+ ruby('-e', src, @t1.path, @t2.path, @t3.path) do |f|
+ assert_equal(expected, f.read.chomp.gsub("\n", ","))
end
end
def test_lineno2
- ruby('-e', <<-SRC, @t1.path, @t2.path, @t3.path) do |f|
+ src = <<-SRC
a = ARGF.dup
a.gets; p $. #=> 1
a.gets; p $. #=> 2
@@ -123,10 +122,12 @@ class TestArgf < Test::Unit::TestCase
a.gets; p $. #=> 2
a.gets; p $. #=> 2
$. = 2000
- a.gets; p $. #=> 2001
+ a.gets; p $. #=> 2000
a.gets; p $. #=> 2000
SRC
- assert_equal("1,2,1,1,1,2,1,1,2,2,2000,2000", f.read.chomp.gsub("\n", ","))
+ expected = src.scan(/\#=> *(.*+)/).join(",")
+ ruby('-e', src, @t1.path, @t2.path, @t3.path) do |f|
+ assert_equal(expected, f.read.chomp.gsub("\n", ","))
end
end
@@ -489,9 +490,11 @@ class TestArgf < Test::Unit::TestCase
t = ""; ARGF.readpartial(1, t); s << t
end
rescue EOFError
+ $stdout.binmode
puts s
end
SRC
+ f.binmode
f.puts("foo")
f.puts("bar")
f.puts("baz")
diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb
index 234fb238a2..9edd31dfa7 100644
--- a/test/ruby/test_array.rb
+++ b/test/ruby/test_array.rb
@@ -814,6 +814,8 @@ class TestArray < Test::Unit::TestCase
s = a.join
assert_equal(true, s.tainted?)
assert_equal(true, s.untrusted?)
+ ensure
+ $, = nil
end
def test_last
@@ -886,7 +888,7 @@ class TestArray < Test::Unit::TestCase
assert_equal("aGVsbG8K\n", @cls["hello\n"].pack("m"))
assert_equal(",:&5L;&\\*:&5L;&\\*\n", @cls["hello\nhello\n"].pack("u"))
- assert_equal("\xc2\xa9B\xe2\x89\xa0", @cls[0xa9, 0x42, 0x2260].pack("U*"))
+ assert_equal("\u{a9 42 2260}", @cls[0xa9, 0x42, 0x2260].pack("U*"))
format = "c2x5CCxsdils_l_a6";
@@ -1155,6 +1157,14 @@ class TestArray < Test::Unit::TestCase
assert_equal(@cls[1], @cls[1].sort!)
assert_equal(@cls[], @cls[].sort!)
+
+ a = @cls[4, 3, 2, 1]
+ a.sort! {|m, n| a.replace([9, 8, 7, 6]); m <=> n }
+ assert_equal([1, 2, 3, 4], a)
+
+ a = @cls[4, 3, 2, 1]
+ a.sort! {|m, n| a.replace([9, 8, 7]); m <=> n }
+ assert_equal([1, 2, 3, 4], a)
end
def test_sort_with_callcc
@@ -1220,8 +1230,8 @@ class TestArray < Test::Unit::TestCase
$, = ":"
a = @cls[1, 2, 3]
assert_equal("[1, 2, 3]", a.to_s)
-
- $, = ""
+ ensure
+ $, = nil
end
def test_uniq
@@ -1260,7 +1270,7 @@ class TestArray < Test::Unit::TestCase
assert_equal(@cls[1,2], @cls[1, 2] | @cls[1, 2])
end
- def test_combination
+ def test_combination
assert_equal(@cls[[]], @cls[1,2,3,4].combination(0).to_a)
assert_equal(@cls[[1],[2],[3],[4]], @cls[1,2,3,4].combination(1).to_a)
assert_equal(@cls[[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]], @cls[1,2,3,4].combination(2).to_a)
@@ -1295,6 +1305,11 @@ class TestArray < Test::Unit::TestCase
"edcba".each_char.to_a.permutation(5).sort)
assert_equal(@cls[].permutation(0).to_a, @cls[[]])
+ a = @cls[1, 2, 3, 4]
+ b = @cls[]
+ a.permutation {|x| b << x; a.replace(@cls[9, 8, 7, 6]) }
+ assert_equal(@cls[9, 8, 7, 6], a)
+ assert_equal(@cls[1, 2, 3, 4].permutation.to_a, b)
end
def test_take
@@ -1543,6 +1558,23 @@ class TestArray < Test::Unit::TestCase
assert([0, 1, 2].include?(sample))
}
end
+
+ srand(0)
+ a = (1..18).to_a
+ (0..20).each do |n|
+ 10000.times do
+ b = a.sample(n)
+ assert_equal([n, 18].min, b.uniq.size)
+ assert_equal(a, (a | b).sort)
+ assert_equal(b.sort, (a & b).sort)
+ end
+
+ h = Hash.new(0)
+ 10000.times do
+ a.sample(n).each {|x| h[x] += 1 }
+ end
+ assert_operator(h.values.min * 2, :>=, h.values.max) if n != 0
+ end
end
def test_cycle
@@ -1590,6 +1622,8 @@ class TestArray < Test::Unit::TestCase
def test_array_subclass
assert_equal(Array2, Array2[1,2,3].uniq.class, "[ruby-dev:34581]")
+ assert_equal(Array2, Array2[1,2][0,1].class) # embeded
+ assert_equal(Array2, Array2[*(1..100)][1..99].class) #not embeded
end
def test_inspect
@@ -1600,4 +1634,33 @@ class TestArray < Test::Unit::TestCase
assert_equal(true, s.tainted?)
assert_equal(true, s.untrusted?)
end
+
+ def test_initialize2
+ a = [1] * 1000
+ a.instance_eval { initialize }
+ assert_equal([], a)
+ end
+
+ def test_shift_shared_ary
+ a = (1..100).to_a
+ b = []
+ b.replace(a)
+ assert_equal((1..10).to_a, a.shift(10))
+ assert_equal((11..100).to_a, a)
+ end
+
+ def test_replace_shared_ary
+ a = [1] * 100
+ b = []
+ b.replace(a)
+ a.replace([1, 2, 3])
+ assert_equal([1, 2, 3], a)
+ assert_equal([1] * 100, b)
+ end
+
+ def test_fill_negative_length
+ a = (1..10).to_a
+ a.fill(:foo, 5, -3)
+ assert_equal((1..10).to_a, a)
+ end
end
diff --git a/test/ruby/test_beginendblock.rb b/test/ruby/test_beginendblock.rb
index 594596698b..463ebd94b6 100644
--- a/test/ruby/test_beginendblock.rb
+++ b/test/ruby/test_beginendblock.rb
@@ -32,11 +32,11 @@ class TestBeginEndBlock < Test::Unit::TestCase
end
def test_begininmethod
- assert_raises(SyntaxError) do
+ assert_raise(SyntaxError) do
eval("def foo; BEGIN {}; end")
end
- assert_raises(SyntaxError) do
+ assert_raise(SyntaxError) do
eval('eval("def foo; BEGIN {}; end")')
end
end
diff --git a/test/ruby/test_call.rb b/test/ruby/test_call.rb
index da7ee93c73..8f861d96a1 100644
--- a/test/ruby/test_call.rb
+++ b/test/ruby/test_call.rb
@@ -8,8 +8,8 @@ class TestCall < Test::Unit::TestCase
end
def test_call
- assert_raises(ArgumentError) {aaa()}
- assert_raises(ArgumentError) {aaa}
+ assert_raise(ArgumentError) {aaa()}
+ assert_raise(ArgumentError) {aaa}
assert_equal([1, 100], aaa(1))
assert_equal([1, 2], aaa(1, 2))
diff --git a/test/ruby/test_clone.rb b/test/ruby/test_clone.rb
index 43c0cffa1d..c5e2469d10 100644
--- a/test/ruby/test_clone.rb
+++ b/test/ruby/test_clone.rb
@@ -21,7 +21,7 @@ class TestClone < Test::Unit::TestCase
assert_equal("test", bar.test)
assert_equal("test", foo.test)
- assert_raises(NoMethodError) {foo.test2}
+ assert_raise(NoMethodError) {foo.test2}
assert_equal([M003, M002, M001], M003.ancestors)
end
diff --git a/test/ruby/test_complex.rb b/test/ruby/test_complex.rb
index ef612e2279..2a193eb155 100644
--- a/test/ruby/test_complex.rb
+++ b/test/ruby/test_complex.rb
@@ -4,26 +4,30 @@ class ComplexSub < Complex; end
class Complex_Test < Test::Unit::TestCase
+ def setup
+ @rational = defined?(Rational)
+ if @rational
+ @keiju = Rational.instance_variable_get('@RCS_ID')
+ end
+ @unify = $".grep(/mathn/).size != 0
+ end
+
def test_compsub
- c = ComplexSub.__send__(:new, 1)
- cc = ComplexSub.__send__(:convert, 1)
+ c = ComplexSub.__send__(:convert, 1)
assert_kind_of(Numeric, c)
- assert_kind_of(Numeric, cc)
- if defined?(ComplexSub::Unify)
+ if @unify
assert_instance_of(Fixnum, c)
- assert_instance_of(Fixnum, cc)
else
assert_instance_of(ComplexSub, c)
- assert_instance_of(ComplexSub, cc)
c2 = c + 1
assert_instance_of(ComplexSub, c2)
c2 = c - 1
assert_instance_of(ComplexSub, c2)
- c3 = c - c2
+ c3 = c - c
assert_instance_of(ComplexSub, c3)
s = Marshal.dump(c)
@@ -42,7 +46,7 @@ class Complex_Test < Test::Unit::TestCase
assert_equal(true, c.eql?(c2))
assert_equal(false, c.eql?(c3))
- if defined?(Complex::Unify)
+ if @unify
assert_equal(true, c.eql?(0))
else
assert_equal(false, c.eql?(0))
@@ -51,6 +55,7 @@ class Complex_Test < Test::Unit::TestCase
def test_hash
assert_instance_of(Fixnum, Complex(1,2).hash)
+ assert_instance_of(Fixnum, Complex(1.0,2.0).hash)
h = {}
h[Complex(0)] = 0
@@ -63,115 +68,58 @@ class Complex_Test < Test::Unit::TestCase
h[Complex(0,0)] = 9
assert_equal(4, h.size)
+
+ h[Complex(0.0,0.0)] = 9.0
+ assert_equal(5, h.size)
end
def test_freeze
c = Complex(1)
c.freeze
- unless defined?(Complex::Unify)
+ unless @unify
assert_equal(true, c.frozen?)
end
assert_instance_of(String, c.to_s)
end
- def test_new_bang # no unify
- assert_instance_of(Complex, Complex.__send__(:new!, 2,0))
- assert_equal([2,0], Complex.__send__(:new!, 2,0).
- instance_eval{[real, image]})
- assert_equal([2,4], Complex.__send__(:new!, 2,4).
- instance_eval{[real, image]})
- assert_equal([-2,4], Complex.__send__(:new!, -2,4).
- instance_eval{[real, image]})
- assert_equal([2,-4], Complex.__send__(:new!, 2,-4).
- instance_eval{[real, image]})
- assert_equal([-2,-4], Complex.__send__(:new!, -2,-4).
- instance_eval{[real, image]})
-
- assert_equal([2,0], Complex.__send__(:new!, Complex(2)).
- instance_eval{[real, image]})
- assert_equal([2,3], Complex.__send__(:new!, Complex(2), Complex(3)).
- instance_eval{[real, image]})
- assert_equal([2,3], Complex.__send__(:new!, 2, Complex(3)).
- instance_eval{[real, image]})
-
- assert_equal([1.1,0], Complex.__send__(:new!, 1.1).
- instance_eval{[real, image]})
- assert_equal([-1.1,0], Complex.__send__(:new!, -1.1).
- instance_eval{[real, image]})
- assert_equal([1,0], Complex.__send__(:new!, '1').
- instance_eval{[real, image]})
- assert_equal([0,0], Complex.__send__(:new!, nil).
- instance_eval{[real, image]})
- end
-
- def test_new
- assert_instance_of(Complex, Complex.__send__(:new, 2,0.0))
- if defined?(Complex::Unify)
- assert_instance_of(Fixnum, Complex.__send__(:new, 2,0))
- else
- assert_instance_of(Complex, Complex.__send__(:new, 2,0))
- assert_equal([2,0], Complex.__send__(:new, 2,0). instance_eval{[real, image]})
- end
- assert_equal([2,4], Complex.__send__(:new, 2,4).instance_eval{[real, image]})
- assert_equal([-2,4], Complex.__send__(:new, -2,4).instance_eval{[real, image]})
- assert_equal([2,-4], Complex.__send__(:new, 2,-4).instance_eval{[real, image]})
- assert_equal([-2,-4], Complex.__send__(:new, -2,-4).instance_eval{[real, image]})
-
- assert_raise(ArgumentError){Complex.__send__(:new, Complex(1,2),2)}
- assert_raise(ArgumentError){Complex.__send__(:new, 2,Complex(1,2))}
- assert_raise(ArgumentError){Complex.__send__(:new, Complex(1,2),Complex(1,2))}
-
- assert_raise(ArgumentError){Complex.__send__(:new, '1')}
- assert_raise(ArgumentError){Complex.__send__(:new, nil)}
-=begin
- assert_raise(ArgumentError){Complex.__send__(:new, Complex(1))}
-=end
- end
-
def test_conv
c = Complex(0,0)
- assert_equal(Complex.__send__(:new, 0,0), c)
+ assert_equal(Complex(0,0), c)
c = Complex(2**32, 2**32)
- assert_equal(Complex.__send__(:new, 2**32,2**32), c)
- assert_equal([2**32,2**32], [c.real,c.image])
+ assert_equal(Complex(2**32,2**32), c)
+ assert_equal([2**32,2**32], [c.real,c.imag])
c = Complex(-2**32, 2**32)
- assert_equal(Complex.__send__(:new, -2**32,2**32), c)
- assert_equal([-2**32,2**32], [c.real,c.image])
+ assert_equal(Complex(-2**32,2**32), c)
+ assert_equal([-2**32,2**32], [c.real,c.imag])
c = Complex(2**32, -2**32)
- assert_equal(Complex.__send__(:new, 2**32,-2**32), c)
- assert_equal([2**32,-2**32], [c.real,c.image])
+ assert_equal(Complex(2**32,-2**32), c)
+ assert_equal([2**32,-2**32], [c.real,c.imag])
c = Complex(-2**32, -2**32)
- assert_equal(Complex.__send__(:new, -2**32,-2**32), c)
- assert_equal([-2**32,-2**32], [c.real,c.image])
-
- c = Complex(Complex(1),0)
- assert_equal(Complex.__send__(:new, 1,0), c)
+ assert_equal(Complex(-2**32,-2**32), c)
+ assert_equal([-2**32,-2**32], [c.real,c.imag])
- c = Complex(0,Complex(1))
- assert_equal(Complex.__send__(:new, 0,1), c)
+ c = Complex(Complex(1,2),2)
+ assert_equal(Complex(1,4), c)
- c = 5.re
- assert_equal(Complex.__send__(:new, 5,0), c)
+ c = Complex(2,Complex(1,2))
+ assert_equal(Complex(0,1), c)
- c = Complex(1,2).re
- assert_equal(Complex.__send__(:new, 1,2), c)
-
- c = 5.im
- assert_equal(Complex.__send__(:new, 0,5), c)
-
- c = Complex(2,0).im
- assert_equal(Complex.__send__(:new, 0,2), c)
- assert_raise(ArgumentError){Complex(1,2).im}
+ c = Complex(Complex(1,2),Complex(1,2))
+ assert_equal(Complex(-1,3), c)
c = Complex::I
- assert_equal(Complex.__send__(:new, 0,1), c)
+ assert_equal(Complex(0,1), c)
- assert_equal(Complex.__send__(:new, 1),Complex(1))
- assert_equal(Complex.__send__(:new, 1),Complex('1'))
+ assert_equal(Complex(1),Complex(1))
+ assert_equal(Complex(1),Complex('1'))
+ assert_equal(Complex(3.0,3.0),Complex('3.0','3.0'))
+ if @rational && !@keiju
+ assert_equal(Complex(1,1),Complex('3/3','3/3'))
+ end
assert_raise(ArgumentError){Complex(nil)}
assert_raise(ArgumentError){Complex(Object.new)}
assert_raise(ArgumentError){Complex()}
@@ -182,64 +130,63 @@ class Complex_Test < Test::Unit::TestCase
c = Complex(4)
assert_equal(4, c.real)
- assert_equal(0, c.image)
+ assert_equal(0, c.imag)
c = Complex(4,5)
assert_equal(4, c.real)
- assert_equal(5, c.image)
+ assert_equal(5, c.imag)
if -0.0.to_s == '-0.0'
c = Complex(-0.0,-0.0)
assert_equal('-0.0', c.real.to_s)
- assert_equal('-0.0', c.image.to_s)
+ assert_equal('-0.0', c.imag.to_s)
end
- c = Complex.__send__(:new, 4)
+ c = Complex(4)
assert_equal(4, c.real)
- assert_equal(0, c.image)
- assert_equal(c.imag, c.image)
+ assert_equal(0, c.imag)
+ assert_equal(c.imag, c.imaginary)
- c = Complex.__send__(:new, 4,5)
+ c = Complex(4,5)
assert_equal(4, c.real)
- assert_equal(5, c.image)
- assert_equal(c.imag, c.image)
+ assert_equal(5, c.imag)
+ assert_equal(c.imag, c.imaginary)
if -0.0.to_s == '-0.0'
- c = Complex.__send__(:new, -0.0,-0.0)
+ c = Complex(-0.0,-0.0)
assert_equal('-0.0', c.real.to_s)
- assert_equal('-0.0', c.image.to_s)
- assert_equal(c.imag.to_s, c.image.to_s)
+ assert_equal('-0.0', c.imag.to_s)
+ assert_equal(c.imag.to_s, c.imaginary.to_s)
end
- c = Complex.__send__(:new!, 4)
+ c = Complex(4)
assert_equal(4, c.real)
- assert_equal(c.imag, c.image)
- assert_equal(0, c.image)
+ assert_equal(c.imag, c.imaginary)
+ assert_equal(0, c.imag)
- c = Complex.__send__(:new!, 4,5)
+ c = Complex(4,5)
assert_equal(4, c.real)
- assert_equal(5, c.image)
- assert_equal(c.imag, c.image)
+ assert_equal(5, c.imag)
+ assert_equal(c.imag, c.imaginary)
- c = Complex.__send__(:new!, -0.0,-0.0)
+ c = Complex(-0.0,-0.0)
assert_equal('-0.0', c.real.to_s)
- assert_equal('-0.0', c.image.to_s)
- assert_equal(c.imag.to_s, c.image.to_s)
+ assert_equal('-0.0', c.imag.to_s)
+ assert_equal(c.imag.to_s, c.imaginary.to_s)
end
def test_attr2
c = Complex(1)
- if defined?(Complex::Unify)
- assert_equal(true, c.scalar?)
+ if @unify
=begin
assert_equal(true, c.finite?)
assert_equal(false, c.infinite?)
@@ -247,13 +194,14 @@ class Complex_Test < Test::Unit::TestCase
assert_equal(true, c.integer?)
assert_equal(false, c.float?)
assert_equal(true, c.rational?)
+=end
assert_equal(true, c.real?)
+=begin
assert_equal(false, c.complex?)
assert_equal(true, c.exact?)
assert_equal(false, c.inexact?)
=end
else
- assert_equal(false, c.scalar?)
=begin
assert_equal(true, c.finite?)
assert_equal(false, c.infinite?)
@@ -261,7 +209,9 @@ class Complex_Test < Test::Unit::TestCase
assert_equal(false, c.integer?)
assert_equal(false, c.float?)
assert_equal(false, c.rational?)
+=end
assert_equal(false, c.real?)
+=begin
assert_equal(true, c.complex?)
assert_equal(true, c.exact?)
assert_equal(false, c.inexact?)
@@ -303,6 +253,16 @@ class Complex_Test < Test::Unit::TestCase
assert_equal(Complex(-1,1), +Complex(-1,1))
assert_equal(Complex(1,-1), +Complex(1,-1))
assert_equal(Complex(-1,-1), +Complex(-1,-1))
+
+ if -0.0.to_s == '-0.0'
+ c = +Complex(0.0,0.0)
+ assert_equal('0.0', c.real.to_s)
+ assert_equal('0.0', c.imag.to_s)
+
+ c = +Complex(-0.0,-0.0)
+ assert_equal('-0.0', c.real.to_s)
+ assert_equal('-0.0', c.imag.to_s)
+ end
end
def test_negate
@@ -313,6 +273,16 @@ class Complex_Test < Test::Unit::TestCase
assert_equal(Complex(-1,1), -Complex(1,-1))
assert_equal(Complex(1,1), -Complex(-1,-1))
+ if -0.0.to_s == '-0.0'
+ c = -Complex(0.0,0.0)
+ assert_equal('-0.0', c.real.to_s)
+ assert_equal('-0.0', c.imag.to_s)
+
+ c = -Complex(-0.0,-0.0)
+ assert_equal('0.0', c.real.to_s)
+ assert_equal('0.0', c.imag.to_s)
+ end
+
=begin
assert_equal(0, Complex(0).negate)
assert_equal(-2, Complex(2).negate)
@@ -329,7 +299,7 @@ class Complex_Test < Test::Unit::TestCase
assert_equal(Complex(3,2), c + 2)
assert_equal(Complex(3.0,2), c + 2.0)
- if defined?(Rational)
+ if @rational
assert_equal(Complex(Rational(3,1),Rational(2)), c + Rational(2))
assert_equal(Complex(Rational(5,3),Rational(2)), c + Rational(2,3))
end
@@ -344,7 +314,7 @@ class Complex_Test < Test::Unit::TestCase
assert_equal(Complex(-1,2), c - 2)
assert_equal(Complex(-1.0,2), c - 2.0)
- if defined?(Rational)
+ if @rational
assert_equal(Complex(Rational(-1,1),Rational(2)), c - Rational(2))
assert_equal(Complex(Rational(1,3),Rational(2)), c - Rational(2,3))
end
@@ -359,7 +329,7 @@ class Complex_Test < Test::Unit::TestCase
assert_equal(Complex(2,4), c * 2)
assert_equal(Complex(2.0,4.0), c * 2.0)
- if defined?(Rational)
+ if @rational
assert_equal(Complex(Rational(2,1),Rational(4)), c * Rational(2))
assert_equal(Complex(Rational(2,3),Rational(4,3)), c * Rational(2,3))
end
@@ -370,12 +340,12 @@ class Complex_Test < Test::Unit::TestCase
c = Complex(1,2)
c2 = Complex(2,3)
- if defined?(Rational)
+ if @rational
assert_equal(Complex(Rational(8,13),Rational(1,13)), c / c2)
else
r = c / c2
assert_in_delta(0.615, r.real, 0.001)
- assert_in_delta(0.076, r.image, 0.001)
+ assert_in_delta(0.076, r.imag, 0.001)
end
c = Complex(1.0,2.0)
@@ -383,19 +353,19 @@ class Complex_Test < Test::Unit::TestCase
r = c / c2
assert_in_delta(0.615, r.real, 0.001)
- assert_in_delta(0.076, r.image, 0.001)
+ assert_in_delta(0.076, r.imag, 0.001)
c = Complex(1,2)
c2 = Complex(2,3)
- if defined?(Rational)
+ if @rational
assert_equal(Complex(Rational(1,2),1), c / 2)
else
assert_equal(Complex(0.5,1.0), c / 2)
end
assert_equal(Complex(0.5,1.0), c / 2.0)
- if defined?(Rational)
+ if @rational
assert_equal(Complex(Rational(1,2),Rational(1)), c / Rational(2))
assert_equal(Complex(Rational(3,2),Rational(3)), c / Rational(2,3))
end
@@ -405,12 +375,12 @@ class Complex_Test < Test::Unit::TestCase
c = Complex(1,2)
c2 = Complex(2,3)
- if defined?(Rational)
+ if @rational
assert_equal(Complex(Rational(8,13),Rational(1,13)), c.quo(c2))
else
r = c.quo(c2)
assert_in_delta(0.615, r.real, 0.001)
- assert_in_delta(0.076, r.image, 0.001)
+ assert_in_delta(0.076, r.imag, 0.001)
end
c = Complex(1.0,2.0)
@@ -418,19 +388,19 @@ class Complex_Test < Test::Unit::TestCase
r = c.quo(c2)
assert_in_delta(0.615, r.real, 0.001)
- assert_in_delta(0.076, r.image, 0.001)
+ assert_in_delta(0.076, r.imag, 0.001)
c = Complex(1,2)
c2 = Complex(2,3)
- if defined?(Rational)
+ if @rational
assert_equal(Complex(Rational(1,2),1), c.quo(2))
else
assert_equal(Complex(0.5,1.0), c.quo(2))
end
assert_equal(Complex(0.5,1.0), c.quo(2.0))
- if defined?(Rational)
+ if @rational
assert_equal(Complex(Rational(1,2),Rational(1)), c / Rational(2))
assert_equal(Complex(Rational(3,2),Rational(3)), c / Rational(2,3))
end
@@ -442,14 +412,14 @@ class Complex_Test < Test::Unit::TestCase
r = c.fdiv(c2)
assert_in_delta(0.615, r.real, 0.001)
- assert_in_delta(0.076, r.image, 0.001)
+ assert_in_delta(0.076, r.imag, 0.001)
c = Complex(1.0,2.0)
c2 = Complex(2.0,3.0)
r = c.fdiv(c2)
assert_in_delta(0.615, r.real, 0.001)
- assert_in_delta(0.076, r.image, 0.001)
+ assert_in_delta(0.076, r.imag, 0.001)
c = Complex(1,2)
c2 = Complex(2,3)
@@ -464,25 +434,25 @@ class Complex_Test < Test::Unit::TestCase
r = c ** c2
assert_in_delta(-0.015, r.real, 0.001)
- assert_in_delta(-0.179, r.image, 0.001)
+ assert_in_delta(-0.179, r.imag, 0.001)
assert_equal(Complex(-3,4), c ** 2)
- if defined?(Rational) && !Rational.instance_variable_get('@RCS_ID')
+ if @rational && !@keiju
assert_equal(Complex(Rational(-3,25),Rational(-4,25)), c ** -2)
else
r = c ** -2
assert_in_delta(-0.12, r.real, 0.001)
- assert_in_delta(-0.16, r.image, 0.001)
+ assert_in_delta(-0.16, r.imag, 0.001)
end
r = c ** 2.0
assert_in_delta(-3.0, r.real, 0.001)
- assert_in_delta(4.0, r.image, 0.001)
+ assert_in_delta(4.0, r.imag, 0.001)
r = c ** -2.0
assert_in_delta(-0.12, r.real, 0.001)
- assert_in_delta(-0.16, r.image, 0.001)
+ assert_in_delta(-0.16, r.imag, 0.001)
- if defined?(Rational) && !Rational.instance_variable_get('@RCS_ID')
+ if @rational && !@keiju
assert_equal(Complex(-3,4), c ** Rational(2))
#=begin
assert_equal(Complex(Rational(-3,25),Rational(-4,25)),
@@ -491,11 +461,11 @@ class Complex_Test < Test::Unit::TestCase
r = c ** Rational(2,3)
assert_in_delta(1.264, r.real, 0.001)
- assert_in_delta(1.150, r.image, 0.001)
+ assert_in_delta(1.150, r.imag, 0.001)
r = c ** Rational(-2,3)
assert_in_delta(0.432, r.real, 0.001)
- assert_in_delta(-0.393, r.image, 0.001)
+ assert_in_delta(-0.393, r.imag, 0.001)
end
end
@@ -507,16 +477,7 @@ class Complex_Test < Test::Unit::TestCase
def test_equal
assert(Complex(1,0) == Complex(1))
- assert(Complex(1,0) == Complex.__send__(:new, 1))
- assert(Complex(1,0) == Complex.__send__(:new, 1,0))
- assert(Complex(1,0) == Complex.__send__(:new!, 1))
- assert(Complex(1,0) == Complex.__send__(:new!, 1,0))
-
assert(Complex(-1,0) == Complex(-1))
- assert(Complex(-1,0) == Complex.__send__(:new, -1))
- assert(Complex(-1,0) == Complex.__send__(:new, -1,0))
- assert(Complex(-1,0) == Complex.__send__(:new!, -1))
- assert(Complex(-1,0) == Complex.__send__(:new!, -1,0))
assert_equal(false, Complex(2,1) == Complex(1))
assert_equal(true, Complex(2,1) != Complex(1))
@@ -525,7 +486,7 @@ class Complex_Test < Test::Unit::TestCase
end
def test_unify
- if defined?(Complex::Unify)
+ if @unify
assert_instance_of(Fixnum, Complex(1,2) + Complex(-1,-2))
assert_instance_of(Fixnum, Complex(1,2) - Complex(1,2))
assert_instance_of(Fixnum, Complex(1,2) * 0)
@@ -544,9 +505,9 @@ class Complex_Test < Test::Unit::TestCase
assert_equal(5, c.abs2)
assert_equal(c.abs, Math.sqrt(c * c.conj))
- assert_equal(c.abs, Math.sqrt(c.real**2 + c.image**2))
+ assert_equal(c.abs, Math.sqrt(c.real**2 + c.imag**2))
assert_equal(c.abs2, c * c.conj)
- assert_equal(c.abs2, c.real**2 + c.image**2)
+ assert_equal(c.abs2, c.real**2 + c.imag**2)
assert_in_delta(1.107, c.arg, 0.001)
assert_in_delta(1.107, c.angle, 0.001)
@@ -586,7 +547,7 @@ class Complex_Test < Test::Unit::TestCase
assert_equal('1.0-2.0i', Complex(1.0,-2.0).to_s)
assert_equal('-1.0-2.0i', Complex(-1.0,-2.0).to_s)
- if defined?(Rational) && !defined?(Complex::Unify) && !Rational.instance_variable_get('@RCS_ID')
+ if @rational && !@unify && !@keiju
assert_equal('0+2/1i', Complex(0,Rational(2)).to_s)
assert_equal('0-2/1i', Complex(0,Rational(-2)).to_s)
assert_equal('1+2/1i', Complex(1,Rational(2)).to_s)
@@ -614,13 +575,15 @@ class Complex_Test < Test::Unit::TestCase
def test_marshal
c = Complex(1,2)
+ c.instance_eval{@ivar = 9}
s = Marshal.dump(c)
c2 = Marshal.load(s)
assert_equal(c, c2)
+ assert_equal(9, c2.instance_variable_get(:@ivar))
assert_instance_of(Complex, c2)
- if defined?(Rational)
+ if @rational
c = Complex(Rational(1,2),Rational(2,3))
s = Marshal.dump(c)
@@ -755,7 +718,7 @@ class Complex_Test < Test::Unit::TestCase
assert_raise(ArgumentError){ Complex('5+3i_')}
assert_raise(ArgumentError){ Complex('5+3ix')}
- if defined?(Rational) && defined?(''.to_r)
+ if @rational && defined?(''.to_r)
assert_equal(Complex(Rational(1,5)), '1/5'.to_c)
assert_equal(Complex(Rational(-1,5)), '-1/5'.to_c)
assert_equal(Complex(Rational(1,5),3), '1/5+3i'.to_c)
@@ -821,51 +784,47 @@ class Complex_Test < Test::Unit::TestCase
end
def test_to_r
- if defined?(Rational) && !Rational.instance_variable_get('@RCS_ID')
+ if @rational && !@keiju
assert_equal(Rational(3), Complex(3).to_r)
assert_equal(Rational(3), Rational(Complex(3)))
assert_raise(RangeError){Complex(3,2).to_r}
- assert_raise(RangeError){Rational(Complex(3,2))}
+# assert_raise(RangeError){Rational(Complex(3,2))}
end
end
def test_to_c
c = nil.to_c
- assert_equal([0,0] , [c.real, c.image])
+ assert_equal([0,0] , [c.real, c.imag])
c = 0.to_c
- assert_equal([0,0] , [c.real, c.image])
+ assert_equal([0,0] , [c.real, c.imag])
c = 1.to_c
- assert_equal([1,0] , [c.real, c.image])
+ assert_equal([1,0] , [c.real, c.imag])
c = 1.1.to_c
- assert_equal([1.1, 0], [c.real, c.image])
+ assert_equal([1.1, 0], [c.real, c.imag])
- if defined?(Rational)
+ if @rational
c = Rational(1,2).to_c
- assert_equal([Rational(1,2), 0], [c.real, c.image])
+ assert_equal([Rational(1,2), 0], [c.real, c.imag])
end
c = Complex(1,2).to_c
- assert_equal([1, 2], [c.real, c.image])
- end
-
- def test_prec
- assert_equal(nil, Complex < Precision)
+ assert_equal([1, 2], [c.real, c.imag])
end
def test_supp
- assert_equal(true, 1.scalar?)
- assert_equal(true, 1.1.scalar?)
+ assert_equal(true, 1.real?)
+ assert_equal(true, 1.1.real?)
assert_equal(1, 1.real)
- assert_equal(0, 1.image)
assert_equal(0, 1.imag)
+ assert_equal(0, 1.imaginary)
assert_equal(1.1, 1.1.real)
- assert_equal(0, 1.1.image)
assert_equal(0, 1.1.imag)
+ assert_equal(0, 1.1.imaginary)
assert_equal(1, 1.magnitude)
assert_equal(1, -1.magnitude)
@@ -919,14 +878,14 @@ class Complex_Test < Test::Unit::TestCase
assert_equal(1.1, 1.1.conj)
assert_equal(-1.1, -1.1.conj)
- if defined?(Rational)
+ if @rational
assert_equal(Complex(Rational(1,2),Rational(1)), Complex(1,2).quo(2))
else
assert_equal(Complex(0.5,1.0), Complex(1,2).quo(2))
end
=begin
- if defined?(Rational) && !Rational.instance_variable_get('@RCS_ID')
+ if @rational && !@keiju
assert_equal(Complex(Rational(1,2),Rational(1)), Complex(1,2).quo(2))
end
=end
@@ -934,7 +893,7 @@ class Complex_Test < Test::Unit::TestCase
assert_equal(0.5, 1.fdiv(2))
assert_equal(5000000000.0, 10000000000.fdiv(2))
assert_equal(0.5, 1.0.fdiv(2))
- if defined?(Rational)
+ if @rational
assert_equal(0.25, Rational(1,2).fdiv(2))
end
assert_equal(Complex(0.5,1.0), Complex(1,2).quo(2))
@@ -944,7 +903,7 @@ class Complex_Test < Test::Unit::TestCase
# assert_equal(true, Math.sqrt(-4.0).inexact?)
assert_equal(Complex(0,2), Math.sqrt(-4))
# assert_equal(true, Math.sqrt(-4).exact?)
- if defined?(Rational)
+ if @rational
assert_equal(Complex(0,2), Math.sqrt(Rational(-4)))
# assert_equal(true, Math.sqrt(Rational(-4)).exact?)
end
@@ -953,98 +912,98 @@ class Complex_Test < Test::Unit::TestCase
# assert_equal(true, Math.sqrt(-9.0).inexact?)
assert_equal(Complex(0,3), Math.sqrt(-9))
# assert_equal(true, Math.sqrt(-9).exact?)
- if defined?(Rational)
+ if @rational
assert_equal(Complex(0,3), Math.sqrt(Rational(-9)))
# assert_equal(true, Math.sqrt(Rational(-9)).exact?)
end
c = Math.sqrt(Complex(1, 2))
assert_in_delta(1.272, c.real, 0.001)
- assert_in_delta(0.786, c.image, 0.001)
+ assert_in_delta(0.786, c.imag, 0.001)
c = Math.sqrt(-9)
assert_in_delta(0.0, c.real, 0.001)
- assert_in_delta(3.0, c.image, 0.001)
+ assert_in_delta(3.0, c.imag, 0.001)
c = Math.exp(Complex(1, 2))
assert_in_delta(-1.131, c.real, 0.001)
- assert_in_delta(2.471, c.image, 0.001)
+ assert_in_delta(2.471, c.imag, 0.001)
c = Math.sin(Complex(1, 2))
assert_in_delta(3.165, c.real, 0.001)
- assert_in_delta(1.959, c.image, 0.001)
+ assert_in_delta(1.959, c.imag, 0.001)
c = Math.cos(Complex(1, 2))
assert_in_delta(2.032, c.real, 0.001)
- assert_in_delta(-3.051, c.image, 0.001)
+ assert_in_delta(-3.051, c.imag, 0.001)
c = Math.tan(Complex(1, 2))
assert_in_delta(0.033, c.real, 0.001)
- assert_in_delta(1.014, c.image, 0.001)
+ assert_in_delta(1.014, c.imag, 0.001)
c = Math.sinh(Complex(1, 2))
assert_in_delta(-0.489, c.real, 0.001)
- assert_in_delta(1.403, c.image, 0.001)
+ assert_in_delta(1.403, c.imag, 0.001)
c = Math.cosh(Complex(1, 2))
assert_in_delta(-0.642, c.real, 0.001)
- assert_in_delta(1.068, c.image, 0.001)
+ assert_in_delta(1.068, c.imag, 0.001)
c = Math.tanh(Complex(1, 2))
assert_in_delta(1.166, c.real, 0.001)
- assert_in_delta(-0.243, c.image, 0.001)
+ assert_in_delta(-0.243, c.imag, 0.001)
c = Math.log(Complex(1, 2))
assert_in_delta(0.804, c.real, 0.001)
- assert_in_delta(1.107, c.image, 0.001)
+ assert_in_delta(1.107, c.imag, 0.001)
c = Math.log(Complex(1, 2), Math::E)
assert_in_delta(0.804, c.real, 0.001)
- assert_in_delta(1.107, c.image, 0.001)
+ assert_in_delta(1.107, c.imag, 0.001)
c = Math.log(-1)
assert_in_delta(0.0, c.real, 0.001)
- assert_in_delta(Math::PI, c.image, 0.001)
+ assert_in_delta(Math::PI, c.imag, 0.001)
c = Math.log(8, 2)
assert_in_delta(3.0, c.real, 0.001)
- assert_in_delta(0.0, c.image, 0.001)
+ assert_in_delta(0.0, c.imag, 0.001)
c = Math.log(-8, -2)
assert_in_delta(1.092, c.real, 0.001)
- assert_in_delta(-0.420, c.image, 0.001)
+ assert_in_delta(-0.420, c.imag, 0.001)
c = Math.log10(Complex(1, 2))
assert_in_delta(0.349, c.real, 0.001)
- assert_in_delta(0.480, c.image, 0.001)
+ assert_in_delta(0.480, c.imag, 0.001)
c = Math.asin(Complex(1, 2))
assert_in_delta(0.427, c.real, 0.001)
- assert_in_delta(1.528, c.image, 0.001)
+ assert_in_delta(1.528, c.imag, 0.001)
c = Math.acos(Complex(1, 2))
assert_in_delta(1.143, c.real, 0.001)
- assert_in_delta(-1.528, c.image, 0.001)
+ assert_in_delta(-1.528, c.imag, 0.001)
c = Math.atan(Complex(1, 2))
assert_in_delta(1.338, c.real, 0.001)
- assert_in_delta(0.402, c.image, 0.001)
+ assert_in_delta(0.402, c.imag, 0.001)
c = Math.atan2(Complex(1, 2), 1)
assert_in_delta(1.338, c.real, 0.001)
- assert_in_delta(0.402, c.image, 0.001)
+ assert_in_delta(0.402, c.imag, 0.001)
c = Math.asinh(Complex(1, 2))
assert_in_delta(1.469, c.real, 0.001)
- assert_in_delta(1.063, c.image, 0.001)
+ assert_in_delta(1.063, c.imag, 0.001)
c = Math.acosh(Complex(1, 2))
assert_in_delta(1.528, c.real, 0.001)
- assert_in_delta(1.143, c.image, 0.001)
+ assert_in_delta(1.143, c.imag, 0.001)
c = Math.atanh(Complex(1, 2))
assert_in_delta(0.173, c.real, 0.001)
- assert_in_delta(1.178, c.image, 0.001)
+ assert_in_delta(1.178, c.imag, 0.001)
end
end
@@ -1056,7 +1015,7 @@ class Complex_Test < Test::Unit::TestCase
end
def test_fixed_bug
- if defined?(Rational) && !Rational.instance_variable_get('@RCS_ID')
+ if @rational && !@keiju
assert_equal(Complex(1), 1 ** Complex(1))
end
assert_equal('-1.0-0.0i', Complex(-1.0, -0.0).to_s)
diff --git a/test/ruby/test_complex2.rb b/test/ruby/test_complex2.rb
new file mode 100644
index 0000000000..4e960c3e36
--- /dev/null
+++ b/test/ruby/test_complex2.rb
@@ -0,0 +1,735 @@
+require 'test/unit'
+
+class Complex_Test2 < Test::Unit::TestCase
+
+ def test_kumi
+ return unless defined?(Rational)
+
+ assert_equal(Complex(1, 0), +Complex(1, 0))
+ assert_equal(Complex(-1, 0), -Complex(1, 0))
+ assert_equal(Complex(2, 0),
+ Complex(1, 0) + Complex(1, 0))
+ assert_equal(Complex(0, 0),
+ Complex(1, 0) - Complex(1, 0))
+ assert_equal(Complex(1, 0),
+ Complex(1, 0) * Complex(1, 0))
+ assert_equal(Complex(1, 0),
+ Complex(1, 0) / Complex(1, 0))
+ assert_equal(Complex(1073741790, 0),
+ Complex(1, 0) + Complex(1073741789, 0))
+ assert_equal(Complex(-1073741788, 0),
+ Complex(1, 0) - Complex(1073741789, 0))
+ assert_equal(Complex(1073741789, 0),
+ Complex(1, 0) * Complex(1073741789, 0))
+ assert_equal(Complex(Rational(1, 1073741789), 0),
+ Complex(1, 0) / Complex(1073741789, 0))
+ assert_equal(Complex(1073741828, 0),
+ Complex(1, 0) + Complex(1073741827, 0))
+ assert_equal(Complex(-1073741826, 0),
+ Complex(1, 0) - Complex(1073741827, 0))
+ assert_equal(Complex(1073741827, 0),
+ Complex(1, 0) * Complex(1073741827, 0))
+ assert_equal(Complex(Rational(1, 1073741827), 0),
+ Complex(1, 0) / Complex(1073741827, 0))
+ assert_equal(Complex(1073741790, 1073741789),
+ Complex(1, 0) + Complex(1073741789, 1073741789))
+ assert_equal(Complex(-1073741788, -1073741789),
+ Complex(1, 0) - Complex(1073741789, 1073741789))
+ assert_equal(Complex(1073741789, 1073741789),
+ Complex(1, 0) * Complex(1073741789, 1073741789))
+ assert_equal(Complex(Rational(1, 2147483578), Rational(-1, 2147483578)),
+ Complex(1, 0) / Complex(1073741789, 1073741789))
+ assert_equal(Complex(1073741790, 1073741827),
+ Complex(1, 0) + Complex(1073741789, 1073741827))
+ assert_equal(Complex(-1073741788, -1073741827),
+ Complex(1, 0) - Complex(1073741789, 1073741827))
+ assert_equal(Complex(1073741789, 1073741827),
+ Complex(1, 0) * Complex(1073741789, 1073741827))
+ assert_equal(Complex(Rational(1073741789, 2305842940494218450), Rational(-1073741827, 2305842940494218450)),
+ Complex(1, 0) / Complex(1073741789, 1073741827))
+ assert_equal(Complex(1073741828, 1073741827),
+ Complex(1, 0) + Complex(1073741827, 1073741827))
+ assert_equal(Complex(-1073741826, -1073741827),
+ Complex(1, 0) - Complex(1073741827, 1073741827))
+ assert_equal(Complex(1073741827, 1073741827),
+ Complex(1, 0) * Complex(1073741827, 1073741827))
+ assert_equal(Complex(Rational(1, 2147483654), Rational(-1, 2147483654)),
+ Complex(1, 0) / Complex(1073741827, 1073741827))
+ assert_equal(Complex(Rational(2147483616, 1073741827), Rational(1073741789, 1073741827)),
+ Complex(1, 0) + Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(Rational(38, 1073741827), Rational(-1073741789, 1073741827)),
+ Complex(1, 0) - Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)),
+ Complex(1, 0) * Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(Rational(1073741827, 2147483578), Rational(-1073741827, 2147483578)),
+ Complex(1, 0) / Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(Rational(2147483616, 1073741789), Rational(1073741827, 1073741789)),
+ Complex(1, 0) + Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(-38, 1073741789), Rational(-1073741827, 1073741789)),
+ Complex(1, 0) - Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)),
+ Complex(1, 0) * Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1073741789, 2147483654), Rational(-1073741789, 2147483654)),
+ Complex(1, 0) / Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(2147483616, 1073741827), Rational(1073741827, 1073741789)),
+ Complex(1, 0) + Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(38, 1073741827), Rational(-1073741827, 1073741789)),
+ Complex(1, 0) - Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)),
+ Complex(1, 0) * Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1329227869515035739611240300898290063, 2658455833113515253509575011810600482), Rational(-1329227963598474519442525600436190287, 2658455833113515253509575011810600482)),
+ Complex(1, 0) / Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(1073741789, 0), +Complex(1073741789, 0))
+ assert_equal(Complex(-1073741789, 0), -Complex(1073741789, 0))
+ assert_equal(Complex(1073741790, 0),
+ Complex(1073741789, 0) + Complex(1, 0))
+ assert_equal(Complex(1073741788, 0),
+ Complex(1073741789, 0) - Complex(1, 0))
+ assert_equal(Complex(1073741789, 0),
+ Complex(1073741789, 0) * Complex(1, 0))
+ assert_equal(Complex(1073741789, 0),
+ Complex(1073741789, 0) / Complex(1, 0))
+ assert_equal(Complex(2147483578, 0),
+ Complex(1073741789, 0) + Complex(1073741789, 0))
+ assert_equal(Complex(0, 0),
+ Complex(1073741789, 0) - Complex(1073741789, 0))
+ assert_equal(Complex(1152921429444920521, 0),
+ Complex(1073741789, 0) * Complex(1073741789, 0))
+ assert_equal(Complex(1, 0),
+ Complex(1073741789, 0) / Complex(1073741789, 0))
+ assert_equal(Complex(2147483616, 0),
+ Complex(1073741789, 0) + Complex(1073741827, 0))
+ assert_equal(Complex(-38, 0),
+ Complex(1073741789, 0) - Complex(1073741827, 0))
+ assert_equal(Complex(1152921470247108503, 0),
+ Complex(1073741789, 0) * Complex(1073741827, 0))
+ assert_equal(Complex(Rational(1073741789, 1073741827), 0),
+ Complex(1073741789, 0) / Complex(1073741827, 0))
+ assert_equal(Complex(2147483578, 1073741789),
+ Complex(1073741789, 0) + Complex(1073741789, 1073741789))
+ assert_equal(Complex(0, -1073741789),
+ Complex(1073741789, 0) - Complex(1073741789, 1073741789))
+ assert_equal(Complex(1152921429444920521, 1152921429444920521),
+ Complex(1073741789, 0) * Complex(1073741789, 1073741789))
+ assert_equal(Complex(Rational(1, 2), Rational(-1, 2)),
+ Complex(1073741789, 0) / Complex(1073741789, 1073741789))
+ assert_equal(Complex(2147483578, 1073741827),
+ Complex(1073741789, 0) + Complex(1073741789, 1073741827))
+ assert_equal(Complex(0, -1073741827),
+ Complex(1073741789, 0) - Complex(1073741789, 1073741827))
+ assert_equal(Complex(1152921429444920521, 1152921470247108503),
+ Complex(1073741789, 0) * Complex(1073741789, 1073741827))
+ assert_equal(Complex(Rational(1152921429444920521, 2305842940494218450), Rational(-1152921470247108503, 2305842940494218450)),
+ Complex(1073741789, 0) / Complex(1073741789, 1073741827))
+ assert_equal(Complex(2147483616, 1073741827),
+ Complex(1073741789, 0) + Complex(1073741827, 1073741827))
+ assert_equal(Complex(-38, -1073741827),
+ Complex(1073741789, 0) - Complex(1073741827, 1073741827))
+ assert_equal(Complex(1152921470247108503, 1152921470247108503),
+ Complex(1073741789, 0) * Complex(1073741827, 1073741827))
+ assert_equal(Complex(Rational(1073741789, 2147483654), Rational(-1073741789, 2147483654)),
+ Complex(1073741789, 0) / Complex(1073741827, 1073741827))
+ assert_equal(Complex(Rational(1152921471320850292, 1073741827), Rational(1073741789, 1073741827)),
+ Complex(1073741789, 0) + Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(Rational(1152921469173366714, 1073741827), Rational(-1073741789, 1073741827)),
+ Complex(1073741789, 0) - Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(Rational(1152921429444920521, 1073741827), Rational(1152921429444920521, 1073741827)),
+ Complex(1073741789, 0) * Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(Rational(1073741827, 2), Rational(-1073741827, 2)),
+ Complex(1073741789, 0) / Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(Rational(1152921430518662348, 1073741789), Rational(1073741827, 1073741789)),
+ Complex(1073741789, 0) + Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1152921428371178694, 1073741789), Rational(-1073741827, 1073741789)),
+ Complex(1073741789, 0) - Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(1073741827, 1073741827),
+ Complex(1073741789, 0) * Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1152921429444920521, 2147483654), Rational(-1152921429444920521, 2147483654)),
+ Complex(1073741789, 0) / Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1152921471320850292, 1073741827), Rational(1073741827, 1073741789)),
+ Complex(1073741789, 0) + Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1152921469173366714, 1073741827), Rational(-1073741827, 1073741789)),
+ Complex(1073741789, 0) - Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1152921429444920521, 1073741827), 1073741827),
+ Complex(1073741789, 0) * Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1427247510601733037449111325195428279286542707, 2658455833113515253509575011810600482), Rational(-1427247611623052908177132720890654139107803443, 2658455833113515253509575011810600482)),
+ Complex(1073741789, 0) / Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(1073741827, 0), +Complex(1073741827, 0))
+ assert_equal(Complex(-1073741827, 0), -Complex(1073741827, 0))
+ assert_equal(Complex(1073741828, 0),
+ Complex(1073741827, 0) + Complex(1, 0))
+ assert_equal(Complex(1073741826, 0),
+ Complex(1073741827, 0) - Complex(1, 0))
+ assert_equal(Complex(1073741827, 0),
+ Complex(1073741827, 0) * Complex(1, 0))
+ assert_equal(Complex(1073741827, 0),
+ Complex(1073741827, 0) / Complex(1, 0))
+ assert_equal(Complex(2147483616, 0),
+ Complex(1073741827, 0) + Complex(1073741789, 0))
+ assert_equal(Complex(38, 0),
+ Complex(1073741827, 0) - Complex(1073741789, 0))
+ assert_equal(Complex(1152921470247108503, 0),
+ Complex(1073741827, 0) * Complex(1073741789, 0))
+ assert_equal(Complex(Rational(1073741827, 1073741789), 0),
+ Complex(1073741827, 0) / Complex(1073741789, 0))
+ assert_equal(Complex(2147483654, 0),
+ Complex(1073741827, 0) + Complex(1073741827, 0))
+ assert_equal(Complex(0, 0),
+ Complex(1073741827, 0) - Complex(1073741827, 0))
+ assert_equal(Complex(1152921511049297929, 0),
+ Complex(1073741827, 0) * Complex(1073741827, 0))
+ assert_equal(Complex(1, 0),
+ Complex(1073741827, 0) / Complex(1073741827, 0))
+ assert_equal(Complex(2147483616, 1073741789),
+ Complex(1073741827, 0) + Complex(1073741789, 1073741789))
+ assert_equal(Complex(38, -1073741789),
+ Complex(1073741827, 0) - Complex(1073741789, 1073741789))
+ assert_equal(Complex(1152921470247108503, 1152921470247108503),
+ Complex(1073741827, 0) * Complex(1073741789, 1073741789))
+ assert_equal(Complex(Rational(1073741827, 2147483578), Rational(-1073741827, 2147483578)),
+ Complex(1073741827, 0) / Complex(1073741789, 1073741789))
+ assert_equal(Complex(2147483616, 1073741827),
+ Complex(1073741827, 0) + Complex(1073741789, 1073741827))
+ assert_equal(Complex(38, -1073741827),
+ Complex(1073741827, 0) - Complex(1073741789, 1073741827))
+ assert_equal(Complex(1152921470247108503, 1152921511049297929),
+ Complex(1073741827, 0) * Complex(1073741789, 1073741827))
+ assert_equal(Complex(Rational(1152921470247108503, 2305842940494218450), Rational(-1152921511049297929, 2305842940494218450)),
+ Complex(1073741827, 0) / Complex(1073741789, 1073741827))
+ assert_equal(Complex(2147483654, 1073741827),
+ Complex(1073741827, 0) + Complex(1073741827, 1073741827))
+ assert_equal(Complex(0, -1073741827),
+ Complex(1073741827, 0) - Complex(1073741827, 1073741827))
+ assert_equal(Complex(1152921511049297929, 1152921511049297929),
+ Complex(1073741827, 0) * Complex(1073741827, 1073741827))
+ assert_equal(Complex(Rational(1, 2), Rational(-1, 2)),
+ Complex(1073741827, 0) / Complex(1073741827, 1073741827))
+ assert_equal(Complex(Rational(1152921512123039718, 1073741827), Rational(1073741789, 1073741827)),
+ Complex(1073741827, 0) + Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(Rational(1152921509975556140, 1073741827), Rational(-1073741789, 1073741827)),
+ Complex(1073741827, 0) - Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(1073741789, 1073741789),
+ Complex(1073741827, 0) * Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(Rational(1152921511049297929, 2147483578), Rational(-1152921511049297929, 2147483578)),
+ Complex(1073741827, 0) / Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(Rational(1152921471320850330, 1073741789), Rational(1073741827, 1073741789)),
+ Complex(1073741827, 0) + Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1152921469173366676, 1073741789), Rational(-1073741827, 1073741789)),
+ Complex(1073741827, 0) - Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1152921511049297929, 1073741789), Rational(1152921511049297929, 1073741789)),
+ Complex(1073741827, 0) * Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1073741789, 2), Rational(-1073741789, 2)),
+ Complex(1073741827, 0) / Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1152921512123039718, 1073741827), Rational(1073741827, 1073741789)),
+ Complex(1073741827, 0) + Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1152921509975556140, 1073741827), Rational(-1073741827, 1073741789)),
+ Complex(1073741827, 0) - Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(1073741789, Rational(1152921511049297929, 1073741789)),
+ Complex(1073741827, 0) * Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1427247561112392079020469430422559713421565101, 2658455833113515253509575011810600482), Rational(-1427247662133715524919164459706626955683034349, 2658455833113515253509575011810600482)),
+ Complex(1073741827, 0) / Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(1073741789, 1073741789), +Complex(1073741789, 1073741789))
+ assert_equal(Complex(-1073741789, -1073741789), -Complex(1073741789, 1073741789))
+ assert_equal(Complex(1073741790, 1073741789),
+ Complex(1073741789, 1073741789) + Complex(1, 0))
+ assert_equal(Complex(1073741788, 1073741789),
+ Complex(1073741789, 1073741789) - Complex(1, 0))
+ assert_equal(Complex(1073741789, 1073741789),
+ Complex(1073741789, 1073741789) * Complex(1, 0))
+ assert_equal(Complex(1073741789, 1073741789),
+ Complex(1073741789, 1073741789) / Complex(1, 0))
+ assert_equal(Complex(2147483578, 1073741789),
+ Complex(1073741789, 1073741789) + Complex(1073741789, 0))
+ assert_equal(Complex(0, 1073741789),
+ Complex(1073741789, 1073741789) - Complex(1073741789, 0))
+ assert_equal(Complex(1152921429444920521, 1152921429444920521),
+ Complex(1073741789, 1073741789) * Complex(1073741789, 0))
+ assert_equal(Complex(1, 1),
+ Complex(1073741789, 1073741789) / Complex(1073741789, 0))
+ assert_equal(Complex(2147483616, 1073741789),
+ Complex(1073741789, 1073741789) + Complex(1073741827, 0))
+ assert_equal(Complex(-38, 1073741789),
+ Complex(1073741789, 1073741789) - Complex(1073741827, 0))
+ assert_equal(Complex(1152921470247108503, 1152921470247108503),
+ Complex(1073741789, 1073741789) * Complex(1073741827, 0))
+ assert_equal(Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)),
+ Complex(1073741789, 1073741789) / Complex(1073741827, 0))
+ assert_equal(Complex(2147483578, 2147483578),
+ Complex(1073741789, 1073741789) + Complex(1073741789, 1073741789))
+ assert_equal(Complex(0, 0),
+ Complex(1073741789, 1073741789) - Complex(1073741789, 1073741789))
+ assert_equal(Complex(0, 2305842858889841042),
+ Complex(1073741789, 1073741789) * Complex(1073741789, 1073741789))
+ assert_equal(Complex(1, 0),
+ Complex(1073741789, 1073741789) / Complex(1073741789, 1073741789))
+ assert_equal(Complex(2147483578, 2147483616),
+ Complex(1073741789, 1073741789) + Complex(1073741789, 1073741827))
+ assert_equal(Complex(0, -38),
+ Complex(1073741789, 1073741789) - Complex(1073741789, 1073741827))
+ assert_equal(Complex(-40802187982, 2305842899692029024),
+ Complex(1073741789, 1073741789) * Complex(1073741789, 1073741827))
+ assert_equal(Complex(Rational(1152921449846014512, 1152921470247109225), Rational(-20401093991, 1152921470247109225)),
+ Complex(1073741789, 1073741789) / Complex(1073741789, 1073741827))
+ assert_equal(Complex(2147483616, 2147483616),
+ Complex(1073741789, 1073741789) + Complex(1073741827, 1073741827))
+ assert_equal(Complex(-38, -38),
+ Complex(1073741789, 1073741789) - Complex(1073741827, 1073741827))
+ assert_equal(Complex(0, 2305842940494217006),
+ Complex(1073741789, 1073741789) * Complex(1073741827, 1073741827))
+ assert_equal(Complex(Rational(1073741789, 1073741827), 0),
+ Complex(1073741789, 1073741789) / Complex(1073741827, 1073741827))
+ assert_equal(Complex(Rational(1152921471320850292, 1073741827), Rational(1152921471320850292, 1073741827)),
+ Complex(1073741789, 1073741789) + Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(Rational(1152921469173366714, 1073741827), Rational(1152921469173366714, 1073741827)),
+ Complex(1073741789, 1073741789) - Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(0, Rational(2305842858889841042, 1073741827)),
+ Complex(1073741789, 1073741789) * Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(1073741827, 0),
+ Complex(1073741789, 1073741789) / Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(Rational(1152921430518662348, 1073741789), Rational(1152921430518662348, 1073741789)),
+ Complex(1073741789, 1073741789) + Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1152921428371178694, 1073741789), Rational(1152921428371178694, 1073741789)),
+ Complex(1073741789, 1073741789) - Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(0, 2147483654),
+ Complex(1073741789, 1073741789) * Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1152921429444920521, 1073741827), 0),
+ Complex(1073741789, 1073741789) / Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1152921471320850292, 1073741827), Rational(1152921430518662348, 1073741789)),
+ Complex(1073741789, 1073741789) + Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1152921469173366714, 1073741827), Rational(1152921428371178694, 1073741789)),
+ Complex(1073741789, 1073741789) - Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(-81604377408, 1073741827), Rational(2305842940494218450, 1073741827)),
+ Complex(1073741789, 1073741789) * Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1427247561112392972813122023043041209197173075, 1329227916556757626754787505905300241), Rational(-50510659935364010697847612929910630368, 1329227916556757626754787505905300241)),
+ Complex(1073741789, 1073741789) / Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(1073741789, 1073741827), +Complex(1073741789, 1073741827))
+ assert_equal(Complex(-1073741789, -1073741827), -Complex(1073741789, 1073741827))
+ assert_equal(Complex(1073741790, 1073741827),
+ Complex(1073741789, 1073741827) + Complex(1, 0))
+ assert_equal(Complex(1073741788, 1073741827),
+ Complex(1073741789, 1073741827) - Complex(1, 0))
+ assert_equal(Complex(1073741789, 1073741827),
+ Complex(1073741789, 1073741827) * Complex(1, 0))
+ assert_equal(Complex(1073741789, 1073741827),
+ Complex(1073741789, 1073741827) / Complex(1, 0))
+ assert_equal(Complex(2147483578, 1073741827),
+ Complex(1073741789, 1073741827) + Complex(1073741789, 0))
+ assert_equal(Complex(0, 1073741827),
+ Complex(1073741789, 1073741827) - Complex(1073741789, 0))
+ assert_equal(Complex(1152921429444920521, 1152921470247108503),
+ Complex(1073741789, 1073741827) * Complex(1073741789, 0))
+ assert_equal(Complex(1, Rational(1073741827, 1073741789)),
+ Complex(1073741789, 1073741827) / Complex(1073741789, 0))
+ assert_equal(Complex(2147483616, 1073741827),
+ Complex(1073741789, 1073741827) + Complex(1073741827, 0))
+ assert_equal(Complex(-38, 1073741827),
+ Complex(1073741789, 1073741827) - Complex(1073741827, 0))
+ assert_equal(Complex(1152921470247108503, 1152921511049297929),
+ Complex(1073741789, 1073741827) * Complex(1073741827, 0))
+ assert_equal(Complex(Rational(1073741789, 1073741827), 1),
+ Complex(1073741789, 1073741827) / Complex(1073741827, 0))
+ assert_equal(Complex(2147483578, 2147483616),
+ Complex(1073741789, 1073741827) + Complex(1073741789, 1073741789))
+ assert_equal(Complex(0, 38),
+ Complex(1073741789, 1073741827) - Complex(1073741789, 1073741789))
+ assert_equal(Complex(-40802187982, 2305842899692029024),
+ Complex(1073741789, 1073741827) * Complex(1073741789, 1073741789))
+ assert_equal(Complex(Rational(1073741808, 1073741789), Rational(19, 1073741789)),
+ Complex(1073741789, 1073741827) / Complex(1073741789, 1073741789))
+ assert_equal(Complex(2147483578, 2147483654),
+ Complex(1073741789, 1073741827) + Complex(1073741789, 1073741827))
+ assert_equal(Complex(0, 0),
+ Complex(1073741789, 1073741827) - Complex(1073741789, 1073741827))
+ assert_equal(Complex(-81604377408, 2305842940494217006),
+ Complex(1073741789, 1073741827) * Complex(1073741789, 1073741827))
+ assert_equal(Complex(1, 0),
+ Complex(1073741789, 1073741827) / Complex(1073741789, 1073741827))
+ assert_equal(Complex(2147483616, 2147483654),
+ Complex(1073741789, 1073741827) + Complex(1073741827, 1073741827))
+ assert_equal(Complex(-38, 0),
+ Complex(1073741789, 1073741827) - Complex(1073741827, 1073741827))
+ assert_equal(Complex(-40802189426, 2305842981296406432),
+ Complex(1073741789, 1073741827) * Complex(1073741827, 1073741827))
+ assert_equal(Complex(Rational(1073741808, 1073741827), Rational(19, 1073741827)),
+ Complex(1073741789, 1073741827) / Complex(1073741827, 1073741827))
+ assert_equal(Complex(Rational(1152921471320850292, 1073741827), Rational(1152921512123039718, 1073741827)),
+ Complex(1073741789, 1073741827) + Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(Rational(1152921469173366714, 1073741827), Rational(1152921509975556140, 1073741827)),
+ Complex(1073741789, 1073741827) - Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(Rational(-40802187982, 1073741827), Rational(2305842899692029024, 1073741827)),
+ Complex(1073741789, 1073741827) * Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(Rational(1152921490648203216, 1073741789), Rational(20401094713, 1073741789)),
+ Complex(1073741789, 1073741827) / Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(Rational(1152921430518662348, 1073741789), Rational(1152921471320850330, 1073741789)),
+ Complex(1073741789, 1073741827) + Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1152921428371178694, 1073741789), Rational(1152921469173366676, 1073741789)),
+ Complex(1073741789, 1073741827) - Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(-40802189426, 1073741789), Rational(2305842981296406432, 1073741789)),
+ Complex(1073741789, 1073741827) * Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1152921449846014512, 1073741827), Rational(20401093991, 1073741827)),
+ Complex(1073741789, 1073741827) / Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1152921471320850292, 1073741827), Rational(1152921471320850330, 1073741789)),
+ Complex(1073741789, 1073741827) + Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1152921469173366714, 1073741827), Rational(1152921469173366676, 1073741789)),
+ Complex(1073741789, 1073741827) - Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(-131433047608170424214, 1152921470247108503), 2147483616),
+ Complex(1073741789, 1073741827) * Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1427247586367724281184137892451027617484788528, 1329227916556757626754787505905300241), Rational(-25255330414578331645234047212843119171, 1329227916556757626754787505905300241)),
+ Complex(1073741789, 1073741827) / Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(1073741827, 1073741827), +Complex(1073741827, 1073741827))
+ assert_equal(Complex(-1073741827, -1073741827), -Complex(1073741827, 1073741827))
+ assert_equal(Complex(1073741828, 1073741827),
+ Complex(1073741827, 1073741827) + Complex(1, 0))
+ assert_equal(Complex(1073741826, 1073741827),
+ Complex(1073741827, 1073741827) - Complex(1, 0))
+ assert_equal(Complex(1073741827, 1073741827),
+ Complex(1073741827, 1073741827) * Complex(1, 0))
+ assert_equal(Complex(1073741827, 1073741827),
+ Complex(1073741827, 1073741827) / Complex(1, 0))
+ assert_equal(Complex(2147483616, 1073741827),
+ Complex(1073741827, 1073741827) + Complex(1073741789, 0))
+ assert_equal(Complex(38, 1073741827),
+ Complex(1073741827, 1073741827) - Complex(1073741789, 0))
+ assert_equal(Complex(1152921470247108503, 1152921470247108503),
+ Complex(1073741827, 1073741827) * Complex(1073741789, 0))
+ assert_equal(Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)),
+ Complex(1073741827, 1073741827) / Complex(1073741789, 0))
+ assert_equal(Complex(2147483654, 1073741827),
+ Complex(1073741827, 1073741827) + Complex(1073741827, 0))
+ assert_equal(Complex(0, 1073741827),
+ Complex(1073741827, 1073741827) - Complex(1073741827, 0))
+ assert_equal(Complex(1152921511049297929, 1152921511049297929),
+ Complex(1073741827, 1073741827) * Complex(1073741827, 0))
+ assert_equal(Complex(1, 1),
+ Complex(1073741827, 1073741827) / Complex(1073741827, 0))
+ assert_equal(Complex(2147483616, 2147483616),
+ Complex(1073741827, 1073741827) + Complex(1073741789, 1073741789))
+ assert_equal(Complex(38, 38),
+ Complex(1073741827, 1073741827) - Complex(1073741789, 1073741789))
+ assert_equal(Complex(0, 2305842940494217006),
+ Complex(1073741827, 1073741827) * Complex(1073741789, 1073741789))
+ assert_equal(Complex(Rational(1073741827, 1073741789), 0),
+ Complex(1073741827, 1073741827) / Complex(1073741789, 1073741789))
+ assert_equal(Complex(2147483616, 2147483654),
+ Complex(1073741827, 1073741827) + Complex(1073741789, 1073741827))
+ assert_equal(Complex(38, 0),
+ Complex(1073741827, 1073741827) - Complex(1073741789, 1073741827))
+ assert_equal(Complex(-40802189426, 2305842981296406432),
+ Complex(1073741827, 1073741827) * Complex(1073741789, 1073741827))
+ assert_equal(Complex(Rational(1152921490648203216, 1152921470247109225), Rational(-20401094713, 1152921470247109225)),
+ Complex(1073741827, 1073741827) / Complex(1073741789, 1073741827))
+ assert_equal(Complex(2147483654, 2147483654),
+ Complex(1073741827, 1073741827) + Complex(1073741827, 1073741827))
+ assert_equal(Complex(0, 0),
+ Complex(1073741827, 1073741827) - Complex(1073741827, 1073741827))
+ assert_equal(Complex(0, 2305843022098595858),
+ Complex(1073741827, 1073741827) * Complex(1073741827, 1073741827))
+ assert_equal(Complex(1, 0),
+ Complex(1073741827, 1073741827) / Complex(1073741827, 1073741827))
+ assert_equal(Complex(Rational(1152921512123039718, 1073741827), Rational(1152921512123039718, 1073741827)),
+ Complex(1073741827, 1073741827) + Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(Rational(1152921509975556140, 1073741827), Rational(1152921509975556140, 1073741827)),
+ Complex(1073741827, 1073741827) - Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(0, 2147483578),
+ Complex(1073741827, 1073741827) * Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(Rational(1152921511049297929, 1073741789), 0),
+ Complex(1073741827, 1073741827) / Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(Rational(1152921471320850330, 1073741789), Rational(1152921471320850330, 1073741789)),
+ Complex(1073741827, 1073741827) + Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1152921469173366676, 1073741789), Rational(1152921469173366676, 1073741789)),
+ Complex(1073741827, 1073741827) - Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(0, Rational(2305843022098595858, 1073741789)),
+ Complex(1073741827, 1073741827) * Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(1073741789, 0),
+ Complex(1073741827, 1073741827) / Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1152921512123039718, 1073741827), Rational(1152921471320850330, 1073741789)),
+ Complex(1073741827, 1073741827) + Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1152921509975556140, 1073741827), Rational(1152921469173366676, 1073741789)),
+ Complex(1073741827, 1073741827) - Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(-81604377408, 1073741789), Rational(2305842940494218450, 1073741789)),
+ Complex(1073741827, 1073741827) * Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1427247611623053801969816945064593334552299725, 1329227916556757626754787505905300241), Rational(-50510661722949347514642033621130734624, 1329227916556757626754787505905300241)),
+ Complex(1073741827, 1073741827) / Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)), +Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(Rational(-1073741789, 1073741827), Rational(-1073741789, 1073741827)), -Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(Rational(2147483616, 1073741827), Rational(1073741789, 1073741827)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) + Complex(1, 0))
+ assert_equal(Complex(Rational(-38, 1073741827), Rational(1073741789, 1073741827)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) - Complex(1, 0))
+ assert_equal(Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) * Complex(1, 0))
+ assert_equal(Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) / Complex(1, 0))
+ assert_equal(Complex(Rational(1152921471320850292, 1073741827), Rational(1073741789, 1073741827)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) + Complex(1073741789, 0))
+ assert_equal(Complex(Rational(-1152921469173366714, 1073741827), Rational(1073741789, 1073741827)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) - Complex(1073741789, 0))
+ assert_equal(Complex(Rational(1152921429444920521, 1073741827), Rational(1152921429444920521, 1073741827)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) * Complex(1073741789, 0))
+ assert_equal(Complex(Rational(1, 1073741827), Rational(1, 1073741827)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) / Complex(1073741789, 0))
+ assert_equal(Complex(Rational(1152921512123039718, 1073741827), Rational(1073741789, 1073741827)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) + Complex(1073741827, 0))
+ assert_equal(Complex(Rational(-1152921509975556140, 1073741827), Rational(1073741789, 1073741827)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) - Complex(1073741827, 0))
+ assert_equal(Complex(1073741789, 1073741789),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) * Complex(1073741827, 0))
+ assert_equal(Complex(Rational(1073741789, 1152921511049297929), Rational(1073741789, 1152921511049297929)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) / Complex(1073741827, 0))
+ assert_equal(Complex(Rational(1152921471320850292, 1073741827), Rational(1152921471320850292, 1073741827)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) + Complex(1073741789, 1073741789))
+ assert_equal(Complex(Rational(-1152921469173366714, 1073741827), Rational(-1152921469173366714, 1073741827)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) - Complex(1073741789, 1073741789))
+ assert_equal(Complex(0, Rational(2305842858889841042, 1073741827)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) * Complex(1073741789, 1073741789))
+ assert_equal(Complex(Rational(1, 1073741827), 0),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) / Complex(1073741789, 1073741789))
+ assert_equal(Complex(Rational(1152921471320850292, 1073741827), Rational(1152921512123039718, 1073741827)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) + Complex(1073741789, 1073741827))
+ assert_equal(Complex(Rational(-1152921469173366714, 1073741827), Rational(-1152921509975556140, 1073741827)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) - Complex(1073741789, 1073741827))
+ assert_equal(Complex(Rational(-40802187982, 1073741827), Rational(2305842899692029024, 1073741827)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) * Complex(1073741789, 1073741827))
+ assert_equal(Complex(Rational(1152921449846014512, 1237940005850657200720054075), Rational(-20401093991, 1237940005850657200720054075)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) / Complex(1073741789, 1073741827))
+ assert_equal(Complex(Rational(1152921512123039718, 1073741827), Rational(1152921512123039718, 1073741827)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) + Complex(1073741827, 1073741827))
+ assert_equal(Complex(Rational(-1152921509975556140, 1073741827), Rational(-1152921509975556140, 1073741827)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) - Complex(1073741827, 1073741827))
+ assert_equal(Complex(0, 2147483578),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) * Complex(1073741827, 1073741827))
+ assert_equal(Complex(Rational(1073741789, 1152921511049297929), 0),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) / Complex(1073741827, 1073741827))
+ assert_equal(Complex(Rational(2147483578, 1073741827), Rational(2147483578, 1073741827)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) + Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(0, 0),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) - Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(0, Rational(2305842858889841042, 1152921511049297929)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) * Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(1, 0),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) / Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(Rational(2305842940494218450, 1152921470247108503), Rational(2305842940494218450, 1152921470247108503)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) + Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(-81604377408, 1152921470247108503), Rational(-81604377408, 1152921470247108503)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) - Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(0, 2),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) * Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1152921429444920521, 1152921511049297929), 0),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) / Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(2147483578, 1073741827), Rational(2305842940494218450, 1152921470247108503)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) + Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(0, Rational(-81604377408, 1152921470247108503)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) - Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(-81604377408, 1152921511049297929), Rational(2305842940494218450, 1152921511049297929)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) * Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1329227869515036572020512360130906225, 1329227916556757626754787505905300241), Rational(-47041717725097069072123994784, 1329227916556757626754787505905300241)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)) / Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)), +Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(-1073741827, 1073741789), Rational(-1073741827, 1073741789)), -Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(2147483616, 1073741789), Rational(1073741827, 1073741789)),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) + Complex(1, 0))
+ assert_equal(Complex(Rational(38, 1073741789), Rational(1073741827, 1073741789)),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) - Complex(1, 0))
+ assert_equal(Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) * Complex(1, 0))
+ assert_equal(Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) / Complex(1, 0))
+ assert_equal(Complex(Rational(1152921430518662348, 1073741789), Rational(1073741827, 1073741789)),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) + Complex(1073741789, 0))
+ assert_equal(Complex(Rational(-1152921428371178694, 1073741789), Rational(1073741827, 1073741789)),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) - Complex(1073741789, 0))
+ assert_equal(Complex(1073741827, 1073741827),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) * Complex(1073741789, 0))
+ assert_equal(Complex(Rational(1073741827, 1152921429444920521), Rational(1073741827, 1152921429444920521)),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) / Complex(1073741789, 0))
+ assert_equal(Complex(Rational(1152921471320850330, 1073741789), Rational(1073741827, 1073741789)),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) + Complex(1073741827, 0))
+ assert_equal(Complex(Rational(-1152921469173366676, 1073741789), Rational(1073741827, 1073741789)),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) - Complex(1073741827, 0))
+ assert_equal(Complex(Rational(1152921511049297929, 1073741789), Rational(1152921511049297929, 1073741789)),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) * Complex(1073741827, 0))
+ assert_equal(Complex(Rational(1, 1073741789), Rational(1, 1073741789)),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) / Complex(1073741827, 0))
+ assert_equal(Complex(Rational(1152921430518662348, 1073741789), Rational(1152921430518662348, 1073741789)),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) + Complex(1073741789, 1073741789))
+ assert_equal(Complex(Rational(-1152921428371178694, 1073741789), Rational(-1152921428371178694, 1073741789)),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) - Complex(1073741789, 1073741789))
+ assert_equal(Complex(0, 2147483654),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) * Complex(1073741789, 1073741789))
+ assert_equal(Complex(Rational(1073741827, 1152921429444920521), 0),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) / Complex(1073741789, 1073741789))
+ assert_equal(Complex(Rational(1152921430518662348, 1073741789), Rational(1152921471320850330, 1073741789)),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) + Complex(1073741789, 1073741827))
+ assert_equal(Complex(Rational(-1152921428371178694, 1073741789), Rational(-1152921469173366676, 1073741789)),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) - Complex(1073741789, 1073741827))
+ assert_equal(Complex(Rational(-40802189426, 1073741789), Rational(2305842981296406432, 1073741789)),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) * Complex(1073741789, 1073741827))
+ assert_equal(Complex(Rational(1152921490648203216, 1237939962039641331329903525), Rational(-20401094713, 1237939962039641331329903525)),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) / Complex(1073741789, 1073741827))
+ assert_equal(Complex(Rational(1152921471320850330, 1073741789), Rational(1152921471320850330, 1073741789)),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) + Complex(1073741827, 1073741827))
+ assert_equal(Complex(Rational(-1152921469173366676, 1073741789), Rational(-1152921469173366676, 1073741789)),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) - Complex(1073741827, 1073741827))
+ assert_equal(Complex(0, Rational(2305843022098595858, 1073741789)),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) * Complex(1073741827, 1073741827))
+ assert_equal(Complex(Rational(1, 1073741789), 0),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) / Complex(1073741827, 1073741827))
+ assert_equal(Complex(Rational(2305842940494218450, 1152921470247108503), Rational(2305842940494218450, 1152921470247108503)),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) + Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(Rational(81604377408, 1152921470247108503), Rational(81604377408, 1152921470247108503)),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) - Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(0, 2),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) * Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(Rational(1152921511049297929, 1152921429444920521), 0),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) / Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(Rational(2147483654, 1073741789), Rational(2147483654, 1073741789)),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) + Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(0, 0),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) - Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(0, Rational(2305843022098595858, 1152921429444920521)),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) * Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(1, 0),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) / Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(2305842940494218450, 1152921470247108503), Rational(2147483654, 1073741789)),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) + Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(81604377408, 1152921470247108503), 0),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) - Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(-81604377408, 1152921429444920521), Rational(2305842940494218450, 1152921429444920521)),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) * Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1329227963598475351851856578029295025, 1329227916556757626754787505905300241), Rational(-47041721054734275145774394016, 1329227916556757626754787505905300241)),
+ Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)) / Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)), +Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(-1073741789, 1073741827), Rational(-1073741827, 1073741789)), -Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(2147483616, 1073741827), Rational(1073741827, 1073741789)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) + Complex(1, 0))
+ assert_equal(Complex(Rational(-38, 1073741827), Rational(1073741827, 1073741789)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) - Complex(1, 0))
+ assert_equal(Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) * Complex(1, 0))
+ assert_equal(Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) / Complex(1, 0))
+ assert_equal(Complex(Rational(1152921471320850292, 1073741827), Rational(1073741827, 1073741789)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) + Complex(1073741789, 0))
+ assert_equal(Complex(Rational(-1152921469173366714, 1073741827), Rational(1073741827, 1073741789)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) - Complex(1073741789, 0))
+ assert_equal(Complex(Rational(1152921429444920521, 1073741827), 1073741827),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) * Complex(1073741789, 0))
+ assert_equal(Complex(Rational(1, 1073741827), Rational(1073741827, 1152921429444920521)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) / Complex(1073741789, 0))
+ assert_equal(Complex(Rational(1152921512123039718, 1073741827), Rational(1073741827, 1073741789)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) + Complex(1073741827, 0))
+ assert_equal(Complex(Rational(-1152921509975556140, 1073741827), Rational(1073741827, 1073741789)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) - Complex(1073741827, 0))
+ assert_equal(Complex(1073741789, Rational(1152921511049297929, 1073741789)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) * Complex(1073741827, 0))
+ assert_equal(Complex(Rational(1073741789, 1152921511049297929), Rational(1, 1073741789)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) / Complex(1073741827, 0))
+ assert_equal(Complex(Rational(1152921471320850292, 1073741827), Rational(1152921430518662348, 1073741789)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) + Complex(1073741789, 1073741789))
+ assert_equal(Complex(Rational(-1152921469173366714, 1073741827), Rational(-1152921428371178694, 1073741789)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) - Complex(1073741789, 1073741789))
+ assert_equal(Complex(Rational(-81604377408, 1073741827), Rational(2305842940494218450, 1073741827)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) * Complex(1073741789, 1073741789))
+ assert_equal(Complex(Rational(1152921470247109225, 1237939962039640556088331867), Rational(40802188704, 1237939962039640556088331867)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) / Complex(1073741789, 1073741789))
+ assert_equal(Complex(Rational(1152921471320850292, 1073741827), Rational(1152921471320850330, 1073741789)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) + Complex(1073741789, 1073741827))
+ assert_equal(Complex(Rational(-1152921469173366714, 1073741827), Rational(-1152921469173366676, 1073741789)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) - Complex(1073741789, 1073741827))
+ assert_equal(Complex(Rational(-131433047608170424214, 1152921470247108503), 2147483616),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) * Complex(1073741789, 1073741827))
+ assert_equal(Complex(Rational(1237939983945150041266564176, 1329227916556755129526882950667240175), Rational(19, 1152921470247109225)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) / Complex(1073741789, 1073741827))
+ assert_equal(Complex(Rational(1152921512123039718, 1073741827), Rational(1152921471320850330, 1073741789)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) + Complex(1073741827, 1073741827))
+ assert_equal(Complex(Rational(-1152921509975556140, 1073741827), Rational(-1152921469173366676, 1073741789)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) - Complex(1073741827, 1073741827))
+ assert_equal(Complex(Rational(-81604377408, 1073741789), Rational(2305842940494218450, 1073741789)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) * Complex(1073741827, 1073741827))
+ assert_equal(Complex(Rational(1152921470247109225, 1237940005850656425478454981), Rational(40802188704, 1237940005850656425478454981)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) / Complex(1073741827, 1073741827))
+ assert_equal(Complex(Rational(2147483578, 1073741827), Rational(2305842940494218450, 1152921470247108503)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) + Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(0, Rational(81604377408, 1152921470247108503)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) - Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(Rational(-81604377408, 1152921511049297929), Rational(2305842940494218450, 1152921511049297929)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) * Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(Rational(1152921470247109225, 1152921429444920521), Rational(40802188704, 1152921429444920521)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) / Complex(Rational(1073741789, 1073741827), Rational(1073741789, 1073741827)))
+ assert_equal(Complex(Rational(2305842940494218450, 1152921470247108503), Rational(2147483654, 1073741789)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) + Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(-81604377408, 1152921470247108503), 0),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) - Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(-81604377408, 1152921429444920521), Rational(2305842940494218450, 1152921429444920521)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) * Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(1152921470247109225, 1152921511049297929), Rational(40802188704, 1152921511049297929)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) / Complex(Rational(1073741827, 1073741789), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(2147483578, 1073741827), Rational(2147483654, 1073741789)),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) + Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(0, 0),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) - Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(Rational(-188166877559662688435796777600, 1329227916556754297117581432254901009), 2),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) * Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ assert_equal(Complex(1, 0),
+ Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)) / Complex(Rational(1073741789, 1073741827), Rational(1073741827, 1073741789)))
+ end
+
+ def test_kumi2
+ assert_equal('0.0+0.0i', (+Complex(+0.0, +0.0)).to_s)
+ assert_equal('-0.0-0.0i', (-Complex(+0.0, +0.0)).to_s)
+ assert_equal('0.0+0.0i', (Complex(+0.0, +0.0) + Complex(+0.0, +0.0)).to_s)
+ assert_equal('0.0+0.0i', (Complex(+0.0, +0.0) - Complex(+0.0, +0.0)).to_s)
+ assert_equal('0.0+0.0i', (Complex(+0.0, +0.0) * Complex(+0.0, +0.0)).to_s)
+ assert_equal('0.0+0.0i', (Complex(+0.0, +0.0) + Complex(-0.0, +0.0)).to_s)
+ assert_equal('0.0+0.0i', (Complex(+0.0, +0.0) - Complex(-0.0, +0.0)).to_s)
+ assert_equal('-0.0+0.0i', (Complex(+0.0, +0.0) * Complex(-0.0, +0.0)).to_s)
+ assert_equal('0.0+0.0i', (Complex(+0.0, +0.0) + Complex(+0.0, -0.0)).to_s)
+ assert_equal('0.0+0.0i', (Complex(+0.0, +0.0) - Complex(+0.0, -0.0)).to_s)
+ assert_equal('0.0+0.0i', (Complex(+0.0, +0.0) * Complex(+0.0, -0.0)).to_s)
+ assert_equal('0.0+0.0i', (Complex(+0.0, +0.0) + Complex(-0.0, -0.0)).to_s)
+ assert_equal('0.0+0.0i', (Complex(+0.0, +0.0) - Complex(-0.0, -0.0)).to_s)
+ assert_equal('0.0-0.0i', (Complex(+0.0, +0.0) * Complex(-0.0, -0.0)).to_s)
+ assert_equal('-0.0+0.0i', (+Complex(-0.0, +0.0)).to_s)
+ assert_equal('0.0-0.0i', (-Complex(-0.0, +0.0)).to_s)
+ assert_equal('0.0+0.0i', (Complex(-0.0, +0.0) + Complex(+0.0, +0.0)).to_s)
+ assert_equal('-0.0+0.0i', (Complex(-0.0, +0.0) - Complex(+0.0, +0.0)).to_s)
+ assert_equal('-0.0+0.0i', (Complex(-0.0, +0.0) * Complex(+0.0, +0.0)).to_s)
+ assert_equal('-0.0+0.0i', (Complex(-0.0, +0.0) + Complex(-0.0, +0.0)).to_s)
+ assert_equal('0.0+0.0i', (Complex(-0.0, +0.0) - Complex(-0.0, +0.0)).to_s)
+ assert_equal('0.0-0.0i', (Complex(-0.0, +0.0) * Complex(-0.0, +0.0)).to_s)
+ assert_equal('0.0+0.0i', (Complex(-0.0, +0.0) + Complex(+0.0, -0.0)).to_s)
+ assert_equal('-0.0+0.0i', (Complex(-0.0, +0.0) - Complex(+0.0, -0.0)).to_s)
+ assert_equal('0.0+0.0i', (Complex(-0.0, +0.0) * Complex(+0.0, -0.0)).to_s)
+ assert_equal('-0.0+0.0i', (Complex(-0.0, +0.0) + Complex(-0.0, -0.0)).to_s)
+ assert_equal('0.0+0.0i', (Complex(-0.0, +0.0) - Complex(-0.0, -0.0)).to_s)
+ assert_equal('0.0+0.0i', (Complex(-0.0, +0.0) * Complex(-0.0, -0.0)).to_s)
+ assert_equal('0.0-0.0i', (+Complex(+0.0, -0.0)).to_s)
+ assert_equal('-0.0+0.0i', (-Complex(+0.0, -0.0)).to_s)
+ assert_equal('0.0+0.0i', (Complex(+0.0, -0.0) + Complex(+0.0, +0.0)).to_s)
+ assert_equal('0.0-0.0i', (Complex(+0.0, -0.0) - Complex(+0.0, +0.0)).to_s)
+ assert_equal('0.0+0.0i', (Complex(+0.0, -0.0) * Complex(+0.0, +0.0)).to_s)
+ assert_equal('0.0+0.0i', (Complex(+0.0, -0.0) + Complex(-0.0, +0.0)).to_s)
+ assert_equal('0.0-0.0i', (Complex(+0.0, -0.0) - Complex(-0.0, +0.0)).to_s)
+ assert_equal('0.0+0.0i', (Complex(+0.0, -0.0) * Complex(-0.0, +0.0)).to_s)
+ assert_equal('0.0-0.0i', (Complex(+0.0, -0.0) + Complex(+0.0, -0.0)).to_s)
+ assert_equal('0.0+0.0i', (Complex(+0.0, -0.0) - Complex(+0.0, -0.0)).to_s)
+ assert_equal('0.0-0.0i', (Complex(+0.0, -0.0) * Complex(+0.0, -0.0)).to_s)
+ assert_equal('0.0-0.0i', (Complex(+0.0, -0.0) + Complex(-0.0, -0.0)).to_s)
+ assert_equal('0.0+0.0i', (Complex(+0.0, -0.0) - Complex(-0.0, -0.0)).to_s)
+ assert_equal('-0.0+0.0i', (Complex(+0.0, -0.0) * Complex(-0.0, -0.0)).to_s)
+ assert_equal('-0.0-0.0i', (+Complex(-0.0, -0.0)).to_s)
+ assert_equal('0.0+0.0i', (-Complex(-0.0, -0.0)).to_s)
+ assert_equal('0.0+0.0i', (Complex(-0.0, -0.0) + Complex(+0.0, +0.0)).to_s)
+ assert_equal('-0.0-0.0i', (Complex(-0.0, -0.0) - Complex(+0.0, +0.0)).to_s)
+ assert_equal('0.0-0.0i', (Complex(-0.0, -0.0) * Complex(+0.0, +0.0)).to_s)
+ assert_equal('-0.0+0.0i', (Complex(-0.0, -0.0) + Complex(-0.0, +0.0)).to_s)
+ assert_equal('0.0-0.0i', (Complex(-0.0, -0.0) - Complex(-0.0, +0.0)).to_s)
+ assert_equal('0.0+0.0i', (Complex(-0.0, -0.0) * Complex(-0.0, +0.0)).to_s)
+ assert_equal('0.0-0.0i', (Complex(-0.0, -0.0) + Complex(+0.0, -0.0)).to_s)
+ assert_equal('-0.0+0.0i', (Complex(-0.0, -0.0) - Complex(+0.0, -0.0)).to_s)
+ assert_equal('-0.0+0.0i', (Complex(-0.0, -0.0) * Complex(+0.0, -0.0)).to_s)
+ assert_equal('-0.0-0.0i', (Complex(-0.0, -0.0) + Complex(-0.0, -0.0)).to_s)
+ assert_equal('0.0+0.0i', (Complex(-0.0, -0.0) - Complex(-0.0, -0.0)).to_s)
+ assert_equal('0.0+0.0i', (Complex(-0.0, -0.0) * Complex(-0.0, -0.0)).to_s)
+ end
+
+end
diff --git a/test/ruby/test_complexrational.rb b/test/ruby/test_complexrational.rb
new file mode 100644
index 0000000000..47c535fca0
--- /dev/null
+++ b/test/ruby/test_complexrational.rb
@@ -0,0 +1,407 @@
+require 'test/unit'
+
+class ComplexRational_Test < Test::Unit::TestCase
+
+ def test_rat_srat
+ return unless defined?(Rational)
+
+ c = SimpleRat(1,3)
+ cc = Rational(3,2)
+
+ assert_kind_of(Numeric, c)
+ assert_kind_of(Numeric, cc)
+
+ assert_instance_of(SimpleRat, c)
+ assert_instance_of(Rational, cc)
+
+ assert_equal(SimpleRat(1,3), +c)
+ assert_equal(SimpleRat(-1,3), -c)
+
+ assert_equal(SimpleRat(7,3), c + 2)
+ assert_equal(SimpleRat(-5,3), c - 2)
+ assert_equal(SimpleRat(2,3), c * 2)
+ assert_equal(SimpleRat(1,6), c / 2)
+ assert_equal(SimpleRat(1,9), c ** 2)
+ assert_equal(-1, c <=> 2)
+
+ assert_equal(SimpleRat(7,3), 2 + c)
+ assert_equal(SimpleRat(5,3), 2 - c)
+ assert_equal(SimpleRat(2,3), 2 * c)
+ assert_equal(SimpleRat(6,1), 2 / c)
+ assert_in_delta(1.2599, 2 ** c, 0.001)
+ assert_equal(1, 2 <=> c)
+
+ assert_equal(SimpleRat(11,6), c + cc)
+ assert_equal(SimpleRat(-7,6), c - cc)
+ assert_equal(SimpleRat(1,2), c * cc)
+ assert_equal(SimpleRat(2,9), c / cc)
+ assert_in_delta(0.1924, c ** cc, 0.001)
+ assert_equal(-1, c <=> cc)
+
+ assert_equal(SimpleRat(11,6), cc + c)
+ assert_equal(SimpleRat(7,6), cc - c)
+ assert_equal(SimpleRat(1,2), cc * c)
+ assert_equal(SimpleRat(9,2), cc / c)
+ assert_in_delta(1.1447, cc ** c, 0.001)
+ assert_equal(1, cc <=> c)
+
+ assert_equal(SimpleRat, (+c).class)
+ assert_equal(SimpleRat, (-c).class)
+
+ assert_equal(SimpleRat, (c + 2).class)
+ assert_equal(SimpleRat, (c - 2).class)
+ assert_equal(SimpleRat, (c * 2).class)
+ assert_equal(SimpleRat, (c / 2).class)
+ assert_equal(SimpleRat, (c ** 2).class)
+
+ assert_equal(SimpleRat, (2 + c).class)
+ assert_equal(SimpleRat, (2 - c).class)
+ assert_equal(SimpleRat, (2 * c).class)
+ assert_equal(SimpleRat, (2 / c).class)
+ assert_equal(Float, (2 ** c).class)
+
+ assert_equal(SimpleRat, (c + cc).class)
+ assert_equal(SimpleRat, (c - cc).class)
+ assert_equal(SimpleRat, (c * cc).class)
+ assert_equal(SimpleRat, (c / cc).class)
+ assert_equal(Float, (c ** cc).class)
+
+ assert_equal(SimpleRat, (cc + c).class)
+ assert_equal(SimpleRat, (cc - c).class)
+ assert_equal(SimpleRat, (cc * c).class)
+ assert_equal(SimpleRat, (cc / c).class)
+ assert_equal(Float, (cc ** c).class)
+
+ assert_equal(0, Rational(2,3) <=> SimpleRat(2,3))
+ assert_equal(0, SimpleRat(2,3) <=> Rational(2,3))
+ assert(Rational(2,3) == SimpleRat(2,3))
+ assert(SimpleRat(2,3) == Rational(2,3))
+
+ assert_equal(SimpleRat, (c + 0).class)
+ assert_equal(SimpleRat, (c - 0).class)
+ assert_equal(SimpleRat, (c * 0).class)
+ assert_equal(SimpleRat, (c * 1).class)
+ assert_equal(SimpleRat, (0 + c).class)
+ assert_equal(SimpleRat, (0 - c).class)
+ assert_equal(SimpleRat, (0 * c).class)
+ assert_equal(SimpleRat, (1 * c).class)
+ end
+
+ def test_comp_srat
+ return unless defined?(Rational)
+
+ c = Complex(SimpleRat(2,3),SimpleRat(1,2))
+ cc = Complex(Rational(3,2),Rational(2,1))
+
+ assert_equal(Complex(SimpleRat(2,3),SimpleRat(1,2)), +c)
+ assert_equal(Complex(SimpleRat(-2,3),SimpleRat(-1,2)), -c)
+
+ assert_equal(Complex(SimpleRat(8,3),SimpleRat(1,2)), c + 2)
+ assert_equal(Complex(SimpleRat(-4,3),SimpleRat(1,2)), c - 2)
+ assert_equal(Complex(SimpleRat(4,3),SimpleRat(1,1)), c * 2)
+ assert_equal(Complex(SimpleRat(1,3),SimpleRat(1,4)), c / 2)
+ assert_equal(Complex(SimpleRat(7,36),SimpleRat(2,3)), c ** 2)
+ assert_raise(NoMethodError){c <=> 2}
+
+ assert_equal(Complex(SimpleRat(8,3),SimpleRat(1,2)), 2 + c)
+ assert_equal(Complex(SimpleRat(4,3),SimpleRat(-1,2)), 2 - c)
+ assert_equal(Complex(SimpleRat(4,3),SimpleRat(1,1)), 2 * c)
+ assert_equal(Complex(SimpleRat(48,25),SimpleRat(-36,25)), 2 / c)
+ r = 2 ** c
+ assert_in_delta(1.4940, r.real, 0.001)
+ assert_in_delta(0.5392, r.imag, 0.001)
+ assert_raise(NoMethodError){2 <=> c}
+
+ assert_equal(Complex(SimpleRat(13,6),SimpleRat(5,2)), c + cc)
+ assert_equal(Complex(SimpleRat(-5,6),SimpleRat(-3,2)), c - cc)
+ assert_equal(Complex(SimpleRat(0,1),SimpleRat(25,12)), c * cc)
+ assert_equal(Complex(SimpleRat(8,25),SimpleRat(-7,75)), c / cc)
+ r = c ** cc
+ assert_in_delta(0.1732, r.real, 0.001)
+ assert_in_delta(0.1186, r.imag, 0.001)
+ assert_raise(NoMethodError){c <=> cc}
+
+ assert_equal(Complex(SimpleRat(13,6),SimpleRat(5,2)), cc + c)
+ assert_equal(Complex(SimpleRat(5,6),SimpleRat(3,2)), cc - c)
+ assert_equal(Complex(SimpleRat(0,1),SimpleRat(25,12)), cc * c)
+ assert_equal(Complex(SimpleRat(72,25),SimpleRat(21,25)), cc / c)
+ r = cc ** c
+ assert_in_delta(0.5498, r.real, 0.001)
+ assert_in_delta(1.0198, r.imag, 0.001)
+ assert_raise(NoMethodError){cc <=> c}
+
+ assert_equal([SimpleRat,SimpleRat],
+ (+c).instance_eval{[real.class, imag.class]})
+ assert_equal([SimpleRat,SimpleRat],
+ (-c).instance_eval{[real.class, imag.class]})
+
+ assert_equal([SimpleRat,SimpleRat],
+ (c + 2).instance_eval{[real.class, imag.class]})
+ assert_equal([SimpleRat,SimpleRat],
+ (c - 2).instance_eval{[real.class, imag.class]})
+ assert_equal([SimpleRat,SimpleRat],
+ (c * 2).instance_eval{[real.class, imag.class]})
+ assert_equal([SimpleRat,SimpleRat],
+ (c / 2).instance_eval{[real.class, imag.class]})
+ assert_equal([SimpleRat,SimpleRat],
+ (c ** 2).instance_eval{[real.class, imag.class]})
+
+ assert_equal([SimpleRat,SimpleRat],
+ (c + cc).instance_eval{[real.class, imag.class]})
+ assert_equal([SimpleRat,SimpleRat],
+ (c - cc).instance_eval{[real.class, imag.class]})
+ assert_equal([SimpleRat,SimpleRat],
+ (c * cc).instance_eval{[real.class, imag.class]})
+ assert_equal([SimpleRat,SimpleRat],
+ (c / cc).instance_eval{[real.class, imag.class]})
+ assert_equal([Float,Float],
+ (c ** cc).instance_eval{[real.class, imag.class]})
+
+ assert_equal([SimpleRat,SimpleRat],
+ (cc + c).instance_eval{[real.class, imag.class]})
+ assert_equal([SimpleRat,SimpleRat],
+ (cc - c).instance_eval{[real.class, imag.class]})
+ assert_equal([SimpleRat,SimpleRat],
+ (cc * c).instance_eval{[real.class, imag.class]})
+ assert_equal([SimpleRat,SimpleRat],
+ (cc / c).instance_eval{[real.class, imag.class]})
+ assert_equal([Float,Float],
+ (cc ** c).instance_eval{[real.class, imag.class]})
+
+ assert(Complex(SimpleRat(2,3),SimpleRat(3,2)) ==
+ Complex(Rational(2,3),Rational(3,2)))
+ assert(Complex(Rational(2,3),Rational(3,2)) ==
+ Complex(SimpleRat(2,3),SimpleRat(3,2)))
+
+ assert_equal([SimpleRat,SimpleRat],
+ (c + 0).instance_eval{[real.class, imag.class]})
+ assert_equal([SimpleRat,SimpleRat],
+ (c - 0).instance_eval{[real.class, imag.class]})
+ assert_equal([SimpleRat,SimpleRat],
+ (c * 0).instance_eval{[real.class, imag.class]})
+ assert_equal([SimpleRat,SimpleRat],
+ (c * 1).instance_eval{[real.class, imag.class]})
+ assert_equal([SimpleRat,SimpleRat],
+ (0 + c).instance_eval{[real.class, imag.class]})
+ assert_equal([SimpleRat,SimpleRat],
+ (0 - c).instance_eval{[real.class, imag.class]})
+ assert_equal([SimpleRat,SimpleRat],
+ (0 * c).instance_eval{[real.class, imag.class]})
+ assert_equal([SimpleRat,SimpleRat],
+ (1 * c).instance_eval{[real.class, imag.class]})
+ end
+
+end
+
+def SimpleRat(*a) SimpleRat.new(*a) end
+
+class SimpleRat < Numeric
+
+ def initialize(num, den = 1)
+ if den == 0
+ raise ZeroDivisionError, "divided by zero"
+ end
+ if den < 0
+ num = -num
+ den = -den
+ end
+ gcd = num.gcd(den)
+ @num = num.div(gcd)
+ @den = den.div(gcd)
+ end
+
+ def numerator() @num end
+ def denominator() @den end
+
+ def +@ () self end
+ def -@ () self.class.new(-@num, @den) end
+
+ def + (o)
+ case o
+ when SimpleRat, Rational
+ a = @num * o.denominator
+ b = o.numerator * @den
+ self.class.new(a + b, @den * o.denominator)
+ when Integer
+ self + self.class.new(o)
+ when Float
+ to_f + o
+ else
+ x, y = o.coerce(self)
+ x + y
+ end
+ end
+
+ def - (o)
+ case o
+ when SimpleRat, Rational
+ a = @num * o.denominator
+ b = o.numerator * @den
+ self.class.new(a - b, @den * o.denominator)
+ when Integer
+ self - self.class.new(o)
+ when Float
+ to_f - o
+ else
+ x, y = o.coerce(self)
+ x - y
+ end
+ end
+
+ def * (o)
+ case o
+ when SimpleRat, Rational
+ a = @num * o.numerator
+ b = @den * o.denominator
+ self.class.new(a, b)
+ when Integer
+ self * self.class.new(o)
+ when Float
+ to_f * o
+ else
+ x, y = o.coerce(self)
+ x * y
+ end
+ end
+
+ def quo(o)
+ case o
+ when SimpleRat, Rational
+ a = @num * o.denominator
+ b = @den * o.numerator
+ self.class.new(a, b)
+ when Integer
+ if o == 0
+ raise raise ZeroDivisionError, "divided by zero"
+ end
+ self.quo(self.class.new(o))
+ when Float
+ to_f.quo(o)
+ else
+ x, y = o.coerce(self)
+ x.quo(y)
+ end
+ end
+
+ alias / quo
+
+ def floor
+ @num.div(@den)
+ end
+
+ def ceil
+ -((-@num).div(@den))
+ end
+
+ def truncate
+ if @num < 0
+ return -((-@num).div(@den))
+ end
+ @num.div(@den)
+ end
+
+ alias to_i truncate
+
+ def round
+ if @num < 0
+ num = -@num
+ num = num * 2 + @den
+ den = @den * 2
+ -(num.div(den))
+ else
+ num = @num * 2 + @den
+ den = @den * 2
+ num.div(den)
+ end
+ end
+
+ def div(o) (self / o).floor end
+ def quot(o) (self / o).truncate end
+
+ def modulo(o)
+ q = div(o)
+ self - o * q
+ end
+
+ def remainder(o)
+ q = quot(o)
+ self - o * q
+ end
+
+ alias % modulo
+
+ def divmod(o) [div(o), modulo(o)] end
+ def quotrem(o) [quot(o), remainder(o)] end
+
+ def ** (o)
+ case o
+ when SimpleRat, Rational
+ Float(self) ** o
+ when Integer
+ if o > 0
+ a = @num ** o
+ b = @den ** o
+ elsif o < 0
+ a = @den ** -o
+ b = @num ** -o
+ else
+ a = b = 1
+ end
+ self.class.new(a, b)
+ when Float
+ to_f ** o
+ else
+ x, y = o.coerce(self)
+ x ** y
+ end
+ end
+
+ def <=> (o)
+ case o
+ when SimpleRat, Rational
+ a = @num * o.denominator
+ b = o.numerator * @den
+ return a <=> b
+ when Integer
+ self <=> self.class.new(o)
+ when Float
+ to_f <=> o
+ else
+ x, y = o.coerce(self)
+ x <=> y
+ end
+ end
+
+ def == (o)
+ begin
+ (self <=> o) == 0
+ rescue
+ false
+ end
+ end
+
+ def coerce(o)
+ case o
+ when Rational
+ [self.class.new(o.numerator, o.denominator), self]
+ when Integer
+ [self.class.new(o), self]
+ when Float
+ [o, self.to_f]
+ else
+ super
+ end
+ end
+
+ def hash() @num.hash ^ @den.hash end
+
+ def to_f() @num.to_f / @den.to_f end
+ def to_r() self end
+ def to_s() format('%s/%s', @num, @den) end
+
+ def inspect() format('#SR(%s)', to_s) end
+
+ def marshal_dump() [@num, @den] end
+ def marshal_load(a) @num, @den = a end
+
+end
diff --git a/test/ruby/test_econv.rb b/test/ruby/test_econv.rb
index 1b2586a040..0f1d18a8e5 100644
--- a/test/ruby/test_econv.rb
+++ b/test/ruby/test_econv.rb
@@ -37,7 +37,7 @@ class TestEncodingConverter < Test::Unit::TestCase
assert_nil(Encoding::Converter.asciicompat_encoding("EUC-JP"))
assert_nil(Encoding::Converter.asciicompat_encoding("UTF-8"))
assert_nil(Encoding::Converter.asciicompat_encoding(Encoding::UTF_8))
- assert_nil(Encoding::Converter.asciicompat_encoding("xml-attr-escaped"))
+ assert_nil(Encoding::Converter.asciicompat_encoding("xml_attr_escape"))
assert_nil(Encoding::Converter.asciicompat_encoding("encoding-not-exist"))
end
@@ -49,16 +49,38 @@ class TestEncodingConverter < Test::Unit::TestCase
assert_equal(str, str3)
end
- def test_new
+ def test_s_new
assert_kind_of(Encoding::Converter, Encoding::Converter.new("UTF-8", "EUC-JP"))
assert_kind_of(Encoding::Converter, Encoding::Converter.new(Encoding::UTF_8, Encoding::EUC_JP))
end
- def test_new_fail
+ def test_s_new_convpath
+ assert_equal([], Encoding::Converter.new([]).convpath)
+ assert_equal([[Encoding::UTF_8, Encoding::EUC_JP]],
+ Encoding::Converter.new([["UTF-8", "EUC-JP"]]).convpath)
+ assert_equal([[Encoding::UTF_8, Encoding::WINDOWS_31J]],
+ Encoding::Converter.new([["utf-8", "cp932"]]).convpath)
+ assert_equal([[Encoding::UTF_8, Encoding::EUC_JP]],
+ Encoding::Converter.new([[Encoding::UTF_8, Encoding::EUC_JP]]).convpath)
+ assert_equal([[Encoding::ISO_8859_1, Encoding::UTF_8],
+ [Encoding::UTF_8, Encoding::EUC_JP]],
+ Encoding::Converter.new([["iso-8859-1", "euc-jp"]]).convpath)
+ assert_equal([[Encoding::ISO_8859_1, Encoding::UTF_8],
+ [Encoding::UTF_8, Encoding::EUC_JP],
+ "universal_newline"],
+ Encoding::Converter.new([["iso-8859-1", "euc-jp"], "universal_newline"]).convpath)
+ assert_equal(["universal_newline",
+ [Encoding::ISO_8859_1, Encoding::UTF_8],
+ [Encoding::UTF_8, Encoding::EUC_JP],
+ "universal_newline"],
+ Encoding::Converter.new(["universal_newline", ["iso-8859-1", "euc-jp"], "universal_newline"]).convpath)
+ end
+
+ def test_s_new_fail
name1 = "encoding-which-is-not-exist-1"
name2 = "encoding-which-is-not-exist-2"
- assert_raise(Encoding::NoConverter) {
+ assert_raise(Encoding::ConverterNotFoundError) {
Encoding::Converter.new(name1, name2)
}
@@ -68,24 +90,24 @@ class TestEncodingConverter < Test::Unit::TestCase
end
def test_newline_converter_with_ascii_incompatible
- assert_raise(Encoding::NoConverter) {
- Encoding::Converter.new("UTF-8", "UTF-16BE", Encoding::Converter::UNIVERSAL_NEWLINE_DECODER)
+ assert_nothing_raised {
+ Encoding::Converter.new("UTF-8", "UTF-16BE", Encoding::Converter::UNIVERSAL_NEWLINE_DECORATOR)
}
- assert_raise(Encoding::NoConverter) {
- Encoding::Converter.new("UTF-16BE", "UTF-8", Encoding::Converter::CRLF_NEWLINE_ENCODER)
+ assert_nothing_raised {
+ Encoding::Converter.new("UTF-16BE", "UTF-8", Encoding::Converter::CRLF_NEWLINE_DECORATOR)
}
- assert_raise(Encoding::NoConverter) {
- Encoding::Converter.new("UTF-16BE", "UTF-8", Encoding::Converter::CR_NEWLINE_ENCODER)
+ assert_nothing_raised {
+ Encoding::Converter.new("UTF-16BE", "UTF-8", Encoding::Converter::CR_NEWLINE_DECORATOR)
}
assert_nothing_raised {
- Encoding::Converter.new("UTF-16BE", "UTF-8", Encoding::Converter::UNIVERSAL_NEWLINE_DECODER)
+ Encoding::Converter.new("UTF-16BE", "UTF-8", Encoding::Converter::UNIVERSAL_NEWLINE_DECORATOR)
}
assert_nothing_raised {
- Encoding::Converter.new("UTF-8", "UTF-16BE", Encoding::Converter::CRLF_NEWLINE_ENCODER)
+ Encoding::Converter.new("UTF-8", "UTF-16BE", Encoding::Converter::CRLF_NEWLINE_DECORATOR)
}
assert_nothing_raised {
- Encoding::Converter.new("UTF-8", "UTF-16BE", Encoding::Converter::CR_NEWLINE_ENCODER)
+ Encoding::Converter.new("UTF-8", "UTF-16BE", Encoding::Converter::CR_NEWLINE_DECORATOR)
}
end
@@ -256,14 +278,14 @@ class TestEncodingConverter < Test::Unit::TestCase
def test_invalid4
ec = Encoding::Converter.new("Shift_JIS", "EUC-JP")
- a = ["", "abc\xFFdef", ec, nil, 10, :output_followed_by_input=>true]
- check_ec("a", "bc\xFFdef", :output_followed_by_input, *a)
- check_ec("ab", "c\xFFdef", :output_followed_by_input, *a)
- check_ec("abc", "\xFFdef", :output_followed_by_input, *a)
+ a = ["", "abc\xFFdef", ec, nil, 10, :after_output=>true]
+ check_ec("a", "bc\xFFdef", :after_output, *a)
+ check_ec("ab", "c\xFFdef", :after_output, *a)
+ check_ec("abc", "\xFFdef", :after_output, *a)
check_ec("abc", "def", :invalid_byte_sequence, *a)
- check_ec("abcd", "ef", :output_followed_by_input, *a)
- check_ec("abcde", "f", :output_followed_by_input, *a)
- check_ec("abcdef", "", :output_followed_by_input, *a)
+ check_ec("abcd", "ef", :after_output, *a)
+ check_ec("abcde", "f", :after_output, *a)
+ check_ec("abcdef", "", :after_output, *a)
check_ec("abcdef", "", :finished, *a)
end
@@ -363,16 +385,16 @@ class TestEncodingConverter < Test::Unit::TestCase
def test_errors2
ec = Encoding::Converter.new("UTF-16BE", "EUC-JP")
- a = ["", "\xFF\xFE\x00A\xDC\x00\x00B", ec, nil, 10, :output_followed_by_input=>true]
+ a = ["", "\xFF\xFE\x00A\xDC\x00\x00B", ec, nil, 10, :after_output=>true]
check_ec("", "\x00A\xDC\x00\x00B", :undefined_conversion, *a)
- check_ec("A", "\xDC\x00\x00B", :output_followed_by_input, *a)
+ check_ec("A", "\xDC\x00\x00B", :after_output, *a)
check_ec("A", "\x00B", :invalid_byte_sequence, *a)
- check_ec("AB", "", :output_followed_by_input, *a)
+ check_ec("AB", "", :after_output, *a)
check_ec("AB", "", :finished, *a)
end
def test_universal_newline
- ec = Encoding::Converter.new("UTF-8", "EUC-JP", universal_newline_decoder: true)
+ ec = Encoding::Converter.new("UTF-8", "EUC-JP", universal_newline: true)
a = ["", src="", ec, nil, 50, :partial_input=>true]
src << "abc\r\ndef"; check_ec("abc\ndef", "", :source_buffer_empty, *a)
src << "ghi\njkl"; check_ec("abc\ndefghi\njkl", "", :source_buffer_empty, *a)
@@ -383,7 +405,7 @@ class TestEncodingConverter < Test::Unit::TestCase
end
def test_universal_newline2
- ec = Encoding::Converter.new("", "", universal_newline_decoder: true)
+ ec = Encoding::Converter.new("", "", universal_newline: true)
a = ["", src="", ec, nil, 50, :partial_input=>true]
src << "abc\r\ndef"; check_ec("abc\ndef", "", :source_buffer_empty, *a)
src << "ghi\njkl"; check_ec("abc\ndefghi\njkl", "", :source_buffer_empty, *a)
@@ -394,35 +416,35 @@ class TestEncodingConverter < Test::Unit::TestCase
end
def test_crlf_newline
- ec = Encoding::Converter.new("UTF-8", "EUC-JP", crlf_newline_encoder: true)
+ ec = Encoding::Converter.new("UTF-8", "EUC-JP", crlf_newline: true)
assert_econv("abc\r\ndef", :finished, 50, ec, "abc\ndef", "")
end
def test_crlf_newline2
- ec = Encoding::Converter.new("", "", crlf_newline_encoder: true)
+ ec = Encoding::Converter.new("", "", crlf_newline: true)
assert_econv("abc\r\ndef", :finished, 50, ec, "abc\ndef", "")
end
def test_cr_newline
- ec = Encoding::Converter.new("UTF-8", "EUC-JP", cr_newline_encoder: true)
+ ec = Encoding::Converter.new("UTF-8", "EUC-JP", cr_newline: true)
assert_econv("abc\rdef", :finished, 50, ec, "abc\ndef", "")
end
def test_cr_newline2
- ec = Encoding::Converter.new("", "", cr_newline_encoder: true)
+ ec = Encoding::Converter.new("", "", cr_newline: true)
assert_econv("abc\rdef", :finished, 50, ec, "abc\ndef", "")
end
- def test_output_followed_by_input
+ def test_after_output
ec = Encoding::Converter.new("UTF-8", "EUC-JP")
- a = ["", "abc\u{3042}def", ec, nil, 100, :output_followed_by_input=>true]
- check_ec("a", "bc\u{3042}def", :output_followed_by_input, *a)
- check_ec("ab", "c\u{3042}def", :output_followed_by_input, *a)
- check_ec("abc", "\u{3042}def", :output_followed_by_input, *a)
- check_ec("abc\xA4\xA2", "def", :output_followed_by_input, *a)
- check_ec("abc\xA4\xA2d", "ef", :output_followed_by_input, *a)
- check_ec("abc\xA4\xA2de", "f", :output_followed_by_input, *a)
- check_ec("abc\xA4\xA2def", "", :output_followed_by_input, *a)
+ a = ["", "abc\u{3042}def", ec, nil, 100, :after_output=>true]
+ check_ec("a", "bc\u{3042}def", :after_output, *a)
+ check_ec("ab", "c\u{3042}def", :after_output, *a)
+ check_ec("abc", "\u{3042}def", :after_output, *a)
+ check_ec("abc\xA4\xA2", "def", :after_output, *a)
+ check_ec("abc\xA4\xA2d", "ef", :after_output, *a)
+ check_ec("abc\xA4\xA2de", "f", :after_output, *a)
+ check_ec("abc\xA4\xA2def", "", :after_output, *a)
check_ec("abc\xA4\xA2def", "", :finished, *a)
end
@@ -491,7 +513,7 @@ class TestEncodingConverter < Test::Unit::TestCase
ec.primitive_convert("", dst, nil, 10, :partial_input=>true)
assert_equal("\e$B!!\e(B???\e$B!\"!!!\#$\"".force_encoding("ISO-2022-JP"), dst)
- assert_raise(Encoding::ConversionUndefined) {
+ assert_raise(Encoding::UndefinedConversionError) {
ec.insert_output("\uFFFD")
}
@@ -502,7 +524,7 @@ class TestEncodingConverter < Test::Unit::TestCase
end
def test_exc_invalid
- err = assert_raise(Encoding::InvalidByteSequence) {
+ err = assert_raise(Encoding::InvalidByteSequenceError) {
"abc\xa4def".encode("ISO-8859-1", "EUC-JP")
}
assert_equal("EUC-JP", err.source_encoding_name)
@@ -515,7 +537,7 @@ class TestEncodingConverter < Test::Unit::TestCase
end
def test_exc_incomplete
- err = assert_raise(Encoding::InvalidByteSequence) {
+ err = assert_raise(Encoding::InvalidByteSequenceError) {
"abc\xa4".encode("ISO-8859-1", "EUC-JP")
}
assert_equal("EUC-JP", err.source_encoding_name)
@@ -528,7 +550,7 @@ class TestEncodingConverter < Test::Unit::TestCase
end
def test_exc_undef
- err = assert_raise(Encoding::ConversionUndefined) {
+ err = assert_raise(Encoding::UndefinedConversionError) {
"abc\xa4\xa2def".encode("ISO-8859-1", "EUC-JP")
}
assert_equal("UTF-8", err.source_encoding_name)
@@ -612,16 +634,16 @@ class TestEncodingConverter < Test::Unit::TestCase
check_ec("abcdefg", "", :source_buffer_empty, *a)
end
- def test_noconv_output_followed_by_input
+ def test_noconv_after_output
ec = Encoding::Converter.new("", "")
- a = ["", "abcdefg", ec, nil, 2, :output_followed_by_input=>true]
- check_ec("a", "bcdefg", :output_followed_by_input, *a)
- check_ec("ab", "cdefg", :output_followed_by_input, *a)
- check_ec("abc", "defg", :output_followed_by_input, *a)
- check_ec("abcd", "efg", :output_followed_by_input, *a)
- check_ec("abcde", "fg", :output_followed_by_input, *a)
- check_ec("abcdef", "g", :output_followed_by_input, *a)
- check_ec("abcdefg", "", :output_followed_by_input, *a)
+ a = ["", "abcdefg", ec, nil, 2, :after_output=>true]
+ check_ec("a", "bcdefg", :after_output, *a)
+ check_ec("ab", "cdefg", :after_output, *a)
+ check_ec("abc", "defg", :after_output, *a)
+ check_ec("abcd", "efg", :after_output, *a)
+ check_ec("abcde", "fg", :after_output, *a)
+ check_ec("abcdef", "g", :after_output, *a)
+ check_ec("abcdefg", "", :after_output, *a)
check_ec("abcdefg", "", :finished, *a)
end
@@ -635,8 +657,8 @@ class TestEncodingConverter < Test::Unit::TestCase
def test_convert
ec = Encoding::Converter.new("utf-8", "euc-jp")
- assert_raise(Encoding::InvalidByteSequence) { ec.convert("a\x80") }
- assert_raise(Encoding::ConversionUndefined) { ec.convert("\ufffd") }
+ assert_raise(Encoding::InvalidByteSequenceError) { ec.convert("a\x80") }
+ assert_raise(Encoding::UndefinedConversionError) { ec.convert("\ufffd") }
ret = ec.primitive_convert(nil, "", nil, nil)
assert_equal(:finished, ret)
assert_raise(ArgumentError) { ec.convert("a") }
@@ -652,28 +674,28 @@ class TestEncodingConverter < Test::Unit::TestCase
def test_finish_incomplete_error
ec = Encoding::Converter.new("utf-8", "euc-jp")
ec.convert("\xEF")
- assert_raise(Encoding::InvalidByteSequence) { ec.finish }
+ assert_raise(Encoding::InvalidByteSequenceError) { ec.finish }
end
def test_last_error1
ec = Encoding::Converter.new("sjis", "euc-jp")
assert_equal(nil, ec.last_error)
assert_equal(:incomplete_input, ec.primitive_convert(src="fo\x81", dst="", nil, nil))
- assert_kind_of(Encoding::InvalidByteSequence, ec.last_error)
+ assert_kind_of(Encoding::InvalidByteSequenceError, ec.last_error)
end
def test_last_error2
ec = Encoding::Converter.new("sjis", "euc-jp")
assert_equal("fo", ec.convert(src="fo\x81"))
- assert_raise(Encoding::InvalidByteSequence) { ec.finish }
- assert_kind_of(Encoding::InvalidByteSequence, ec.last_error)
+ assert_raise(Encoding::InvalidByteSequenceError) { ec.finish }
+ assert_kind_of(Encoding::InvalidByteSequenceError, ec.last_error)
end
def test_us_ascii
ec = Encoding::Converter.new("UTF-8", "US-ASCII")
ec.primitive_convert(src="\u{3042}", dst="")
err = ec.last_error
- assert_kind_of(Encoding::ConversionUndefined, err)
+ assert_kind_of(Encoding::UndefinedConversionError, err)
assert_equal("\u{3042}", err.error_char)
end
@@ -681,7 +703,7 @@ class TestEncodingConverter < Test::Unit::TestCase
ec = Encoding::Converter.new("UTF-8", "ISO-8859-1")
ec.primitive_convert(src="\u{3042}", dst="")
err = ec.last_error
- assert_kind_of(Encoding::ConversionUndefined, err)
+ assert_kind_of(Encoding::UndefinedConversionError, err)
assert_equal("\u{3042}", err.error_char)
end
@@ -733,62 +755,62 @@ class TestEncodingConverter < Test::Unit::TestCase
end
def test_xml_escape_text
- ec = Encoding::Converter.new("", "amp-escaped")
+ ec = Encoding::Converter.new("", "amp_escape")
assert_equal('&amp;<>"', ec.convert("&<>\""))
assert_equal('', ec.finish)
- ec = Encoding::Converter.new("", "xml-text-escaped")
+ ec = Encoding::Converter.new("", "xml_text_escape")
assert_equal('&amp;&lt;&gt;"', ec.convert("&<>\""))
assert_equal('', ec.finish)
end
def test_xml_escape_attr_content
- ec = Encoding::Converter.new("", "xml-attr-content-escaped")
+ ec = Encoding::Converter.new("", "xml_attr_content_escape")
assert_equal('', ec.finish)
- ec = Encoding::Converter.new("", "xml-attr-content-escaped")
+ ec = Encoding::Converter.new("", "xml_attr_content_escape")
assert_equal('', ec.convert(""))
assert_equal('', ec.finish)
- ec = Encoding::Converter.new("", "xml-attr-content-escaped")
+ ec = Encoding::Converter.new("", "xml_attr_content_escape")
assert_equal('&quot;', ec.convert('"'))
assert_equal('', ec.finish)
- ec = Encoding::Converter.new("", "xml-attr-content-escaped")
+ ec = Encoding::Converter.new("", "xml_attr_content_escape")
assert_equal('&amp;&lt;&gt;&quot;', ec.convert("&<>\""))
assert_equal('', ec.finish)
end
def test_xml_escape_attr_quote
- ec = Encoding::Converter.new("", "xml-attr-quoted")
+ ec = Encoding::Converter.new("", "xml_attr_quote")
assert_equal('""', ec.finish)
- ec = Encoding::Converter.new("", "xml-attr-quoted")
+ ec = Encoding::Converter.new("", "xml_attr_quote")
assert_equal('', ec.convert(""))
assert_equal('""', ec.finish)
- ec = Encoding::Converter.new("", "xml-attr-quoted")
+ ec = Encoding::Converter.new("", "xml_attr_quote")
assert_equal('""', ec.convert('"'))
assert_equal('"', ec.finish)
- ec = Encoding::Converter.new("", "xml-attr-quoted")
+ ec = Encoding::Converter.new("", "xml_attr_quote")
assert_equal('"&<>"', ec.convert("&<>\""))
assert_equal('"', ec.finish)
end
def test_xml_escape_with_charref
- ec = Encoding::Converter.new("utf-8", "euc-jp", Encoding::Converter::XML_TEXT_ENCODER|Encoding::Converter::UNDEF_HEX_CHARREF)
+ ec = Encoding::Converter.new("utf-8", "euc-jp", Encoding::Converter::XML_TEXT_DECORATOR|Encoding::Converter::UNDEF_HEX_CHARREF)
assert_equal('&lt;&#x2665;&gt;&amp;"&#x2661;"', ec.convert("<\u2665>&\"\u2661\""))
assert_equal('', ec.finish)
ec = Encoding::Converter.new("utf-8", "euc-jp",
- Encoding::Converter::XML_ATTR_CONTENT_ENCODER|
- Encoding::Converter::XML_ATTR_QUOTE_ENCODER|
+ Encoding::Converter::XML_ATTR_CONTENT_DECORATOR|
+ Encoding::Converter::XML_ATTR_QUOTE_DECORATOR|
Encoding::Converter::UNDEF_HEX_CHARREF)
assert_equal('"&lt;&#x2665;&gt;&amp;&quot;&#x2661;&quot;', ec.convert("<\u2665>&\"\u2661\""))
assert_equal('"', ec.finish)
- ec = Encoding::Converter.new("utf-8", "iso-2022-jp", Encoding::Converter::XML_TEXT_ENCODER)
+ ec = Encoding::Converter.new("utf-8", "iso-2022-jp", Encoding::Converter::XML_TEXT_DECORATOR)
assert_equal("&amp;\e$B$&\e(B&amp;".force_encoding("iso-2022-jp"), ec.convert("&\u3046&"))
assert_equal('', ec.finish)
end
@@ -807,4 +829,53 @@ class TestEncodingConverter < Test::Unit::TestCase
assert_equal("?x".force_encoding("iso-2022-jp"),
"\222\xA1x".encode("iso-2022-jp", "stateless-iso-2022-jp", :invalid => :replace))
end
+
+ def test_convpath
+ eucjp = Encoding::EUC_JP
+ utf8 = Encoding::UTF_8
+ utf16be = Encoding::UTF_16BE
+ utf16le = Encoding::UTF_16LE
+ iso88591 = Encoding::ISO_8859_1
+ iso2022jp = Encoding::ISO_2022_JP
+ siso2022jp = Encoding::STATELESS_ISO_2022_JP
+
+ assert_equal([], Encoding::Converter.new("", "").convpath)
+ assert_equal([[eucjp, utf8], [utf8, iso88591]],
+ Encoding::Converter.new(eucjp, iso88591).convpath)
+ assert_equal([[eucjp, siso2022jp], [siso2022jp, iso2022jp]],
+ Encoding::Converter.new(eucjp, iso2022jp).convpath)
+ assert_equal([[iso2022jp, siso2022jp],
+ [siso2022jp, eucjp],
+ [eucjp, utf8],
+ [utf8, iso88591]],
+ Encoding::Converter.new(iso2022jp, iso88591).convpath)
+ assert_equal(["universal_newline", [utf8, utf16be]],
+ Encoding::Converter.new(utf8, utf16be, universal_newline: true).convpath)
+ assert_equal([[utf16be, utf8], "universal_newline"],
+ Encoding::Converter.new(utf16be, utf8, universal_newline: true).convpath)
+ assert_equal([[utf16be, utf8], "universal_newline", [utf8, utf16le]],
+ Encoding::Converter.new(utf16be, utf16le, universal_newline: true).convpath)
+ end
+
+ def test_search_convpath
+ eucjp = Encoding::EUC_JP
+ utf8 = Encoding::UTF_8
+ utf32be = Encoding::UTF_32BE
+ iso88591 = Encoding::ISO_8859_1
+ assert_equal([[iso88591,utf8], [utf8,eucjp]],
+ Encoding::Converter.search_convpath("ISO-8859-1", "EUC-JP"))
+ assert_equal([[iso88591,utf8], [utf8,eucjp]],
+ Encoding::Converter.search_convpath(iso88591, eucjp))
+ assert_equal([[iso88591,utf8], [utf8,eucjp], "universal_newline"],
+ Encoding::Converter.search_convpath("ISO-8859-1", "EUC-JP", universal_newline: true))
+ assert_equal([[iso88591,utf8], "universal_newline", [utf8,utf32be]],
+ Encoding::Converter.search_convpath("ISO-8859-1", "UTF-32BE", universal_newline: true))
+ end
+
+ def test_invalid_replace
+ assert_raise(ArgumentError) {
+ broken = "\x80".force_encoding("euc-jp")
+ "".encode("euc-jp", :undef => :replace, :replace => broken)
+ }
+ end
end
diff --git a/test/ruby/test_encoding.rb b/test/ruby/test_encoding.rb
index 24000796fa..9f48d30d1d 100644
--- a/test/ruby/test_encoding.rb
+++ b/test/ruby/test_encoding.rb
@@ -14,6 +14,15 @@ class TestEncoding < Test::Unit::TestCase
assert_equal(e, Encoding.find(e.name.downcase))
end
end
+
+ def test_enc_names
+ aliases = Encoding.aliases
+ aliases.each do |a, en|
+ e = Encoding.find(a)
+ assert_equal(e.name, en)
+ assert(e.names.include?(a))
+ end
+ end
# Test that Encoding objects can't be copied
# And that they can be compared by object_id
diff --git a/test/ruby/test_env.rb b/test/ruby/test_env.rb
index 28f0e87b59..65fd79fa8f 100644
--- a/test/ruby/test_env.rb
+++ b/test/ruby/test_env.rb
@@ -1,8 +1,8 @@
require 'test/unit'
class TestEnv < Test::Unit::TestCase
- IGNORE_CASE = /djgpp|bccwin|mswin|mingw/ =~ RUBY_PLATFORM
- PATH_ENV = /human68k/ =~ RUBY_PLATFORM ? "path" : "PATH"
+ IGNORE_CASE = /bccwin|mswin|mingw/ =~ RUBY_PLATFORM
+ PATH_ENV = "PATH"
def setup
@verbose = $VERBOSE
@@ -36,13 +36,13 @@ class TestEnv < Test::Unit::TestCase
assert_equal('foo', ENV['test'])
end
- assert_raises(TypeError) {
+ assert_raise(TypeError) {
tmp = ENV[1]
}
- assert_raises(TypeError) {
+ assert_raise(TypeError) {
ENV[1] = 'foo'
}
- assert_raises(TypeError) {
+ assert_raise(TypeError) {
ENV['test'] = 0
}
end
@@ -118,7 +118,8 @@ class TestEnv < Test::Unit::TestCase
ENV["test"] = "foo"
end.join
end
- assert_raise(TypeError) { ENV["test"] = nil }
+ assert_nothing_raised { ENV["test"] = nil }
+ assert_equal(nil, ENV["test"])
assert_raise(ArgumentError) { ENV["foo\0bar"] = "test" }
assert_raise(ArgumentError) { ENV["test"] = "foo\0bar" }
ENV[PATH_ENV] = "/tmp/".taint
diff --git a/test/ruby/test_exception.rb b/test/ruby/test_exception.rb
index 3300fcdd74..cba88f5c90 100644
--- a/test/ruby/test_exception.rb
+++ b/test/ruby/test_exception.rb
@@ -24,7 +24,7 @@ class TestException < Test::Unit::TestCase
# exception in rescue clause
$string = "this must be handled no.3"
- e = assert_raises(RuntimeError) do
+ e = assert_raise(RuntimeError) do
begin
raise "exception in rescue clause"
rescue
@@ -36,7 +36,7 @@ class TestException < Test::Unit::TestCase
# exception in ensure clause
$string = "exception in ensure clause"
- e = assert_raises(RuntimeError) do
+ e = assert_raise(RuntimeError) do
begin
raise "this must be handled no.4"
ensure
diff --git a/test/ruby/test_file.rb b/test/ruby/test_file.rb
index f6fcf89a14..b4666ad4a6 100644
--- a/test/ruby/test_file.rb
+++ b/test/ruby/test_file.rb
@@ -42,8 +42,9 @@ class TestFile < Test::Unit::TestCase
f.print "abc"
f.truncate(0)
f.print "def"
- f.close
+ f.flush
assert_equal("\0\0\0def", File.read(f.path), "[ruby-dev:24191]")
+ f.close
end
def test_truncate_rbuf
@@ -65,40 +66,77 @@ class TestFile < Test::Unit::TestCase
end
def test_read_all_extended_file
- f = Tempfile.new("test-extended-file")
- assert_nil(f.getc)
- open(f.path, "w") {|g| g.print "a" }
- assert_equal("a", f.read)
+ [nil, {:textmode=>true}, {:binmode=>true}].each do |mode|
+ f = Tempfile.new("test-extended-file", mode)
+ assert_nil(f.getc)
+ f.print "a"
+ f.rewind
+ assert_equal("a", f.read, "mode = <#{mode}>")
+ end
end
def test_gets_extended_file
- f = Tempfile.new("test-extended-file")
- assert_nil(f.getc)
- open(f.path, "w") {|g| g.print "a" }
- assert_equal("a", f.gets("a"))
+ [nil, {:textmode=>true}, {:binmode=>true}].each do |mode|
+ f = Tempfile.new("test-extended-file", mode)
+ assert_nil(f.getc)
+ f.print "a"
+ f.rewind
+ assert_equal("a", f.gets("a"), "mode = <#{mode}>")
+ end
end
def test_gets_para_extended_file
- f = Tempfile.new("test-extended-file")
- assert_nil(f.getc)
- open(f.path, "w") {|g| g.print "\na" }
- assert_equal("a", f.gets(""))
+ [nil, {:textmode=>true}, {:binmode=>true}].each do |mode|
+ f = Tempfile.new("test-extended-file", mode)
+ assert_nil(f.getc)
+ f.print "\na"
+ f.rewind
+ assert_equal("a", f.gets(""), "mode = <#{mode}>")
+ end
+ end
+
+ def test_each_char_extended_file
+ [nil, {:textmode=>true}, {:binmode=>true}].each do |mode|
+ f = Tempfile.new("test-extended-file", mode)
+ assert_nil(f.getc)
+ f.print "a"
+ f.rewind
+ result = []
+ f.each_char {|b| result << b }
+ assert_equal([?a], result, "mode = <#{mode}>")
+ end
end
def test_each_byte_extended_file
- f = Tempfile.new("test-extended-file")
- assert_nil(f.getc)
- open(f.path, "w") {|g| g.print "a" }
- result = []
- f.each_byte {|b| result << b.chr }
- assert_equal([?a], result)
+ [nil, {:textmode=>true}, {:binmode=>true}].each do |mode|
+ f = Tempfile.new("test-extended-file", mode)
+ assert_nil(f.getc)
+ f.print "a"
+ f.rewind
+ result = []
+ f.each_byte {|b| result << b.chr }
+ assert_equal([?a], result, "mode = <#{mode}>")
+ end
end
def test_getc_extended_file
- f = Tempfile.new("test-extended-file")
- assert_nil(f.getc)
- open(f.path, "w") {|g| g.print "a" }
- assert_equal(?a, f.getc)
+ [nil, {:textmode=>true}, {:binmode=>true}].each do |mode|
+ f = Tempfile.new("test-extended-file", mode)
+ assert_nil(f.getc)
+ f.print "a"
+ f.rewind
+ assert_equal(?a, f.getc, "mode = <#{mode}>")
+ end
+ end
+
+ def test_getbyte_extended_file
+ [nil, {:textmode=>true}, {:binmode=>true}].each do |mode|
+ f = Tempfile.new("test-extended-file", mode)
+ assert_nil(f.getc)
+ f.print "a"
+ f.rewind
+ assert_equal(?a, f.getbyte.chr, "mode = <#{mode}>")
+ end
end
def test_s_chown
diff --git a/test/ruby/test_fixnum.rb b/test/ruby/test_fixnum.rb
index 8fa751ba98..e55e324bd1 100644
--- a/test/ruby/test_fixnum.rb
+++ b/test/ruby/test_fixnum.rb
@@ -119,15 +119,6 @@ class TestFixnum < Test::Unit::TestCase
assert_equal(0x4000000000000000, (-0x4000000000000000).abs)
end
- def test_induced_from
- assert_equal(1, Fixnum.induced_from(1))
- assert_raise(RangeError) do
- Fixnum.induced_from(2**31-1)
- Fixnum.induced_from(2**63-1)
- end
- assert_equal(1, Fixnum.induced_from((2**32).coerce(1).first))
- end
-
def test_to_s
assert_equal("1010", 10.to_s(2))
assert_equal("a", 10.to_s(36))
diff --git a/test/ruby/test_float.rb b/test/ruby/test_float.rb
index d4bbd688d2..5d7bbb178b 100644
--- a/test/ruby/test_float.rb
+++ b/test/ruby/test_float.rb
@@ -275,13 +275,6 @@ class TestFloat < Test::Unit::TestCase
assert_equal(11100.0, 11111.1.round(-2))
end
- def test_induced_from
- assert_equal(1.0, Float.induced_from(1))
- assert_equal(1.0, Float.induced_from(1.0))
- assert_raise(TypeError) { Float.induced_from(nil) }
- end
-
-
VS = [
18446744073709551617.0,
18446744073709551616.0,
diff --git a/test/ruby/test_hash.rb b/test/ruby/test_hash.rb
index de0ba37fb7..5a17ac4fb5 100644
--- a/test/ruby/test_hash.rb
+++ b/test/ruby/test_hash.rb
@@ -627,6 +627,7 @@ class TestHash < Test::Unit::TestCase
assert_equal(h.inspect, h.to_s)
h = @cls[]
assert_equal(h.inspect, h.to_s)
+ ensure
$, = nil
end
diff --git a/test/ruby/test_integer.rb b/test/ruby/test_integer.rb
index e31fb1880d..232a7fae30 100644
--- a/test/ruby/test_integer.rb
+++ b/test/ruby/test_integer.rb
@@ -122,12 +122,6 @@ class TestInteger < Test::Unit::TestCase
assert_raise(RangeError) { 0x100.chr }
end
- def test_induced_from
- assert_equal(1, Integer.induced_from(1))
- assert_equal(1, Integer.induced_from(1.0))
- assert_raise(TypeError) { Integer.induced_from(nil) }
- end
-
def test_upto
a = []
1.upto(3) {|x| a << x }
diff --git a/test/ruby/test_io.rb b/test/ruby/test_io.rb
index 35f575aa13..34a8d017c0 100644
--- a/test/ruby/test_io.rb
+++ b/test/ruby/test_io.rb
@@ -1,5 +1,6 @@
require 'test/unit'
require 'tmpdir'
+require "fcntl"
require 'io/nonblock'
require 'socket'
require 'stringio'
@@ -8,6 +9,19 @@ require 'tempfile'
require_relative 'envutil'
class TestIO < Test::Unit::TestCase
+ def have_close_on_exec?
+ begin
+ $stdin.close_on_exec?
+ true
+ rescue NotImplementedError
+ false
+ end
+ end
+
+ def have_nonblock?
+ IO.instance_methods.index(:"nonblock=")
+ end
+
def test_gets_rs
# default_rs
r, w = IO.pipe
@@ -236,18 +250,20 @@ class TestIO < Test::Unit::TestCase
assert_equal(content[1,1], r.read)
}
- with_read_pipe("abc") {|r1|
- assert_equal("a", r1.getc)
- with_pipe {|r2, w2|
- w2.nonblock = true
- s = w2.syswrite("a" * 100000)
- t = Thread.new { sleep 0.1; r2.read }
- ret = IO.copy_stream(r1, w2)
- w2.close
- assert_equal(2, ret)
- assert_equal("a" * s + "bc", t.value)
+ if have_nonblock?
+ with_read_pipe("abc") {|r1|
+ assert_equal("a", r1.getc)
+ with_pipe {|r2, w2|
+ w2.nonblock = true
+ s = w2.syswrite("a" * 100000)
+ t = Thread.new { sleep 0.1; r2.read }
+ ret = IO.copy_stream(r1, w2)
+ w2.close
+ assert_equal(2, ret)
+ assert_equal("a" * s + "bc", t.value)
+ }
}
- }
+ end
bigcontent = "abc" * 123456
File.open("bigsrc", "w") {|f| f << bigcontent }
@@ -266,15 +282,19 @@ class TestIO < Test::Unit::TestCase
assert_equal(bigcontent[100, 30000], File.read("bigdst"))
File.open("bigsrc") {|f|
- assert_equal(0, f.pos)
- ret = IO.copy_stream(f, "bigdst", nil, 10)
- assert_equal(bigcontent.bytesize-10, ret)
- assert_equal(bigcontent[10..-1], File.read("bigdst"))
- assert_equal(0, f.pos)
- ret = IO.copy_stream(f, "bigdst", 40, 30)
- assert_equal(40, ret)
- assert_equal(bigcontent[30, 40], File.read("bigdst"))
- assert_equal(0, f.pos)
+ begin
+ assert_equal(0, f.pos)
+ ret = IO.copy_stream(f, "bigdst", nil, 10)
+ assert_equal(bigcontent.bytesize-10, ret)
+ assert_equal(bigcontent[10..-1], File.read("bigdst"))
+ assert_equal(0, f.pos)
+ ret = IO.copy_stream(f, "bigdst", 40, 30)
+ assert_equal(40, ret)
+ assert_equal(bigcontent[30, 40], File.read("bigdst"))
+ assert_equal(0, f.pos)
+ rescue NotImplementedError
+ #skip "pread(2) is not implemtented."
+ end
}
with_pipe {|r, w|
@@ -285,19 +305,21 @@ class TestIO < Test::Unit::TestCase
megacontent = "abc" * 1234567
File.open("megasrc", "w") {|f| f << megacontent }
- with_pipe {|r1, w1|
- with_pipe {|r2, w2|
- t1 = Thread.new { w1 << megacontent; w1.close }
- t2 = Thread.new { r2.read }
- r1.nonblock = true
- w2.nonblock = true
- ret = IO.copy_stream(r1, w2)
- assert_equal(megacontent.bytesize, ret)
- w2.close
- t1.join
- assert_equal(megacontent, t2.value)
+ if have_nonblock?
+ with_pipe {|r1, w1|
+ with_pipe {|r2, w2|
+ t1 = Thread.new { w1 << megacontent; w1.close }
+ t2 = Thread.new { r2.read }
+ r1.nonblock = true
+ w2.nonblock = true
+ ret = IO.copy_stream(r1, w2)
+ assert_equal(megacontent.bytesize, ret)
+ w2.close
+ t1.join
+ assert_equal(megacontent, t2.value)
+ }
}
- }
+ end
with_pipe {|r1, w1|
with_pipe {|r2, w2|
@@ -323,15 +345,19 @@ class TestIO < Test::Unit::TestCase
def test_copy_stream_rbuf
mkcdtmpdir {
- with_pipe {|r, w|
- File.open("foo", "w") {|f| f << "abcd" }
- File.open("foo") {|f|
- f.read(1)
- assert_equal(3, IO.copy_stream(f, w, 10, 1))
+ begin
+ with_pipe {|r, w|
+ File.open("foo", "w") {|f| f << "abcd" }
+ File.open("foo") {|f|
+ f.read(1)
+ assert_equal(3, IO.copy_stream(f, w, 10, 1))
+ }
+ w.close
+ assert_equal("bcd", r.read)
}
- w.close
- assert_equal("bcd", r.read)
- }
+ rescue NotImplementedError
+ skip "pread(2) is not implemtented."
+ end
}
end
@@ -410,15 +436,17 @@ class TestIO < Test::Unit::TestCase
megacontent = "abc" * 1234567
File.open("megasrc", "w") {|f| f << megacontent }
- with_socketpair {|s1, s2|
- t = Thread.new { s2.read }
- s1.nonblock = true
- ret = IO.copy_stream("megasrc", s1)
- assert_equal(megacontent.bytesize, ret)
- s1.close
- result = t.value
- assert_equal(megacontent, result)
- }
+ if have_nonblock?
+ with_socketpair {|s1, s2|
+ t = Thread.new { s2.read }
+ s1.nonblock = true
+ ret = IO.copy_stream("megasrc", s1)
+ assert_equal(megacontent.bytesize, ret)
+ s1.close
+ result = t.value
+ assert_equal(megacontent, result)
+ }
+ end
}
end
@@ -578,18 +606,6 @@ class TestIO < Test::Unit::TestCase
(wt.kill; wt.join) if wt
end
- def pipe2(&b)
- a = []
- a << IO.pipe while true
- rescue Errno::EMFILE, Errno::ENFILE, Errno::ENOMEM
- yield(*a.last)
- ensure
- a.each do |r, w|
- r.close unless !r || r.closed?
- w.close unless !w || w.closed?
- end
- end
-
def ruby(*args)
args = ['-e', '$>.write($<.read)'] if args.empty?
ruby = EnvUtil.rubybin
@@ -636,14 +652,16 @@ class TestIO < Test::Unit::TestCase
assert_equal("", f2.read)
end
- proc do
- open(__FILE__) # see Bug #493 [ruby-dev:35957]
- end.call
-
- pipe2 do |r, w|
- assert_raise(Errno::EMFILE, Errno::ENFILE, Errno::ENOMEM) do
- r2, w2 = r.dup, w.dup
- end
+ a = []
+ assert_raise(Errno::EMFILE, Errno::ENFILE, Errno::ENOMEM) do
+ loop {a << IO.pipe}
+ end
+ assert_raise(Errno::EMFILE, Errno::ENFILE, Errno::ENOMEM) do
+ loop {a << [a[-1][0].dup, a[-1][1].dup]}
+ end
+ a.each do |r, w|
+ r.close unless !r || r.closed?
+ w.close unless !w || w.closed?
end
end
@@ -705,6 +723,7 @@ class TestIO < Test::Unit::TestCase
end
def test_write_nonblock
+ skip "IO#write_nonblock is not supported on file/pipe." if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM
pipe(proc do |w|
w.write_nonblock(1)
w.close
@@ -822,7 +841,7 @@ class TestIO < Test::Unit::TestCase
f.gets; p $.
end
SRC
- assert_equal("nil,1,2,2,1001,1001,1001,1,2,3,3", f.read.chomp.gsub("\n", ","))
+ assert_equal("0,1,2,2,1001,1001,1001,1,2,3,3", f.read.chomp.gsub("\n", ","))
end
pipe(proc do |w|
@@ -884,6 +903,7 @@ class TestIO < Test::Unit::TestCase
def test_bytes
pipe(proc do |w|
+ w.binmode
w.puts "foo"
w.puts "bar"
w.puts "baz"
@@ -914,11 +934,13 @@ class TestIO < Test::Unit::TestCase
def test_readbyte
pipe(proc do |w|
+ w.binmode
w.puts "foo"
w.puts "bar"
w.puts "baz"
w.close
end, proc do |r|
+ r.binmode
(%w(f o o) + ["\n"] + %w(b a r) + ["\n"] + %w(b a z) + ["\n"]).each do |c|
assert_equal(c.ord, r.readbyte)
end
@@ -941,7 +963,7 @@ class TestIO < Test::Unit::TestCase
end
def test_close_on_exec
- # xxx
+ skip "IO\#close_on_exec is not implemented." unless have_close_on_exec?
ruby do |f|
assert_equal(false, f.close_on_exec?)
f.close_on_exec = true
@@ -1032,7 +1054,11 @@ class TestIO < Test::Unit::TestCase
fd = IO.sysopen(t.path, "w", 0666)
assert_kind_of(Integer, fd)
- f = IO.for_fd(fd)
+ if defined?(Fcntl::F_GETFL)
+ f = IO.for_fd(fd)
+ else
+ f = IO.for_fd(fd, 0666)
+ end
f.write("FOO\n")
f.close
diff --git a/test/ruby/test_io_m17n.rb b/test/ruby/test_io_m17n.rb
index 57943df25f..71299181ec 100644
--- a/test/ruby/test_io_m17n.rb
+++ b/test/ruby/test_io_m17n.rb
@@ -59,7 +59,7 @@ EOT
with_tmpdir {
generate_file('tmp', "")
open("tmp", "rb") {|f|
- assert_equal(Encoding.default_external, f.external_encoding)
+ assert_equal(Encoding.find("ASCII-8BIT"), f.external_encoding)
assert_equal(nil, f.internal_encoding)
}
}
@@ -137,7 +137,7 @@ EOT
def test_open_wb
with_tmpdir {
open("tmp", "wb") {|f|
- assert_equal(nil, f.external_encoding)
+ assert_equal(Encoding.find("ASCII-8BIT"), f.external_encoding)
assert_equal(nil, f.internal_encoding)
}
}
@@ -374,7 +374,7 @@ EOT
with_pipe("euc-jp:utf-8") {|r, w|
w << "\xa1xyz"
w.close
- err = assert_raise(Encoding::InvalidByteSequence) { r.getc }
+ err = assert_raise(Encoding::InvalidByteSequenceError) { r.getc }
assert_equal("\xA1".force_encoding("ascii-8bit"), err.error_bytes)
assert_equal("xyz", r.read(10))
}
@@ -652,7 +652,7 @@ EOT
after = "\u{3046}\u{3048}"
w << before + invalid + after
w.close
- err = assert_raise(Encoding::InvalidByteSequence) { r.gets }
+ err = assert_raise(Encoding::InvalidByteSequenceError) { r.gets }
assert_equal(invalid.force_encoding("ascii-8bit"), err.error_bytes)
assert_equal(after.encode("euc-jp"), r.gets)
}
@@ -669,7 +669,7 @@ EOT
w.close
assert_equal(before1.encode("euc-jp"), r.getc)
assert_equal(before2.encode("euc-jp"), r.getc)
- err = assert_raise(Encoding::InvalidByteSequence) { r.getc }
+ err = assert_raise(Encoding::InvalidByteSequenceError) { r.getc }
assert_equal(invalid.force_encoding("ascii-8bit"), err.error_bytes)
assert_equal(after1.encode("euc-jp"), r.getc)
assert_equal(after2.encode("euc-jp"), r.getc)
@@ -677,7 +677,7 @@ EOT
end
def test_getc_invalid3
- with_pipe("utf-16le:euc-jp") {|r, w|
+ with_pipe("utf-16le:euc-jp", binmode: true) {|r, w|
before1 = "\x42\x30".force_encoding("utf-16le")
before2 = "\x44\x30".force_encoding("utf-16le")
invalid = "\x00\xd8".force_encoding("utf-16le")
@@ -687,7 +687,7 @@ EOT
w.close
assert_equal(before1.encode("euc-jp"), r.getc)
assert_equal(before2.encode("euc-jp"), r.getc)
- err = assert_raise(Encoding::InvalidByteSequence) { r.getc }
+ err = assert_raise(Encoding::InvalidByteSequenceError) { r.getc }
assert_equal(invalid.force_encoding("ascii-8bit"), err.error_bytes)
assert_equal(after1.encode("euc-jp"), r.getc)
assert_equal(after2.encode("euc-jp"), r.getc)
@@ -710,7 +710,7 @@ EOT
after = "\u{3046}\u{3048}"
w << before + invalid + after
w.close
- err = assert_raise(Encoding::InvalidByteSequence) { r.read }
+ err = assert_raise(Encoding::InvalidByteSequenceError) { r.read }
assert_equal(invalid.force_encoding("ascii-8bit"), err.error_bytes)
assert_equal(after.encode("euc-jp"), r.read)
}
@@ -806,6 +806,36 @@ EOT
}
end
+ def test_set_encoding_binmode
+ assert_raise(ArgumentError) {
+ open(__FILE__, "rt") {|f|
+ f.set_encoding("iso-2022-jp")
+ }
+ }
+ assert_raise(ArgumentError) {
+ open(__FILE__, "r") {|f|
+ f.set_encoding("iso-2022-jp")
+ }
+ }
+ assert_nothing_raised {
+ open(__FILE__, "rb") {|f|
+ f.set_encoding("iso-2022-jp")
+ }
+ }
+ assert_nothing_raised {
+ open(__FILE__, "r") {|f|
+ f.binmode
+ f.set_encoding("iso-2022-jp")
+ }
+ }
+ assert_nothing_raised {
+ open(__FILE__, "rt") {|f|
+ f.binmode
+ f.set_encoding("iso-2022-jp")
+ }
+ }
+ end
+
def test_write_conversion_fixenc
with_pipe {|r, w|
w.set_encoding("iso-2022-jp:utf-8")
@@ -853,7 +883,6 @@ EOT
def test_read_stateful
with_pipe("euc-jp:iso-2022-jp") {|r, w|
- r.binmode
w << "\xA4\xA2"
w.close
assert_equal("\e$B$\"\e(B".force_encoding("iso-2022-jp"), r.read)
@@ -1226,34 +1255,31 @@ EOT
}
end
- def test_textmode_read_ascii_incompat_internal
+ def test_read_newline_conversion_with_encoding_conversion
with_tmpdir {
- # ascii incompatible internal encoding needs binmode.
- assert_raise(ArgumentError) {
- open("t.utf8.crlf", "rt:utf-8:utf-16be") {|f| }
- }
- assert_raise(ArgumentError) {
- open("t.utf8.crlf", "r:utf-8:utf-16be") {|f| }
+ generate_file("t.utf8.crlf", "a\r\nb\r\n")
+ open("t.utf8.crlf", "rb:utf-8:utf-16be") {|f|
+ content = f.read
+ assert_equal("\0a\0\r\0\n\0b\0\r\0\n".force_encoding("UTF-16BE"), content)
}
- assert_raise(ArgumentError) {
- open("t.utf16.crlf", "rt:utf-16be") {|f| }
+ open("t.utf8.crlf", "rt:utf-8:utf-16be") {|f|
+ content = f.read
+ assert_equal("\0a\0\n\0b\0\n".force_encoding("UTF-16BE"), content)
}
- assert_raise(ArgumentError) {
- open("t.utf16.crlf", "r:utf-16be") {|f| }
+ open("t.utf8.crlf", "r:utf-8:utf-16be") {|f|
+ content = f.read
+ if system_newline == "\n"
+ assert_equal("\0a\0\r\0\n\0b\0\r\0\n".force_encoding("UTF-16BE"), content)
+ else
+ assert_equal("\0a\0\n\0b\0\n".force_encoding("UTF-16BE"), content)
+ end
}
}
end
- def test_binmode_read_ascii_incompat_internal
+ def test_read_newline_conversion_without_encoding_conversion
with_tmpdir {
- generate_file("t.utf8.crlf", "a\r\nb\r\n")
generate_file("t.utf16.crlf", "\0a\0\r\0\n\0b\0\r\0\n")
- # ascii incompatible internal encoding needs binmode.
- open("t.utf8.crlf", "rb:utf-8:utf-16be") {|f|
- content = f.read
- assert_equal("\0a\0\r\0\n\0b\0\r\0\n".force_encoding("UTF-16BE"),
- content)
- }
open("t.utf16.crlf", "rb:utf-16be") {|f|
content = f.read
assert_equal("\0a\0\r\0\n\0b\0\r\0\n".force_encoding("UTF-16BE"),
@@ -1262,27 +1288,182 @@ EOT
}
end
- def test_textmode_write_ascii_incompat_internal
+ def test_read_newline_conversion_error
with_tmpdir {
- # ascii incompatible internal encoding needs binmode.
+ generate_file("empty.txt", "")
+ # ascii incompatible encoding without conversion needs binmode.
assert_raise(ArgumentError) {
- open("t.utf8", "wt:utf-8:utf-16be") {|f| }
+ open("empty.txt", "rt:utf-16be") {|f| }
}
assert_raise(ArgumentError) {
- open("t.utf8", "w:utf-8:utf-16be") {|f| }
+ open("empty.txt", "r:utf-16be") {|f| }
}
- assert_raise(ArgumentError) {
- open("t.utf8", "w:utf-8:utf-16be") {|f| }
- }
- assert_raise(ArgumentError) {
- open("t.utf16", "wt:utf-16be") {|f| }
- }
- assert_raise(ArgumentError) {
- open("t.utf16", "w:utf-16be") {|f| }
+ }
+ end
+
+ def test_read_mode
+ with_tmpdir {
+ generate_file("t", "a\rb\r\nc\n\xc2\xa2")
+ generate_file("ie", "a\rb\r\nc\n\e$B\x42\x22\e(B")
+ generate_file("iu", "a\rb\r\nc\n\e$B\x21\x71\e(B")
+ generate_file("be", "\0a\0\r\0b\0\r\0\n\0c\0\n\x85\x35")
+ generate_file("bu", "\0a\0\r\0b\0\r\0\n\0c\0\n\0\xa2")
+ # "\xc2\xa2" is valid as EUC-JP and UTF-8
+ # EUC-JP UTF-8 Unicode
+ # 0xC2A2 0xE894B5 U+8535
+ # 0xA1F1 0xC2A2 U+00A2
+
+ open("t","rt") {|f| assert_equal("a\nb\nc\n\xc2\xa2".force_encoding(Encoding.default_external), f.read) }
+ open("t","rb") {|f| assert_equal("a\rb\r\nc\n\xc2\xa2".force_encoding(Encoding::ASCII_8BIT), f.read) }
+
+ open("t","rt:euc-jp") {|f| assert_equal("a\nb\nc\n\xc2\xa2".force_encoding("EUC-JP"), f.read) }
+ open("t","rb:euc-jp") {|f| assert_equal("a\rb\r\nc\n\xc2\xa2".force_encoding("EUC-JP"), f.read) }
+ open("t","rt:utf-8") {|f| assert_equal("a\nb\nc\n\xc2\xa2".force_encoding("UTF-8"), f.read) }
+ open("t","rb:utf-8") {|f| assert_equal("a\rb\r\nc\n\xc2\xa2".force_encoding("UTF-8"), f.read) }
+ assert_raise(ArgumentError) { open("t", "rt:iso-2022-jp") {|f| } }
+ open("t","rb:iso-2022-jp") {|f| assert_equal("a\rb\r\nc\n\xc2\xa2".force_encoding("ISO-2022-JP"), f.read) }
+
+ open("t","rt:euc-jp:utf-8") {|f| assert_equal("a\nb\nc\n\u8535", f.read) }
+ open("t","rt:utf-8:euc-jp") {|f| assert_equal("a\nb\nc\n\xa1\xf1".force_encoding("EUC-JP"), f.read) }
+ open("t","rb:euc-jp:utf-8") {|f| assert_equal("a\rb\r\nc\n\u8535", f.read) }
+ open("t","rb:utf-8:euc-jp") {|f| assert_equal("a\rb\r\nc\n\xa1\xf1".force_encoding("EUC-JP"), f.read) }
+
+ open("t","rt:euc-jp:iso-2022-jp"){|f| assert_equal("a\nb\nc\n\e$B\x42\x22\e(B".force_encoding("ISO-2022-JP"), f.read) }
+ open("t","rt:utf-8:iso-2022-jp"){|f| assert_equal("a\nb\nc\n\e$B\x21\x71\e(B".force_encoding("ISO-2022-JP"), f.read) }
+ open("t","rt:euc-jp:utf-16be"){|f| assert_equal("\0a\0\n\0b\0\n\0c\0\n\x85\x35".force_encoding("UTF-16BE"), f.read) }
+ open("t","rt:utf-8:utf-16be"){|f| assert_equal("\0a\0\n\0b\0\n\0c\0\n\0\xa2".force_encoding("UTF-16BE"), f.read) }
+ open("t","rb:euc-jp:iso-2022-jp"){|f|assert_equal("a\rb\r\nc\n\e$B\x42\x22\e(B".force_encoding("ISO-2022-JP"),f.read)}
+ open("t","rb:utf-8:iso-2022-jp"){|f|assert_equal("a\rb\r\nc\n\e$B\x21\x71\e(B".force_encoding("ISO-2022-JP"),f.read)}
+ open("t","rb:euc-jp:utf-16be"){|f|assert_equal("\0a\0\r\0b\0\r\0\n\0c\0\n\x85\x35".force_encoding("UTF-16BE"),f.read)}
+ open("t","rb:utf-8:utf-16be"){|f|assert_equal("\0a\0\r\0b\0\r\0\n\0c\0\n\0\xa2".force_encoding("UTF-16BE"),f.read)}
+
+ open("ie","rt:iso-2022-jp:euc-jp"){|f| assert_equal("a\nb\nc\n\xc2\xa2".force_encoding("EUC-JP"), f.read) }
+ open("iu","rt:iso-2022-jp:utf-8"){|f| assert_equal("a\nb\nc\n\xc2\xa2".force_encoding("UTF-8"), f.read) }
+ open("be","rt:utf-16be:euc-jp"){|f| assert_equal("a\nb\nc\n\xc2\xa2".force_encoding("EUC-JP"), f.read) }
+ open("bu","rt:utf-16be:utf-8"){|f| assert_equal("a\nb\nc\n\xc2\xa2".force_encoding("UTF-8"), f.read) }
+ open("ie","rb:iso-2022-jp:euc-jp"){|f|assert_equal("a\rb\r\nc\n\xc2\xa2".force_encoding("EUC-JP"),f.read)}
+ open("iu","rb:iso-2022-jp:utf-8"){|f|assert_equal("a\rb\r\nc\n\xc2\xa2".force_encoding("UTF-8"),f.read)}
+ open("be","rb:utf-16be:euc-jp"){|f|assert_equal("a\rb\r\nc\n\xc2\xa2".force_encoding("EUC-JP"),f.read)}
+ open("bu","rb:utf-16be:utf-8"){|f|assert_equal("a\rb\r\nc\n\xc2\xa2".force_encoding("UTF-8"),f.read)}
+
+ open("ie","rt:iso-2022-jp:utf-16be"){|f|assert_equal("\0a\0\n\0b\0\n\0c\0\n\x85\x35".force_encoding("UTF-16BE"),f.read)}
+ open("be","rt:utf-16be:iso-2022-jp"){|f|assert_equal("a\nb\nc\n\e$B\x42\x22\e(B".force_encoding("ISO-2022-JP"),f.read)}
+ open("ie","rb:iso-2022-jp:utf-16be"){|f|assert_equal("\0a\0\r\0b\0\r\0\n\0c\0\n\x85\x35".force_encoding("UTF-16BE"),f.read)}
+ open("be","rb:utf-16be:iso-2022-jp"){|f|assert_equal("a\rb\r\nc\n\e$B\x42\x22\e(B".force_encoding("ISO-2022-JP"),f.read)}
+ }
+ end
+
+ def assert_write(expected, mode, *args)
+ with_tmpdir {
+ open("t", mode) {|f|
+ args.each {|arg| f.print arg }
+ }
+ content = File.read("t", :mode=>"rb:ascii-8bit")
+ assert_equal(expected.dup.force_encoding("ascii-8bit"),
+ content.force_encoding("ascii-8bit"))
+ }
+ end
+
+ def test_write_mode
+ # "\xc2\xa2" is valid as EUC-JP and UTF-8
+ # EUC-JP UTF-8 Unicode
+ # 0xC2A2 0xE894B5 U+8535
+ # 0xA1F1 0xC2A2 U+00A2
+ a = "a\rb\r\nc\n"
+ e = "\xc2\xa2".force_encoding("euc-jp")
+ u8 = "\xc2\xa2".force_encoding("utf-8")
+ u16 = "\x85\x35\0\r\x00\xa2\0\r\0\n\0\n".force_encoding("utf-16be")
+ i = "\e$B\x42\x22\e(B\r\e$B\x21\x71\e(B\r\n\n".force_encoding("iso-2022-jp")
+ n = system_newline
+ un = n.encode("utf-16be").force_encoding("ascii-8bit")
+
+ assert_write("a\rb\r#{n}c#{n}", "wt", a)
+ assert_write("\xc2\xa2", "wt", e)
+ assert_write("\xc2\xa2", "wt", u8)
+
+ assert_write("a\rb\r\nc\n", "wb", a)
+ assert_write("\xc2\xa2", "wb", e)
+ assert_write("\xc2\xa2", "wb", u8)
+
+ #assert_write("\x85\x35\0\r\x00\xa2\0\r\0\n\0\n", "wt", u16) should raise
+ #assert_write("\e$B\x42\x22\e(B\r\e$B\x21\x71\e(B\r\n\n", "wt", i) should raise
+ assert_write("\x85\x35\0\r\x00\xa2\0\r\0\n\0\n", "wb", u16)
+ assert_write("\e$B\x42\x22\e(B\r\e$B\x21\x71\e(B\r\n\n", "wb", i)
+
+ t_write_mode_enc
+ t_write_mode_enc(":utf-8")
+ end
+
+ def t_write_mode_enc(enc="")
+ # "\xc2\xa2" is valid as EUC-JP and UTF-8
+ # EUC-JP UTF-8 Unicode
+ # 0xC2A2 0xE894B5 U+8535
+ # 0xA1F1 0xC2A2 U+00A2
+ a = "a\rb\r\nc\n"
+ e = "\xc2\xa2".force_encoding("euc-jp")
+ u8 = "\xc2\xa2".force_encoding("utf-8")
+ u16 = "\x85\x35\0\r\x00\xa2\0\r\0\n\0\n".force_encoding("utf-16be")
+ i = "\e$B\x42\x22\e(B\r\e$B\x21\x71\e(B\r\n\n".force_encoding("iso-2022-jp")
+ n = system_newline
+ un = n.encode("utf-16be").force_encoding("ascii-8bit")
+
+ assert_write("a\rb\r#{n}c#{n}", "wt:euc-jp#{enc}", a)
+ assert_write("\xc2\xa2", "wt:euc-jp#{enc}", e)
+ assert_write("\xa1\xf1", "wt:euc-jp#{enc}", u8)
+
+ assert_write("a\rb\r\nc\n", "wb:euc-jp#{enc}", a)
+ assert_write("\xc2\xa2", "wb:euc-jp#{enc}", e)
+ assert_write("\xa1\xf1", "wb:euc-jp#{enc}", u8)
+
+ assert_write("\xc2\xa2\r\xa1\xf1\r#{n}#{n}", "wt:euc-jp#{enc}", u16)
+ assert_write("\xc2\xa2\r\xa1\xf1\r#{n}#{n}", "wt:euc-jp#{enc}", i)
+ assert_write("\xc2\xa2\r\xa1\xf1\r\n\n", "wb:euc-jp#{enc}", u16)
+ assert_write("\xc2\xa2\r\xa1\xf1\r\n\n", "wb:euc-jp#{enc}", i)
+
+ assert_write("\0a\0\r\0b\0\r#{un}\0c#{un}", "wt:utf-16be#{enc}", a)
+ assert_write("\x85\x35", "wt:utf-16be#{enc}", e)
+ assert_write("\x00\xa2", "wt:utf-16be#{enc}", u8)
+ assert_write("a\rb\r#{n}c#{n}", "wt:iso-2022-jp#{enc}", a)
+ assert_write("\e$B\x42\x22\e(B", "wt:iso-2022-jp#{enc}", e)
+ assert_write("\e$B\x21\x71\e(B", "wt:iso-2022-jp#{enc}", u8)
+
+ assert_write("\0a\0\r\0b\0\r\0\n\0c\0\n", "wb:utf-16be#{enc}", a)
+ assert_write("\x85\x35", "wb:utf-16be#{enc}", e)
+ assert_write("\x00\xa2", "wb:utf-16be#{enc}", u8)
+ assert_write("a\rb\r\nc\n", "wb:iso-2022-jp#{enc}", a)
+ assert_write("\e$B\x42\x22\e(B", "wb:iso-2022-jp#{enc}", e)
+ assert_write("\e$B\x21\x71\e(B", "wb:iso-2022-jp#{enc}", u8)
+
+ assert_write("\x85\x35\0\r\x00\xa2\0\r#{un}#{un}", "wt:utf-16be#{enc}", u16)
+ assert_write("\x85\x35\0\r\x00\xa2\0\r#{un}#{un}", "wt:utf-16be#{enc}", i)
+ assert_write("\x85\x35\0\r\x00\xa2\0\r\0\n\0\n", "wb:utf-16be#{enc}", u16)
+ assert_write("\x85\x35\0\r\x00\xa2\0\r\0\n\0\n", "wb:utf-16be#{enc}", i)
+ assert_write("\e$B\x42\x22\e(B\r\e$B\x21\x71\e(B\r#{n}#{n}", "wt:iso-2022-jp#{enc}", u16)
+ assert_write("\e$B\x42\x22\e(B\r\e$B\x21\x71\e(B\r#{n}#{n}", "wt:iso-2022-jp#{enc}", i)
+ assert_write("\e$B\x42\x22\e(B\r\e$B\x21\x71\e(B\r\n\n", "wb:iso-2022-jp#{enc}", u16)
+ assert_write("\e$B\x42\x22\e(B\r\e$B\x21\x71\e(B\r\n\n", "wb:iso-2022-jp#{enc}", i)
+ end
+
+ def test_write_mode_fail
+ return if system_newline == "\n"
+ with_tmpdir {
+ open("t", "wt") {|f|
+ assert_raise(ArgumentError) { f.print "\0\r\0\r\0\n\0\n".force_encoding("utf-16be") }
}
}
end
+ def test_write_ascii_incompat
+ with_tmpdir {
+ open("t.utf8", "wb:utf-8:utf-16be") {|f| }
+ open("t.utf8", "wt:utf-8:utf-16be") {|f| }
+ open("t.utf8", "w:utf-8:utf-16be") {|f| }
+ open("t.utf16", "wb:utf-16be") {|f| }
+ open("t.utf16", "wt:utf-16be") {|f| }
+ open("t.utf16", "w:utf-16be") {|f| }
+ }
+ end
+
def test_binmode_write_ascii_incompat_internal
with_tmpdir {
open("t.utf8.lf", "wb:utf-8:utf-16be") {|f|
@@ -1357,6 +1538,20 @@ EOT
}
end
+ def test_binmode3
+ with_tmpdir {
+ src = "\u3042\r\n"
+ generate_file("t.txt", src)
+ srcbin = src.dup.force_encoding("ascii-8bit")
+ open("t.txt", "rt:utf-8:euc-jp") {|f|
+ f.binmode
+ result = f.read
+ assert_str_equal(srcbin, result)
+ assert_equal(Encoding::ASCII_8BIT, result.encoding)
+ }
+ }
+ end
+
def test_invalid_r
with_tmpdir {
generate_file("t.txt", "a\x80b")
@@ -1367,11 +1562,11 @@ EOT
assert_equal("ab", f.read)
}
open("t.txt", "r:utf-8:euc-jp", :undef => :replace) {|f|
- assert_raise(Encoding::InvalidByteSequence) { f.read }
+ assert_raise(Encoding::InvalidByteSequenceError) { f.read }
assert_equal("b", f.read)
}
open("t.txt", "r:utf-8:euc-jp", :undef => :replace, :replace => "") {|f|
- assert_raise(Encoding::InvalidByteSequence) { f.read }
+ assert_raise(Encoding::InvalidByteSequenceError) { f.read }
assert_equal("b", f.read)
}
}
@@ -1387,11 +1582,11 @@ EOT
assert_equal("ab", f.read)
}
open("t.txt", "r:utf-8:euc-jp", :invalid => :replace) {|f|
- assert_raise(Encoding::ConversionUndefined) { f.read }
+ assert_raise(Encoding::UndefinedConversionError) { f.read }
assert_equal("b", f.read)
}
open("t.txt", "r:utf-8:euc-jp", :invalid => :replace, :replace => "") {|f|
- assert_raise(Encoding::ConversionUndefined) { f.read }
+ assert_raise(Encoding::UndefinedConversionError) { f.read }
assert_equal("b", f.read)
}
}
@@ -1411,10 +1606,10 @@ EOT
assert_equal("ab", File.read("t.txt"))
open("t.txt", "w:euc-jp", :undef => :replace) {|f|
- assert_raise(Encoding::InvalidByteSequence) { f.write invalid_utf8 }
+ assert_raise(Encoding::InvalidByteSequenceError) { f.write invalid_utf8 }
}
open("t.txt", "w:euc-jp", :undef => :replace, :replace => "") {|f|
- assert_raise(Encoding::InvalidByteSequence) { f.write invalid_utf8 }
+ assert_raise(Encoding::InvalidByteSequenceError) { f.write invalid_utf8 }
}
}
end
@@ -1431,10 +1626,10 @@ EOT
}
assert_equal("ab", File.read("t.txt"))
open("t.txt", "w:euc-jp:utf-8", :invalid => :replace) {|f|
- assert_raise(Encoding::ConversionUndefined) { f.write "a\uFFFDb" }
+ assert_raise(Encoding::UndefinedConversionError) { f.write "a\uFFFDb" }
}
open("t.txt", "w:euc-jp:utf-8", :invalid => :replace, :replace => "") {|f|
- assert_raise(Encoding::ConversionUndefined) { f.write "a\uFFFDb" }
+ assert_raise(Encoding::UndefinedConversionError) { f.write "a\uFFFDb" }
}
}
end
@@ -1451,10 +1646,10 @@ EOT
}
assert_equal("ab", File.read("t.txt"))
open("t.txt", "w:iso-2022-jp:utf-8", :invalid => :replace) {|f|
- assert_raise(Encoding::ConversionUndefined) { f.write "a\uFFFDb" }
+ assert_raise(Encoding::UndefinedConversionError) { f.write "a\uFFFDb" }
}
open("t.txt", "w:iso-2022-jp:utf-8", :invalid => :replace, :replace => "") {|f|
- assert_raise(Encoding::ConversionUndefined) { f.write "a\uFFFDb" }
+ assert_raise(Encoding::UndefinedConversionError) { f.write "a\uFFFDb" }
}
}
end
@@ -1473,6 +1668,10 @@ EOT
content = File.read("iso-2022-jp.txt", :mode=>"rb:ascii-8bit")
assert_equal("\"&amp;&lt;&gt;&quot;'&#x4E02;\e$B$\"\e(B\n\"".force_encoding("ascii-8bit"), content)
+ open("utf-16be.txt", "wb:utf-16be", xml: :attr) {|f| f.print '&<>"\''; f.puts "\u4E02\u3042" }
+ content = File.read("utf-16be.txt", :mode=>"rb:ascii-8bit")
+ assert_equal("\0\"\0&\0a\0m\0p\0;\0&\0l\0t\0;\0&\0g\0t\0;\0&\0q\0u\0o\0t\0;\0'\x4E\x02\x30\x42\0\n\0\"".force_encoding("ascii-8bit"), content)
+
open("eucjp.txt", "w:euc-jp:utf-8", xml: :attr) {|f|
f.print "\u4E02" # U+4E02 is 0x3021 in JIS X 0212
}
diff --git a/test/ruby/test_iterator.rb b/test/ruby/test_iterator.rb
index f6ac645321..ca6022a4fb 100644
--- a/test/ruby/test_iterator.rb
+++ b/test/ruby/test_iterator.rb
@@ -54,7 +54,7 @@ class TestIterator < Test::Unit::TestCase
tt{|i| break if i == 5}
assert_equal(0, i)
- assert_raises(ArgumentError) do
+ assert_raise(ArgumentError) do
tt3{}
end
end
@@ -64,7 +64,7 @@ class TestIterator < Test::Unit::TestCase
end
def test_block_argument_without_paren
- assert_raises(ArgumentError) do
+ assert_raise(ArgumentError) do
tt4{}
end
end
@@ -216,10 +216,10 @@ class TestIterator < Test::Unit::TestCase
def test_argument
assert_nothing_raised {lambda{||}.call}
- assert_raises(ArgumentError) {lambda{||}.call(1)}
+ assert_raise(ArgumentError) {lambda{||}.call(1)}
assert_nothing_raised {lambda{|a,|}.call(1)}
- assert_raises(ArgumentError) {lambda{|a,|}.call()}
- assert_raises(ArgumentError) {lambda{|a,|}.call(1,2)}
+ assert_raise(ArgumentError) {lambda{|a,|}.call()}
+ assert_raise(ArgumentError) {lambda{|a,|}.call(1,2)}
end
def get_block(&block)
@@ -235,9 +235,9 @@ class TestIterator < Test::Unit::TestCase
assert_nothing_raised {get_block{|a,|}.call(1,2)}
assert_nothing_raised {get_block(&lambda{||}).call()}
- assert_raises(ArgumentError) {get_block(&lambda{||}).call(1)}
+ assert_raise(ArgumentError) {get_block(&lambda{||}).call(1)}
assert_nothing_raised {get_block(&lambda{|a,|}).call(1)}
- assert_raises(ArgumentError) {get_block(&lambda{|a,|}).call(1,2)}
+ assert_raise(ArgumentError) {get_block(&lambda{|a,|}).call(1,2)}
block = get_block{11}
assert_instance_of(Proc, block)
@@ -298,7 +298,7 @@ class TestIterator < Test::Unit::TestCase
end
def test_ljump
- assert_raises(LocalJumpError) {get_block{break}.call}
+ assert_raise(LocalJumpError) {get_block{break}.call}
# cannot use assert_nothing_raised due to passing block.
begin
@@ -483,7 +483,7 @@ class TestIterator < Test::Unit::TestCase
assert_equal(1, e.next)
assert_equal(2, e.next)
assert_equal(3, e.next)
- assert_raises(StopIteration){e.next}
+ assert_raise(StopIteration){e.next}
e.rewind
assert_equal(1, e.next)
e.rewind
diff --git a/test/ruby/test_lambda.rb b/test/ruby/test_lambda.rb
index bb0861ab53..241042d2c7 100644
--- a/test/ruby/test_lambda.rb
+++ b/test/ruby/test_lambda.rb
@@ -9,17 +9,17 @@ class TestLambdaParameters < Test::Unit::TestCase
def test_call_simple
assert_equal(1, lambda{|a| a}.call(1))
assert_equal([1,2], lambda{|a, b| [a,b]}.call(1,2))
- assert_raises(ArgumentError) { lambda{|a|}.call(1,2) }
- assert_raises(ArgumentError) { lambda{|a|}.call() }
- assert_raises(ArgumentError) { lambda{}.call(1) }
- assert_raises(ArgumentError) { lambda{|a, b|}.call(1,2,3) }
+ assert_raise(ArgumentError) { lambda{|a|}.call(1,2) }
+ assert_raise(ArgumentError) { lambda{|a|}.call() }
+ assert_raise(ArgumentError) { lambda{}.call(1) }
+ assert_raise(ArgumentError) { lambda{|a, b|}.call(1,2,3) }
assert_equal(1, ->(a){ a }.call(1))
assert_equal([1,2], ->(a,b){ [a,b] }.call(1,2))
- assert_raises(ArgumentError) { ->(a){ }.call(1,2) }
- assert_raises(ArgumentError) { ->(a){ }.call() }
- assert_raises(ArgumentError) { ->(){ }.call(1) }
- assert_raises(ArgumentError) { ->(a,b){ }.call(1,2,3) }
+ assert_raise(ArgumentError) { ->(a){ }.call(1,2) }
+ assert_raise(ArgumentError) { ->(a){ }.call() }
+ assert_raise(ArgumentError) { ->(){ }.call(1) }
+ assert_raise(ArgumentError) { ->(a,b){ }.call(1,2,3) }
end
end
@@ -34,21 +34,21 @@ __END__
def test_call_rest_args
assert_equal([1,2], ->(*a){ a }.call(1,2))
assert_equal([1,2,[]], ->(a,b,*c){ [a,b,c] }.call(1,2))
- assert_raises(ArgumentError){ ->(a,*b){ }.call() }
+ assert_raise(ArgumentError){ ->(a,*b){ }.call() }
end
def test_call_opt_args
assert_equal([1,2,3,4], ->(a,b,c=3,d=4){ [a,b,c,d] }.call(1,2))
assert_equal([1,2,3,4], ->(a,b,c=0,d=4){ [a,b,c,d] }.call(1,2,3))
- assert_raises(ArgumentError){ ->(a,b=1){ }.call() }
- assert_raises(ArgumentError){ ->(a,b=1){ }.call(1,2,3) }
+ assert_raise(ArgumentError){ ->(a,b=1){ }.call() }
+ assert_raise(ArgumentError){ ->(a,b=1){ }.call(1,2,3) }
end
def test_call_rest_and_opt
assert_equal([1,2,3,[]], ->(a,b=2,c=3,*d){ [a,b,c,d] }.call(1))
assert_equal([1,2,3,[]], ->(a,b=0,c=3,*d){ [a,b,c,d] }.call(1,2))
assert_equal([1,2,3,[4,5,6]], ->(a,b=0,c=0,*d){ [a,b,c,d] }.call(1,2,3,4,5,6))
- assert_raises(ArgumentError){ ->(a,b=1,*c){ }.call() }
+ assert_raise(ArgumentError){ ->(a,b=1,*c){ }.call() }
end
def test_call_with_block
diff --git a/test/ruby/test_m17n.rb b/test/ruby/test_m17n.rb
index a878227534..416d8e190c 100644
--- a/test/ruby/test_m17n.rb
+++ b/test/ruby/test_m17n.rb
@@ -146,17 +146,17 @@ class TestM17N < Test::Unit::TestCase
# tests start
def test_string_ascii_literal
- assert_encoding("US-ASCII", eval(a(%{""})).encoding)
- assert_encoding("US-ASCII", eval(a(%{"a"})).encoding)
+ assert_encoding("ASCII-8BIT", eval(a(%{""})).encoding)
+ assert_encoding("ASCII-8BIT", eval(a(%{"a"})).encoding)
end
def test_string_eucjp_literal
- assert_encoding("US-ASCII", eval(e(%{""})).encoding)
- assert_encoding("US-ASCII", eval(e(%{"a"})).encoding)
+ assert_encoding("EUC-JP", eval(e(%{""})).encoding)
+ assert_encoding("EUC-JP", eval(e(%{"a"})).encoding)
assert_encoding("EUC-JP", eval(e(%{"\xa1\xa1"})).encoding)
assert_encoding("EUC-JP", eval(e(%{"\\xa1\\xa1"})).encoding)
- assert_encoding("US-ASCII", eval(e(%{"\\x20"})).encoding)
- assert_encoding("US-ASCII", eval(e(%{"\\n"})).encoding)
+ assert_encoding("EUC-JP", eval(e(%{"\\x20"})).encoding)
+ assert_encoding("EUC-JP", eval(e(%{"\\n"})).encoding)
assert_encoding("EUC-JP", eval(e(%{"\\x80"})).encoding)
end
@@ -746,7 +746,7 @@ class TestM17N < Test::Unit::TestCase
#assert_raise(ArgumentError) { s("%c") % 0xc2a1 }
assert_strenc("\u{c2a1}", 'UTF-8', u("%c") % 0xc2a1)
assert_strenc("\u{c2}", 'UTF-8', u("%c") % 0xc2)
- assert_raise(EncodingCompatibilityError) {
+ assert_raise(Encoding::CompatibilityError) {
"%s%s" % [s("\xc2\xa1"), e("\xc2\xa1")]
}
end
@@ -866,22 +866,22 @@ class TestM17N < Test::Unit::TestCase
def test_str_aref_substr
assert_equal(a("\xa1\xc2"), a("\xc2\xa1\xc2\xa2\xc2\xa3")[a("\xa1\xc2")])
- assert_raise(EncodingCompatibilityError) { a("\xc2\xa1\xc2\xa2\xc2\xa3")[e("\xa1\xc2")] }
+ assert_raise(Encoding::CompatibilityError) { a("\xc2\xa1\xc2\xa2\xc2\xa3")[e("\xa1\xc2")] }
assert_equal(nil, e("\xc2\xa1\xc2\xa2\xc2\xa3")[e("\xa1\xc2")])
- assert_raise(EncodingCompatibilityError) { e("\xc2\xa1\xc2\xa2\xc2\xa3")[s("\xa1\xc2")] }
+ assert_raise(Encoding::CompatibilityError) { e("\xc2\xa1\xc2\xa2\xc2\xa3")[s("\xa1\xc2")] }
assert_equal(s("\xa1\xc2"), s("\xc2\xa1\xc2\xa2\xc2\xa3")[s("\xa1\xc2")])
- assert_raise(EncodingCompatibilityError) { s("\xc2\xa1\xc2\xa2\xc2\xa3")[u("\xa1\xc2")] }
+ assert_raise(Encoding::CompatibilityError) { s("\xc2\xa1\xc2\xa2\xc2\xa3")[u("\xa1\xc2")] }
assert_equal(nil, u("\xc2\xa1\xc2\xa2\xc2\xa3")[u("\xa1\xc2")])
- assert_raise(EncodingCompatibilityError) { u("\xc2\xa1\xc2\xa2\xc2\xa3")[a("\xa1\xc2")] }
+ assert_raise(Encoding::CompatibilityError) { u("\xc2\xa1\xc2\xa2\xc2\xa3")[a("\xa1\xc2")] }
assert_nil(e("\xa1\xa2\xa3\xa4")[e("\xa2\xa3")])
end
def test_aset
s = e("\xa3\xb0\xa3\xb1\xa3\xb2\xa3\xb3\xa3\xb4")
- assert_raise(EncodingCompatibilityError){s["\xb0\xa3"] = "foo"}
+ assert_raise(Encoding::CompatibilityError){s["\xb0\xa3"] = "foo"}
end
def test_str_center
@@ -917,13 +917,13 @@ class TestM17N < Test::Unit::TestCase
def test_count
assert_equal(0, e("\xa1\xa2").count("z"))
s = e("\xa3\xb0\xa3\xb1\xa3\xb2\xa3\xb3\xa3\xb4")
- assert_raise(EncodingCompatibilityError){s.count(a("\xa3\xb0"))}
+ assert_raise(Encoding::CompatibilityError){s.count(a("\xa3\xb0"))}
end
def test_delete
assert_equal(1, e("\xa1\xa2").delete("z").length)
s = e("\xa3\xb0\xa3\xb1\xa3\xb2\xa3\xb3\xa3\xb4")
- assert_raise(EncodingCompatibilityError){s.delete(a("\xa3\xb2"))}
+ assert_raise(Encoding::CompatibilityError){s.delete(a("\xa3\xb2"))}
a = "\u3042\u3044\u3046\u3042\u3044\u3046"
a.delete!("\u3042\u3044", "^\u3044")
@@ -942,7 +942,7 @@ class TestM17N < Test::Unit::TestCase
assert_nil(e("\xa1\xa2\xa3\xa4").index(e("\xa3")))
assert_nil(e("\xa1\xa2\xa3\xa4").rindex(e("\xa3")))
s = e("\xa3\xb0\xa3\xb1\xa3\xb2\xa3\xb3\xa3\xb4")
- assert_raise(EncodingCompatibilityError){s.rindex(a("\xb1\xa3"))}
+ assert_raise(Encoding::CompatibilityError){s.rindex(a("\xb1\xa3"))}
end
def test_next
@@ -959,6 +959,21 @@ class TestM17N < Test::Unit::TestCase
assert_equal(Encoding::EUC_JP, "\xa4\xa2".force_encoding("euc-jp").gsub(/./, '\&').encoding)
end
+ def test_sub2
+ s = "\x80".force_encoding("ASCII-8BIT")
+ r = Regexp.new("\x80".force_encoding("ASCII-8BIT"))
+ s2 = s.sub(r, "")
+ assert(s2.empty?)
+ assert(s2.ascii_only?)
+ end
+
+ def test_sub3
+ repl = "\x81".force_encoding("sjis")
+ assert_equal(false, repl.valid_encoding?)
+ s = "a@".sub(/a/, repl)
+ assert(s.valid_encoding?)
+ end
+
def test_insert
s = e("\xa3\xb0\xa3\xb1\xa3\xb2\xa3\xb3\xa3\xb4")
assert_equal(e("\xa3\xb0\xa3\xb1\xa3\xb2\xa3\xb3\xa3\xb4a"), s.insert(-1, "a"))
@@ -985,7 +1000,7 @@ class TestM17N < Test::Unit::TestCase
def test_upto
s1 = e("\xa1\xa2")
s2 = s("\xa1\xa2")
- assert_raise(EncodingCompatibilityError){s1.upto(s2) {|x| break }}
+ assert_raise(Encoding::CompatibilityError){s1.upto(s2) {|x| break }}
end
def test_casecmp
@@ -1005,12 +1020,12 @@ class TestM17N < Test::Unit::TestCase
end
def test_plus
- assert_raise(EncodingCompatibilityError){u("\xe3\x81\x82") + a("\xa1")}
+ assert_raise(Encoding::CompatibilityError){u("\xe3\x81\x82") + a("\xa1")}
end
def test_chomp
s = e("\xa3\xb0\xa3\xb1\xa3\xb2\xa3\xb3\xa3\xb4")
- assert_raise(EncodingCompatibilityError){s.chomp(s("\xa3\xb4"))}
+ assert_raise(Encoding::CompatibilityError){s.chomp(s("\xa3\xb4"))}
end
def test_gsub
@@ -1023,7 +1038,7 @@ class TestM17N < Test::Unit::TestCase
t = s.gsub(/b/, "\xa1\xa1".force_encoding("euc-jp"))
assert_equal(Encoding::ASCII_8BIT, s.encoding)
- assert_raise(EncodingCompatibilityError) {
+ assert_raise(Encoding::CompatibilityError) {
"abc".gsub(/[ac]/) {
$& == "a" ? "\xc2\xa1".force_encoding("euc-jp") :
"\xc2\xa1".force_encoding("utf-8")
@@ -1044,7 +1059,7 @@ class TestM17N < Test::Unit::TestCase
def test_each_line
s = e("\xa3\xb0\xa3\xb1\xa3\xb2\xa3\xb3\xa3\xb4")
- assert_raise(EncodingCompatibilityError){s.each_line(a("\xa3\xb1")) {|l| }}
+ assert_raise(Encoding::CompatibilityError){s.each_line(a("\xa3\xb1")) {|l| }}
s = e("\xa4\xa2\nfoo")
actual = []
@@ -1280,11 +1295,20 @@ class TestM17N < Test::Unit::TestCase
end
def test_compatible
- assert_raise(TypeError) {Encoding.compatible?("",0)}
+ assert_nil Encoding.compatible?("",0)
+ assert_equal(Encoding::UTF_8, Encoding.compatible?(Encoding::UTF_8, Encoding::UTF_8))
+ assert_equal(Encoding::UTF_8, Encoding.compatible?(Encoding::UTF_8, Encoding::US_ASCII))
+ assert_equal(Encoding::ASCII_8BIT,
+ Encoding.compatible?(Encoding::ASCII_8BIT, Encoding::US_ASCII))
+ assert_nil Encoding.compatible?(Encoding::UTF_8, Encoding::ASCII_8BIT)
end
def test_force_encoding
assert(("".center(1, "\x80".force_encoding("utf-8")); true),
"moved from btest/knownbug, [ruby-dev:33807]")
end
+
+ def test_combchar_codepoint
+ assert_equal([0x30BB, 0x309A], "\u30BB\u309A".codepoints.to_a)
+ end
end
diff --git a/test/ruby/test_m17n_comb.rb b/test/ruby/test_m17n_comb.rb
index 37b1a687a2..b5208f44f1 100644
--- a/test/ruby/test_m17n_comb.rb
+++ b/test/ruby/test_m17n_comb.rb
@@ -105,9 +105,8 @@ class TestM17NComb < Test::Unit::TestCase
u("\xc2"), u("\x80"),
# for transitivity test
- u("\xe0\xa0\xa1"),
- e("\xe0\xa0\xa1"),
- s("\xe0\xa0\xa1"),
+ u("\xe0\xa0\xa1"), e("\xe0\xa0\xa1"), s("\xe0\xa0\xa1"), # [ruby-dev:32693]
+ e("\xa1\xa1"), a("\xa1\xa1"), s("\xa1\xa1"), # [ruby-dev:36484]
#"aa".force_encoding("utf-16be"),
#"aaaa".force_encoding("utf-32be"),
@@ -116,6 +115,7 @@ class TestM17NComb < Test::Unit::TestCase
def combination(*args, &b)
AllPairs.each(*args, &b)
+ #AllPairs.exhaustive_each(*args, &b)
end
def encdump(str)
@@ -261,7 +261,7 @@ class TestM17NComb < Test::Unit::TestCase
def test_str_plus
combination(STRINGS, STRINGS) {|s1, s2|
if s1.encoding != s2.encoding && !s1.ascii_only? && !s2.ascii_only?
- assert_raise(EncodingCompatibilityError) { s1 + s2 }
+ assert_raise(Encoding::CompatibilityError) { s1 + s2 }
else
t = enccall(s1, :+, s2)
assert(t.valid_encoding?) if s1.valid_encoding? && s2.valid_encoding?
@@ -318,10 +318,9 @@ class TestM17NComb < Test::Unit::TestCase
def test_str_eq
combination(STRINGS, STRINGS) {|s1, s2|
desc_eq = "#{encdump s1} == #{encdump s2}"
- if s1.ascii_only? && s2.ascii_only? && a(s1) == a(s2)
- assert(s1 == s2, desc_eq)
- assert(s1.eql?(s2), desc_eq)
- elsif s1.encoding == s2.encoding && a(s1) == a(s2)
+ if a(s1) == a(s2) and
+ (s1.ascii_only? && s2.ascii_only? or
+ s1.encoding == s2.encoding) then
assert(s1 == s2, desc_eq)
assert(!(s1 != s2))
assert_equal(0, s1 <=> s2)
@@ -344,7 +343,7 @@ class TestM17NComb < Test::Unit::TestCase
assert_equal(a(s), a(s1) + a(s2))
assert_str_enc_propagation(s, s1, s2)
else
- assert_raise(EncodingCompatibilityError) { s << s2 }
+ assert_raise(Encoding::CompatibilityError) { s << s2 }
end
}
end
@@ -396,7 +395,7 @@ class TestM17NComb < Test::Unit::TestCase
end
end
else
- assert_raise(EncodingCompatibilityError) { s1[s2] }
+ assert_raise(Encoding::CompatibilityError) { s1[s2] }
end
}
end
@@ -481,7 +480,7 @@ class TestM17NComb < Test::Unit::TestCase
end
end
else
- assert_raise(EncodingCompatibilityError) { t[i] = s2 }
+ assert_raise(Encoding::CompatibilityError) { t[i] = s2 }
end
}
}
@@ -513,7 +512,7 @@ class TestM17NComb < Test::Unit::TestCase
end
end
else
- assert_raise(EncodingCompatibilityError) { t[i,len] = s2 }
+ assert_raise(Encoding::CompatibilityError) { t[i,len] = s2 }
end
}
end
@@ -526,7 +525,7 @@ class TestM17NComb < Test::Unit::TestCase
!s2.ascii_only? ? s2.encoding : nil,
!s3.ascii_only? ? s3.encoding : nil].uniq.compact
if 1 < encs.length
- assert_raise(EncodingCompatibilityError, IndexError) { t[s2] = s3 }
+ assert_raise(Encoding::CompatibilityError, IndexError) { t[s2] = s3 }
else
if encs.empty?
encs = [
@@ -565,7 +564,7 @@ class TestM17NComb < Test::Unit::TestCase
end
end
else
- assert_raise(EncodingCompatibilityError, RangeError,
+ assert_raise(Encoding::CompatibilityError, RangeError,
"t=#{encdump(s1)};t[#{first}..#{last}]=#{encdump(s2)}") {
t[first..last] = s2
}
@@ -592,7 +591,7 @@ class TestM17NComb < Test::Unit::TestCase
end
end
else
- assert_raise(EncodingCompatibilityError, RangeError,
+ assert_raise(Encoding::CompatibilityError, RangeError,
"t=#{encdump(s1)};t[#{first}...#{last}]=#{encdump(s2)}") {
t[first...last] = s2
}
@@ -655,7 +654,7 @@ class TestM17NComb < Test::Unit::TestCase
next
end
if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
- assert_raise(EncodingCompatibilityError) { s1.center(width, s2) }
+ assert_raise(Encoding::CompatibilityError) { s1.center(width, s2) }
next
end
t = enccall(s1, :center, width, s2)
@@ -676,7 +675,7 @@ class TestM17NComb < Test::Unit::TestCase
next
end
if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
- assert_raise(EncodingCompatibilityError) { s1.ljust(width, s2) }
+ assert_raise(Encoding::CompatibilityError) { s1.ljust(width, s2) }
next
end
t = enccall(s1, :ljust, width, s2)
@@ -697,7 +696,7 @@ class TestM17NComb < Test::Unit::TestCase
next
end
if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
- assert_raise(EncodingCompatibilityError) { s1.rjust(width, s2) }
+ assert_raise(Encoding::CompatibilityError) { s1.rjust(width, s2) }
next
end
t = enccall(s1, :rjust, width, s2)
@@ -711,7 +710,7 @@ class TestM17NComb < Test::Unit::TestCase
combination(STRINGS, STRINGS) {|s1, s2|
if !s1.ascii_only? && !s2.ascii_only? && !Encoding.compatible?(s1,s2)
if s1.bytesize > s2.bytesize
- assert_raise(EncodingCompatibilityError) { s1.chomp(s2) }
+ assert_raise(Encoding::CompatibilityError) { s1.chomp(s2) }
end
next
end
@@ -777,11 +776,11 @@ class TestM17NComb < Test::Unit::TestCase
def test_str_count
combination(STRINGS, STRINGS) {|s1, s2|
if !s1.valid_encoding? || !s2.valid_encoding?
- assert_raise(ArgumentError, EncodingCompatibilityError) { s1.count(s2) }
+ assert_raise(ArgumentError, Encoding::CompatibilityError) { s1.count(s2) }
next
end
if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
- assert_raise(EncodingCompatibilityError) { s1.count(s2) }
+ assert_raise(Encoding::CompatibilityError) { s1.count(s2) }
next
end
n = enccall(s1, :count, s2)
@@ -809,11 +808,11 @@ class TestM17NComb < Test::Unit::TestCase
next
end
if !s1.valid_encoding? || !s2.valid_encoding?
- assert_raise(ArgumentError, EncodingCompatibilityError) { s1.delete(s2) }
+ assert_raise(ArgumentError, Encoding::CompatibilityError) { s1.delete(s2) }
next
end
if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
- assert_raise(EncodingCompatibilityError) { s1.delete(s2) }
+ assert_raise(Encoding::CompatibilityError) { s1.delete(s2) }
next
end
t = enccall(s1, :delete, s2)
@@ -855,11 +854,11 @@ class TestM17NComb < Test::Unit::TestCase
def test_str_each_line
combination(STRINGS, STRINGS) {|s1, s2|
if !s1.valid_encoding? || !s2.valid_encoding?
- assert_raise(ArgumentError, EncodingCompatibilityError) { s1.each_line(s2) {} }
+ assert_raise(ArgumentError, Encoding::CompatibilityError) { s1.each_line(s2) {} }
next
end
if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
- assert_raise(EncodingCompatibilityError) { s1.each_line(s2) {} }
+ assert_raise(Encoding::CompatibilityError) { s1.each_line(s2) {} }
next
end
lines = []
@@ -908,9 +907,9 @@ class TestM17NComb < Test::Unit::TestCase
def test_str_include?
combination(STRINGS, STRINGS) {|s1, s2|
if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
- assert_raise(EncodingCompatibilityError) { s1.include?(s2) }
- assert_raise(EncodingCompatibilityError) { s1.index(s2) }
- assert_raise(EncodingCompatibilityError) { s1.rindex(s2) }
+ assert_raise(Encoding::CompatibilityError) { s1.include?(s2) }
+ assert_raise(Encoding::CompatibilityError) { s1.index(s2) }
+ assert_raise(Encoding::CompatibilityError) { s1.rindex(s2) }
next
end
t = enccall(s1, :include?, s2)
@@ -941,7 +940,7 @@ class TestM17NComb < Test::Unit::TestCase
def test_str_index
combination(STRINGS, STRINGS, -2..2) {|s1, s2, pos|
if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
- assert_raise(EncodingCompatibilityError) { s1.index(s2) }
+ assert_raise(Encoding::CompatibilityError) { s1.index(s2) }
next
end
t = enccall(s1, :index, s2, pos)
@@ -974,7 +973,7 @@ class TestM17NComb < Test::Unit::TestCase
def test_str_rindex
combination(STRINGS, STRINGS, -2..2) {|s1, s2, pos|
if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
- assert_raise(EncodingCompatibilityError) { s1.rindex(s2) }
+ assert_raise(Encoding::CompatibilityError) { s1.rindex(s2) }
next
end
t = enccall(s1, :rindex, s2, pos)
@@ -1023,11 +1022,11 @@ class TestM17NComb < Test::Unit::TestCase
t2 = s1.dup
begin
t1[nth, 0] = s2
- rescue EncodingCompatibilityError, IndexError => e1
+ rescue Encoding::CompatibilityError, IndexError => e1
end
begin
t2.insert(nth, s2)
- rescue EncodingCompatibilityError, IndexError => e2
+ rescue Encoding::CompatibilityError, IndexError => e2
end
assert_equal(t1, t2, "t=#{encdump s1}; t.insert(#{nth},#{encdump s2}); t")
assert_equal(e1.class, e2.class, "begin #{encdump s1}.insert(#{nth},#{encdump s2}); rescue ArgumentError, IndexError => e; e end")
@@ -1041,7 +1040,7 @@ class TestM17NComb < Test::Unit::TestCase
t1.insert(nth, s2)
slen = s2.length
assert_equal(t1[nth-slen+1,slen], s2, "t=#{encdump s1}; t.insert(#{nth},#{encdump s2}); t")
- rescue EncodingCompatibilityError, IndexError => e
+ rescue Encoding::CompatibilityError, IndexError => e
end
}
end
@@ -1158,11 +1157,11 @@ class TestM17NComb < Test::Unit::TestCase
def test_str_split
combination(STRINGS, STRINGS) {|s1, s2|
if !s2.valid_encoding?
- assert_raise(RegexpError) { s1.split(s2) }
+ assert_raise(ArgumentError, RegexpError) { s1.split(s2) }
next
end
if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
- assert_raise(ArgumentError) { s1.split(s2) }
+ assert_raise(ArgumentError, Encoding::CompatibilityError) { s1.split(s2) }
next
end
if !s1.valid_encoding?
@@ -1186,11 +1185,11 @@ class TestM17NComb < Test::Unit::TestCase
def test_str_squeeze
combination(STRINGS, STRINGS) {|s1, s2|
if !s1.valid_encoding? || !s2.valid_encoding?
- assert_raise(ArgumentError, EncodingCompatibilityError, "#{encdump s1}.squeeze(#{encdump s2})") { s1.squeeze(s2) }
+ assert_raise(ArgumentError, Encoding::CompatibilityError, "#{encdump s1}.squeeze(#{encdump s2})") { s1.squeeze(s2) }
next
end
if !s1.ascii_only? && !s2.ascii_only? && s1.encoding != s2.encoding
- assert_raise(EncodingCompatibilityError) { s1.squeeze(s2) }
+ assert_raise(Encoding::CompatibilityError) { s1.squeeze(s2) }
next
end
t = enccall(s1, :squeeze, s2)
@@ -1280,7 +1279,7 @@ class TestM17NComb < Test::Unit::TestCase
next
end
if !str_enc_compatible?(s1, s2, s3)
- assert_raise(EncodingCompatibilityError, desc) { s1.tr(s2, s3) }
+ assert_raise(Encoding::CompatibilityError, desc) { s1.tr(s2, s3) }
next
end
if !s1.valid_encoding?
@@ -1309,11 +1308,11 @@ class TestM17NComb < Test::Unit::TestCase
next
end
if !s1.valid_encoding?
- assert_raise(ArgumentError, EncodingCompatibilityError, desc) { s1.tr_s(s2, s3) }
+ assert_raise(ArgumentError, Encoding::CompatibilityError, desc) { s1.tr_s(s2, s3) }
next
end
if !str_enc_compatible?(s1, s2, s3)
- assert_raise(EncodingCompatibilityError, desc) { s1.tr(s2, s3) }
+ assert_raise(Encoding::CompatibilityError, desc) { s1.tr(s2, s3) }
next
end
if s2.empty?
@@ -1395,21 +1394,25 @@ class TestM17NComb < Test::Unit::TestCase
[
[
"#{encdump s1}.sub(Regexp.new(#{encdump s2}), #{encdump s3})",
- lambda { s1.sub(r2, s3) }
+ lambda { s1.sub(r2, s3) },
+ false
],
[
"#{encdump s1}.sub(Regexp.new(#{encdump s2}), #{encdump s3})",
- lambda { s1.sub(r2) { s3 } }
+ lambda { s1.sub(r2) { s3 } },
+ false
],
[
"#{encdump s1}.gsub(Regexp.new(#{encdump s2}), #{encdump s3})",
- lambda { s1.gsub(r2, s3) }
+ lambda { s1.gsub(r2, s3) },
+ true
],
[
"#{encdump s1}.gsub(Regexp.new(#{encdump s2}), #{encdump s3})",
- lambda { s1.gsub(r2) { s3 } }
+ lambda { s1.gsub(r2) { s3 } },
+ true
]
- ].each {|desc, doit|
+ ].each {|desc, doit, g|
if !s1.valid_encoding?
assert_raise(ArgumentError, desc) { doit.call }
next
@@ -1422,8 +1425,8 @@ class TestM17NComb < Test::Unit::TestCase
assert_equal(s1, doit.call)
next
end
- if !str_enc_compatible?(s1.gsub(r2, ''), s3)
- assert_raise(EncodingCompatibilityError, desc) { doit.call }
+ if !str_enc_compatible?(g ? s1.gsub(r2, '') : s1.sub(r2, ''), s3)
+ assert_raise(Encoding::CompatibilityError, desc) { doit.call }
next
end
t = nil
@@ -1449,21 +1452,25 @@ class TestM17NComb < Test::Unit::TestCase
[
[
"t=#{encdump s1}.dup;t.sub!(Regexp.new(#{encdump s2}), #{encdump s3})",
- lambda { t=s1.dup; [t, t.sub!(r2, s3)] }
+ lambda { t=s1.dup; [t, t.sub!(r2, s3)] },
+ false
],
[
"t=#{encdump s1}.dup;t.sub!(Regexp.new(#{encdump s2}), #{encdump s3})",
- lambda { t=s1.dup; [t, t.sub!(r2) { s3 }] }
+ lambda { t=s1.dup; [t, t.sub!(r2) { s3 }] },
+ false
],
[
"t=#{encdump s1}.dup;t.gsub!(Regexp.new(#{encdump s2}), #{encdump s3})",
- lambda { t=s1.dup; [t, t.gsub!(r2, s3)] }
+ lambda { t=s1.dup; [t, t.gsub!(r2, s3)] },
+ true
],
[
"t=#{encdump s1}.dup;t.gsub!(Regexp.new(#{encdump s2}), #{encdump s3})",
- lambda { t=s1.dup; [t, t.gsub!(r2) { s3 }] }
+ lambda { t=s1.dup; [t, t.gsub!(r2) { s3 }] },
+ true
]
- ].each {|desc, doit|
+ ].each {|desc, doit, g|
if !s1.valid_encoding?
assert_raise(ArgumentError, desc) { doit.call }
next
@@ -1476,8 +1483,8 @@ class TestM17NComb < Test::Unit::TestCase
assert_equal([s1, nil], doit.call)
next
end
- if !str_enc_compatible?(s1.gsub(r2, ''), s3)
- assert_raise(EncodingCompatibilityError, desc) { doit.call }
+ if !str_enc_compatible?(g ? s1.gsub(r2, '') : s1.sub(r2, ''), s3)
+ assert_raise(Encoding::CompatibilityError, desc) { doit.call }
next
end
t = ret = nil
@@ -1538,7 +1545,7 @@ class TestM17NComb < Test::Unit::TestCase
combination(STRINGS, STRINGS) {|s1, s2|
desc = "#{encdump s1}.end_with?(#{encdump s2})"
if !str_enc_compatible?(s1, s2)
- assert_raise(EncodingCompatibilityError, desc) { s1.end_with?(s2) }
+ assert_raise(Encoding::CompatibilityError, desc) { s1.end_with?(s2) }
next
end
if s1.length < s2.length
@@ -1557,7 +1564,7 @@ class TestM17NComb < Test::Unit::TestCase
combination(STRINGS, STRINGS) {|s1, s2|
desc = "#{encdump s1}.start_with?(#{encdump s2})"
if !str_enc_compatible?(s1, s2)
- assert_raise(EncodingCompatibilityError, desc) { s1.start_with?(s2) }
+ assert_raise(Encoding::CompatibilityError, desc) { s1.start_with?(s2) }
next
end
s1 = s1.dup.force_encoding("ASCII-8BIT")
@@ -1592,7 +1599,7 @@ class TestM17NComb < Test::Unit::TestCase
combination(STRINGS, STRINGS) {|s1, s2|
desc = "#{encdump s1}.partition(#{encdump s2})"
if !str_enc_compatible?(s1, s2)
- assert_raise(EncodingCompatibilityError, desc) { s1.partition(s2) }
+ assert_raise(Encoding::CompatibilityError, desc) { s1.partition(s2) }
next
end
i = enccall(s1, :index, s2)
@@ -1608,7 +1615,7 @@ class TestM17NComb < Test::Unit::TestCase
combination(STRINGS, STRINGS) {|s1, s2|
desc = "#{encdump s1}.rpartition(#{encdump s2})"
if !str_enc_compatible?(s1, s2)
- assert_raise(EncodingCompatibilityError, desc) { s1.rpartition(s2) }
+ assert_raise(Encoding::CompatibilityError, desc) { s1.rpartition(s2) }
next
end
i = enccall(s1, :rindex, s2)
diff --git a/test/ruby/test_math.rb b/test/ruby/test_math.rb
index 55f354664c..d4dbf9dbf0 100644
--- a/test/ruby/test_math.rb
+++ b/test/ruby/test_math.rb
@@ -113,6 +113,7 @@ class TestMath < Test::Unit::TestCase
assert_equal(1.0/0, Math.log(1.0/0))
assert_raise(Errno::EDOM, Errno::ERANGE) { Math.log(0) }
assert_raise(Errno::EDOM, Errno::ERANGE) { Math.log(-1) }
+ assert_raise(TypeError) { Math.log(1,nil) }
end
def test_log2
diff --git a/test/ruby/test_mixed_unicode_escapes.rb b/test/ruby/test_mixed_unicode_escapes.rb
index f274ae7090..982b57e286 100644
--- a/test/ruby/test_mixed_unicode_escapes.rb
+++ b/test/ruby/test_mixed_unicode_escapes.rb
@@ -1,4 +1,4 @@
-# -*- coding: sjis -*-
+# -*- coding: cp932 -*-
# This test is in a differnt file than TestUnicodeEscapes
# So that we can have a different coding comment above
@@ -18,8 +18,8 @@ class TestMixedUnicodeEscape < Test::Unit::TestCase
# String interpolation turns into an expression and we get
# a different kind of error, but we still can't mix these
- assert_raise(EncodingCompatibilityError) { eval %q("\u{1234}#{nil}")}
- assert_raise(EncodingCompatibilityError) { eval %q("#{nil}\u1234")}
+ assert_raise(Encoding::CompatibilityError) { eval %q("\u{1234}#{nil}")}
+ assert_raise(Encoding::CompatibilityError) { eval %q("#{nil}\u1234")}
end
end
diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb
index edbbf250dd..e1f7299636 100644
--- a/test/ruby/test_module.rb
+++ b/test/ruby/test_module.rb
@@ -5,6 +5,10 @@ require_relative 'envutil'
$m0 = Module.nesting
class TestModule < Test::Unit::TestCase
+ def _wrap_assertion
+ yield
+ end
+
def assert_method_defined?(klass, mid, message="")
message = build_message(message, "#{klass}\##{mid} expected to be defined.")
_wrap_assertion do
@@ -206,14 +210,6 @@ class TestModule < Test::Unit::TestCase
assert(Other.constants.include?(:CLASS_EVAL))
end
- def test_class_variable_set
- # TODO
- end
-
- def test_class_variable_get
- # TODO
- end
-
def test_const_defined?
assert(Math.const_defined?(:PI))
assert(Math.const_defined?("PI"))
@@ -441,7 +437,7 @@ class TestModule < Test::Unit::TestCase
assert_raise(NameError) { c1.const_defined?(:foo) }
end
- def test_class_variable_get2
+ def test_class_variable_get
c = Class.new
c.class_eval { @@foo = :foo }
assert_equal(:foo, c.class_variable_get(:@@foo))
@@ -449,7 +445,7 @@ class TestModule < Test::Unit::TestCase
assert_raise(NameError) { c.class_variable_get(:foo) }
end
- def test_class_variable_set2
+ def test_class_variable_set
c = Class.new
c.class_variable_set(:@@foo, :foo)
assert_equal(:foo, c.class_eval { @@foo })
@@ -464,6 +460,13 @@ class TestModule < Test::Unit::TestCase
assert_raise(NameError) { c.class_variable_defined?(:foo) }
end
+ def test_remove_class_variable
+ c = Class.new
+ c.class_eval { @@foo = :foo }
+ c.class_eval { remove_class_variable(:@@foo) }
+ assert_equal(false, c.class_variable_defined?(:@@foo))
+ end
+
def test_export_method
m = Module.new
assert_raise(NameError) do
@@ -540,10 +543,11 @@ class TestModule < Test::Unit::TestCase
end
def test_mod_constants
- Module.const_set(:Foo, :foo)
- assert_equal([:Foo], Module.constants(true))
- assert_equal([:Foo], Module.constants(false))
- Module.instance_eval { remove_const(:Foo) }
+ m = Module.new
+ m.const_set(:Foo, :foo)
+ assert_equal([:Foo], m.constants(true))
+ assert_equal([:Foo], m.constants(false))
+ m.instance_eval { remove_const(:Foo) }
end
def test_frozen_class
diff --git a/test/ruby/test_numeric.rb b/test/ruby/test_numeric.rb
index 3db054fdae..0dd7b2e99c 100644
--- a/test/ruby/test_numeric.rb
+++ b/test/ruby/test_numeric.rb
@@ -72,8 +72,8 @@ class TestNumeric < Test::Unit::TestCase
end
end
- def test_scalar_p
- assert(Numeric.new.scalar?)
+ def test_real_p
+ assert(Numeric.new.real?)
end
def test_integer_p
diff --git a/test/ruby/test_object.rb b/test/ruby/test_object.rb
index 5190eb69e5..2116c6a216 100644
--- a/test/ruby/test_object.rb
+++ b/test/ruby/test_object.rb
@@ -170,6 +170,13 @@ class TestObject < Test::Unit::TestCase
assert_raise(NameError) { o.instance_variable_defined?(:foo) }
end
+ def test_remove_instance_variable
+ o = Object.new
+ o.instance_eval { @foo = :foo }
+ o.instance_eval { remove_instance_variable(:@foo) }
+ assert_equal(false, o.instance_variable_defined?(:@foo))
+ end
+
def test_convert_type
o = Object.new
def o.to_s; 1; end
diff --git a/test/ruby/test_pack.rb b/test/ruby/test_pack.rb
index 30ffe13426..2666bb0e90 100644
--- a/test/ruby/test_pack.rb
+++ b/test/ruby/test_pack.rb
@@ -47,15 +47,15 @@ class TestPack < Test::Unit::TestCase
end
def test_pack_U
- assert_raises(RangeError) { [-0x40000001].pack("U") }
- assert_raises(RangeError) { [-0x40000000].pack("U") }
- assert_raises(RangeError) { [-1].pack("U") }
+ assert_raise(RangeError) { [-0x40000001].pack("U") }
+ assert_raise(RangeError) { [-0x40000000].pack("U") }
+ assert_raise(RangeError) { [-1].pack("U") }
assert_equal "\000", [0].pack("U")
- assert_equal "\374\277\277\277\277\277", [0x3fffffff].pack("U")
- assert_equal "\375\200\200\200\200\200", [0x40000000].pack("U")
- assert_equal "\375\277\277\277\277\277", [0x7fffffff].pack("U")
- assert_raises(RangeError) { [0x80000000].pack("U") }
- assert_raises(RangeError) { [0x100000000].pack("U") }
+ assert_equal "\374\277\277\277\277\277".force_encoding(Encoding::UTF_8), [0x3fffffff].pack("U")
+ assert_equal "\375\200\200\200\200\200".force_encoding(Encoding::UTF_8), [0x40000000].pack("U")
+ assert_equal "\375\277\277\277\277\277".force_encoding(Encoding::UTF_8), [0x7fffffff].pack("U")
+ assert_raise(RangeError) { [0x80000000].pack("U") }
+ assert_raise(RangeError) { [0x100000000].pack("U") }
end
def test_pack_P
@@ -379,6 +379,36 @@ class TestPack < Test::Unit::TestCase
assert_equal(["\377\377\377"], "////\n".unpack("m"))
end
+ def test_pack_unpack_m0
+ assert_equal("", [""].pack("m0"))
+ assert_equal("AA==", ["\0"].pack("m0"))
+ assert_equal("AAA=", ["\0\0"].pack("m0"))
+ assert_equal("AAAA", ["\0\0\0"].pack("m0"))
+ assert_equal("/w==", ["\377"].pack("m0"))
+ assert_equal("//8=", ["\377\377"].pack("m0"))
+ assert_equal("////", ["\377\377\377"].pack("m0"))
+
+ assert_equal([""], "".unpack("m0"))
+ assert_equal(["\0"], "AA==".unpack("m0"))
+ assert_equal(["\0\0"], "AAA=".unpack("m0"))
+ assert_equal(["\0\0\0"], "AAAA".unpack("m0"))
+ assert_equal(["\377"], "/w==".unpack("m0"))
+ assert_equal(["\377\377"], "//8=".unpack("m0"))
+ assert_equal(["\377\377\377"], "////".unpack("m0"))
+
+ assert_raise(ArgumentError) { "^".unpack("m0") }
+ assert_raise(ArgumentError) { "A".unpack("m0") }
+ assert_raise(ArgumentError) { "A^".unpack("m0") }
+ assert_raise(ArgumentError) { "AA".unpack("m0") }
+ assert_raise(ArgumentError) { "AA=".unpack("m0") }
+ assert_raise(ArgumentError) { "AA===".unpack("m0") }
+ assert_raise(ArgumentError) { "AA=x".unpack("m0") }
+ assert_raise(ArgumentError) { "AAA".unpack("m0") }
+ assert_raise(ArgumentError) { "AAA^".unpack("m0") }
+ assert_raise(ArgumentError) { "AB==".unpack("m0") }
+ assert_raise(ArgumentError) { "AAB=".unpack("m0") }
+ end
+
def test_pack_unpack_M
assert_equal("a b c\td =\n\ne=\n", ["a b c\td \ne"].pack("M"))
assert_equal(["a b c\td \ne"], "a b c\td =\n\ne=\n".unpack("M"))
diff --git a/test/ruby/test_path.rb b/test/ruby/test_path.rb
index 18c701f033..0489e7fe8c 100644
--- a/test/ruby/test_path.rb
+++ b/test/ruby/test_path.rb
@@ -45,7 +45,7 @@ class TestPath < Test::Unit::TestCase
end
def test_dirname
- if /(bcc|ms)win\d|mingw|cygwin|djgpp|human|emx/ =~ RUBY_PLATFORM
+ if /(bcc|ms)win\d|mingw|cygwin|emx/ =~ RUBY_PLATFORM
# DOSISH_DRIVE_LETTER
assert_equal('C:.', File.dirname('C:'))
assert_equal('C:.', File.dirname('C:a'))
@@ -101,7 +101,7 @@ class TestPath < Test::Unit::TestCase
assert_equal('/', File.dirname('/a/'))
assert_equal('/a', File.dirname('/a/b'))
- if /(bcc|ms|cyg)win|mingw|djgpp|human|emx/ =~ RUBY_PLATFORM
+ if /(bcc|ms|cyg)win|mingw|emx/ =~ RUBY_PLATFORM
# DOSISH_UNC
assert_equal('//', File.dirname('//'))
assert_equal('//a', File.dirname('//a'))
@@ -135,7 +135,7 @@ class TestPath < Test::Unit::TestCase
end
def test_basename
- if /(bcc|ms)win\d|mingw|cygwin|djgpp|human|emx/ =~ RUBY_PLATFORM
+ if /(bcc|ms)win\d|mingw|cygwin|emx/ =~ RUBY_PLATFORM
# DOSISH_DRIVE_LETTER
assert_equal('', File.basename('C:'))
assert_equal('a', File.basename('C:a'))
@@ -189,7 +189,7 @@ class TestPath < Test::Unit::TestCase
assert_equal('a', File.basename('/a/'))
assert_equal('b', File.basename('/a/b'))
- if /(bcc|ms|cyg)win|mingw|djgpp|human|emx/ =~ RUBY_PLATFORM
+ if /(bcc|ms|cyg)win|mingw|emx/ =~ RUBY_PLATFORM
# DOSISH_UNC
assert_equal('/', File.basename('//'))
assert_equal('/', File.basename('//a'))
diff --git a/test/ruby/test_prec.rb b/test/ruby/test_prec.rb
deleted file mode 100644
index d872242c11..0000000000
--- a/test/ruby/test_prec.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-require 'test/unit'
-
-class TestPrecision < Test::Unit::TestCase
- def test_prec_i
- assert_same(1, 1.0.prec(Integer))
- assert_same(1, 1.0.prec_i)
- assert_same(1, Integer.induced_from(1.0))
- end
-
- def test_prec_f
- assert_equal(1.0, 1.prec(Float))
- assert_equal(1.0, 1.prec_f)
- assert_equal(1.0, Float.induced_from(1))
- end
-
- def test_induced_from
- m = Module.new
- m.instance_eval { include(Precision) }
- assert_raise(TypeError) { m.induced_from(0) }
- end
-end
diff --git a/test/ruby/test_proc.rb b/test/ruby/test_proc.rb
index ee53eeaf3a..83ef8f38dd 100644
--- a/test/ruby/test_proc.rb
+++ b/test/ruby/test_proc.rb
@@ -309,4 +309,368 @@ class TestProc < Test::Unit::TestCase
def test_binding2
assert_raise(ArgumentError) { proc {}.curry.binding }
end
+
+ def test_proc_args_plain
+ pr = proc {|a,b,c,d,e|
+ [a,b,c,d,e]
+ }
+ assert_equal [nil,nil,nil,nil,nil], pr.call()
+ assert_equal [1,nil,nil,nil,nil], pr.call(1)
+ assert_equal [1,2,nil,nil,nil], pr.call(1,2)
+ assert_equal [1,2,3,nil,nil], pr.call(1,2,3)
+ assert_equal [1,2,3,4,nil], pr.call(1,2,3,4)
+ assert_equal [1,2,3,4,5], pr.call(1,2,3,4,5)
+ assert_equal [1,2,3,4,5], pr.call(1,2,3,4,5,6)
+
+ assert_equal [nil,nil,nil,nil,nil], pr.call([])
+ assert_equal [1,nil,nil,nil,nil], pr.call([1])
+ assert_equal [1,2,nil,nil,nil], pr.call([1,2])
+ assert_equal [1,2,3,nil,nil], pr.call([1,2,3])
+ assert_equal [1,2,3,4,nil], pr.call([1,2,3,4])
+ assert_equal [1,2,3,4,5], pr.call([1,2,3,4,5])
+ assert_equal [1,2,3,4,5], pr.call([1,2,3,4,5,6])
+
+ r = proc{|a| a}.call([1,2,3])
+ assert_equal [1,2,3], r
+
+ r = proc{|a,| a}.call([1,2,3])
+ assert_equal 1, r
+
+ r = proc{|a,| a}.call([])
+ assert_equal nil, r
+ end
+
+
+ def test_proc_args_rest
+ pr = proc {|a,b,c,*d|
+ [a,b,c,d]
+ }
+ assert_equal [nil,nil,nil,[]], pr.call()
+ assert_equal [1,nil,nil,[]], pr.call(1)
+ assert_equal [1,2,nil,[]], pr.call(1,2)
+ assert_equal [1,2,3,[]], pr.call(1,2,3)
+ assert_equal [1,2,3,[4]], pr.call(1,2,3,4)
+ assert_equal [1,2,3,[4,5]], pr.call(1,2,3,4,5)
+ assert_equal [1,2,3,[4,5,6]], pr.call(1,2,3,4,5,6)
+
+ assert_equal [nil,nil,nil,[]], pr.call([])
+ assert_equal [1,nil,nil,[]], pr.call([1])
+ assert_equal [1,2,nil,[]], pr.call([1,2])
+ assert_equal [1,2,3,[]], pr.call([1,2,3])
+ assert_equal [1,2,3,[4]], pr.call([1,2,3,4])
+ assert_equal [1,2,3,[4,5]], pr.call([1,2,3,4,5])
+ assert_equal [1,2,3,[4,5,6]], pr.call([1,2,3,4,5,6])
+
+ r = proc{|*a| a}.call([1,2,3])
+ assert [1,2,3], r
+ end
+
+ def test_proc_args_rest_and_post
+ pr = proc {|a,b,*c,d,e|
+ [a,b,c,d,e]
+ }
+ assert_equal [nil, nil, [], nil, nil], pr.call()
+ assert_equal [1, nil, [], nil, nil], pr.call(1)
+ assert_equal [1, 2, [], nil, nil], pr.call(1,2)
+ assert_equal [1, 2, [], 3, nil], pr.call(1,2,3)
+ assert_equal [1, 2, [], 3, 4], pr.call(1,2,3,4)
+ assert_equal [1, 2, [3], 4, 5], pr.call(1,2,3,4,5)
+ assert_equal [1, 2, [3, 4], 5, 6], pr.call(1,2,3,4,5,6)
+ assert_equal [1, 2, [3, 4, 5], 6,7], pr.call(1,2,3,4,5,6,7)
+
+ assert_equal [nil, nil, [], nil, nil], pr.call([])
+ assert_equal [1, nil, [], nil, nil], pr.call([1])
+ assert_equal [1, 2, [], nil, nil], pr.call([1,2])
+ assert_equal [1, 2, [], 3, nil], pr.call([1,2,3])
+ assert_equal [1, 2, [], 3, 4], pr.call([1,2,3,4])
+ assert_equal [1, 2, [3], 4, 5], pr.call([1,2,3,4,5])
+ assert_equal [1, 2, [3, 4], 5, 6], pr.call([1,2,3,4,5,6])
+ assert_equal [1, 2, [3, 4, 5], 6,7], pr.call([1,2,3,4,5,6,7])
+ end
+
+ def test_proc_args_opt
+ pr = proc {|a,b,c=:c|
+ [a,b,c]
+ }
+ assert_equal [nil, nil, :c], pr.call()
+ assert_equal [1, nil, :c], pr.call(1)
+ assert_equal [1, 2, :c], pr.call(1,2)
+ assert_equal [1, 2, 3], pr.call(1,2,3)
+ assert_equal [1, 2, 3], pr.call(1,2,3,4)
+ assert_equal [1, 2, 3], pr.call(1,2,3,4,5)
+ assert_equal [1, 2, 3], pr.call(1,2,3,4,5,6)
+
+ assert_equal [nil, nil, :c], pr.call([])
+ assert_equal [1, nil, :c], pr.call([1])
+ assert_equal [1, 2, :c], pr.call([1,2])
+ assert_equal [1, 2, 3], pr.call([1,2,3])
+ assert_equal [1, 2, 3], pr.call([1,2,3,4])
+ assert_equal [1, 2, 3], pr.call([1,2,3,4,5])
+ assert_equal [1, 2, 3], pr.call([1,2,3,4,5,6])
+ end
+
+ def test_proc_args_opt_and_post
+ pr = proc {|a,b,c=:c,d,e|
+ [a,b,c,d,e]
+ }
+ assert_equal [nil, nil, :c, nil, nil], pr.call()
+ assert_equal [1, nil, :c, nil, nil], pr.call(1)
+ assert_equal [1, 2, :c, nil, nil], pr.call(1,2)
+ assert_equal [1, 2, :c, 3, nil], pr.call(1,2,3)
+ assert_equal [1, 2, :c, 3, 4], pr.call(1,2,3,4)
+ assert_equal [1, 2, 3, 4, 5], pr.call(1,2,3,4,5)
+ assert_equal [1, 2, 3, 4, 5], pr.call(1,2,3,4,5,6)
+
+ assert_equal [nil, nil, :c, nil, nil], pr.call([])
+ assert_equal [1, nil, :c, nil, nil], pr.call([1])
+ assert_equal [1, 2, :c, nil, nil], pr.call([1,2])
+ assert_equal [1, 2, :c, 3, nil], pr.call([1,2,3])
+ assert_equal [1, 2, :c, 3, 4], pr.call([1,2,3,4])
+ assert_equal [1, 2, 3, 4, 5], pr.call([1,2,3,4,5])
+ assert_equal [1, 2, 3, 4, 5], pr.call([1,2,3,4,5,6])
+ end
+
+ def test_proc_args_opt_and_rest
+ pr = proc {|a,b,c=:c,*d|
+ [a,b,c,d]
+ }
+ assert_equal [nil, nil, :c, []], pr.call()
+ assert_equal [1, nil, :c, []], pr.call(1)
+ assert_equal [1, 2, :c, []], pr.call(1,2)
+ assert_equal [1, 2, 3, []], pr.call(1,2,3)
+ assert_equal [1, 2, 3, [4]], pr.call(1,2,3,4)
+ assert_equal [1, 2, 3, [4, 5]], pr.call(1,2,3,4,5)
+
+ assert_equal [nil, nil, :c, []], pr.call([])
+ assert_equal [1, nil, :c, []], pr.call([1])
+ assert_equal [1, 2, :c, []], pr.call([1,2])
+ assert_equal [1, 2, 3, []], pr.call([1,2,3])
+ assert_equal [1, 2, 3, [4]], pr.call([1,2,3,4])
+ assert_equal [1, 2, 3, [4, 5]], pr.call([1,2,3,4,5])
+ end
+
+ def test_proc_args_opt_and_rest_and_post
+ pr = proc {|a,b,c=:c,*d,e|
+ [a,b,c,d,e]
+ }
+ assert_equal [nil, nil, :c, [], nil], pr.call()
+ assert_equal [1, nil, :c, [], nil], pr.call(1)
+ assert_equal [1, 2, :c, [], nil], pr.call(1,2)
+ assert_equal [1, 2, :c, [], 3], pr.call(1,2,3)
+ assert_equal [1, 2, 3, [], 4], pr.call(1,2,3,4)
+ assert_equal [1, 2, 3, [4], 5], pr.call(1,2,3,4,5)
+ assert_equal [1, 2, 3, [4,5], 6], pr.call(1,2,3,4,5,6)
+
+ assert_equal [nil, nil, :c, [], nil], pr.call([])
+ assert_equal [1, nil, :c, [], nil], pr.call([1])
+ assert_equal [1, 2, :c, [], nil], pr.call([1,2])
+ assert_equal [1, 2, :c, [], 3], pr.call([1,2,3])
+ assert_equal [1, 2, 3, [], 4], pr.call([1,2,3,4])
+ assert_equal [1, 2, 3, [4], 5], pr.call([1,2,3,4,5])
+ assert_equal [1, 2, 3, [4,5], 6], pr.call([1,2,3,4,5,6])
+ end
+
+ def test_proc_args_block
+ pr = proc {|a,b,&c|
+ [a, b, c.class, c&&c.call(:x)]
+ }
+ assert_equal [nil, nil, NilClass, nil], pr.call()
+ assert_equal [1, nil, NilClass, nil], pr.call(1)
+ assert_equal [1, 2, NilClass, nil], pr.call(1,2)
+ assert_equal [1, 2, NilClass, nil], pr.call(1,2,3)
+ assert_equal [1, 2, NilClass, nil], pr.call(1,2,3,4)
+
+ assert_equal [nil, nil, Proc, :proc], (pr.call(){ :proc })
+ assert_equal [1, nil, Proc, :proc], (pr.call(1){ :proc })
+ assert_equal [1, 2, Proc, :proc], (pr.call(1, 2){ :proc })
+ assert_equal [1, 2, Proc, :proc], (pr.call(1, 2, 3){ :proc })
+ assert_equal [1, 2, Proc, :proc], (pr.call(1, 2, 3, 4){ :proc })
+
+ assert_equal [nil, nil, Proc, :x], (pr.call(){|x| x})
+ assert_equal [1, nil, Proc, :x], (pr.call(1){|x| x})
+ assert_equal [1, 2, Proc, :x], (pr.call(1, 2){|x| x})
+ assert_equal [1, 2, Proc, :x], (pr.call(1, 2, 3){|x| x})
+ assert_equal [1, 2, Proc, :x], (pr.call(1, 2, 3, 4){|x| x})
+ end
+
+ def test_proc_args_rest_and_block
+ pr = proc {|a,b,*c,&d|
+ [a, b, c, d.class, d&&d.call(:x)]
+ }
+ assert_equal [nil, nil, [], NilClass, nil], pr.call()
+ assert_equal [1, nil, [], NilClass, nil], pr.call(1)
+ assert_equal [1, 2, [], NilClass, nil], pr.call(1,2)
+ assert_equal [1, 2, [3], NilClass, nil], pr.call(1,2,3)
+ assert_equal [1, 2, [3,4], NilClass, nil], pr.call(1,2,3,4)
+
+ assert_equal [nil, nil, [], Proc, :proc], (pr.call(){ :proc })
+ assert_equal [1, nil, [], Proc, :proc], (pr.call(1){ :proc })
+ assert_equal [1, 2, [], Proc, :proc], (pr.call(1, 2){ :proc })
+ assert_equal [1, 2, [3], Proc, :proc], (pr.call(1, 2, 3){ :proc })
+ assert_equal [1, 2, [3,4], Proc, :proc], (pr.call(1, 2, 3, 4){ :proc })
+
+ assert_equal [nil, nil, [], Proc, :x], (pr.call(){|x| x})
+ assert_equal [1, nil, [], Proc, :x], (pr.call(1){|x| x})
+ assert_equal [1, 2, [], Proc, :x], (pr.call(1, 2){|x| x})
+ assert_equal [1, 2, [3], Proc, :x], (pr.call(1, 2, 3){|x| x})
+ assert_equal [1, 2, [3,4], Proc, :x], (pr.call(1, 2, 3, 4){|x| x})
+ end
+
+ def test_proc_args_rest_and_post_and_block
+ pr = proc {|a,b,*c,d,e,&f|
+ [a, b, c, d, e, f.class, f&&f.call(:x)]
+ }
+ assert_equal [nil, nil, [], nil, nil, NilClass, nil], pr.call()
+ assert_equal [1, nil, [], nil, nil, NilClass, nil], pr.call(1)
+ assert_equal [1, 2, [], nil, nil, NilClass, nil], pr.call(1,2)
+ assert_equal [1, 2, [], 3, nil, NilClass, nil], pr.call(1,2,3)
+ assert_equal [1, 2, [], 3, 4, NilClass, nil], pr.call(1,2,3,4)
+ assert_equal [1, 2, [3], 4, 5, NilClass, nil], pr.call(1,2,3,4,5)
+ assert_equal [1, 2, [3,4], 5, 6, NilClass, nil], pr.call(1,2,3,4,5,6)
+
+ assert_equal [nil, nil, [], nil, nil, Proc, :proc], (pr.call(){ :proc })
+ assert_equal [1, nil, [], nil, nil, Proc, :proc], (pr.call(1){ :proc })
+ assert_equal [1, 2, [], nil, nil, Proc, :proc], (pr.call(1, 2){ :proc })
+ assert_equal [1, 2, [], 3, nil, Proc, :proc], (pr.call(1, 2, 3){ :proc })
+ assert_equal [1, 2, [], 3, 4, Proc, :proc], (pr.call(1, 2, 3, 4){ :proc })
+ assert_equal [1, 2, [3], 4, 5, Proc, :proc], (pr.call(1, 2, 3, 4, 5){ :proc })
+ assert_equal [1, 2, [3,4], 5, 6, Proc, :proc], (pr.call(1, 2, 3, 4, 5, 6){ :proc })
+
+ assert_equal [nil, nil, [], nil, nil, Proc, :x], (pr.call(){|x| x})
+ assert_equal [1, nil, [], nil, nil, Proc, :x], (pr.call(1){|x| x})
+ assert_equal [1, 2, [], nil, nil, Proc, :x], (pr.call(1, 2){|x| x})
+ assert_equal [1, 2, [], 3, nil, Proc, :x], (pr.call(1, 2, 3){|x| x})
+ assert_equal [1, 2, [], 3, 4, Proc, :x], (pr.call(1, 2, 3, 4){|x| x})
+ assert_equal [1, 2, [3], 4, 5, Proc, :x], (pr.call(1, 2, 3, 4, 5){|x| x})
+ assert_equal [1, 2, [3,4], 5, 6, Proc, :x], (pr.call(1, 2, 3, 4, 5, 6){|x| x})
+ end
+
+ def test_proc_args_opt_and_block
+ pr = proc {|a,b,c=:c,d=:d,&e|
+ [a, b, c, d, e.class, e&&e.call(:x)]
+ }
+ assert_equal [nil, nil, :c, :d, NilClass, nil], pr.call()
+ assert_equal [1, nil, :c, :d, NilClass, nil], pr.call(1)
+ assert_equal [1, 2, :c, :d, NilClass, nil], pr.call(1,2)
+ assert_equal [1, 2, 3, :d, NilClass, nil], pr.call(1,2,3)
+ assert_equal [1, 2, 3, 4, NilClass, nil], pr.call(1,2,3,4)
+ assert_equal [1, 2, 3, 4, NilClass, nil], pr.call(1,2,3,4,5)
+
+ assert_equal [nil, nil, :c, :d, Proc, :proc], (pr.call(){ :proc })
+ assert_equal [1, nil, :c, :d, Proc, :proc], (pr.call(1){ :proc })
+ assert_equal [1, 2, :c, :d, Proc, :proc], (pr.call(1, 2){ :proc })
+ assert_equal [1, 2, 3, :d, Proc, :proc], (pr.call(1, 2, 3){ :proc })
+ assert_equal [1, 2, 3, 4, Proc, :proc], (pr.call(1, 2, 3, 4){ :proc })
+ assert_equal [1, 2, 3, 4, Proc, :proc], (pr.call(1, 2, 3, 4, 5){ :proc })
+
+ assert_equal [nil, nil, :c, :d, Proc, :x], (pr.call(){|x| x})
+ assert_equal [1, nil, :c, :d, Proc, :x], (pr.call(1){|x| x})
+ assert_equal [1, 2, :c, :d, Proc, :x], (pr.call(1, 2){|x| x})
+ assert_equal [1, 2, 3, :d, Proc, :x], (pr.call(1, 2, 3){|x| x})
+ assert_equal [1, 2, 3, 4, Proc, :x], (pr.call(1, 2, 3, 4){|x| x})
+ assert_equal [1, 2, 3, 4, Proc, :x], (pr.call(1, 2, 3, 4, 5){|x| x})
+ end
+
+ def test_proc_args_opt_and_post_and_block
+ pr = proc {|a,b,c=:c,d=:d,e,f,&g|
+ [a, b, c, d, e, f, g.class, g&&g.call(:x)]
+ }
+ assert_equal [nil, nil, :c, :d, nil, nil, NilClass, nil], pr.call()
+ assert_equal [1, nil, :c, :d, nil, nil, NilClass, nil], pr.call(1)
+ assert_equal [1, 2, :c, :d, nil, nil, NilClass, nil], pr.call(1,2)
+ assert_equal [1, 2, :c, :d, 3, nil, NilClass, nil], pr.call(1,2,3)
+ assert_equal [1, 2, :c, :d, 3, 4, NilClass, nil], pr.call(1,2,3,4)
+ assert_equal [1, 2, 3, :d, 4, 5, NilClass, nil], pr.call(1,2,3,4,5)
+ assert_equal [1, 2, 3, 4, 5, 6, NilClass, nil], pr.call(1,2,3,4,5,6)
+ assert_equal [1, 2, 3, 4, 5, 6, NilClass, nil], pr.call(1,2,3,4,5,6,7)
+
+ assert_equal [nil, nil, :c, :d, nil, nil, Proc, :proc], (pr.call(){ :proc })
+ assert_equal [1, nil, :c, :d, nil, nil, Proc, :proc], (pr.call(1){ :proc })
+ assert_equal [1, 2, :c, :d, nil, nil, Proc, :proc], (pr.call(1, 2){ :proc })
+ assert_equal [1, 2, :c, :d, 3, nil, Proc, :proc], (pr.call(1, 2, 3){ :proc })
+ assert_equal [1, 2, :c, :d, 3, 4, Proc, :proc], (pr.call(1, 2, 3, 4){ :proc })
+ assert_equal [1, 2, 3, :d, 4, 5, Proc, :proc], (pr.call(1, 2, 3, 4, 5){ :proc })
+ assert_equal [1, 2, 3, 4, 5, 6, Proc, :proc], (pr.call(1, 2, 3, 4, 5, 6){ :proc })
+ assert_equal [1, 2, 3, 4, 5, 6, Proc, :proc], (pr.call(1, 2, 3, 4, 5, 6, 7){ :proc })
+
+ assert_equal [nil, nil, :c, :d, nil, nil, Proc, :x], (pr.call(){|x| x})
+ assert_equal [1, nil, :c, :d, nil, nil, Proc, :x], (pr.call(1){|x| x})
+ assert_equal [1, 2, :c, :d, nil, nil, Proc, :x], (pr.call(1, 2){|x| x})
+ assert_equal [1, 2, :c, :d, 3, nil, Proc, :x], (pr.call(1, 2, 3){|x| x})
+ assert_equal [1, 2, :c, :d, 3, 4, Proc, :x], (pr.call(1, 2, 3, 4){|x| x})
+ assert_equal [1, 2, 3, :d, 4, 5, Proc, :x], (pr.call(1, 2, 3, 4, 5){|x| x})
+ assert_equal [1, 2, 3, 4, 5, 6, Proc, :x], (pr.call(1, 2, 3, 4, 5, 6){|x| x})
+ assert_equal [1, 2, 3, 4, 5, 6, Proc, :x], (pr.call(1, 2, 3, 4, 5, 6, 7){|x| x})
+ end
+
+ def test_proc_args_opt_and_block
+ pr = proc {|a,b,c=:c,d=:d,*e,&f|
+ [a, b, c, d, e, f.class, f&&f.call(:x)]
+ }
+ assert_equal [nil, nil, :c, :d, [], NilClass, nil], pr.call()
+ assert_equal [1, nil, :c, :d, [], NilClass, nil], pr.call(1)
+ assert_equal [1, 2, :c, :d, [], NilClass, nil], pr.call(1,2)
+ assert_equal [1, 2, 3, :d, [], NilClass, nil], pr.call(1,2,3)
+ assert_equal [1, 2, 3, 4, [], NilClass, nil], pr.call(1,2,3,4)
+ assert_equal [1, 2, 3, 4, [5], NilClass, nil], pr.call(1,2,3,4,5)
+ assert_equal [1, 2, 3, 4, [5,6], NilClass, nil], pr.call(1,2,3,4,5,6)
+
+ assert_equal [nil, nil, :c, :d, [], Proc, :proc], (pr.call(){ :proc })
+ assert_equal [1, nil, :c, :d, [], Proc, :proc], (pr.call(1){ :proc })
+ assert_equal [1, 2, :c, :d, [], Proc, :proc], (pr.call(1, 2){ :proc })
+ assert_equal [1, 2, 3, :d, [], Proc, :proc], (pr.call(1, 2, 3){ :proc })
+ assert_equal [1, 2, 3, 4, [], Proc, :proc], (pr.call(1, 2, 3, 4){ :proc })
+ assert_equal [1, 2, 3, 4, [5], Proc, :proc], (pr.call(1, 2, 3, 4, 5){ :proc })
+ assert_equal [1, 2, 3, 4, [5,6], Proc, :proc], (pr.call(1, 2, 3, 4, 5, 6){ :proc })
+
+ assert_equal [nil, nil, :c, :d, [], Proc, :x], (pr.call(){|x| x})
+ assert_equal [1, nil, :c, :d, [], Proc, :x], (pr.call(1){|x| x})
+ assert_equal [1, 2, :c, :d, [], Proc, :x], (pr.call(1, 2){|x| x})
+ assert_equal [1, 2, 3, :d, [], Proc, :x], (pr.call(1, 2, 3){|x| x})
+ assert_equal [1, 2, 3, 4, [], Proc, :x], (pr.call(1, 2, 3, 4){|x| x})
+ assert_equal [1, 2, 3, 4, [5], Proc, :x], (pr.call(1, 2, 3, 4, 5){|x| x})
+ assert_equal [1, 2, 3, 4, [5,6], Proc, :x], (pr.call(1, 2, 3, 4, 5, 6){|x| x})
+ end
+
+ def test_proc_args_opt_and_rest_and_post_and_block
+ pr = proc {|a,b,c=:c,d=:d,*e,f,g,&h|
+ [a, b, c, d, e, f, g, h.class, h&&h.call(:x)]
+ }
+ assert_equal [nil, nil, :c, :d, [], nil, nil, NilClass, nil], pr.call()
+ assert_equal [1, nil, :c, :d, [], nil, nil, NilClass, nil], pr.call(1)
+ assert_equal [1, 2, :c, :d, [], nil, nil, NilClass, nil], pr.call(1,2)
+ assert_equal [1, 2, :c, :d, [], 3, nil, NilClass, nil], pr.call(1,2,3)
+ assert_equal [1, 2, :c, :d, [], 3, 4, NilClass, nil], pr.call(1,2,3,4)
+ assert_equal [1, 2, 3, :d, [], 4, 5, NilClass, nil], pr.call(1,2,3,4,5)
+ assert_equal [1, 2, 3, 4, [], 5, 6, NilClass, nil], pr.call(1,2,3,4,5,6)
+ assert_equal [1, 2, 3, 4, [5], 6, 7, NilClass, nil], pr.call(1,2,3,4,5,6,7)
+ assert_equal [1, 2, 3, 4, [5,6], 7, 8, NilClass, nil], pr.call(1,2,3,4,5,6,7,8)
+
+ assert_equal [nil, nil, :c, :d, [], nil, nil, Proc, :proc], (pr.call(){ :proc })
+ assert_equal [1, nil, :c, :d, [], nil, nil, Proc, :proc], (pr.call(1){ :proc })
+ assert_equal [1, 2, :c, :d, [], nil, nil, Proc, :proc], (pr.call(1, 2){ :proc })
+ assert_equal [1, 2, :c, :d, [], 3, nil, Proc, :proc], (pr.call(1, 2, 3){ :proc })
+ assert_equal [1, 2, :c, :d, [], 3, 4, Proc, :proc], (pr.call(1, 2, 3, 4){ :proc })
+ assert_equal [1, 2, 3, :d, [], 4, 5, Proc, :proc], (pr.call(1, 2, 3, 4, 5){ :proc })
+ assert_equal [1, 2, 3, 4, [], 5, 6, Proc, :proc], (pr.call(1, 2, 3, 4, 5, 6){ :proc })
+ assert_equal [1, 2, 3, 4, [5], 6, 7, Proc, :proc], (pr.call(1, 2, 3, 4, 5, 6, 7){ :proc })
+ assert_equal [1, 2, 3, 4, [5,6], 7, 8, Proc, :proc], (pr.call(1, 2, 3, 4, 5, 6, 7, 8){ :proc })
+
+ assert_equal [nil, nil, :c, :d, [], nil, nil, Proc, :x], (pr.call(){|x| x})
+ assert_equal [1, nil, :c, :d, [], nil, nil, Proc, :x], (pr.call(1){|x| x})
+ assert_equal [1, 2, :c, :d, [], nil, nil, Proc, :x], (pr.call(1, 2){|x| x})
+ assert_equal [1, 2, :c, :d, [], 3, nil, Proc, :x], (pr.call(1, 2, 3){|x| x})
+ assert_equal [1, 2, :c, :d, [], 3, 4, Proc, :x], (pr.call(1, 2, 3, 4){|x| x})
+ assert_equal [1, 2, 3, :d, [], 4, 5, Proc, :x], (pr.call(1, 2, 3, 4, 5){|x| x})
+ assert_equal [1, 2, 3, 4, [], 5, 6, Proc, :x], (pr.call(1, 2, 3, 4, 5, 6){|x| x})
+ assert_equal [1, 2, 3, 4, [5], 6, 7, Proc, :x], (pr.call(1, 2, 3, 4, 5, 6, 7){|x| x})
+ assert_equal [1, 2, 3, 4, [5,6], 7, 8, Proc, :x], (pr.call(1, 2, 3, 4, 5, 6, 7, 8){|x| x})
+ end
+
+ def test_proc_args_unleashed
+ r = proc {|a,b=1,*c,d,e|
+ [a,b,c,d,e]
+ }.call(1,2,3,4,5)
+ assert_equal([1,2,[3],4,5], r, "[ruby-core:19485]")
+ end
end
diff --git a/test/ruby/test_rational.rb b/test/ruby/test_rational.rb
index 71763242df..5758749d5e 100644
--- a/test/ruby/test_rational.rb
+++ b/test/ruby/test_rational.rb
@@ -4,19 +4,23 @@ class RationalSub < Rational; end
class Rational_Test < Test::Unit::TestCase
+ def setup
+ @complex = defined?(Complex)
+ if @complex
+ @keiju = Complex.instance_variable_get('@RCS_ID')
+ end
+ @unify = $".grep(/mathn/).size != 0
+ end
+
def test_ratsub
- c = RationalSub.__send__(:new, 1)
- cc = RationalSub.__send__(:convert, 1)
+ c = RationalSub.__send__(:convert, 1)
assert_kind_of(Numeric, c)
- assert_kind_of(Numeric, cc)
- if defined?(RationalSub::Unify)
+ if @unify
assert_instance_of(Fixnum, c)
- assert_instance_of(Fixnum, cc)
else
assert_instance_of(RationalSub, c)
- assert_instance_of(RationalSub, cc)
c2 = c + 1
assert_instance_of(RationalSub, c2)
@@ -41,7 +45,7 @@ class Rational_Test < Test::Unit::TestCase
assert_equal(true, c.eql?(c2))
assert_equal(false, c.eql?(c3))
- if defined?(Rational::Unify)
+ if @unify
assert_equal(true, c.eql?(0))
else
assert_equal(false, c.eql?(0))
@@ -67,145 +71,59 @@ class Rational_Test < Test::Unit::TestCase
def test_freeze
c = Rational(1)
c.freeze
- unless defined?(Rational::Unify)
+ unless @unify
assert_equal(true, c.frozen?)
end
assert_instance_of(String, c.to_s)
end
- def test_new_bang # no unify & no reduce
- assert_instance_of(Rational, Rational.__send__(:new!, 2,1))
- assert_equal([2,1], Rational.__send__(:new!, 2,1).
- instance_eval{[numerator, denominator]})
- assert_equal([2,4], Rational.__send__(:new!, 2,4).
- instance_eval{[numerator, denominator]})
- assert_equal([-2,4], Rational.__send__(:new!, -2,4).
- instance_eval{[numerator, denominator]})
- assert_equal([-2,4], Rational.__send__(:new!, 2,-4).
- instance_eval{[numerator, denominator]})
- assert_equal([2,4], Rational.__send__(:new!, -2,-4).
- instance_eval{[numerator, denominator]})
-
- # to_i
- assert_equal([2,1], Rational.__send__(:new!, Rational(2)).
- instance_eval{[numerator, denominator]})
- assert_equal([2,3], Rational.__send__(:new!, Rational(2), Rational(3)).
- instance_eval{[numerator, denominator]})
- assert_equal([2,3], Rational.__send__(:new!, 2, Rational(3)).
- instance_eval{[numerator, denominator]})
-
- assert_equal([1,1], Rational.__send__(:new!, 1.1).
- instance_eval{[numerator, denominator]})
- assert_equal([-1,1], Rational.__send__(:new!, -1.1).
- instance_eval{[numerator, denominator]})
- assert_equal([1,1], Rational.__send__(:new!, '1').
- instance_eval{[numerator, denominator]})
- assert_equal([0,1], Rational.__send__(:new!, nil).
- instance_eval{[numerator, denominator]})
-
- assert_raise(ZeroDivisionError){Rational.__send__(:new!, 1, 0)}
- end
-
-=begin
- def test_reduce
- if defined?(Rational::Unify)
- assert_instance_of(Fixnum, Rational.__send__(:reduce, 2,1))
- else
- assert_instance_of(Rational, Rational.__send__(:reduce, 2,1))
- assert_instance_of(Rational, Rational.__send__(:reduce, 2,1))
- end
- assert_equal([2,1], Rational.__send__(:reduce, 2,1).
- instance_eval{[numerator, denominator]})
- assert_equal([1,2], Rational.__send__(:reduce, 2,4).
- instance_eval{[numerator, denominator]})
- assert_equal([-1,2], Rational.__send__(:reduce, -2,4).
- instance_eval{[numerator, denominator]})
- assert_equal([-1,2], Rational.__send__(:reduce, 2,-4).
- instance_eval{[numerator, denominator]})
- assert_equal([1,2], Rational.__send__(:reduce, -2,-4).
- instance_eval{[numerator, denominator]})
-
- assert_raise(ArgumentError){Rational.__send__(:reduce, Rational(1,2),2)}
- assert_raise(ArgumentError){Rational.__send__(:reduce, 2,Rational(1,2))}
- assert_raise(ArgumentError){Rational.
- __send__(:reduce, Rational(1,2),Rational(1,2))}
-
- assert_raise(ArgumentError){Rational.__send__(:reduce, 1.1)}
- assert_raise(ArgumentError){Rational.__send__(:reduce, -1.1)}
- assert_raise(ArgumentError){Rational.__send__(:reduce, '1')}
- assert_raise(ArgumentError){Rational.__send__(:reduce, nil)}
- end
-=end
-
- def test_new
- if defined?(Rational::Unify)
- assert_instance_of(Fixnum, Rational.__send__(:new, 2,1))
- else
- assert_instance_of(Rational, Rational.__send__(:new, 2,1))
- assert_equal([2,1], Rational.__send__(:new, 2,1).
- instance_eval{[numerator, denominator]})
- end
- assert_equal([1,2], Rational.__send__(:new, 2,4).
- instance_eval{[numerator, denominator]})
- assert_equal([-1,2], Rational.__send__(:new, -2,4).
- instance_eval{[numerator, denominator]})
- assert_equal([-1,2], Rational.__send__(:new, 2,-4).
- instance_eval{[numerator, denominator]})
- assert_equal([1,2], Rational.__send__(:new, -2,-4).
- instance_eval{[numerator, denominator]})
-
- assert_raise(ArgumentError){Rational.__send__(:new, Rational(1,2),2)}
- assert_raise(ArgumentError){Rational.__send__(:new, 2,Rational(1,2))}
- assert_raise(ArgumentError){Rational.__send__(:new, Rational(1,2),Rational(1,2))}
-
- assert_raise(ArgumentError){Rational.__send__(:new, 1.1)}
- assert_raise(ArgumentError){Rational.__send__(:new, -1.1)}
- assert_raise(ArgumentError){Rational.__send__(:new, '1')}
- assert_raise(ArgumentError){Rational.__send__(:new, nil)}
-=begin
- assert_raise(ArgumentError){Rational.__send__(:new, Rational(1))}
- if defined?(Complex)
- assert_raise(ArgumentError){Rational.__send__(:new, Complex(1))}
- end
-=end
- end
-
def test_conv
c = Rational(0,1)
- assert_equal(Rational.__send__(:new, 0,1), c)
+ assert_equal(Rational(0,1), c)
c = Rational(2**32, 2**32)
- assert_equal(Rational.__send__(:new, 2**32,2**32), c)
+ assert_equal(Rational(2**32,2**32), c)
assert_equal([1,1], [c.numerator,c.denominator])
c = Rational(-2**32, 2**32)
- assert_equal(Rational.__send__(:new, -2**32,2**32), c)
+ assert_equal(Rational(-2**32,2**32), c)
assert_equal([-1,1], [c.numerator,c.denominator])
c = Rational(2**32, -2**32)
- assert_equal(Rational.__send__(:new, 2**32,-2**32), c)
+ assert_equal(Rational(2**32,-2**32), c)
assert_equal([-1,1], [c.numerator,c.denominator])
c = Rational(-2**32, -2**32)
- assert_equal(Rational.__send__(:new, -2**32,-2**32), c)
+ assert_equal(Rational(-2**32,-2**32), c)
assert_equal([1,1], [c.numerator,c.denominator])
c = Rational(Rational(1,2),2)
- assert_equal(Rational.__send__(:new, 1,4), c)
+ assert_equal(Rational(1,4), c)
c = Rational(2,Rational(1,2))
- assert_equal(Rational.__send__(:new, 4), c)
+ assert_equal(Rational(4), c)
c = Rational(Rational(1,2),Rational(1,2))
- assert_equal(Rational.__send__(:new, 1), c)
+ assert_equal(Rational(1), c)
- assert_equal(Rational.__send__(:new, 3),Rational(3))
- assert_equal(Rational.__send__(:new, 1),Rational(3,3))
+ if @complex && !@keiju
+ c = Rational(Complex(1,2),2)
+ assert_equal(Complex(Rational(1,2),1), c)
+
+ c = Rational(2,Complex(1,2))
+ assert_equal(Complex(Rational(2,5),Rational(-4,5)), c)
+
+ c = Rational(Complex(1,2),Complex(1,2))
+ assert_equal(Rational(1), c)
+ end
+
+ assert_equal(Rational(3),Rational(3))
+ assert_equal(Rational(1),Rational(3,3))
assert_equal(3.3.to_r,Rational(3.3))
assert_equal(1,Rational(3.3,3.3))
- assert_equal(Rational.__send__(:new, 3),Rational('3'))
- assert_equal(Rational.__send__(:new, 1),Rational('3.0','3.0'))
- assert_equal(Rational.__send__(:new, 1),Rational('3/3','3/3'))
+ assert_equal(Rational(3),Rational('3'))
+ assert_equal(Rational(1),Rational('3.0','3.0'))
+ assert_equal(Rational(1),Rational('3/3','3/3'))
assert_raise(ArgumentError){Rational(nil)}
assert_raise(ArgumentError){Rational('')}
assert_raise(ArgumentError){Rational(Object.new)}
@@ -224,22 +142,22 @@ class Rational_Test < Test::Unit::TestCase
assert_equal(4, c.numerator)
assert_equal(5, c.denominator)
- c = Rational.__send__(:new, 4)
+ c = Rational(4)
assert_equal(4, c.numerator)
assert_equal(1, c.denominator)
- c = Rational.__send__(:new, 4,5)
+ c = Rational(4,5)
assert_equal(4, c.numerator)
assert_equal(5, c.denominator)
- c = Rational.__send__(:new!, 4)
+ c = Rational(4)
assert_equal(4, c.numerator)
assert_equal(1, c.denominator)
- c = Rational.__send__(:new!, 4,5)
+ c = Rational(4,5)
assert_equal(4, c.numerator)
assert_equal(5, c.denominator)
@@ -248,8 +166,7 @@ class Rational_Test < Test::Unit::TestCase
def test_attr2
c = Rational(1)
- if defined?(Rational::Unify)
- assert_equal(true, c.scalar?)
+ if @unify
=begin
assert_equal(true, c.finite?)
assert_equal(false, c.infinite?)
@@ -257,13 +174,14 @@ class Rational_Test < Test::Unit::TestCase
assert_equal(true, c.integer?)
assert_equal(false, c.float?)
assert_equal(true, c.rational?)
+=end
assert_equal(true, c.real?)
+=begin
assert_equal(false, c.complex?)
assert_equal(true, c.exact?)
assert_equal(false, c.inexact?)
=end
else
- assert_equal(true, c.scalar?)
=begin
assert_equal(true, c.finite?)
assert_equal(false, c.infinite?)
@@ -271,7 +189,9 @@ class Rational_Test < Test::Unit::TestCase
assert_equal(false, c.integer?)
assert_equal(false, c.float?)
assert_equal(true, c.rational?)
+=end
assert_equal(true, c.real?)
+=begin
assert_equal(false, c.complex?)
assert_equal(true, c.exact?)
assert_equal(false, c.inexact?)
@@ -406,7 +326,7 @@ class Rational_Test < Test::Unit::TestCase
assert_equal(-2, (-c).div(c2))
assert_equal(1, (-c).div(-c2))
- unless defined?(Rational::Unify)
+ unless @unify
c = Rational(11)
c2 = Rational(3)
@@ -441,7 +361,7 @@ class Rational_Test < Test::Unit::TestCase
assert_equal(Rational(99,100), (-c).modulo(c2))
assert_equal(Rational(-101,100), (-c).modulo(-c2))
- unless defined?(Rational::Unify)
+ unless @unify
c = Rational(11)
c2 = Rational(3)
@@ -476,7 +396,7 @@ class Rational_Test < Test::Unit::TestCase
assert_equal([-2, Rational(99,100)], (-c).divmod(c2))
assert_equal([1, Rational(-101,100)], (-c).divmod(-c2))
- unless defined?(Rational::Unify)
+ unless @unify
c = Rational(11)
c2 = Rational(3)
@@ -512,7 +432,7 @@ class Rational_Test < Test::Unit::TestCase
assert_equal(-1, (-c).quot(c2))
assert_equal(1, (-c).quot(-c2))
- unless defined?(Rational::Unify)
+ unless @unify
c = Rational(11)
c2 = Rational(3)
@@ -548,7 +468,7 @@ class Rational_Test < Test::Unit::TestCase
assert_equal(Rational(-101,100), (-c).remainder(c2))
assert_equal(Rational(-101,100), (-c).remainder(-c2))
- unless defined?(Rational::Unify)
+ unless @unify
c = Rational(11)
c2 = Rational(3)
@@ -584,7 +504,7 @@ class Rational_Test < Test::Unit::TestCase
assert_equal([-1, Rational(-101,100)], (-c).quotrem(c2))
assert_equal([1, Rational(-101,100)], (-c).quotrem(-c2))
- unless defined?(Rational::Unify)
+ unless @unify
c = Rational(11)
c2 = Rational(3)
@@ -603,7 +523,7 @@ class Rational_Test < Test::Unit::TestCase
assert_equal(Rational(3,4), c.quo(c2))
assert_equal(Rational(1,4), c.quo(2))
- assert_equal(Rational(0.25), c.quo(2.0))
+ assert_equal(0.25, c.quo(2.0))
end
def test_fdiv
@@ -641,7 +561,7 @@ class Rational_Test < Test::Unit::TestCase
# p ** p
x = 2 ** Rational(2)
assert_equal(Rational(4), x)
- unless defined?(Rational::Unify)
+ unless @unify
assert_instance_of(Rational, x)
end
assert_equal(4, x.numerator)
@@ -649,7 +569,7 @@ class Rational_Test < Test::Unit::TestCase
x = Rational(2) ** 2
assert_equal(Rational(4), x)
- unless defined?(Rational::Unify)
+ unless @unify
assert_instance_of(Rational, x)
end
assert_equal(4, x.numerator)
@@ -657,7 +577,7 @@ class Rational_Test < Test::Unit::TestCase
x = Rational(2) ** Rational(2)
assert_equal(Rational(4), x)
- unless defined?(Rational::Unify)
+ unless @unify
assert_instance_of(Rational, x)
end
assert_equal(4, x.numerator)
@@ -666,7 +586,7 @@ class Rational_Test < Test::Unit::TestCase
# -p ** p
x = (-2) ** Rational(2)
assert_equal(Rational(4), x)
- unless defined?(Rational::Unify)
+ unless @unify
assert_instance_of(Rational, x)
end
assert_equal(4, x.numerator)
@@ -674,7 +594,7 @@ class Rational_Test < Test::Unit::TestCase
x = Rational(-2) ** 2
assert_equal(Rational(4), x)
- unless defined?(Rational::Unify)
+ unless @unify
assert_instance_of(Rational, x)
end
assert_equal(4, x.numerator)
@@ -682,7 +602,7 @@ class Rational_Test < Test::Unit::TestCase
x = Rational(-2) ** Rational(2)
assert_equal(Rational(4), x)
- unless defined?(Rational::Unify)
+ unless @unify
assert_instance_of(Rational, x)
end
assert_equal(4, x.numerator)
@@ -726,7 +646,7 @@ class Rational_Test < Test::Unit::TestCase
assert_equal(1, x.numerator)
assert_equal(4, x.denominator)
- unless defined?(Rational::Unify) # maybe bug mathn
+ unless @unify # maybe bug mathn
assert_raise(ZeroDivisionError){0 ** -1}
end
end
@@ -769,16 +689,7 @@ class Rational_Test < Test::Unit::TestCase
def test_equal
assert(Rational(1,1) == Rational(1))
- assert(Rational(1,1) == Rational.__send__(:new, 1))
- assert(Rational(1,1) == Rational.__send__(:new, 1,1))
- assert(Rational(1,1) == Rational.__send__(:new!, 1))
- assert(Rational(1,1) == Rational.__send__(:new!, 1,1))
-
assert(Rational(-1,1) == Rational(-1))
- assert(Rational(-1,1) == Rational.__send__(:new, -1))
- assert(Rational(-1,1) == Rational.__send__(:new, -1,1))
- assert(Rational(-1,1) == Rational.__send__(:new!, -1))
- assert(Rational(-1,1) == Rational.__send__(:new!, -1,1))
assert_equal(false, Rational(2,1) == Rational(1))
assert_equal(true, Rational(2,1) != Rational(1))
@@ -787,7 +698,7 @@ class Rational_Test < Test::Unit::TestCase
end
def test_unify
- if defined?(Rational::Unify)
+ if @unify
assert_instance_of(Fixnum, Rational(1,2) + Rational(1,2))
assert_instance_of(Fixnum, Rational(1,2) - Rational(1,2))
assert_instance_of(Fixnum, Rational(1,2) * 2)
@@ -801,7 +712,7 @@ class Rational_Test < Test::Unit::TestCase
def test_math
assert_equal(Rational(1,2), Rational(1,2).abs)
assert_equal(Rational(1,2), Rational(-1,2).abs)
- if defined?(Complex) && !Complex.instance_variable_get('@RCS_ID')
+ if @complex && !@keiju
assert_equal(Rational(1,2), Rational(1,2).magnitude)
assert_equal(Rational(1,2), Rational(-1,2).magnitude)
end
@@ -831,7 +742,7 @@ class Rational_Test < Test::Unit::TestCase
assert_instance_of(String, c.to_s)
assert_equal('1/2', c.to_s)
- if defined?(Rational::Unify)
+ if @unify
assert_equal('0', Rational(0,2).to_s)
assert_equal('0', Rational(0,-2).to_s)
else
@@ -854,10 +765,12 @@ class Rational_Test < Test::Unit::TestCase
def test_marshal
c = Rational(1,2)
+ c.instance_eval{@ivar = 9}
s = Marshal.dump(c)
c2 = Marshal.load(s)
assert_equal(c, c2)
+ assert_equal(9, c2.instance_variable_get(:@ivar))
assert_instance_of(Rational, c2)
assert_raise(ZeroDivisionError){
@@ -987,8 +900,8 @@ class Rational_Test < Test::Unit::TestCase
end
def test_to_c
- if defined?(Complex) && !Complex.instance_variable_get('@RCS_ID')
- if defined?(Rational::Unify)
+ if @complex && !@keiju
+ if @unify
assert_equal(Rational(3,2), Rational(3,2).to_c)
assert_equal(Rational(3,2), Complex(Rational(3,2)))
else
@@ -1015,8 +928,8 @@ class Rational_Test < Test::Unit::TestCase
c = Rational(1,2).to_r
assert_equal([1,2] , [c.numerator, c.denominator])
- if defined?(Complex)
- if Complex.instance_variable_get('@RCS_ID')
+ if @complex
+ if @keiju
assert_raise(NoMethodError){Complex(1,2).to_r}
else
assert_raise(RangeError){Complex(1,2).to_r}
@@ -1024,16 +937,6 @@ class Rational_Test < Test::Unit::TestCase
end
end
- def test_prec
- assert_equal(true, Rational < Precision)
-
- c = Rational(3,2)
-
- assert_eql(1, c.prec(Integer))
- assert_eql(1.5, c.prec(Float))
- assert_eql(c, c.prec(Rational))
- end
-
def test_gcdlcm
assert_equal(7, 91.gcd(-49))
assert_equal(5, 5.gcd(0))
@@ -1052,8 +955,8 @@ class Rational_Test < Test::Unit::TestCase
end
def test_supp
- assert_equal(true, 1.scalar?)
- assert_equal(true, 1.1.scalar?)
+ assert_equal(true, 1.real?)
+ assert_equal(true, 1.1.real?)
assert_equal(1, 1.numerator)
assert_equal(9, 9.numerator)
@@ -1089,7 +992,7 @@ class Rational_Test < Test::Unit::TestCase
end
def test_fixed_bug
- if defined?(Rational::Unify)
+ if @unify
assert_instance_of(Fixnum, Rational(1,2) ** 0) # mathn's bug
end
diff --git a/test/ruby/test_rational2.rb b/test/ruby/test_rational2.rb
index 641bfea565..3b6a985bc6 100644
--- a/test/ruby/test_rational2.rb
+++ b/test/ruby/test_rational2.rb
@@ -3,6 +3,8 @@ require 'test/unit'
class Rational_Test2 < Test::Unit::TestCase
def test_kumi
+ assert_equal(Rational(1, 1), +Rational(1, 1))
+ assert_equal(Rational(-1, 1), -Rational(1, 1))
assert_equal(Rational(2, 1),
Rational(1, 1) + Rational(1, 1))
assert_equal(Rational(0, 1),
@@ -107,6 +109,8 @@ class Rational_Test2 < Test::Unit::TestCase
Rational(1, 1) * Rational(1073741827, 1073741789))
assert_equal(Rational(1073741789, 1073741827),
Rational(1, 1) / Rational(1073741827, 1073741789))
+ assert_equal(Rational(2, 1), +Rational(2, 1))
+ assert_equal(Rational(-2, 1), -Rational(2, 1))
assert_equal(Rational(3, 1),
Rational(2, 1) + Rational(1, 1))
assert_equal(Rational(1, 1),
@@ -211,6 +215,8 @@ class Rational_Test2 < Test::Unit::TestCase
Rational(2, 1) * Rational(1073741827, 1073741789))
assert_equal(Rational(2147483578, 1073741827),
Rational(2, 1) / Rational(1073741827, 1073741789))
+ assert_equal(Rational(3, 1), +Rational(3, 1))
+ assert_equal(Rational(-3, 1), -Rational(3, 1))
assert_equal(Rational(4, 1),
Rational(3, 1) + Rational(1, 1))
assert_equal(Rational(2, 1),
@@ -315,6 +321,8 @@ class Rational_Test2 < Test::Unit::TestCase
Rational(3, 1) * Rational(1073741827, 1073741789))
assert_equal(Rational(3221225367, 1073741827),
Rational(3, 1) / Rational(1073741827, 1073741789))
+ assert_equal(Rational(1073741789, 1), +Rational(1073741789, 1))
+ assert_equal(Rational(-1073741789, 1), -Rational(1073741789, 1))
assert_equal(Rational(1073741790, 1),
Rational(1073741789, 1) + Rational(1, 1))
assert_equal(Rational(1073741788, 1),
@@ -419,6 +427,8 @@ class Rational_Test2 < Test::Unit::TestCase
Rational(1073741789, 1) * Rational(1073741827, 1073741789))
assert_equal(Rational(1152921429444920521, 1073741827),
Rational(1073741789, 1) / Rational(1073741827, 1073741789))
+ assert_equal(Rational(1073741827, 1), +Rational(1073741827, 1))
+ assert_equal(Rational(-1073741827, 1), -Rational(1073741827, 1))
assert_equal(Rational(1073741828, 1),
Rational(1073741827, 1) + Rational(1, 1))
assert_equal(Rational(1073741826, 1),
@@ -523,6 +533,8 @@ class Rational_Test2 < Test::Unit::TestCase
Rational(1073741827, 1) * Rational(1073741827, 1073741789))
assert_equal(Rational(1073741789, 1),
Rational(1073741827, 1) / Rational(1073741827, 1073741789))
+ assert_equal(Rational(2, 3), +Rational(2, 3))
+ assert_equal(Rational(-2, 3), -Rational(2, 3))
assert_equal(Rational(5, 3),
Rational(2, 3) + Rational(1, 1))
assert_equal(Rational(-1, 3),
@@ -627,6 +639,8 @@ class Rational_Test2 < Test::Unit::TestCase
Rational(2, 3) * Rational(1073741827, 1073741789))
assert_equal(Rational(2147483578, 3221225481),
Rational(2, 3) / Rational(1073741827, 1073741789))
+ assert_equal(Rational(3, 2), +Rational(3, 2))
+ assert_equal(Rational(-3, 2), -Rational(3, 2))
assert_equal(Rational(5, 2),
Rational(3, 2) + Rational(1, 1))
assert_equal(Rational(1, 2),
@@ -731,6 +745,8 @@ class Rational_Test2 < Test::Unit::TestCase
Rational(3, 2) * Rational(1073741827, 1073741789))
assert_equal(Rational(3221225367, 2147483654),
Rational(3, 2) / Rational(1073741827, 1073741789))
+ assert_equal(Rational(3, 1073741789), +Rational(3, 1073741789))
+ assert_equal(Rational(-3, 1073741789), -Rational(3, 1073741789))
assert_equal(Rational(1073741792, 1073741789),
Rational(3, 1073741789) + Rational(1, 1))
assert_equal(Rational(-1073741786, 1073741789),
@@ -835,6 +851,8 @@ class Rational_Test2 < Test::Unit::TestCase
Rational(3, 1073741789) * Rational(1073741827, 1073741789))
assert_equal(Rational(3, 1073741827),
Rational(3, 1073741789) / Rational(1073741827, 1073741789))
+ assert_equal(Rational(1073741789, 3), +Rational(1073741789, 3))
+ assert_equal(Rational(-1073741789, 3), -Rational(1073741789, 3))
assert_equal(Rational(1073741792, 3),
Rational(1073741789, 3) + Rational(1, 1))
assert_equal(Rational(1073741786, 3),
@@ -939,6 +957,8 @@ class Rational_Test2 < Test::Unit::TestCase
Rational(1073741789, 3) * Rational(1073741827, 1073741789))
assert_equal(Rational(1152921429444920521, 3221225481),
Rational(1073741789, 3) / Rational(1073741827, 1073741789))
+ assert_equal(Rational(3, 1073741827), +Rational(3, 1073741827))
+ assert_equal(Rational(-3, 1073741827), -Rational(3, 1073741827))
assert_equal(Rational(1073741830, 1073741827),
Rational(3, 1073741827) + Rational(1, 1))
assert_equal(Rational(-1073741824, 1073741827),
@@ -1043,6 +1063,8 @@ class Rational_Test2 < Test::Unit::TestCase
Rational(3, 1073741827) * Rational(1073741827, 1073741789))
assert_equal(Rational(3221225367, 1152921511049297929),
Rational(3, 1073741827) / Rational(1073741827, 1073741789))
+ assert_equal(Rational(1073741827, 3), +Rational(1073741827, 3))
+ assert_equal(Rational(-1073741827, 3), -Rational(1073741827, 3))
assert_equal(Rational(1073741830, 3),
Rational(1073741827, 3) + Rational(1, 1))
assert_equal(Rational(1073741824, 3),
@@ -1147,6 +1169,8 @@ class Rational_Test2 < Test::Unit::TestCase
Rational(1073741827, 3) * Rational(1073741827, 1073741789))
assert_equal(Rational(1073741789, 3),
Rational(1073741827, 3) / Rational(1073741827, 1073741789))
+ assert_equal(Rational(1073741789, 1073741827), +Rational(1073741789, 1073741827))
+ assert_equal(Rational(-1073741789, 1073741827), -Rational(1073741789, 1073741827))
assert_equal(Rational(2147483616, 1073741827),
Rational(1073741789, 1073741827) + Rational(1, 1))
assert_equal(Rational(-38, 1073741827),
@@ -1251,6 +1275,8 @@ class Rational_Test2 < Test::Unit::TestCase
Rational(1073741789, 1073741827) * Rational(1073741827, 1073741789))
assert_equal(Rational(1152921429444920521, 1152921511049297929),
Rational(1073741789, 1073741827) / Rational(1073741827, 1073741789))
+ assert_equal(Rational(1073741827, 1073741789), +Rational(1073741827, 1073741789))
+ assert_equal(Rational(-1073741827, 1073741789), -Rational(1073741827, 1073741789))
assert_equal(Rational(2147483616, 1073741789),
Rational(1073741827, 1073741789) + Rational(1, 1))
assert_equal(Rational(38, 1073741789),
diff --git a/test/ruby/test_readpartial.rb b/test/ruby/test_readpartial.rb
index c4f9d193f2..fd601e7d33 100644
--- a/test/ruby/test_readpartial.rb
+++ b/test/ruby/test_readpartial.rb
@@ -38,8 +38,8 @@ class TestReadPartial < Test::Unit::TestCase
w.close
assert_equal('ab', r.readpartial(2))
assert_equal('c', r.readpartial(2))
- assert_raises(EOFError) { r.readpartial(2) }
- assert_raises(EOFError) { r.readpartial(2) }
+ assert_raise(EOFError) { r.readpartial(2) }
+ assert_raise(EOFError) { r.readpartial(2) }
}
end
@@ -48,7 +48,7 @@ class TestReadPartial < Test::Unit::TestCase
w << 'abc'
assert_equal('ab', r.readpartial(2))
assert_equal('c', r.readpartial(2))
- assert_raises(TimeoutError) {
+ assert_raise(TimeoutError) {
timeout(0.1) { r.readpartial(2) }
}
}
@@ -62,7 +62,7 @@ class TestReadPartial < Test::Unit::TestCase
assert_equal("de", r.readpartial(2))
assert_equal("f\n", r.readpartial(4096))
assert_equal("ghi\n", r.readpartial(4096))
- assert_raises(TimeoutError) {
+ assert_raise(TimeoutError) {
timeout(0.1) { r.readpartial(2) }
}
}
diff --git a/test/ruby/test_regexp.rb b/test/ruby/test_regexp.rb
index ad222c5483..fdfef04b4d 100644
--- a/test/ruby/test_regexp.rb
+++ b/test/ruby/test_regexp.rb
@@ -272,8 +272,9 @@ class TestRegexp < Test::Unit::TestCase
Thread.new { $SAFE = 4; re.instance_eval { initialize(re) } }.join
end
- assert_equal(Encoding.find("ASCII-8BIT"), Regexp.new("b..", nil, "n").encoding)
+ assert_equal(Encoding.find("US-ASCII"), Regexp.new("b..", nil, "n").encoding)
assert_equal("bar", "foobarbaz"[Regexp.new("b..", nil, "n")])
+ assert_equal(//n, Regexp.new("", nil, "n"))
assert_raise(RegexpError) { Regexp.new(")(") }
end
diff --git a/test/ruby/test_require.rb b/test/ruby/test_require.rb
index a5f453a055..4048ba038d 100644
--- a/test/ruby/test_require.rb
+++ b/test/ruby/test_require.rb
@@ -27,11 +27,15 @@ class TestRequire < Test::Unit::TestCase
end
INPUT
- assert_in_out_err(["-S", "foo/" * 10000 + "foo"], "") do |r, e|
- assert_equal([], r)
- assert_operator(2, :<=, e.size)
- assert_equal("openpath: pathname too long (ignored)", e.first)
- assert_match(/\(LoadError\)/, e.last)
+ begin
+ assert_in_out_err(["-S", "foo/" * 10000 + "foo"], "") do |r, e|
+ assert_equal([], r)
+ assert_operator(2, :<=, e.size)
+ assert_equal("openpath: pathname too long (ignored)", e.first)
+ assert_match(/\(LoadError\)/, e.last)
+ end
+ rescue Errno::EINVAL
+ # too long commandline may be blocked by OS.
end
end
diff --git a/test/ruby/test_rubyoptions.rb b/test/ruby/test_rubyoptions.rb
index af4ca282ee..c55c99d0d1 100644
--- a/test/ruby/test_rubyoptions.rb
+++ b/test/ruby/test_rubyoptions.rb
@@ -199,17 +199,21 @@ class TestRubyOptions < Test::Unit::TestCase
ENV['RUBYOPT'] = ' - -'
assert_in_out_err([], "", [], [])
+ assert_in_out_err(['-e', 'p $:.include?(".")'], "", ["true"], [])
+
ENV['RUBYOPT'] = '-e "p 1"'
assert_in_out_err([], "", [], /invalid switch in RUBYOPT: -e \(RuntimeError\)/)
ENV['RUBYOPT'] = '-T1'
assert_in_out_err([], "", [], /no program input from stdin allowed in tainted mode \(SecurityError\)/)
+ assert_in_out_err(['-e', 'p $:.include?(".")'], "", ["false"], [])
+
ENV['RUBYOPT'] = '-T4'
assert_in_out_err([], "", [], /no program input from stdin allowed in tainted mode \(SecurityError\)/)
- ENV['RUBYOPT'] = '-KN -Eus-ascii'
- assert_in_out_err(%w(-KU -Eutf-8), "p '\u3042'") do |r, e|
+ ENV['RUBYOPT'] = '-Eus-ascii -KN'
+ assert_in_out_err(%w(-Eutf-8 -KU), "p '\u3042'") do |r, e|
assert_equal("\"\u3042\"", r.join.force_encoding(Encoding::UTF_8))
assert_equal([], e)
end
diff --git a/test/ruby/test_settracefunc.rb b/test/ruby/test_settracefunc.rb
index c098e548b8..a446969f38 100644
--- a/test/ruby/test_settracefunc.rb
+++ b/test/ruby/test_settracefunc.rb
@@ -60,7 +60,7 @@ class TestSetTraceFunc < Test::Unit::TestCase
events.shift)
assert_equal(["line", 7, __method__, self.class],
events.shift)
- assert_equal(["call", 6, :add, self.class],
+ assert_equal(["call", 4, :add, self.class],
events.shift)
assert_equal(["line", 5, :add, self.class],
events.shift)
@@ -68,7 +68,7 @@ class TestSetTraceFunc < Test::Unit::TestCase
events.shift)
assert_equal(["c-return", 5, :+, Fixnum],
events.shift)
- assert_equal(["return", 6, :add, self.class],
+ assert_equal(["return", 4, :add, self.class],
events.shift)
assert_equal(["line", 8, __method__, self.class],
events.shift)
@@ -118,9 +118,9 @@ class TestSetTraceFunc < Test::Unit::TestCase
events.shift)
assert_equal(["c-return", 8, :new, Class],
events.shift)
- assert_equal(["call", 6, :bar, Foo],
+ assert_equal(["call", 5, :bar, Foo],
events.shift)
- assert_equal(["return", 6, :bar, Foo],
+ assert_equal(["return", 5, :bar, Foo],
events.shift)
assert_equal(["line", 9, __method__, self.class],
events.shift)
diff --git a/test/ruby/test_signal.rb b/test/ruby/test_signal.rb
index 0bc2078c18..9414b6539e 100644
--- a/test/ruby/test_signal.rb
+++ b/test/ruby/test_signal.rb
@@ -21,7 +21,7 @@ class TestSignal < Test::Unit::TestCase
assert_equal 2, x
Signal.trap(:INT) { raise "Interrupt" }
- ex = assert_raises(RuntimeError) {
+ ex = assert_raise(RuntimeError) {
Process.kill :INT, Process.pid
sleep 0.1
}
@@ -41,7 +41,7 @@ class TestSignal < Test::Unit::TestCase
Signal.trap(:USR1, "EXIT")
w0.close
w.syswrite("a")
- Thread.start { Thread.pass }
+ Thread.start { sleep(2) }
r0.sysread(4096)
}
r.sysread(1)
diff --git a/test/ruby/test_sprintf_comb.rb b/test/ruby/test_sprintf_comb.rb
index 8b2c1a7e05..5dee7305fb 100644
--- a/test/ruby/test_sprintf_comb.rb
+++ b/test/ruby/test_sprintf_comb.rb
@@ -131,6 +131,11 @@ class TestSprintfComb < Test::Unit::TestCase
zr = nil if mi && zr
case type
+ when 'B'
+ radix = 2
+ digitmap = {0 => '0', 1 => '1'}
+ complement = !pl && !sp
+ prefix = '0B' if hs && v != 0
when 'b'
radix = 2
digitmap = {0 => '0', 1 => '1'}
@@ -265,7 +270,7 @@ class TestSprintfComb < Test::Unit::TestCase
def test_format_integer
combination(
- %w[b d o X x],
+ %w[B b d o X x],
[nil, 0, 5, 20],
["", ".", ".0", ".8", ".20"],
['', ' '],
diff --git a/test/ruby/test_thread.rb b/test/ruby/test_thread.rb
index 4332b0fe2e..97e58cd9ea 100644
--- a/test/ruby/test_thread.rb
+++ b/test/ruby/test_thread.rb
@@ -71,7 +71,7 @@ class TestThread < Test::Unit::TestCase
mutex = Mutex.new
condvar = ConditionVariable.new
- assert_raises(ThreadError) { condvar.wait(mutex) }
+ assert_raise(ThreadError) { condvar.wait(mutex) }
end
def test_condvar_wait_exception_handling
@@ -98,7 +98,7 @@ class TestThread < Test::Unit::TestCase
end
thread.raise Interrupt, "interrupt a dead condition variable"
- assert_raises(Interrupt) { thread.value }
+ assert_raise(Interrupt) { thread.value }
assert(locked)
end
diff --git a/test/ruby/test_transcode.rb b/test/ruby/test_transcode.rb
index d7a4aca99c..1d16d98422 100644
--- a/test/ruby/test_transcode.rb
+++ b/test/ruby/test_transcode.rb
@@ -3,31 +3,14 @@
require 'test/unit'
class TestTranscode < Test::Unit::TestCase
- def setup_really_needed? # trick to create all the necessary encodings
- all_encodings = [ 'ISO-8859-1', 'ISO-8859-2',
- 'ISO-8859-3', 'ISO-8859-4',
- 'ISO-8859-5', 'ISO-8859-6',
- 'ISO-8859-7', 'ISO-8859-8',
- 'ISO-8859-9', 'ISO-8859-10',
- 'ISO-8859-11', 'ISO-8859-13',
- 'ISO-8859-14', 'ISO-8859-15',
- 'UTF-16BE'
- ]
- all_encodings.each do |enc|
- 'abc'.encode(enc, 'UTF-8')
- end
- end
-
def test_errors
- assert_raise(ArgumentError) { 'abc'.encode }
- assert_raise(ArgumentError) { 'abc'.encode! }
- assert_raise(Encoding::NoConverter) { 'abc'.encode('foo', 'bar') }
- assert_raise(Encoding::NoConverter) { 'abc'.encode!('foo', 'bar') }
- assert_raise(Encoding::NoConverter) { 'abc'.force_encoding('utf-8').encode('foo') }
- assert_raise(Encoding::NoConverter) { 'abc'.force_encoding('utf-8').encode!('foo') }
- assert_raise(Encoding::ConversionUndefined) { "\x80".encode('utf-8','ASCII-8BIT') }
- assert_raise(Encoding::InvalidByteSequence) { "\x80".encode('utf-8','US-ASCII') }
- assert_raise(Encoding::ConversionUndefined) { "\xA5".encode('utf-8','iso-8859-3') }
+ assert_raise(Encoding::ConverterNotFoundError) { 'abc'.encode('foo', 'bar') }
+ assert_raise(Encoding::ConverterNotFoundError) { 'abc'.encode!('foo', 'bar') }
+ assert_raise(Encoding::ConverterNotFoundError) { 'abc'.force_encoding('utf-8').encode('foo') }
+ assert_raise(Encoding::ConverterNotFoundError) { 'abc'.force_encoding('utf-8').encode!('foo') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x80".encode('utf-8','ASCII-8BIT') }
+ assert_raise(Encoding::InvalidByteSequenceError) { "\x80".encode('utf-8','US-ASCII') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA5".encode('utf-8','iso-8859-3') }
end
def test_arguments
@@ -133,6 +116,712 @@ class TestTranscode < Test::Unit::TestCase
end
end
+ def test_windows_874
+ check_both_ways("\u20AC", "\x80", 'windows-874') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x81".encode("utf-8", 'windows-874') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x84".encode("utf-8", 'windows-874') }
+ check_both_ways("\u2026", "\x85", 'windows-874') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x86".encode("utf-8", 'windows-874') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x8F".encode("utf-8", 'windows-874') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x90".encode("utf-8", 'windows-874') }
+ check_both_ways("\u2018", "\x91", 'windows-874') #
+ check_both_ways("\u2014", "\x97", 'windows-874') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x98".encode("utf-8", 'windows-874') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x9F".encode("utf-8", 'windows-874') }
+ check_both_ways("\u00A0", "\xA0", 'windows-874') # non-breaking space
+ check_both_ways("\u0E0F", "\xAF", 'windows-874') # 犖
+ check_both_ways("\u0E10", "\xB0", 'windows-874') # 犖
+ check_both_ways("\u0E1F", "\xBF", 'windows-874') # 犖
+ check_both_ways("\u0E20", "\xC0", 'windows-874') # 犖
+ check_both_ways("\u0E2F", "\xCF", 'windows-874') # 犖
+ check_both_ways("\u0E30", "\xD0", 'windows-874') # 犖
+ check_both_ways("\u0E3A", "\xDA", 'windows-874') # 犖
+ assert_raise(Encoding::UndefinedConversionError) { "\xDB".encode("utf-8", 'windows-874') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xDE".encode("utf-8", 'windows-874') }
+ check_both_ways("\u0E3F", "\xDF", 'windows-874') # 犖
+ check_both_ways("\u0E40", "\xE0", 'windows-874') # 犢
+ check_both_ways("\u0E4F", "\xEF", 'windows-874') # 犢
+ check_both_ways("\u0E50", "\xF0", 'windows-874') # 犢
+ check_both_ways("\u0E5B", "\xFB", 'windows-874') # 犢
+ assert_raise(Encoding::UndefinedConversionError) { "\xFC".encode("utf-8", 'windows-874') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xFF".encode("utf-8", 'windows-874') }
+ end
+
+ def test_windows_1250
+ check_both_ways("\u20AC", "\x80", 'windows-1250') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x81".encode("utf-8", 'windows-1250') }
+ check_both_ways("\u201A", "\x82", 'windows-1250') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x83".encode("utf-8", 'windows-1250') }
+ check_both_ways("\u201E", "\x84", 'windows-1250') #
+ check_both_ways("\u2021", "\x87", 'windows-1250') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x88".encode("utf-8", 'windows-1250') }
+ check_both_ways("\u2030", "\x89", 'windows-1250') #
+ check_both_ways("\u0179", "\x8F", 'windows-1250') # 店
+ assert_raise(Encoding::UndefinedConversionError) { "\x90".encode("utf-8", 'windows-1250') }
+ check_both_ways("\u2018", "\x91", 'windows-1250') #
+ check_both_ways("\u2014", "\x97", 'windows-1250') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x98".encode("utf-8", 'windows-1250') }
+ check_both_ways("\u2122", "\x99", 'windows-1250') #
+ check_both_ways("\u00A0", "\xA0", 'windows-1250') # non-breaking space
+ check_both_ways("\u017B", "\xAF", 'windows-1250') # 纏
+ check_both_ways("\u00B0", "\xB0", 'windows-1250') # 属
+ check_both_ways("\u017C", "\xBF", 'windows-1250') # 甜
+ check_both_ways("\u0154", "\xC0", 'windows-1250') #
+ check_both_ways("\u010E", "\xCF", 'windows-1250') #
+ check_both_ways("\u0110", "\xD0", 'windows-1250') #
+ check_both_ways("\u00DF", "\xDF", 'windows-1250') #
+ check_both_ways("\u0155", "\xE0", 'windows-1250') #
+ check_both_ways("\u010F", "\xEF", 'windows-1250') #
+ check_both_ways("\u0111", "\xF0", 'windows-1250') #
+ check_both_ways("\u02D9", "\xFF", 'windows-1250') #
+ end
+
+ def test_windows_1251
+ check_both_ways("\u0402", "\x80", 'windows-1251') #
+ check_both_ways("\u20AC", "\x88", 'windows-1251') #
+ check_both_ways("\u040F", "\x8F", 'windows-1251') #
+ check_both_ways("\u0452", "\x90", 'windows-1251') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x98".encode("utf-8", 'windows-1251') }
+ check_both_ways("\u045F", "\x9F", 'windows-1251') #
+ check_both_ways("\u00A0", "\xA0", 'windows-1251') # non-breaking space
+ check_both_ways("\u0407", "\xAF", 'windows-1251') #
+ check_both_ways("\u00B0", "\xB0", 'windows-1251') # 属
+ check_both_ways("\u0457", "\xBF", 'windows-1251') #
+ check_both_ways("\u0410", "\xC0", 'windows-1251') #
+ check_both_ways("\u041F", "\xCF", 'windows-1251') #
+ check_both_ways("\u0420", "\xD0", 'windows-1251') #
+ check_both_ways("\u042F", "\xDF", 'windows-1251') # 亊
+ check_both_ways("\u0430", "\xE0", 'windows-1251') # 舒
+ check_both_ways("\u043F", "\xEF", 'windows-1251') # 仗
+ check_both_ways("\u0440", "\xF0", 'windows-1251') #
+ check_both_ways("\u044F", "\xFF", 'windows-1251') #
+ end
+
+ def test_windows_1252
+ check_both_ways("\u20AC", "\x80", 'windows-1252') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x81".encode("utf-8", 'windows-1252') }
+ check_both_ways("\u201A", "\x82", 'windows-1252') #
+ check_both_ways("\u0152", "\x8C", 'windows-1252') # >
+ assert_raise(Encoding::UndefinedConversionError) { "\x8D".encode("utf-8", 'windows-1252') }
+ check_both_ways("\u017D", "\x8E", 'windows-1252') # 貼
+ assert_raise(Encoding::UndefinedConversionError) { "\x8F".encode("utf-8", 'windows-1252') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x90".encode("utf-8", 'windows-1252') }
+ check_both_ways("\u2018", "\x91", 'windows-1252') #
+ check_both_ways("\u0153", "\x9C", 'windows-1252') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x9D".encode("utf-8", 'windows-1252') }
+ check_both_ways("\u017E", "\x9E", 'windows-1252') # 転
+ check_both_ways("\u00A0", "\xA0", 'windows-1252') # non-breaking space
+ check_both_ways("\u00AF", "\xAF", 'windows-1252') # 俗
+ check_both_ways("\u00B0", "\xB0", 'windows-1252') # 属
+ check_both_ways("\u00BF", "\xBF", 'windows-1252') # 多
+ check_both_ways("\u00C0", "\xC0", 'windows-1252') #
+ check_both_ways("\u00CF", "\xCF", 'windows-1252') #
+ check_both_ways("\u00D0", "\xD0", 'windows-1252') #
+ check_both_ways("\u00DF", "\xDF", 'windows-1252') #
+ check_both_ways("\u00E0", "\xE0", 'windows-1252') #
+ check_both_ways("\u00EF", "\xEF", 'windows-1252') # 誰
+ check_both_ways("\u00F0", "\xF0", 'windows-1252') # 丹
+ check_both_ways("\u00FF", "\xFF", 'windows-1252') # 耽
+ end
+
+ def test_windows_1253
+ check_both_ways("\u20AC", "\x80", 'windows-1253') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x81".encode("utf-8", 'windows-1253') }
+ check_both_ways("\u201A", "\x82", 'windows-1253') #
+ check_both_ways("\u2021", "\x87", 'windows-1253') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x88".encode("utf-8", 'windows-1253') }
+ check_both_ways("\u2030", "\x89", 'windows-1253') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x8A".encode("utf-8", 'windows-1253') }
+ check_both_ways("\u2039", "\x8B", 'windows-1253') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x8C".encode("utf-8", 'windows-1253') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x8F".encode("utf-8", 'windows-1253') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x90".encode("utf-8", 'windows-1253') }
+ check_both_ways("\u2018", "\x91", 'windows-1253') #
+ check_both_ways("\u2014", "\x97", 'windows-1253') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x98".encode("utf-8", 'windows-1253') }
+ check_both_ways("\u2122", "\x99", 'windows-1253') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x9A".encode("utf-8", 'windows-1253') }
+ check_both_ways("\u203A", "\x9B", 'windows-1253') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x9C".encode("utf-8", 'windows-1253') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x9F".encode("utf-8", 'windows-1253') }
+ check_both_ways("\u00A0", "\xA0", 'windows-1253') # non-breaking space
+ check_both_ways("\u2015", "\xAF", 'windows-1253') #
+ check_both_ways("\u00B0", "\xB0", 'windows-1253') # 属
+ check_both_ways("\u038F", "\xBF", 'windows-1253') #
+ check_both_ways("\u0390", "\xC0", 'windows-1253') #
+ check_both_ways("\u039F", "\xCF", 'windows-1253') #
+ check_both_ways("\u03A0", "\xD0", 'windows-1253') #
+ check_both_ways("\u03A1", "\xD1", 'windows-1253') # 痢
+ assert_raise(Encoding::UndefinedConversionError) { "\xD2".encode("utf-8", 'windows-1253') }
+ check_both_ways("\u03A3", "\xD3", 'windows-1253') # 裡
+ check_both_ways("\u03AF", "\xDF", 'windows-1253') # 溜
+ check_both_ways("\u03B0", "\xE0", 'windows-1253') # 琉
+ check_both_ways("\u03BF", "\xEF", 'windows-1253') # 凌
+ check_both_ways("\u03C0", "\xF0", 'windows-1253') #
+ check_both_ways("\u03CE", "\xFE", 'windows-1253') #
+ assert_raise(Encoding::UndefinedConversionError) { "\xFF".encode("utf-8", 'windows-1253') }
+ end
+
+ def test_windows_1254
+ check_both_ways("\u20AC", "\x80", 'windows-1254') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x81".encode("utf-8", 'windows-1254') }
+ check_both_ways("\u201A", "\x82", 'windows-1254') #
+ check_both_ways("\u0152", "\x8C", 'windows-1254') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x8D".encode("utf-8", 'windows-1254') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x8F".encode("utf-8", 'windows-1254') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x90".encode("utf-8", 'windows-1254') }
+ check_both_ways("\u2018", "\x91", 'windows-1254') #
+ check_both_ways("\u0153", "\x9C", 'windows-1254') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x9D".encode("utf-8", 'windows-1254') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x9E".encode("utf-8", 'windows-1254') }
+ check_both_ways("\u0178", "\x9F", 'windows-1254') # 展
+ check_both_ways("\u00A0", "\xA0", 'windows-1254') # non-breaking space
+ check_both_ways("\u00AF", "\xAF", 'windows-1254') # 俗
+ check_both_ways("\u00B0", "\xB0", 'windows-1254') # 属
+ check_both_ways("\u00BF", "\xBF", 'windows-1254') # 多
+ check_both_ways("\u00C0", "\xC0", 'windows-1254') #
+ check_both_ways("\u00CF", "\xCF", 'windows-1254') #
+ check_both_ways("\u011E", "\xD0", 'windows-1254') #
+ check_both_ways("\u00DF", "\xDF", 'windows-1254') #
+ check_both_ways("\u00E0", "\xE0", 'windows-1254') #
+ check_both_ways("\u00EF", "\xEF", 'windows-1254') # 誰
+ check_both_ways("\u011F", "\xF0", 'windows-1254') #
+ check_both_ways("\u00FF", "\xFF", 'windows-1254') # 耽
+ end
+
+ def test_windows_1255
+ check_both_ways("\u20AC", "\x80", 'windows-1255') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x81".encode("utf-8", 'windows-1255') }
+ check_both_ways("\u201A", "\x82", 'windows-1255') #
+ check_both_ways("\u2030", "\x89", 'windows-1255') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x8A".encode("utf-8", 'windows-1255') }
+ check_both_ways("\u2039", "\x8B", 'windows-1255') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x8C".encode("utf-8", 'windows-1255') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x8F".encode("utf-8", 'windows-1255') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x90".encode("utf-8", 'windows-1255') }
+ check_both_ways("\u2018", "\x91", 'windows-1255') #
+ check_both_ways("\u2122", "\x99", 'windows-1255') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x9A".encode("utf-8", 'windows-1255') }
+ check_both_ways("\u203A", "\x9B", 'windows-1255') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x9C".encode("utf-8", 'windows-1255') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x9F".encode("utf-8", 'windows-1255') }
+ check_both_ways("\u00A0", "\xA0", 'windows-1255') # non-breaking space
+ check_both_ways("\u00A1", "\xA1", 'windows-1255') # 臓
+ check_both_ways("\u00D7", "\xAA", 'windows-1255') #
+ check_both_ways("\u00AF", "\xAF", 'windows-1255') # 俗
+ check_both_ways("\u00B0", "\xB0", 'windows-1255') # 属
+ check_both_ways("\u00B8", "\xB8", 'windows-1255') # 存
+ check_both_ways("\u00F7", "\xBA", 'windows-1255') # 歎
+ check_both_ways("\u00BF", "\xBF", 'windows-1255') # 多
+ check_both_ways("\u05B0", "\xC0", 'windows-1255') # 岼
+ check_both_ways("\u05B9", "\xC9", 'windows-1255') # 峭
+ assert_raise(Encoding::UndefinedConversionError) { "\xCA".encode("utf-8", 'windows-1255') }
+ check_both_ways("\u05BB", "\xCB", 'windows-1255') # 峪
+ check_both_ways("\u05BF", "\xCF", 'windows-1255') # 嵜
+ check_both_ways("\u05C0", "\xD0", 'windows-1255') #
+ check_both_ways("\u05F3", "\xD7", 'windows-1255') # 彝
+ check_both_ways("\u05F4", "\xD8", 'windows-1255') # 彜
+ assert_raise(Encoding::UndefinedConversionError) { "\xD9".encode("utf-8", 'windows-1255') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xDF".encode("utf-8", 'windows-1255') }
+ check_both_ways("\u05D0", "\xE0", 'windows-1255') #
+ check_both_ways("\u05DF", "\xEF", 'windows-1255') #
+ check_both_ways("\u05E0", "\xF0", 'windows-1255') #
+ check_both_ways("\u05EA", "\xFA", 'windows-1255') # 廬
+ assert_raise(Encoding::UndefinedConversionError) { "\xFB".encode("utf-8", 'windows-1255') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xFC".encode("utf-8", 'windows-1255') }
+ check_both_ways("\u200E", "\xFD", 'windows-1255') # left-to-right mark
+ check_both_ways("\u200F", "\xFE", 'windows-1255') # right-to-left mark
+ assert_raise(Encoding::UndefinedConversionError) { "\xFF".encode("utf-8", 'windows-1255') }
+ end
+
+ def test_windows_1256
+ check_both_ways("\u20AC", "\x80", 'windows-1256') #
+ check_both_ways("\u0679", "\x8A", 'windows-1256') # 拗
+ check_both_ways("\u0688", "\x8F", 'windows-1256') #
+ check_both_ways("\u06AF", "\x90", 'windows-1256') # 擯
+ check_both_ways("\u06A9", "\x98", 'windows-1256') # 擧
+ check_both_ways("\u0691", "\x9A", 'windows-1256') #
+ check_both_ways("\u06BA", "\x9F", 'windows-1256') # 攤
+ check_both_ways("\u00A0", "\xA0", 'windows-1256') # non-breaking space
+ check_both_ways("\u06BE", "\xAA", 'windows-1256') # 攵
+ check_both_ways("\u00AF", "\xAF", 'windows-1256') # 俗
+ check_both_ways("\u00B0", "\xB0", 'windows-1256') # 属
+ check_both_ways("\u061F", "\xBF", 'windows-1256') #
+ check_both_ways("\u06C1", "\xC0", 'windows-1256') #
+ check_both_ways("\u062F", "\xCF", 'windows-1256') # 惆
+ check_both_ways("\u0630", "\xD0", 'windows-1256') # 悵
+ check_both_ways("\u0643", "\xDF", 'windows-1256') #
+ check_both_ways("\u00E0", "\xE0", 'windows-1256') #
+ check_both_ways("\u00EF", "\xEF", 'windows-1256') # 誰
+ check_both_ways("\u064B", "\xF0", 'windows-1256') #
+ check_both_ways("\u06D2", "\xFF", 'windows-1256') #
+ end
+
+ def test_windows_1257
+ check_both_ways("\u20AC", "\x80", 'windows-1257') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x81".encode("utf-8", 'windows-1257') }
+ check_both_ways("\u201A", "\x82", 'windows-1257') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x83".encode("utf-8", 'windows-1257') }
+ check_both_ways("\u201E", "\x84", 'windows-1257') #
+ check_both_ways("\u2021", "\x87", 'windows-1257') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x88".encode("utf-8", 'windows-1257') }
+ check_both_ways("\u2030", "\x89", 'windows-1257') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x8A".encode("utf-8", 'windows-1257') }
+ check_both_ways("\u2039", "\x8B", 'windows-1257') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x8C".encode("utf-8", 'windows-1257') }
+ check_both_ways("\u00A8", "\x8D", 'windows-1257') # 即
+ check_both_ways("\u02C7", "\x8E", 'windows-1257') #
+ check_both_ways("\u00B8", "\x8F", 'windows-1257') # 存
+ assert_raise(Encoding::UndefinedConversionError) { "\x90".encode("utf-8", 'windows-1257') }
+ check_both_ways("\u2018", "\x91", 'windows-1257') #
+ check_both_ways("\u2014", "\x97", 'windows-1257') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x98".encode("utf-8", 'windows-1257') }
+ check_both_ways("\u2122", "\x99", 'windows-1257') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x9A".encode("utf-8", 'windows-1257') }
+ check_both_ways("\u203A", "\x9B", 'windows-1257') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x9C".encode("utf-8", 'windows-1257') }
+ check_both_ways("\u00AF", "\x9D", 'windows-1257') # 俗
+ check_both_ways("\u02DB", "\x9E", 'windows-1257') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x9F".encode("utf-8", 'windows-1257') }
+ check_both_ways("\u00A0", "\xA0", 'windows-1257') # non-breaking space
+ assert_raise(Encoding::UndefinedConversionError) { "\xA1".encode("utf-8", 'windows-1257') }
+ check_both_ways("\u00A2", "\xA2", 'windows-1257') # 蔵
+ check_both_ways("\u00A4", "\xA4", 'windows-1257') # 造
+ assert_raise(Encoding::UndefinedConversionError) { "\xA5".encode("utf-8", 'windows-1257') }
+ check_both_ways("\u00A6", "\xA6", 'windows-1257') # 側
+ check_both_ways("\u00C6", "\xAF", 'windows-1257') #
+ check_both_ways("\u00B0", "\xB0", 'windows-1257') # 属
+ check_both_ways("\u00E6", "\xBF", 'windows-1257') # 脱
+ check_both_ways("\u0104", "\xC0", 'windows-1257') #
+ check_both_ways("\u013B", "\xCF", 'windows-1257') # 鳥
+ check_both_ways("\u0160", "\xD0", 'windows-1257') #
+ check_both_ways("\u00DF", "\xDF", 'windows-1257') #
+ check_both_ways("\u0105", "\xE0", 'windows-1257') #
+ check_both_ways("\u013C", "\xEF", 'windows-1257') # 勅
+ check_both_ways("\u0161", "\xF0", 'windows-1257') # 邸
+ check_both_ways("\u02D9", "\xFF", 'windows-1257') #
+ end
+
+ def test_IBM437
+ check_both_ways("\u00C7", "\x80", 'IBM437') #
+ check_both_ways("\u00C5", "\x8F", 'IBM437') #
+ check_both_ways("\u00C9", "\x90", 'IBM437') #
+ check_both_ways("\u0192", "\x9F", 'IBM437') #
+ check_both_ways("\u00E1", "\xA0", 'IBM437') # 叩
+ check_both_ways("\u00BB", "\xAF", 'IBM437') # 損
+ check_both_ways("\u2591", "\xB0", 'IBM437') #
+ check_both_ways("\u2510", "\xBF", 'IBM437') #
+ check_both_ways("\u2514", "\xC0", 'IBM437') #
+ check_both_ways("\u2567", "\xCF", 'IBM437') #
+ check_both_ways("\u2568", "\xD0", 'IBM437') #
+ check_both_ways("\u2580", "\xDF", 'IBM437') #
+ check_both_ways("\u03B1", "\xE0", 'IBM437') # 留
+ check_both_ways("\u2229", "\xEF", 'IBM437') #
+ check_both_ways("\u2261", "\xF0", 'IBM437') #
+ check_both_ways("\u00A0", "\xFF", 'IBM437') # non-breaking space
+ end
+
+ def test_IBM775
+ check_both_ways("\u0106", "\x80", 'IBM775') #
+ check_both_ways("\u00C5", "\x8F", 'IBM775') #
+ check_both_ways("\u00C9", "\x90", 'IBM775') #
+ check_both_ways("\u00A4", "\x9F", 'IBM775') # 造
+ check_both_ways("\u0100", "\xA0", 'IBM775') #
+ check_both_ways("\u00BB", "\xAF", 'IBM775') # 損
+ check_both_ways("\u2591", "\xB0", 'IBM775') #
+ check_both_ways("\u2510", "\xBF", 'IBM775') #
+ check_both_ways("\u2514", "\xC0", 'IBM775') #
+ check_both_ways("\u017D", "\xCF", 'IBM775') # 貼
+ check_both_ways("\u0105", "\xD0", 'IBM775') #
+ check_both_ways("\u2580", "\xDF", 'IBM775') #
+ check_both_ways("\u00D3", "\xE0", 'IBM775') #
+ check_both_ways("\u2019", "\xEF", 'IBM775') #
+ check_both_ways("\u00AD", "\xF0", 'IBM775') # osft hyphen
+ check_both_ways("\u00A0", "\xFF", 'IBM775') # non-breaking space
+ end
+
+ def test_IBM852
+ check_both_ways("\u00C7", "\x80", 'IBM852') #
+ check_both_ways("\u0106", "\x8F", 'IBM852') #
+ check_both_ways("\u00C9", "\x90", 'IBM852') #
+ check_both_ways("\u010D", "\x9F", 'IBM852') #
+ check_both_ways("\u00E1", "\xA0", 'IBM852') # 叩
+ check_both_ways("\u00BB", "\xAF", 'IBM852') # 損
+ check_both_ways("\u2591", "\xB0", 'IBM852') #
+ check_both_ways("\u2510", "\xBF", 'IBM852') #
+ check_both_ways("\u2514", "\xC0", 'IBM852') #
+ check_both_ways("\u00A4", "\xCF", 'IBM852') # 造
+ check_both_ways("\u0111", "\xD0", 'IBM852') #
+ check_both_ways("\u2580", "\xDF", 'IBM852') #
+ check_both_ways("\u00D3", "\xE0", 'IBM852') #
+ check_both_ways("\u00B4", "\xEF", 'IBM852') # 卒
+ check_both_ways("\u00AD", "\xF0", 'IBM852') # osft hyphen
+ check_both_ways("\u00A0", "\xFF", 'IBM852') # non-breaking space
+ end
+
+ def test_IBM855
+ check_both_ways("\u0452", "\x80", 'IBM855') #
+ check_both_ways("\u0408", "\x8F", 'IBM855') #
+ check_both_ways("\u0459", "\x90", 'IBM855') #
+ check_both_ways("\u042A", "\x9F", 'IBM855') # 乖
+ check_both_ways("\u0430", "\xA0", 'IBM855') # 舒
+ check_both_ways("\u00BB", "\xAF", 'IBM855') # 損
+ check_both_ways("\u2591", "\xB0", 'IBM855') #
+ check_both_ways("\u2510", "\xBF", 'IBM855') #
+ check_both_ways("\u2514", "\xC0", 'IBM855') #
+ check_both_ways("\u00A4", "\xCF", 'IBM855') # 造
+ check_both_ways("\u043B", "\xD0", 'IBM855') # 仍
+ check_both_ways("\u2580", "\xDF", 'IBM855') #
+ check_both_ways("\u042F", "\xE0", 'IBM855') # 亊
+ check_both_ways("\u2116", "\xEF", 'IBM855') #
+ check_both_ways("\u00AD", "\xF0", 'IBM855') # osft hyphen
+ check_both_ways("\u00A0", "\xFF", 'IBM855') # non-breaking space
+ end
+
+ def test_IBM857
+ check_both_ways("\u00C7", "\x80", 'IBM857') #
+ check_both_ways("\u00C5", "\x8F", 'IBM857') #
+ check_both_ways("\u00C9", "\x90", 'IBM857') #
+ check_both_ways("\u015F", "\x9F", 'IBM857') #
+ check_both_ways("\u00E1", "\xA0", 'IBM857') # 叩
+ check_both_ways("\u00BB", "\xAF", 'IBM857') # 損
+ check_both_ways("\u2591", "\xB0", 'IBM857') #
+ check_both_ways("\u2510", "\xBF", 'IBM857') #
+ check_both_ways("\u2514", "\xC0", 'IBM857') #
+ check_both_ways("\u00A4", "\xCF", 'IBM857') # 造
+ check_both_ways("\u00BA", "\xD0", 'IBM857') # 尊
+ check_both_ways("\u00C8", "\xD4", 'IBM857') #
+ assert_raise(Encoding::UndefinedConversionError) { "\xD5".encode("utf-8", 'IBM857') }
+ check_both_ways("\u00CD", "\xD6", 'IBM857') #
+ check_both_ways("\u2580", "\xDF", 'IBM857') #
+ check_both_ways("\u00D3", "\xE0", 'IBM857') #
+ check_both_ways("\u00B5", "\xE6", 'IBM857') # 袖
+ assert_raise(Encoding::UndefinedConversionError) { "\xE7".encode("utf-8", 'IBM857') }
+ check_both_ways("\u00D7", "\xE8", 'IBM857') #
+ check_both_ways("\u00B4", "\xEF", 'IBM857') # 卒
+ check_both_ways("\u00AD", "\xF0", 'IBM857') # soft hyphen
+ check_both_ways("\u00B1", "\xF1", 'IBM857') # 賊
+ assert_raise(Encoding::UndefinedConversionError) { "\xF2".encode("utf-8", 'IBM857') }
+ check_both_ways("\u00BE", "\xF3", 'IBM857') # 他
+ check_both_ways("\u00A0", "\xFF", 'IBM857') # non-breaking space
+ end
+
+ def test_IBM860
+ check_both_ways("\u00C7", "\x80", 'IBM860') #
+ check_both_ways("\u00C2", "\x8F", 'IBM860') #
+ check_both_ways("\u00C9", "\x90", 'IBM860') #
+ check_both_ways("\u00D3", "\x9F", 'IBM860') #
+ check_both_ways("\u00E1", "\xA0", 'IBM860') # 叩
+ check_both_ways("\u00BB", "\xAF", 'IBM860') # 損
+ check_both_ways("\u2591", "\xB0", 'IBM860') #
+ check_both_ways("\u2510", "\xBF", 'IBM860') #
+ check_both_ways("\u2514", "\xC0", 'IBM860') #
+ check_both_ways("\u2567", "\xCF", 'IBM860') #
+ check_both_ways("\u2568", "\xD0", 'IBM860') #
+ check_both_ways("\u2580", "\xDF", 'IBM860') #
+ check_both_ways("\u03B1", "\xE0", 'IBM860') # 留
+ check_both_ways("\u2229", "\xEF", 'IBM860') #
+ check_both_ways("\u2261", "\xF0", 'IBM860') #
+ check_both_ways("\u00A0", "\xFF", 'IBM860') # non-breaking space
+ end
+
+ def test_IBM861
+ check_both_ways("\u00C7", "\x80", 'IBM861') #
+ check_both_ways("\u00C5", "\x8F", 'IBM861') #
+ check_both_ways("\u00C9", "\x90", 'IBM861') #
+ check_both_ways("\u0192", "\x9F", 'IBM861') #
+ check_both_ways("\u00E1", "\xA0", 'IBM861') # 叩
+ check_both_ways("\u00BB", "\xAF", 'IBM861') # 損
+ check_both_ways("\u2591", "\xB0", 'IBM861') #
+ check_both_ways("\u2510", "\xBF", 'IBM861') #
+ check_both_ways("\u2514", "\xC0", 'IBM861') #
+ check_both_ways("\u2567", "\xCF", 'IBM861') #
+ check_both_ways("\u2568", "\xD0", 'IBM861') #
+ check_both_ways("\u2580", "\xDF", 'IBM861') #
+ check_both_ways("\u03B1", "\xE0", 'IBM861') # 留
+ check_both_ways("\u2229", "\xEF", 'IBM861') #
+ check_both_ways("\u2261", "\xF0", 'IBM861') #
+ check_both_ways("\u00A0", "\xFF", 'IBM861') # non-breaking space
+ end
+
+ def test_IBM862
+ check_both_ways("\u05D0", "\x80", 'IBM862') #
+ check_both_ways("\u05DF", "\x8F", 'IBM862') #
+ check_both_ways("\u05E0", "\x90", 'IBM862') #
+ check_both_ways("\u0192", "\x9F", 'IBM862') #
+ check_both_ways("\u00E1", "\xA0", 'IBM862') # 叩
+ check_both_ways("\u00BB", "\xAF", 'IBM862') # 損
+ check_both_ways("\u2591", "\xB0", 'IBM862') #
+ check_both_ways("\u2510", "\xBF", 'IBM862') #
+ check_both_ways("\u2514", "\xC0", 'IBM862') #
+ check_both_ways("\u2567", "\xCF", 'IBM862') #
+ check_both_ways("\u2568", "\xD0", 'IBM862') #
+ check_both_ways("\u2580", "\xDF", 'IBM862') #
+ check_both_ways("\u03B1", "\xE0", 'IBM862') # 留
+ check_both_ways("\u2229", "\xEF", 'IBM862') #
+ check_both_ways("\u2261", "\xF0", 'IBM862') #
+ check_both_ways("\u00A0", "\xFF", 'IBM862') # non-breaking space
+ end
+
+ def test_IBM863
+ check_both_ways("\u00C7", "\x80", 'IBM863') #
+ check_both_ways("\u00A7", "\x8F", 'IBM863') # 則
+ check_both_ways("\u00C9", "\x90", 'IBM863') #
+ check_both_ways("\u0192", "\x9F", 'IBM863') #
+ check_both_ways("\u00A6", "\xA0", 'IBM863') # 側
+ check_both_ways("\u00BB", "\xAF", 'IBM863') # 損
+ check_both_ways("\u2591", "\xB0", 'IBM863') #
+ check_both_ways("\u2510", "\xBF", 'IBM863') #
+ check_both_ways("\u2514", "\xC0", 'IBM863') #
+ check_both_ways("\u2567", "\xCF", 'IBM863') #
+ check_both_ways("\u2568", "\xD0", 'IBM863') #
+ check_both_ways("\u2580", "\xDF", 'IBM863') #
+ check_both_ways("\u03B1", "\xE0", 'IBM863') # 留
+ check_both_ways("\u2229", "\xEF", 'IBM863') #
+ check_both_ways("\u2261", "\xF0", 'IBM863') #
+ check_both_ways("\u00A0", "\xFF", 'IBM863') # non-breaking space
+ end
+
+ def test_IBM865
+ check_both_ways("\u00C7", "\x80", 'IBM865') #
+ check_both_ways("\u00C5", "\x8F", 'IBM865') #
+ check_both_ways("\u00C9", "\x90", 'IBM865') #
+ check_both_ways("\u0192", "\x9F", 'IBM865') #
+ check_both_ways("\u00E1", "\xA0", 'IBM865') # 叩
+ check_both_ways("\u00A4", "\xAF", 'IBM865') # 造
+ check_both_ways("\u2591", "\xB0", 'IBM865') #
+ check_both_ways("\u2510", "\xBF", 'IBM865') #
+ check_both_ways("\u2514", "\xC0", 'IBM865') #
+ check_both_ways("\u2567", "\xCF", 'IBM865') #
+ check_both_ways("\u2568", "\xD0", 'IBM865') #
+ check_both_ways("\u2580", "\xDF", 'IBM865') #
+ check_both_ways("\u03B1", "\xE0", 'IBM865') # 留
+ check_both_ways("\u2229", "\xEF", 'IBM865') #
+ check_both_ways("\u2261", "\xF0", 'IBM865') #
+ check_both_ways("\u00A0", "\xFF", 'IBM865') # non-breaking space
+ end
+
+ def test_IBM866
+ check_both_ways("\u0410", "\x80", 'IBM866') #
+ check_both_ways("\u041F", "\x8F", 'IBM866') #
+ check_both_ways("\u0420", "\x90", 'IBM866') #
+ check_both_ways("\u042F", "\x9F", 'IBM866') # 亊
+ check_both_ways("\u0430", "\xA0", 'IBM866') # 舒
+ check_both_ways("\u043F", "\xAF", 'IBM866') # 仗
+ check_both_ways("\u2591", "\xB0", 'IBM866') #
+ check_both_ways("\u2510", "\xBF", 'IBM866') #
+ check_both_ways("\u2514", "\xC0", 'IBM866') #
+ check_both_ways("\u2567", "\xCF", 'IBM866') #
+ check_both_ways("\u2568", "\xD0", 'IBM866') #
+ check_both_ways("\u2580", "\xDF", 'IBM866') #
+ check_both_ways("\u0440", "\xE0", 'IBM866') #
+ check_both_ways("\u044F", "\xEF", 'IBM866') #
+ check_both_ways("\u0401", "\xF0", 'IBM866') #
+ check_both_ways("\u00A0", "\xFF", 'IBM866') # non-breaking space
+ end
+
+ def test_IBM869
+ assert_raise(Encoding::UndefinedConversionError) { "\x80".encode("utf-8", 'IBM869') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x85".encode("utf-8", 'IBM869') }
+ check_both_ways("\u0386", "\x86", 'IBM869') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x87".encode("utf-8", 'IBM869') }
+ check_both_ways("\u00B7", "\x88", 'IBM869') # 揃
+ check_both_ways("\u0389", "\x8F", 'IBM869') #
+ check_both_ways("\u038A", "\x90", 'IBM869') #
+ check_both_ways("\u038C", "\x92", 'IBM869') #
+ assert_raise(Encoding::UndefinedConversionError) { "\x93".encode("utf-8", 'IBM869') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x94".encode("utf-8", 'IBM869') }
+ check_both_ways("\u038E", "\x95", 'IBM869') #
+ check_both_ways("\u03AF", "\x9F", 'IBM869') # 溜
+ check_both_ways("\u03CA", "\xA0", 'IBM869') #
+ check_both_ways("\u00BB", "\xAF", 'IBM869') # 損
+ check_both_ways("\u2591", "\xB0", 'IBM869') #
+ check_both_ways("\u2510", "\xBF", 'IBM869') #
+ check_both_ways("\u2514", "\xC0", 'IBM869') #
+ check_both_ways("\u03A3", "\xCF", 'IBM869') # 裡
+ check_both_ways("\u03A4", "\xD0", 'IBM869') # 里
+ check_both_ways("\u2580", "\xDF", 'IBM869') #
+ check_both_ways("\u03B6", "\xE0", 'IBM869') # 龍
+ check_both_ways("\u0384", "\xEF", 'IBM869') #
+ check_both_ways("\u00AD", "\xF0", 'IBM869') # soft hyphen
+ check_both_ways("\u00A0", "\xFF", 'IBM869') # non-breaking space
+ end
+
+ def test_macCroatian
+ check_both_ways("\u00C4", "\x80", 'macCroatian') #
+ check_both_ways("\u00E8", "\x8F", 'macCroatian') # 竪
+ check_both_ways("\u00EA", "\x90", 'macCroatian') # 棚
+ check_both_ways("\u00FC", "\x9F", 'macCroatian') # 端
+ check_both_ways("\u2020", "\xA0", 'macCroatian') #
+ check_both_ways("\u00D8", "\xAF", 'macCroatian') #
+ check_both_ways("\u221E", "\xB0", 'macCroatian') #
+ check_both_ways("\u00F8", "\xBF", 'macCroatian') # 淡
+ check_both_ways("\u00BF", "\xC0", 'macCroatian') # 多
+ check_both_ways("\u0153", "\xCF", 'macCroatian') #
+ check_both_ways("\u0110", "\xD0", 'macCroatian') #
+ check_both_ways("\u00A9", "\xD9", 'macCroatian') # 息
+ check_both_ways("\u2044", "\xDA", 'macCroatian') #
+ check_both_ways("\u203A", "\xDD", 'macCroatian') #
+ check_both_ways("\u00C6", "\xDE", 'macCroatian') #
+ check_both_ways("\u00BB", "\xDF", 'macCroatian') # 損
+ check_both_ways("\u2013", "\xE0", 'macCroatian') #
+ check_both_ways("\u00B7", "\xE1", 'macCroatian') # 揃
+ check_both_ways("\u00C2", "\xE5", 'macCroatian') #
+ check_both_ways("\u0107", "\xE6", 'macCroatian') #
+ check_both_ways("\u00C1", "\xE7", 'macCroatian') #
+ check_both_ways("\u010D", "\xE8", 'macCroatian') #
+ check_both_ways("\u00C8", "\xE9", 'macCroatian') #
+ check_both_ways("\u00D4", "\xEF", 'macCroatian') #
+ check_both_ways("\u0111", "\xF0", 'macCroatian') #
+ check_both_ways("\u00D2", "\xF1", 'macCroatian') #
+ check_both_ways("\u00AF", "\xF8", 'macCroatian') # 俗
+ check_both_ways("\u03C0", "\xF9", 'macCroatian') #
+ check_both_ways("\u00CB", "\xFA", 'macCroatian') #
+ check_both_ways("\u00CA", "\xFD", 'macCroatian') #
+ check_both_ways("\u00E6", "\xFE", 'macCroatian') # 脱
+ check_both_ways("\u02C7", "\xFF", 'macCroatian') #
+ end
+
+ def test_macCyrillic
+ check_both_ways("\u0410", "\x80", 'macCyrillic') #
+ check_both_ways("\u041F", "\x8F", 'macCyrillic') #
+ check_both_ways("\u0420", "\x90", 'macCyrillic') #
+ check_both_ways("\u042F", "\x9F", 'macCyrillic') # 亊
+ check_both_ways("\u2020", "\xA0", 'macCyrillic') #
+ check_both_ways("\u0453", "\xAF", 'macCyrillic') #
+ check_both_ways("\u221E", "\xB0", 'macCyrillic') #
+ check_both_ways("\u045A", "\xBF", 'macCyrillic') #
+ check_both_ways("\u0458", "\xC0", 'macCyrillic') #
+ check_both_ways("\u0455", "\xCF", 'macCyrillic') #
+ check_both_ways("\u2013", "\xD0", 'macCyrillic') #
+ check_both_ways("\u044F", "\xDF", 'macCyrillic') #
+ check_both_ways("\u0430", "\xE0", 'macCyrillic') # 舒
+ check_both_ways("\u043F", "\xEF", 'macCyrillic') # 仗
+ check_both_ways("\u0440", "\xF0", 'macCyrillic') #
+ check_both_ways("\u00A4", "\xFF", 'macCyrillic') # 造
+ end
+
+ def test_macGreek
+ check_both_ways("\u00C4", "\x80", 'macGreek') #
+ check_both_ways("\u00E8", "\x8F", 'macGreek') # 竪
+ check_both_ways("\u00EA", "\x90", 'macGreek') # 棚
+ check_both_ways("\u00FC", "\x9F", 'macGreek') # 端
+ check_both_ways("\u2020", "\xA0", 'macGreek') #
+ check_both_ways("\u0393", "\xA1", 'macGreek') #
+ check_both_ways("\u0387", "\xAF", 'macGreek') #
+ check_both_ways("\u0391", "\xB0", 'macGreek') #
+ check_both_ways("\u03A9", "\xBF", 'macGreek') # 立
+ check_both_ways("\u03AC", "\xC0", 'macGreek') # 略
+ check_both_ways("\u0153", "\xCF", 'macGreek') #
+ check_both_ways("\u2013", "\xD0", 'macGreek') #
+ check_both_ways("\u038F", "\xDF", 'macGreek') #
+ check_both_ways("\u03CD", "\xE0", 'macGreek') #
+ check_both_ways("\u03BF", "\xEF", 'macGreek') # 凌
+ check_both_ways("\u03C0", "\xF0", 'macGreek') #
+ check_both_ways("\u03B0", "\xFE", 'macGreek') # 琉
+ assert_raise(Encoding::UndefinedConversionError) { "\xFF".encode("utf-8", 'macGreek') }
+ end
+
+ def test_macIceland
+ check_both_ways("\u00C4", "\x80", 'macIceland') #
+ check_both_ways("\u00E8", "\x8F", 'macIceland') # 竪
+ check_both_ways("\u00EA", "\x90", 'macIceland') # 棚
+ check_both_ways("\u00FC", "\x9F", 'macIceland') # 端
+ check_both_ways("\u00DD", "\xA0", 'macIceland') #
+ check_both_ways("\u00D8", "\xAF", 'macIceland') #
+ check_both_ways("\u221E", "\xB0", 'macIceland') #
+ check_both_ways("\u00F8", "\xBF", 'macIceland') # 淡
+ check_both_ways("\u00BF", "\xC0", 'macIceland') # 多
+ check_both_ways("\u0153", "\xCF", 'macIceland') #
+ check_both_ways("\u2013", "\xD0", 'macIceland') #
+ check_both_ways("\u00FE", "\xDF", 'macIceland') # 綻
+ check_both_ways("\u00FD", "\xE0", 'macIceland') # 箪
+ check_both_ways("\u00D4", "\xEF", 'macIceland') #
+ #check_both_ways("\uF8FF", "\xF0", 'macIceland') # Apple logo
+ check_both_ways("\u02C7", "\xFF", 'macIceland') #
+ end
+
+ def test_macRoman
+ check_both_ways("\u00C4", "\x80", 'macRoman') #
+ check_both_ways("\u00E8", "\x8F", 'macRoman') # 竪
+ check_both_ways("\u00EA", "\x90", 'macRoman') # 棚
+ check_both_ways("\u00FC", "\x9F", 'macRoman') # 端
+ check_both_ways("\u2020", "\xA0", 'macRoman') #
+ #check_both_ways("\u00DB", "\xAF", 'macRoman') #
+ check_both_ways("\u221E", "\xB0", 'macRoman') #
+ check_both_ways("\u00F8", "\xBF", 'macRoman') # 淡
+ check_both_ways("\u00BF", "\xC0", 'macRoman') # 多
+ check_both_ways("\u0153", "\xCF", 'macRoman') #
+ check_both_ways("\u2013", "\xD0", 'macRoman') #
+ check_both_ways("\u00A4", "\xDB", 'macRoman') # 造
+ check_both_ways("\uFB02", "\xDF", 'macRoman') # 鍖
+ check_both_ways("\u2021", "\xE0", 'macRoman') #
+ check_both_ways("\u00D4", "\xEF", 'macRoman') #
+ #check_both_ways("\uF8FF", "\xF0", 'macRoman') # Apple logo
+ check_both_ways("\u02C7", "\xFF", 'macRoman') #
+ end
+
+ def test_macRomania
+ check_both_ways("\u00C4", "\x80", 'macRomania') #
+ check_both_ways("\u00E8", "\x8F", 'macRomania') # 竪
+ check_both_ways("\u00EA", "\x90", 'macRomania') # 棚
+ check_both_ways("\u00FC", "\x9F", 'macRomania') # 端
+ check_both_ways("\u2020", "\xA0", 'macRomania') #
+ check_both_ways("\u015E", "\xAF", 'macRomania') #
+ check_both_ways("\u221E", "\xB0", 'macRomania') #
+ check_both_ways("\u015F", "\xBF", 'macRomania') #
+ check_both_ways("\u00BF", "\xC0", 'macRomania') # 多
+ check_both_ways("\u0153", "\xCF", 'macRomania') #
+ check_both_ways("\u2013", "\xD0", 'macRomania') #
+ check_both_ways("\u00A4", "\xDB", 'macRomania') #
+ check_both_ways("\u0163", "\xDF", 'macRomania') # 釘
+ check_both_ways("\u2021", "\xE0", 'macRomania') #
+ check_both_ways("\u00D4", "\xEF", 'macRomania') #
+ #check_both_ways("\uF8FF", "\xF0", 'macRomania') # Apple logo
+ check_both_ways("\u02C7", "\xFF", 'macRomania') #
+ end
+
+ def test_macTurkish
+ check_both_ways("\u00C4", "\x80", 'macTurkish') #
+ check_both_ways("\u00E8", "\x8F", 'macTurkish') # 竪
+ check_both_ways("\u00EA", "\x90", 'macTurkish') # 棚
+ check_both_ways("\u00FC", "\x9F", 'macTurkish') # 端
+ check_both_ways("\u2020", "\xA0", 'macTurkish') #
+ check_both_ways("\u00D8", "\xAF", 'macTurkish') #
+ check_both_ways("\u221E", "\xB0", 'macTurkish') #
+ check_both_ways("\u00F8", "\xBF", 'macTurkish') # 淡
+ check_both_ways("\u00BF", "\xC0", 'macTurkish') # 多
+ check_both_ways("\u0153", "\xCF", 'macTurkish') #
+ check_both_ways("\u2013", "\xD0", 'macTurkish') #
+ check_both_ways("\u015F", "\xDF", 'macTurkish') #
+ check_both_ways("\u2021", "\xE0", 'macTurkish') #
+ check_both_ways("\u00D4", "\xEF", 'macTurkish') #
+ #check_both_ways("\uF8FF", "\xF0", 'macTurkish') # Apple logo
+ check_both_ways("\u00D9", "\xF4", 'macTurkish') #
+ assert_raise(Encoding::UndefinedConversionError) { "\xF5".encode("utf-8", 'macTurkish') }
+ check_both_ways("\u02C6", "\xF6", 'macTurkish') #
+ check_both_ways("\u02C7", "\xFF", 'macTurkish') #
+ end
+
+ def test_macUkraine
+ check_both_ways("\u0410", "\x80", 'macUkraine') #
+ check_both_ways("\u041F", "\x8F", 'macUkraine') #
+ check_both_ways("\u0420", "\x90", 'macUkraine') #
+ check_both_ways("\u042F", "\x9F", 'macUkraine') # 亊
+ check_both_ways("\u2020", "\xA0", 'macUkraine') #
+ check_both_ways("\u0453", "\xAF", 'macUkraine') #
+ check_both_ways("\u221E", "\xB0", 'macUkraine') #
+ check_both_ways("\u045A", "\xBF", 'macUkraine') #
+ check_both_ways("\u0458", "\xC0", 'macUkraine') #
+ check_both_ways("\u0455", "\xCF", 'macUkraine') #
+ check_both_ways("\u2013", "\xD0", 'macUkraine') #
+ check_both_ways("\u044F", "\xDF", 'macUkraine') #
+ check_both_ways("\u0430", "\xE0", 'macUkraine') # 舒
+ check_both_ways("\u043F", "\xEF", 'macUkraine') # 仗
+ check_both_ways("\u0440", "\xF0", 'macUkraine') #
+ check_both_ways("\u00A4", "\xFF", 'macUkraine') # 造
+ end
+
def check_utf_16_both_ways(utf8, raw)
copy = raw.dup
0.step(copy.length-1, 2) { |i| copy[i+1], copy[i] = copy[i], copy[i+1] }
@@ -355,24 +1044,24 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u71FC", "\xE0\x9E", 'shift_jis') #
check_both_ways("\u71F9", "\xE0\x9F", 'shift_jis') #
check_both_ways("\u73F1", "\xE0\xFC", 'shift_jis') #
- assert_raise(Encoding::ConversionUndefined) { "\xEF\x40".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::ConversionUndefined) { "\xEF\x7E".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::ConversionUndefined) { "\xEF\x80".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::ConversionUndefined) { "\xEF\x9E".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::ConversionUndefined) { "\xEF\x9F".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::ConversionUndefined) { "\xEF\xFC".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::ConversionUndefined) { "\xF0\x40".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::ConversionUndefined) { "\xF0\x7E".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::ConversionUndefined) { "\xF0\x80".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::ConversionUndefined) { "\xF0\x9E".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::ConversionUndefined) { "\xF0\x9F".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::ConversionUndefined) { "\xF0\xFC".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xEF\x40".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xEF\x7E".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xEF\x80".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xEF\x9E".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xEF\x9F".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xEF\xFC".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xF0\x40".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xF0\x7E".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xF0\x80".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xF0\x9E".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xF0\x9F".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xF0\xFC".encode("utf-8", 'shift_jis') }
#check_both_ways("\u9ADC", "\xFC\x40", 'shift_jis') # 蕭 (IBM extended)
- assert_raise(Encoding::ConversionUndefined) { "\xFC\x7E".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::ConversionUndefined) { "\xFC\x80".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::ConversionUndefined) { "\xFC\x9E".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::ConversionUndefined) { "\xFC\x9F".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::ConversionUndefined) { "\xFC\xFC".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xFC\x7E".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xFC\x80".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xFC\x9E".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xFC\x9F".encode("utf-8", 'shift_jis') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xFC\xFC".encode("utf-8", 'shift_jis') }
check_both_ways("\u677E\u672C\u884C\u5F18", "\x8f\xbc\x96\x7b\x8d\x73\x8d\x4f", 'shift_jis') # 丈茵綣
check_both_ways("\u9752\u5C71\u5B66\u9662\u5927\u5B66", "\x90\xC2\x8E\x52\x8A\x77\x89\x40\x91\xE5\x8A\x77", 'shift_jis') # 絮怨√ぇ絖
check_both_ways("\u795E\u6797\u7FA9\u535A", "\x90\x5F\x97\xD1\x8B\x60\x94\x8E", 'shift_jis') # 腑臂
@@ -392,34 +1081,34 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u00F7", "\xA1\xE0", 'euc-jp') # 歎
check_both_ways("\u25C7", "\xA1\xFE", 'euc-jp') #
check_both_ways("\u25C6", "\xA2\xA1", 'euc-jp') #
- assert_raise(Encoding::ConversionUndefined) { "\xA2\xAF".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA2\xB9".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA2\xC2".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA2\xC9".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA2\xD1".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA2\xDB".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA2\xEB".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA2\xF1".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA2\xFA".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA2\xFD".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA2\xAF".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA2\xB9".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA2\xC2".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA2\xC9".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA2\xD1".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA2\xDB".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA2\xEB".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA2\xF1".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA2\xFA".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA2\xFD".encode("utf-8", 'euc-jp') }
check_both_ways("\u25EF", "\xA2\xFE", 'euc-jp') #
- assert_raise(Encoding::ConversionUndefined) { "\xA3\xAF".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA3\xBA".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA3\xC0".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA3\xDB".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA3\xE0".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA3\xFB".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA4\xF4".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA5\xF7".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA6\xB9".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA6\xC0".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA6\xD9".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA7\xC2".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA7\xD0".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA7\xF2".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xA8\xC1".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xCF\xD4".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::ConversionUndefined) { "\xCF\xFE".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA3\xAF".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA3\xBA".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA3\xC0".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA3\xDB".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA3\xE0".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA3\xFB".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA4\xF4".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA5\xF7".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA6\xB9".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA6\xC0".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA6\xD9".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA7\xC2".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA7\xD0".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA7\xF2".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xA8\xC1".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xCF\xD4".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xCF\xFE".encode("utf-8", 'euc-jp') }
check_both_ways("\u6A97", "\xDD\xA1", 'euc-jp') # 罟
check_both_ways("\u6BEF", "\xDD\xDF", 'euc-jp') # 罸
check_both_ways("\u9EBE", "\xDD\xE0", 'euc-jp') # 藝
@@ -432,7 +1121,7 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u71FC", "\xDF\xFE", 'euc-jp') #
check_both_ways("\u71F9", "\xE0\xA1", 'euc-jp') #
check_both_ways("\u73F1", "\xE0\xFE", 'euc-jp') #
- assert_raise(Encoding::ConversionUndefined) { "\xF4\xA7".encode("utf-8", 'euc-jp') }
+ assert_raise(Encoding::UndefinedConversionError) { "\xF4\xA7".encode("utf-8", 'euc-jp') }
#check_both_ways("\u9ADC", "\xFC\xE3", 'euc-jp') # 蕭 (IBM extended)
check_both_ways("\u677E\u672C\u884C\u5F18", "\xBE\xBE\xCB\xDC\xB9\xD4\xB9\xB0", 'euc-jp') # 丈茵綣
@@ -491,33 +1180,33 @@ class TestTranscode < Test::Unit::TestCase
end
def test_eucjp_sjis_undef
- assert_raise(Encoding::ConversionUndefined) { "\x8e\xe0".encode("Shift_JIS", "EUC-JP") }
- assert_raise(Encoding::ConversionUndefined) { "\x8e\xfe".encode("Shift_JIS", "EUC-JP") }
- assert_raise(Encoding::ConversionUndefined) { "\x8f\xa1\xa1".encode("Shift_JIS", "EUC-JP") }
- assert_raise(Encoding::ConversionUndefined) { "\x8f\xa1\xfe".encode("Shift_JIS", "EUC-JP") }
- assert_raise(Encoding::ConversionUndefined) { "\x8f\xfe\xa1".encode("Shift_JIS", "EUC-JP") }
- assert_raise(Encoding::ConversionUndefined) { "\x8f\xfe\xfe".encode("Shift_JIS", "EUC-JP") }
-
- assert_raise(Encoding::ConversionUndefined) { "\xf0\x40".encode("EUC-JP", "Shift_JIS") }
- assert_raise(Encoding::ConversionUndefined) { "\xf0\x7e".encode("EUC-JP", "Shift_JIS") }
- assert_raise(Encoding::ConversionUndefined) { "\xf0\x80".encode("EUC-JP", "Shift_JIS") }
- assert_raise(Encoding::ConversionUndefined) { "\xf0\xfc".encode("EUC-JP", "Shift_JIS") }
- assert_raise(Encoding::ConversionUndefined) { "\xfc\x40".encode("EUC-JP", "Shift_JIS") }
- assert_raise(Encoding::ConversionUndefined) { "\xfc\x7e".encode("EUC-JP", "Shift_JIS") }
- assert_raise(Encoding::ConversionUndefined) { "\xfc\x80".encode("EUC-JP", "Shift_JIS") }
- assert_raise(Encoding::ConversionUndefined) { "\xfc\xfc".encode("EUC-JP", "Shift_JIS") }
+ assert_raise(Encoding::UndefinedConversionError) { "\x8e\xe0".encode("Shift_JIS", "EUC-JP") }
+ assert_raise(Encoding::UndefinedConversionError) { "\x8e\xfe".encode("Shift_JIS", "EUC-JP") }
+ assert_raise(Encoding::UndefinedConversionError) { "\x8f\xa1\xa1".encode("Shift_JIS", "EUC-JP") }
+ assert_raise(Encoding::UndefinedConversionError) { "\x8f\xa1\xfe".encode("Shift_JIS", "EUC-JP") }
+ assert_raise(Encoding::UndefinedConversionError) { "\x8f\xfe\xa1".encode("Shift_JIS", "EUC-JP") }
+ assert_raise(Encoding::UndefinedConversionError) { "\x8f\xfe\xfe".encode("Shift_JIS", "EUC-JP") }
+
+ assert_raise(Encoding::UndefinedConversionError) { "\xf0\x40".encode("EUC-JP", "Shift_JIS") }
+ assert_raise(Encoding::UndefinedConversionError) { "\xf0\x7e".encode("EUC-JP", "Shift_JIS") }
+ assert_raise(Encoding::UndefinedConversionError) { "\xf0\x80".encode("EUC-JP", "Shift_JIS") }
+ assert_raise(Encoding::UndefinedConversionError) { "\xf0\xfc".encode("EUC-JP", "Shift_JIS") }
+ assert_raise(Encoding::UndefinedConversionError) { "\xfc\x40".encode("EUC-JP", "Shift_JIS") }
+ assert_raise(Encoding::UndefinedConversionError) { "\xfc\x7e".encode("EUC-JP", "Shift_JIS") }
+ assert_raise(Encoding::UndefinedConversionError) { "\xfc\x80".encode("EUC-JP", "Shift_JIS") }
+ assert_raise(Encoding::UndefinedConversionError) { "\xfc\xfc".encode("EUC-JP", "Shift_JIS") }
end
def test_iso_2022_jp
- assert_raise(Encoding::InvalidByteSequence) { "\x1b(A".encode("utf-8", "iso-2022-jp") }
- assert_raise(Encoding::InvalidByteSequence) { "\x1b$(A".encode("utf-8", "iso-2022-jp") }
- assert_raise(Encoding::InvalidByteSequence) { "\x1b$C".encode("utf-8", "iso-2022-jp") }
- assert_raise(Encoding::InvalidByteSequence) { "\x0e".encode("utf-8", "iso-2022-jp") }
- assert_raise(Encoding::InvalidByteSequence) { "\x80".encode("utf-8", "iso-2022-jp") }
- assert_raise(Encoding::InvalidByteSequence) { "\x1b$(Dd!\x1b(B".encode("utf-8", "iso-2022-jp") }
- assert_raise(Encoding::ConversionUndefined) { "\u9299".encode("iso-2022-jp") }
- assert_raise(Encoding::ConversionUndefined) { "\uff71\uff72\uff73\uff74\uff75".encode("iso-2022-jp") }
- assert_raise(Encoding::InvalidByteSequence) { "\x1b(I12345\x1b(B".encode("utf-8", "iso-2022-jp") }
+ assert_raise(Encoding::InvalidByteSequenceError) { "\x1b(A".encode("utf-8", "iso-2022-jp") }
+ assert_raise(Encoding::InvalidByteSequenceError) { "\x1b$(A".encode("utf-8", "iso-2022-jp") }
+ assert_raise(Encoding::InvalidByteSequenceError) { "\x1b$C".encode("utf-8", "iso-2022-jp") }
+ assert_raise(Encoding::InvalidByteSequenceError) { "\x0e".encode("utf-8", "iso-2022-jp") }
+ assert_raise(Encoding::InvalidByteSequenceError) { "\x80".encode("utf-8", "iso-2022-jp") }
+ assert_raise(Encoding::InvalidByteSequenceError) { "\x1b$(Dd!\x1b(B".encode("utf-8", "iso-2022-jp") }
+ assert_raise(Encoding::UndefinedConversionError) { "\u9299".encode("iso-2022-jp") }
+ assert_raise(Encoding::UndefinedConversionError) { "\uff71\uff72\uff73\uff74\uff75".encode("iso-2022-jp") }
+ assert_raise(Encoding::InvalidByteSequenceError) { "\x1b(I12345\x1b(B".encode("utf-8", "iso-2022-jp") }
assert_equal("\xA1\xA1".force_encoding("euc-jp"),
"\e$B!!\e(B".encode("EUC-JP", "ISO-2022-JP"))
assert_equal("\e$B!!\e(B".force_encoding("ISO-2022-JP"),
@@ -548,11 +1237,13 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u005C", "\x5C", "ISO-2022-JP")
assert_equal("\u005C", "\e(B\x5C\e(B".encode("UTF-8", "ISO-2022-JP"))
assert_equal("\u005C", "\e(J\x5C\e(B".encode("UTF-8", "ISO-2022-JP"))
- assert_raise(Encoding::ConversionUndefined) { "\u00A5".encode("Shift_JIS") }
- assert_raise(Encoding::ConversionUndefined) { "\u00A5".encode("Windows-31J") }
- assert_raise(Encoding::ConversionUndefined) { "\u00A5".encode("EUC-JP") }
- assert_raise(Encoding::ConversionUndefined) { "\u00A5".encode("eucJP-ms") }
- assert_raise(Encoding::ConversionUndefined) { "\u00A5".encode("CP51932") }
+ assert_equal("\u005C", "\x5C".encode("stateless-ISO-2022-JP", "ISO-2022-JP"))
+ assert_equal("\u005C", "\e(J\x5C\e(B".encode("stateless-ISO-2022-JP", "ISO-2022-JP"))
+ assert_raise(Encoding::UndefinedConversionError) { "\u00A5".encode("Shift_JIS") }
+ assert_raise(Encoding::UndefinedConversionError) { "\u00A5".encode("Windows-31J") }
+ assert_raise(Encoding::UndefinedConversionError) { "\u00A5".encode("EUC-JP") }
+ assert_raise(Encoding::UndefinedConversionError) { "\u00A5".encode("eucJP-ms") }
+ assert_raise(Encoding::UndefinedConversionError) { "\u00A5".encode("CP51932") }
# FULLWIDTH REVERSE SOLIDUS
check_both_ways("\uFF3C", "\x81\x5F", "Shift_JIS")
@@ -571,11 +1262,19 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u007E", "\x7E", "ISO-2022-JP")
assert_equal("\u007E", "\e(B\x7E\e(B".encode("UTF-8", "ISO-2022-JP"))
assert_equal("\u007E", "\e(J\x7E\e(B".encode("UTF-8", "ISO-2022-JP"))
- assert_raise(Encoding::ConversionUndefined) { "\u203E".encode("Shift_JIS") }
- assert_raise(Encoding::ConversionUndefined) { "\u203E".encode("Windows-31J") }
- assert_raise(Encoding::ConversionUndefined) { "\u203E".encode("EUC-JP") }
- assert_raise(Encoding::ConversionUndefined) { "\u203E".encode("eucJP-ms") }
- assert_raise(Encoding::ConversionUndefined) { "\u203E".encode("CP51932") }
+ assert_equal("\u007E", "\x7E".encode("stateless-ISO-2022-JP", "ISO-2022-JP"))
+ assert_equal("\u007E", "\e(J\x7E\e(B".encode("stateless-ISO-2022-JP", "ISO-2022-JP"))
+ assert_raise(Encoding::UndefinedConversionError) { "\u203E".encode("Shift_JIS") }
+ assert_raise(Encoding::UndefinedConversionError) { "\u203E".encode("Windows-31J") }
+ assert_raise(Encoding::UndefinedConversionError) { "\u203E".encode("EUC-JP") }
+ assert_raise(Encoding::UndefinedConversionError) { "\u203E".encode("eucJP-ms") }
+ assert_raise(Encoding::UndefinedConversionError) { "\u203E".encode("CP51932") }
end
+ def test_nothing_changed
+ a = "James".force_encoding("US-ASCII")
+ b = a.encode("Shift_JIS")
+ assert_equal(Encoding::US_ASCII, a.encoding)
+ assert_equal(Encoding::Shift_JIS, b.encoding)
+ end
end
diff --git a/test/ruby/test_unicode_escape.rb b/test/ruby/test_unicode_escape.rb
index e86489ec5c..f64b184230 100644
--- a/test/ruby/test_unicode_escape.rb
+++ b/test/ruby/test_unicode_escape.rb
@@ -263,5 +263,5 @@ EOS
# assert_raise(SyntaxError) { "\uDFFF" } # surrogate block
# assert_raise(SyntaxError) { "\uD847\uDD9A" } # surrogate pair
- end
+ end
end
diff --git a/test/ruby/test_variable.rb b/test/ruby/test_variable.rb
index 53cd151585..c0c386040f 100644
--- a/test/ruby/test_variable.rb
+++ b/test/ruby/test_variable.rb
@@ -37,9 +37,10 @@ class TestVariable < Test::Unit::TestCase
assert_instance_of(Fixnum, $$)
# read-only variable
- assert_raises(NameError) do
+ assert_raise(NameError) do
$$ = 5
end
+ assert_normal_exit("$*=0; $*", "[ruby-dev:36698]")
foobar = "foobar"
$_ = foobar
diff --git a/test/ruby/test_yield.rb b/test/ruby/test_yield.rb
index 452c17b141..2a2c6ae80f 100644
--- a/test/ruby/test_yield.rb
+++ b/test/ruby/test_yield.rb
@@ -72,6 +72,17 @@ class TestRubyYield < Test::Unit::TestCase
obj.each{|*v| assert_equal([], [], '[ruby-dev:32392]')}
obj.to_enum.each{|*v| assert_equal([], [], '[ruby-dev:32392]')}
end
+
+ def block_args_unleashed
+ yield(1,2,3,4,5)
+ end
+
+ def test_block_args_unleashed
+ r = block_args_unleashed {|a,b=1,*c,d,e|
+ [a,b,c,d,e]
+ }
+ assert_equal([1,2,[3],4,5], r, "[ruby-core:19485]")
+ end
end
require_relative 'sentence'
diff --git a/test/rubygems/functional.rb b/test/rubygems/functional.rb
index 4838167324..98e7cf6661 100644
--- a/test/rubygems/functional.rb
+++ b/test/rubygems/functional.rb
@@ -5,13 +5,14 @@
# See LICENSE.txt for permissions.
#++
-require 'test/unit'
require 'rubygems'
+require 'minitest/unit'
require 'test/insure_session'
require 'rubygems/format'
require 'rubygems/command_manager'
-class FunctionalTest < Test::Unit::TestCase
+class FunctionalTest < MiniTest::Unit::TestCase
+
def setup
@gem_path = File.expand_path("bin/gem")
lib_path = File.expand_path("lib")
@@ -93,3 +94,6 @@ class FunctionalTest < Test::Unit::TestCase
end
end
+
+MiniTest::Unit.autorun
+
diff --git a/test/rubygems/gem_installer_test_case.rb b/test/rubygems/gem_installer_test_case.rb
index 0d684eb1eb..944ec71435 100644
--- a/test/rubygems/gem_installer_test_case.rb
+++ b/test/rubygems/gem_installer_test_case.rb
@@ -1,4 +1,4 @@
-require 'test/unit'
+require 'minitest/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/installer'
diff --git a/test/rubygems/gemutilities.rb b/test/rubygems/gemutilities.rb
index 0ab2c5272c..3720da5d6a 100644
--- a/test/rubygems/gemutilities.rb
+++ b/test/rubygems/gemutilities.rb
@@ -1,4 +1,3 @@
-#!/usr/bin/env ruby
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
@@ -9,8 +8,14 @@ at_exit { $SAFE = 1 }
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
+require 'rubygems'
require 'fileutils'
-require 'test/unit'
+begin
+ require 'minitest/unit'
+rescue LoadError
+ warn "Install minitest gem"
+ raise
+end
require 'tmpdir'
require 'uri'
require 'rubygems/package'
@@ -19,6 +24,10 @@ require 'rubygems/test_utilities'
require File.join(File.expand_path(File.dirname(__FILE__)), 'mockgemui')
module Gem
+ def self.searcher=(searcher)
+ MUTEX.synchronize do @searcher = searcher end
+ end
+
def self.source_index=(si)
@@source_index = si
end
@@ -26,13 +35,13 @@ module Gem
def self.win_platform=(val)
@@win_platform = val
end
-
+
module DefaultUserInteraction
@ui = MockGemUi.new
end
end
-class RubyGemTestCase < Test::Unit::TestCase
+class RubyGemTestCase < MiniTest::Unit::TestCase
include Gem::DefaultUserInteraction
@@ -53,6 +62,7 @@ class RubyGemTestCase < Test::Unit::TestCase
@latest_usrcache = File.join(@gemhome, ".gem", "latest_user_cache")
@userhome = File.join @tempdir, 'userhome'
+ @orig_ENV_HOME = ENV['HOME']
ENV['HOME'] = @userhome
Gem.instance_variable_set :@user_home, nil
@@ -89,6 +99,27 @@ class RubyGemTestCase < Test::Unit::TestCase
'private_key.pem')
@public_cert = File.expand_path File.join(File.dirname(__FILE__),
'public_cert.pem')
+
+ Gem.post_install_hooks.clear
+ Gem.post_uninstall_hooks.clear
+ Gem.pre_install_hooks.clear
+ Gem.pre_uninstall_hooks.clear
+
+ Gem.post_install do |installer|
+ @post_install_hook_arg = installer
+ end
+
+ Gem.post_uninstall do |uninstaller|
+ @post_uninstall_hook_arg = uninstaller
+ end
+
+ Gem.pre_install do |installer|
+ @pre_install_hook_arg = installer
+ end
+
+ Gem.pre_uninstall do |uninstaller|
+ @pre_uninstall_hook_arg = uninstaller
+ end
end
def teardown
@@ -106,6 +137,12 @@ class RubyGemTestCase < Test::Unit::TestCase
ENV.delete 'GEM_PATH'
Gem.clear_paths
+
+ if @orig_ENV_HOME then
+ ENV['HOME'] = @orig_ENV_HOME
+ else
+ ENV.delete 'HOME'
+ end
end
def install_gem gem
@@ -435,7 +472,17 @@ class RubyGemTestCase < Test::Unit::TestCase
end
@@ruby = rubybin
- @@rake = ENV["rake"] || (@@ruby + " " + File.expand_path("../../../bin/rake", __FILE__))
+ env_rake = ENV['rake']
+ ruby19_rake = File.expand_path("../../../bin/rake", __FILE__)
+ @@rake = if env_rake then
+ ENV["rake"]
+ elsif File.exist? ruby19_rake then
+ @@ruby + " " + ruby19_rake
+ else
+ 'rake'
+ end
end
+MiniTest::Unit.autorun
+
diff --git a/test/rubygems/mockgemui.rb b/test/rubygems/mockgemui.rb
index 95a95fbf98..57582ef57d 100644
--- a/test/rubygems/mockgemui.rb
+++ b/test/rubygems/mockgemui.rb
@@ -12,8 +12,28 @@ require 'rubygems/user_interaction'
class MockGemUi < Gem::StreamUI
class TermError < RuntimeError; end
- def initialize(input="")
- super(StringIO.new(input), StringIO.new, StringIO.new)
+ module TTY
+
+ attr_accessor :tty
+
+ def tty?()
+ @tty = true unless defined?(@tty)
+ @tty
+ end
+
+ end
+
+ def initialize(input = "")
+ ins = StringIO.new input
+ outs = StringIO.new
+ errs = StringIO.new
+
+ ins.extend TTY
+ outs.extend TTY
+ errs.extend TTY
+
+ super ins, outs, errs
+
@terminated = false
end
diff --git a/test/rubygems/test_config.rb b/test/rubygems/test_config.rb
index 0568996c4a..beaa2325dc 100644
--- a/test/rubygems/test_config.rb
+++ b/test/rubygems/test_config.rb
@@ -1,11 +1,9 @@
-#!/usr/bin/env ruby
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rbconfig'
require 'rubygems'
diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb
index c26eeb573d..f5bfa28e54 100644
--- a/test/rubygems/test_gem.rb
+++ b/test/rubygems/test_gem.rb
@@ -11,7 +11,11 @@ class TestGem < RubyGemTestCase
super
@additional = %w[a b].map { |d| File.join @tempdir, d }
- @default_dir_re = %r|/[Rr]uby/[Gg]ems/[0-9.]+|
+ @default_dir_re = if RUBY_VERSION > '1.9' then
+ %r|/.*?[Rr]uby.*?/[Gg]ems/[0-9.]+|
+ else
+ %r|/[Rr]uby/[Gg]ems/[0-9.]+|
+ end
end
def test_self_all_load_paths
@@ -45,7 +49,12 @@ class TestGem < RubyGemTestCase
def test_self_bindir_default_dir
default = Gem.default_dir
- bindir = (defined? RUBY_FRAMEWORK_VERSION) ? '/usr/bin' : Config::CONFIG['bindir']
+ bindir = if defined?(RUBY_FRAMEWORK_VERSION) then
+ '/usr/bin'
+ else
+ Config::CONFIG['bindir']
+ end
+
assert_equal bindir, Gem.bindir(default)
assert_equal bindir, Gem.bindir(Pathname.new(default))
end
@@ -60,8 +69,8 @@ class TestGem < RubyGemTestCase
assert_equal nil, Gem.instance_variable_get(:@gem_home)
assert_equal nil, Gem.instance_variable_get(:@gem_path)
- assert_not_equal searcher, Gem.searcher
- assert_not_equal source_index.object_id, Gem.source_index.object_id
+ refute_equal searcher, Gem.searcher
+ refute_equal source_index.object_id, Gem.source_index.object_id
end
def test_self_configuration
@@ -209,15 +218,45 @@ class TestGem < RubyGemTestCase
orig_Gem_ssl_available = Gem.ssl_available?
Gem.ssl_available = true
- assert_nothing_raised do Gem.ensure_ssl_available end
+ Gem.ensure_ssl_available
Gem.ssl_available = false
- e = assert_raise Gem::Exception do Gem.ensure_ssl_available end
+ e = assert_raises Gem::Exception do Gem.ensure_ssl_available end
assert_equal 'SSL is not installed on this system', e.message
ensure
Gem.ssl_available = orig_Gem_ssl_available
end
+ def test_self_find_files
+ foo1 = quick_gem 'foo', '1' do |s|
+ s.files << 'lib/foo/discover.rb'
+ end
+
+ foo2 = quick_gem 'foo', '2' do |s|
+ s.files << 'lib/foo/discover.rb'
+ end
+
+ path = File.join 'gems', foo1.full_name, 'lib', 'foo', 'discover.rb'
+ write_file(path) { |fp| fp.puts "# #{path}" }
+
+ path = File.join 'gems', foo2.full_name, 'lib', 'foo', 'discover.rb'
+ write_file(path) { |fp| fp.puts "# #{path}" }
+
+ @fetcher = Gem::FakeFetcher.new
+ Gem::RemoteFetcher.fetcher = @fetcher
+
+ Gem.source_index = util_setup_spec_fetcher foo1, foo2
+
+ Gem.searcher = nil
+
+ expected = [
+ File.join(foo1.full_gem_path, 'lib', 'foo', 'discover.rb'),
+ File.join(foo2.full_gem_path, 'lib', 'foo', 'discover.rb'),
+ ]
+
+ assert_equal expected, Gem.find_files('foo/discover').sort
+ end
+
def test_self_latest_load_paths
util_make_gems
@@ -261,20 +300,21 @@ class TestGem < RubyGemTestCase
unless win_platform?
def test_self_path_APPLE_GEM_HOME
Gem.clear_paths
- Dir.mktmpdir("apple_gem_home") {|d|
- Gem.const_set :APPLE_GEM_HOME, d
- assert Gem.path.include?(d)
- }
+ apple_gem_home = File.join @tempdir, 'apple_gem_home'
+ Gem.const_set :APPLE_GEM_HOME, apple_gem_home
+
+ assert Gem.path.include?(apple_gem_home)
ensure
Gem.send :remove_const, :APPLE_GEM_HOME
end
-
+
def test_self_path_APPLE_GEM_HOME_GEM_PATH
Gem.clear_paths
ENV['GEM_PATH'] = @gemhome
- Gem.const_set :APPLE_GEM_HOME, '/tmp/apple_gem_home'
-
- assert !Gem.path.include?('/tmp/apple_gem_home')
+ apple_gem_home = File.join @tempdir, 'apple_gem_home'
+ Gem.const_set :APPLE_GEM_HOME, apple_gem_home
+
+ assert !Gem.path.include?(apple_gem_home)
ensure
Gem.send :remove_const, :APPLE_GEM_HOME
end
@@ -291,7 +331,7 @@ class TestGem < RubyGemTestCase
assert_equal path_count + @additional.size, Gem.path.size,
"extra path components: #{Gem.path[2..-1].inspect}"
- assert_match Gem.dir, Gem.path.last
+ assert_equal Gem.dir, Gem.path.last
end
def test_self_path_duplicate
@@ -390,6 +430,44 @@ class TestGem < RubyGemTestCase
Gem.required_location("a", "code.rb", "= 2")
end
+ def test_self_ruby_escaping_spaces_in_path
+ orig_ruby = Gem.ruby
+ orig_bindir = Gem::ConfigMap[:bindir]
+ orig_ruby_install_name = Gem::ConfigMap[:ruby_install_name]
+ orig_exe_ext = Gem::ConfigMap[:EXEEXT]
+
+ Gem::ConfigMap[:bindir] = "C:/Ruby 1.8/bin"
+ Gem::ConfigMap[:ruby_install_name] = "ruby"
+ Gem::ConfigMap[:EXEEXT] = ".exe"
+ Gem.instance_variable_set("@ruby", nil)
+
+ assert_equal "\"C:/Ruby 1.8/bin/ruby.exe\"", Gem.ruby
+ ensure
+ Gem.instance_variable_set("@ruby", orig_ruby)
+ Gem::ConfigMap[:bindir] = orig_bindir
+ Gem::ConfigMap[:ruby_install_name] = orig_ruby_install_name
+ Gem::ConfigMap[:EXEEXT] = orig_exe_ext
+ end
+
+ def test_self_ruby_path_without_spaces
+ orig_ruby = Gem.ruby
+ orig_bindir = Gem::ConfigMap[:bindir]
+ orig_ruby_install_name = Gem::ConfigMap[:ruby_install_name]
+ orig_exe_ext = Gem::ConfigMap[:EXEEXT]
+
+ Gem::ConfigMap[:bindir] = "C:/Ruby18/bin"
+ Gem::ConfigMap[:ruby_install_name] = "ruby"
+ Gem::ConfigMap[:EXEEXT] = ".exe"
+ Gem.instance_variable_set("@ruby", nil)
+
+ assert_equal "C:/Ruby18/bin/ruby.exe", Gem.ruby
+ ensure
+ Gem.instance_variable_set("@ruby", orig_ruby)
+ Gem::ConfigMap[:bindir] = orig_bindir
+ Gem::ConfigMap[:ruby_install_name] = orig_ruby_install_name
+ Gem::ConfigMap[:EXEEXT] = orig_exe_ext
+ end
+
def test_self_ruby_version
version = RUBY_VERSION.dup
version << ".#{RUBY_PATCHLEVEL}" if defined? RUBY_PATCHLEVEL
@@ -401,6 +479,27 @@ class TestGem < RubyGemTestCase
assert_kind_of Gem::GemPathSearcher, Gem.searcher
end
+ def test_self_set_paths
+ other = File.join @tempdir, 'other'
+ path = [@userhome, other].join File::PATH_SEPARATOR
+ Gem.send :set_paths, path
+
+ assert File.exist?(File.join(@userhome, 'gems'))
+ assert File.exist?(File.join(other, 'gems'))
+ end
+
+ def test_self_set_paths_nonexistent_home
+ Gem.clear_paths
+
+ other = File.join @tempdir, 'other'
+
+ ENV['HOME'] = other
+
+ Gem.send :set_paths, other
+
+ refute File.exist?(File.join(other, 'gems'))
+ end
+
def test_self_source_index
assert_kind_of Gem::SourceIndex, Gem.source_index
end
@@ -430,6 +529,11 @@ class TestGem < RubyGemTestCase
assert_equal @additional + [Gem.dir], Gem.path
end
+ def test_self_user_dir
+ assert_equal File.join(@userhome, '.gem', Gem.ruby_engine,
+ Gem::ConfigMap[:ruby_version]), Gem.user_dir
+ end
+
def test_self_user_home
if ENV['HOME'] then
assert_equal ENV['HOME'], Gem.user_home
@@ -438,6 +542,28 @@ class TestGem < RubyGemTestCase
end
end
+ def test_self_user_home_user_drive_and_path
+ Gem.clear_paths
+
+ # safe-keep env variables
+ orig_home, orig_user_profile = ENV['HOME'], ENV['USERPROFILE']
+ orig_user_drive, orig_user_path = ENV['HOMEDRIVE'], ENV['HOMEPATH']
+
+ # prepare the environment
+ ENV.delete('HOME')
+ ENV.delete('USERPROFILE')
+ ENV['HOMEDRIVE'] = 'Z:'
+ ENV['HOMEPATH'] = '\\Users\\RubyUser'
+
+ assert_equal "Z:\\Users\\RubyUser", Gem.user_home
+
+ ensure
+ ENV['HOME'] = orig_home
+ ENV['USERPROFILE'] = orig_user_profile
+ ENV['USERDRIVE'] = orig_user_drive
+ ENV['USERPATH'] = orig_user_path
+ end
+
def util_ensure_gem_dirs
Gem.ensure_gem_subdirectories @gemhome
@additional.each do |dir|
diff --git a/test/rubygems/test_gem_builder.rb b/test/rubygems/test_gem_builder.rb
index 31a0d71880..acddeddad1 100644
--- a/test/rubygems/test_gem_builder.rb
+++ b/test/rubygems/test_gem_builder.rb
@@ -4,7 +4,6 @@
# See LICENSE.txt for permissions.
#++
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/builder'
diff --git a/test/rubygems/test_gem_command.rb b/test/rubygems/test_gem_command.rb
index 9ed57b3692..08da9fb7d6 100644
--- a/test/rubygems/test_gem_command.rb
+++ b/test/rubygems/test_gem_command.rb
@@ -5,7 +5,6 @@
# See LICENSE.txt for permissions.
#++
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/command'
@@ -63,7 +62,7 @@ class TestGemCommand < RubyGemTestCase
assert_match %r|-x, --zip|, @cmd.parser.to_s
assert_match %r|-z, --exe|, @cmd.parser.to_s
- assert_no_match %r|-x, --exe|, @cmd.parser.to_s
+ refute_match %r|-x, --exe|, @cmd.parser.to_s
end
def test_basic_accessors
@@ -109,7 +108,7 @@ class TestGemCommand < RubyGemTestCase
use_ui @ui do
@cmd.when_invoked do true end
- ex = assert_raise(OptionParser::InvalidOption) do
+ ex = assert_raises OptionParser::InvalidOption do
@cmd.invoke('-zzz')
end
diff --git a/test/rubygems/test_gem_command_manager.rb b/test/rubygems/test_gem_command_manager.rb
index ee58e89844..bcfe65b359 100644
--- a/test/rubygems/test_gem_command_manager.rb
+++ b/test/rubygems/test_gem_command_manager.rb
@@ -4,7 +4,6 @@
# See LICENSE.txt for permissions.
#++
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/command_manager'
diff --git a/test/rubygems/test_gem_commands_build_command.rb b/test/rubygems/test_gem_commands_build_command.rb
index a49b6777bd..b9e02ce76e 100644
--- a/test/rubygems/test_gem_commands_build_command.rb
+++ b/test/rubygems/test_gem_commands_build_command.rb
@@ -1,4 +1,3 @@
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/commands/build_command'
require 'rubygems/format'
diff --git a/test/rubygems/test_gem_commands_cert_command.rb b/test/rubygems/test_gem_commands_cert_command.rb
index 79e3e72158..749fe62198 100644
--- a/test/rubygems/test_gem_commands_cert_command.rb
+++ b/test/rubygems/test_gem_commands_cert_command.rb
@@ -1,4 +1,3 @@
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/commands/cert_command'
diff --git a/test/rubygems/test_gem_commands_check_command.rb b/test/rubygems/test_gem_commands_check_command.rb
index eea7cc5cfa..3199ac71ac 100644
--- a/test/rubygems/test_gem_commands_check_command.rb
+++ b/test/rubygems/test_gem_commands_check_command.rb
@@ -4,7 +4,6 @@
# See LICENSE.txt for permissions.
#++
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/commands/check_command'
diff --git a/test/rubygems/test_gem_commands_contents_command.rb b/test/rubygems/test_gem_commands_contents_command.rb
index cdb89673da..b891094ed8 100644
--- a/test/rubygems/test_gem_commands_contents_command.rb
+++ b/test/rubygems/test_gem_commands_contents_command.rb
@@ -1,4 +1,3 @@
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/commands/contents_command'
@@ -28,7 +27,7 @@ class TestGemCommandsContentsCommand < RubyGemTestCase
def test_execute_bad_gem
@cmd.options[:args] = %w[foo]
- assert_raise MockGemUi::TermError do
+ assert_raises MockGemUi::TermError do
use_ui @ui do
@cmd.execute
end
@@ -71,7 +70,7 @@ class TestGemCommandsContentsCommand < RubyGemTestCase
end
assert_match %r|lib/foo\.rb|, @ui.output
- assert_no_match %r|Rakefile|, @ui.output
+ refute_match %r|Rakefile|, @ui.output
assert_equal "", @ui.error
end
diff --git a/test/rubygems/test_gem_commands_dependency_command.rb b/test/rubygems/test_gem_commands_dependency_command.rb
index e143110a71..ebf713c36e 100644
--- a/test/rubygems/test_gem_commands_dependency_command.rb
+++ b/test/rubygems/test_gem_commands_dependency_command.rb
@@ -1,4 +1,3 @@
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/commands/dependency_command'
@@ -61,7 +60,7 @@ Gem pl-1-x86-linux
def test_execute_no_match
@cmd.options[:args] = %w[foo]
- assert_raise MockGemUi::TermError do
+ assert_raises MockGemUi::TermError do
use_ui @ui do
@cmd.execute
end
@@ -146,7 +145,7 @@ Gem foo-2
@cmd.options[:reverse_dependencies] = true
@cmd.options[:domain] = :remote
- assert_raise MockGemUi::TermError do
+ assert_raises MockGemUi::TermError do
use_ui @ui do
@cmd.execute
end
@@ -199,7 +198,7 @@ ERROR: Only reverse dependencies for local gems are supported.
@fetcher.data["#{@gem_repo}Marshal.#{Gem.marshal_version}"] =
si.dump
- @fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"] = nil
+ @fetcher.data.delete "#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"
FileUtils.rm File.join(@gemhome, 'specifications',
"#{foo.full_name}.gemspec")
diff --git a/test/rubygems/test_gem_commands_environment_command.rb b/test/rubygems/test_gem_commands_environment_command.rb
index 78246b0301..7f80b3e1a3 100644
--- a/test/rubygems/test_gem_commands_environment_command.rb
+++ b/test/rubygems/test_gem_commands_environment_command.rb
@@ -1,4 +1,3 @@
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/commands/environment_command'
@@ -109,7 +108,7 @@ class TestGemCommandsEnvironmentCommand < RubyGemTestCase
def test_execute_unknown
@cmd.send :handle_options, %w[unknown]
- assert_raise Gem::CommandLineError do
+ assert_raises Gem::CommandLineError do
use_ui @ui do
@cmd.execute
end
diff --git a/test/rubygems/test_gem_commands_fetch_command.rb b/test/rubygems/test_gem_commands_fetch_command.rb
index eaa13595b7..08cca0970f 100644
--- a/test/rubygems/test_gem_commands_fetch_command.rb
+++ b/test/rubygems/test_gem_commands_fetch_command.rb
@@ -1,4 +1,3 @@
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/package'
require 'rubygems/security'
diff --git a/test/rubygems/test_gem_commands_generate_index_command.rb b/test/rubygems/test_gem_commands_generate_index_command.rb
index 548197841b..d886fc5e2c 100644
--- a/test/rubygems/test_gem_commands_generate_index_command.rb
+++ b/test/rubygems/test_gem_commands_generate_index_command.rb
@@ -1,4 +1,4 @@
-require 'test/unit'
+require 'minitest/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/indexer'
require 'rubygems/commands/generate_index_command'
diff --git a/test/rubygems/test_gem_commands_install_command.rb b/test/rubygems/test_gem_commands_install_command.rb
index ef04072b93..46e5e28caf 100644
--- a/test/rubygems/test_gem_commands_install_command.rb
+++ b/test/rubygems/test_gem_commands_install_command.rb
@@ -1,4 +1,3 @@
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/commands/install_command'
@@ -16,7 +15,7 @@ class TestGemCommandsInstallCommand < RubyGemTestCase
@cmd.options[:include_dependencies] = true
@cmd.options[:args] = []
- assert_raise Gem::CommandLineError do
+ assert_raises Gem::CommandLineError do
use_ui @ui do
@cmd.execute
end
@@ -79,7 +78,7 @@ class TestGemCommandsInstallCommand < RubyGemTestCase
def test_execute_no_gem
@cmd.options[:args] = %w[]
- assert_raise Gem::CommandLineError do
+ assert_raises Gem::CommandLineError do
@cmd.execute
end
end
diff --git a/test/rubygems/test_gem_commands_list_command.rb b/test/rubygems/test_gem_commands_list_command.rb
new file mode 100644
index 0000000000..db3fe90baf
--- /dev/null
+++ b/test/rubygems/test_gem_commands_list_command.rb
@@ -0,0 +1,36 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/list_command'
+
+class TestGemCommandsListCommand < RubyGemTestCase
+
+ def setup
+ super
+
+ @cmd = Gem::Commands::ListCommand.new
+
+ util_setup_fake_fetcher
+
+ @si = util_setup_spec_fetcher @a1, @a2, @pl1
+
+ @fetcher.data["#{@gem_repo}Marshal.#{Gem.marshal_version}"] = proc do
+ raise Gem::RemoteFetcher::FetchError
+ end
+ end
+
+ def test_execute_installed
+ @cmd.handle_options %w[c --installed]
+
+ e = assert_raises Gem::SystemExitException do
+ use_ui @ui do
+ @cmd.execute
+ end
+ end
+
+ assert_equal 0, e.exit_code
+
+ assert_equal "true\n", @ui.output
+
+ assert_equal '', @ui.error
+ end
+
+end
diff --git a/test/rubygems/test_gem_commands_lock_command.rb b/test/rubygems/test_gem_commands_lock_command.rb
new file mode 100644
index 0000000000..e5d8dbe7b0
--- /dev/null
+++ b/test/rubygems/test_gem_commands_lock_command.rb
@@ -0,0 +1,68 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/lock_command'
+
+class TestGemCommandsLockCommand < RubyGemTestCase
+
+ def setup
+ super
+
+ @a1 = quick_gem 'a', '1'
+ @b1 = quick_gem 'b', '1' do |s|
+ s.add_runtime_dependency 'a'
+ end
+
+ @d1 = quick_gem 'd', '1' do |s|
+ s.add_runtime_dependency 'z'
+ end
+
+ @cmd = Gem::Commands::LockCommand.new
+ end
+
+ def test_execute
+ @cmd.handle_options %w[b-1]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ expected = <<-EXPECTED
+require 'rubygems'
+gem 'b', '= 1'
+gem 'a', '= 1'
+ EXPECTED
+
+ assert_equal expected, @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_missing_dependency
+ @cmd.handle_options %w[d-1]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ expected = <<-EXPECTED
+require 'rubygems'
+gem 'd', '= 1'
+# Unable to satisfy 'z (>= 0, runtime)' from currently installed gems
+ EXPECTED
+
+ assert_equal expected, @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_strict
+ @cmd.handle_options %w[c-1 --strict]
+
+ e = assert_raises Gem::Exception do
+ use_ui @ui do
+ @cmd.execute
+ end
+ end
+
+ assert_equal 'Could not find gem c-1, try using the full name', e.message
+ end
+
+end
+
diff --git a/test/rubygems/test_gem_commands_mirror_command.rb b/test/rubygems/test_gem_commands_mirror_command.rb
index 359ba5481e..f9a3b22545 100644
--- a/test/rubygems/test_gem_commands_mirror_command.rb
+++ b/test/rubygems/test_gem_commands_mirror_command.rb
@@ -1,4 +1,3 @@
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/indexer'
require 'rubygems/commands/mirror_command'
diff --git a/test/rubygems/test_gem_commands_outdated_command.rb b/test/rubygems/test_gem_commands_outdated_command.rb
index a6668c01fc..7ea3d8d2be 100644
--- a/test/rubygems/test_gem_commands_outdated_command.rb
+++ b/test/rubygems/test_gem_commands_outdated_command.rb
@@ -1,4 +1,3 @@
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/commands/outdated_command'
diff --git a/test/rubygems/test_gem_commands_pristine_command.rb b/test/rubygems/test_gem_commands_pristine_command.rb
index d5d2d7f339..307cba7b7f 100644
--- a/test/rubygems/test_gem_commands_pristine_command.rb
+++ b/test/rubygems/test_gem_commands_pristine_command.rb
@@ -1,4 +1,3 @@
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/commands/pristine_command'
@@ -96,7 +95,7 @@ class TestGemCommandsPristineCommand < RubyGemTestCase
def test_execute_no_gem
@cmd.options[:args] = %w[]
- e = assert_raise Gem::CommandLineError do
+ e = assert_raises Gem::CommandLineError do
use_ui @ui do
@cmd.execute
end
diff --git a/test/rubygems/test_gem_commands_query_command.rb b/test/rubygems/test_gem_commands_query_command.rb
index 1b65fc7633..785a08cd6c 100644
--- a/test/rubygems/test_gem_commands_query_command.rb
+++ b/test/rubygems/test_gem_commands_query_command.rb
@@ -1,4 +1,3 @@
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/commands/query_command'
@@ -99,7 +98,7 @@ pl (1)
def test_execute_installed
@cmd.handle_options %w[-n c --installed]
- e = assert_raise Gem::SystemExitException do
+ e = assert_raises Gem::SystemExitException do
use_ui @ui do
@cmd.execute
end
@@ -115,7 +114,7 @@ pl (1)
def test_execute_installed_no_name
@cmd.handle_options %w[--installed]
- e = assert_raise Gem::SystemExitException do
+ e = assert_raises Gem::SystemExitException do
use_ui @ui do
@cmd.execute
end
@@ -130,7 +129,7 @@ pl (1)
def test_execute_installed_not_installed
@cmd.handle_options %w[-n not_installed --installed]
- e = assert_raise Gem::SystemExitException do
+ e = assert_raises Gem::SystemExitException do
use_ui @ui do
@cmd.execute
end
@@ -145,7 +144,7 @@ pl (1)
def test_execute_installed_version
@cmd.handle_options %w[-n c --installed --version 1.2]
- e = assert_raise Gem::SystemExitException do
+ e = assert_raises Gem::SystemExitException do
use_ui @ui do
@cmd.execute
end
@@ -160,7 +159,7 @@ pl (1)
def test_execute_installed_version_not_installed
@cmd.handle_options %w[-n c --installed --version 2]
- e = assert_raise Gem::SystemExitException do
+ e = assert_raises Gem::SystemExitException do
use_ui @ui do
@cmd.execute
end
@@ -180,7 +179,7 @@ pl (1)
@fetcher.data["#{@gem_repo}Marshal.#{Gem.marshal_version}"] =
si.dump
- @fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"] = nil
+ @fetcher.data.delete "#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"
@cmd.handle_options %w[-r]
@@ -265,6 +264,27 @@ pl (1)
assert_equal '', @ui.error
end
+ def test_execute_local_notty
+ @cmd.handle_options %w[]
+
+ @ui.outs.tty = false
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ expected = <<-EOF
+a (2, 1)
+a_evil (9)
+b (2)
+c (1.2)
+pl (1)
+ EOF
+
+ assert_equal expected, @ui.output
+ assert_equal '', @ui.error
+ end
+
def test_execute_no_versions
@cmd.handle_options %w[-r --no-versions]
@@ -284,5 +304,23 @@ pl
assert_equal '', @ui.error
end
+ def test_execute_notty
+ @cmd.handle_options %w[-r]
+
+ @ui.outs.tty = false
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ expected = <<-EOF
+a (2)
+pl (1)
+ EOF
+
+ assert_equal expected, @ui.output
+ assert_equal '', @ui.error
+ end
+
end
diff --git a/test/rubygems/test_gem_commands_server_command.rb b/test/rubygems/test_gem_commands_server_command.rb
index 2985b036d8..93d5a6ed47 100644
--- a/test/rubygems/test_gem_commands_server_command.rb
+++ b/test/rubygems/test_gem_commands_server_command.rb
@@ -1,4 +1,3 @@
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/commands/server_command'
diff --git a/test/rubygems/test_gem_commands_sources_command.rb b/test/rubygems/test_gem_commands_sources_command.rb
index 623c732e50..016a6d0616 100644
--- a/test/rubygems/test_gem_commands_sources_command.rb
+++ b/test/rubygems/test_gem_commands_sources_command.rb
@@ -1,4 +1,3 @@
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/commands/sources_command'
diff --git a/test/rubygems/test_gem_commands_specification_command.rb b/test/rubygems/test_gem_commands_specification_command.rb
index 7ac0429f32..c2379595c7 100644
--- a/test/rubygems/test_gem_commands_specification_command.rb
+++ b/test/rubygems/test_gem_commands_specification_command.rb
@@ -1,4 +1,3 @@
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/commands/specification_command'
@@ -46,7 +45,7 @@ class TestGemCommandsSpecificationCommand < RubyGemTestCase
def test_execute_bad_name
@cmd.options[:args] = %w[foo]
- assert_raise MockGemUi::TermError do
+ assert_raises MockGemUi::TermError do
use_ui @ui do
@cmd.execute
end
diff --git a/test/rubygems/test_gem_commands_stale_command.rb b/test/rubygems/test_gem_commands_stale_command.rb
index 6f66c854a5..d38e54179a 100644
--- a/test/rubygems/test_gem_commands_stale_command.rb
+++ b/test/rubygems/test_gem_commands_stale_command.rb
@@ -1,4 +1,3 @@
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/commands/stale_command'
diff --git a/test/rubygems/test_gem_commands_uninstall_command.rb b/test/rubygems/test_gem_commands_uninstall_command.rb
new file mode 100644
index 0000000000..cded63f447
--- /dev/null
+++ b/test/rubygems/test_gem_commands_uninstall_command.rb
@@ -0,0 +1,61 @@
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require File.join(File.expand_path(File.dirname(__FILE__)),
+ 'gem_installer_test_case')
+require 'rubygems/commands/uninstall_command'
+
+class TestGemCommandsUninstallCommand < GemInstallerTestCase
+
+ def setup
+ super
+
+ ui = MockGemUi.new
+ util_setup_gem ui
+
+ build_rake_in do
+ use_ui ui do
+ @installer.install
+ end
+ end
+
+ @cmd = Gem::Commands::UninstallCommand.new
+ @cmd.options[:executables] = true
+ @executable = File.join(@gemhome, 'bin', 'executable')
+ end
+
+ def test_execute_removes_executable
+ if win_platform?
+ assert_equal true, File.exist?(@executable)
+ else
+ assert_equal true, File.symlink?(@executable)
+ end
+
+ # Evil hack to prevent false removal success
+ FileUtils.rm_f @executable
+ File.open(@executable, "wb+") {|f| f.puts "binary"}
+
+ @cmd.options[:args] = Array(@spec.name)
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ output = @ui.output.split "\n"
+ assert_match(/Removing executable/, output.shift)
+ assert_match(/Successfully uninstalled/, output.shift)
+ assert_equal false, File.exist?(@executable)
+ assert_nil output.shift, "UI output should have contained only two lines"
+ end
+
+ def test_execute_not_installed
+ @cmd.options[:args] = ["foo"]
+ e = assert_raises Gem::InstallError do
+ use_ui @ui do
+ @cmd.execute
+ end
+ end
+
+ assert_match(/\AUnknown gem foo >= 0$/, e.message)
+ output = @ui.output.split "\n"
+ assert output.empty?, "UI output should be empty after an uninstall error"
+ end
+end
+
diff --git a/test/rubygems/test_gem_commands_unpack_command.rb b/test/rubygems/test_gem_commands_unpack_command.rb
index 3a62a914a4..6dac927757 100644
--- a/test/rubygems/test_gem_commands_unpack_command.rb
+++ b/test/rubygems/test_gem_commands_unpack_command.rb
@@ -1,4 +1,3 @@
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/commands/unpack_command'
diff --git a/test/rubygems/test_gem_commands_update_command.rb b/test/rubygems/test_gem_commands_update_command.rb
index 11da1f8a83..77727fe6db 100644
--- a/test/rubygems/test_gem_commands_update_command.rb
+++ b/test/rubygems/test_gem_commands_update_command.rb
@@ -1,4 +1,3 @@
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/commands/update_command'
diff --git a/test/rubygems/test_gem_config_file.rb b/test/rubygems/test_gem_config_file.rb
index 06321d4e7c..fdae7faa32 100644
--- a/test/rubygems/test_gem_config_file.rb
+++ b/test/rubygems/test_gem_config_file.rb
@@ -1,11 +1,9 @@
-#!/usr/bin/env ruby
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/config_file'
@@ -57,6 +55,9 @@ class TestGemConfigFile < RubyGemTestCase
fp.puts ":sources:"
fp.puts " - http://more-gems.example.com"
fp.puts "install: --wrappers"
+ fp.puts ":gempath:"
+ fp.puts "- /usr/ruby/1.8/lib/ruby/gems/1.8"
+ fp.puts "- /var/ruby/1.8/gem_home"
end
util_config_file
@@ -68,6 +69,8 @@ class TestGemConfigFile < RubyGemTestCase
assert_equal false, @cfg.update_sources
assert_equal %w[http://more-gems.example.com], Gem.sources
assert_equal '--wrappers', @cfg[:install]
+ assert_equal(['/usr/ruby/1.8/lib/ruby/gems/1.8', '/var/ruby/1.8/gem_home'],
+ @cfg.path)
end
def test_initialize_handle_arguments_config_file
diff --git a/test/rubygems/test_gem_dependency.rb b/test/rubygems/test_gem_dependency.rb
index 315c49d6ce..5b409fa1a8 100644
--- a/test/rubygems/test_gem_dependency.rb
+++ b/test/rubygems/test_gem_dependency.rb
@@ -4,7 +4,6 @@
# See LICENSE.txt for permissions.
#++
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/version'
@@ -70,7 +69,7 @@ class TestGemDependency < RubyGemTestCase
end
def test_type_is_restricted
- assert_raise(ArgumentError) do
+ assert_raises ArgumentError do
Gem::Dependency.new("pkg", [:sometimes])
end
end
@@ -79,21 +78,21 @@ class TestGemDependency < RubyGemTestCase
assert_equal @pkg1_0, @pkg1_0.dup
assert_equal @pkg1_0.dup, @pkg1_0
- assert_not_equal @pkg1_0, @pkg1_1, "requirements different"
- assert_not_equal @pkg1_1, @pkg1_0, "requirements different"
+ refute_equal @pkg1_0, @pkg1_1, "requirements different"
+ refute_equal @pkg1_1, @pkg1_0, "requirements different"
- assert_not_equal @pkg1_0, @oth1_0, "names different"
- assert_not_equal @oth1_0, @pkg1_0, "names different"
+ refute_equal @pkg1_0, @oth1_0, "names different"
+ refute_equal @oth1_0, @pkg1_0, "names different"
- assert_not_equal @pkg1_0, Object.new
- assert_not_equal Object.new, @pkg1_0
+ refute_equal @pkg1_0, Object.new
+ refute_equal Object.new, @pkg1_0
end
def test_equals2_type
runtime = Gem::Dependency.new("pkg", [])
development = Gem::Dependency.new("pkg", [], :development)
- assert_not_equal(runtime, development)
+ refute_equal(runtime, development)
end
def test_equals_tilde
@@ -123,18 +122,18 @@ class TestGemDependency < RubyGemTestCase
assert_equal @pkg1_0.hash, @pkg1_0.dup.hash
assert_equal @pkg1_0.dup.hash, @pkg1_0.hash
- assert_not_equal @pkg1_0.hash, @pkg1_1.hash, "requirements different"
- assert_not_equal @pkg1_1.hash, @pkg1_0.hash, "requirements different"
+ refute_equal @pkg1_0.hash, @pkg1_1.hash, "requirements different"
+ refute_equal @pkg1_1.hash, @pkg1_0.hash, "requirements different"
- assert_not_equal @pkg1_0.hash, @oth1_0.hash, "names different"
- assert_not_equal @oth1_0.hash, @pkg1_0.hash, "names different"
+ refute_equal @pkg1_0.hash, @oth1_0.hash, "names different"
+ refute_equal @oth1_0.hash, @pkg1_0.hash, "names different"
end
def test_hash_type
runtime = Gem::Dependency.new("pkg", [])
development = Gem::Dependency.new("pkg", [], :development)
- assert_not_equal(runtime.hash, development.hash)
+ refute_equal(runtime.hash, development.hash)
end
end
diff --git a/test/rubygems/test_gem_dependency_installer.rb b/test/rubygems/test_gem_dependency_installer.rb
index 10e7fdfbda..3a57c05e79 100644
--- a/test/rubygems/test_gem_dependency_installer.rb
+++ b/test/rubygems/test_gem_dependency_installer.rb
@@ -1,4 +1,3 @@
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/dependency_installer'
@@ -360,7 +359,7 @@ class TestGemDependencyInstaller < RubyGemTestCase
Gem.source_index.gems.delete @a1.full_name
Dir.chdir @tempdir do
- e = assert_raise Gem::InstallError do
+ e = assert_raises Gem::InstallError do
inst = Gem::DependencyInstaller.new :domain => :local
inst.install 'b'
end
@@ -498,7 +497,7 @@ class TestGemDependencyInstaller < RubyGemTestCase
policy = Gem::Security::HighSecurity
inst = Gem::DependencyInstaller.new :security_policy => policy
- e = assert_raise Gem::Exception do
+ e = assert_raises Gem::Exception do
inst.install 'b'
end
@@ -516,8 +515,8 @@ class TestGemDependencyInstaller < RubyGemTestCase
inst = Gem::DependencyInstaller.new :wrappers => false
inst.install 'a'
- assert_no_match(%r|This file was generated by RubyGems.|,
- File.read(File.join(@gemhome, 'bin', 'a_bin')))
+ refute_match(%r|This file was generated by RubyGems.|,
+ File.read(File.join(@gemhome, 'bin', 'a_bin')))
end
end
diff --git a/test/rubygems/test_gem_dependency_list.rb b/test/rubygems/test_gem_dependency_list.rb
index 5fdc227f05..a10a1a4b2c 100644
--- a/test/rubygems/test_gem_dependency_list.rb
+++ b/test/rubygems/test_gem_dependency_list.rb
@@ -1,12 +1,9 @@
-#!/usr/bin/env ruby
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++
-
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/dependency_list'
diff --git a/test/rubygems/test_gem_digest.rb b/test/rubygems/test_gem_digest.rb
index 9d825b2796..13613c96a8 100755
--- a/test/rubygems/test_gem_digest.rb
+++ b/test/rubygems/test_gem_digest.rb
@@ -1,44 +1,46 @@
-#!/usr/bin/env ruby
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++
-require "test/unit"
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require "rubygems/digest/md5"
require "rubygems/digest/sha1"
require "rubygems/digest/sha2"
-class TestRubygemsGemDigest < Test::Unit::TestCase
+class TestRubygemsGemDigest < RubyGemTestCase
+
def test_sha256_hex_digest_works
digester = Gem::SHA256.new
assert_equal "b5d4045c3f466fa91fe2cc6abe79232a1a57cdf104f7a26e716e0a1e2789df78", digester.hexdigest("ABC")
end
-
+
def test_sha256_digest_works
digester = Gem::SHA256.new
- assert_equal "\265\324\004\\?Fo\251\037\342\314j\276y#*\032W\315\361\004\367\242nqn\n\036'\211\337x",
+ assert_equal "\265\324\004\\?Fo\251\037\342\314j\276y#*\032W\315\361\004\367\242nqn\n\036'\211\337x",
digester.digest("ABC")
end
-
+
def test_sha1_hex_digest_works
digester = Gem::SHA1.new
assert_equal "3c01bdbb26f358bab27f267924aa2c9a03fcfdb8", digester.hexdigest("ABC")
end
-
+
def test_sha1_digest_works
digester = Gem::SHA1.new
assert_equal "<\001\275\273&\363X\272\262\177&y$\252,\232\003\374\375\270", digester.digest("ABC")
end
-
+
def test_md5_hex_digest_works
digester = Gem::MD5.new
assert_equal "902fbdd2b1df0c4f70b4a5d23525e932", digester.hexdigest("ABC")
end
-
+
def test_md5_digest_works
digester = Gem::MD5.new
assert_equal "\220/\275\322\261\337\fOp\264\245\3225%\3512", digester.digest("ABC")
end
-end \ No newline at end of file
+
+end
+
diff --git a/test/rubygems/test_gem_doc_manager.rb b/test/rubygems/test_gem_doc_manager.rb
index e52fb9f0cd..f519ce7cd4 100644
--- a/test/rubygems/test_gem_doc_manager.rb
+++ b/test/rubygems/test_gem_doc_manager.rb
@@ -4,7 +4,6 @@
# See LICENSE.txt for permissions.
#++
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/doc_manager'
@@ -21,7 +20,7 @@ class TestGemDocManager < RubyGemTestCase
orig_mode = File.stat(@spec.installation_path).mode
File.chmod 0, @spec.installation_path
- assert_raise Gem::FilePermissionError do
+ assert_raises Gem::FilePermissionError do
@manager.uninstall_doc
end
ensure
diff --git a/test/rubygems/test_gem_ext_configure_builder.rb b/test/rubygems/test_gem_ext_configure_builder.rb
index 9ce17075bc..837c3a1929 100644
--- a/test/rubygems/test_gem_ext_configure_builder.rb
+++ b/test/rubygems/test_gem_ext_configure_builder.rb
@@ -1,4 +1,3 @@
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/ext'
@@ -41,7 +40,7 @@ class TestGemExtConfigureBuilder < RubyGemTestCase
return if RUBY_PLATFORM =~ /mswin/ # HACK
output = []
- error = assert_raise Gem::InstallError do
+ error = assert_raises Gem::InstallError do
Dir.chdir @ext do
Gem::Ext::ConfigureBuilder.build nil, nil, @dest_path, output
end
@@ -53,12 +52,13 @@ class TestGemExtConfigureBuilder < RubyGemTestCase
expected = %r(configure failed:
#{Regexp.escape sh_prefix_configure}#{Regexp.escape @dest_path}
-.*?: #{shell_error_msg})
+.*?: #{shell_error_msg}
+)
assert_match expected, error.message
assert_equal "#{sh_prefix_configure}#{@dest_path}", output.shift
- assert_match %r(#{shell_error_msg}\n), output.shift
+ assert_match %r(#{shell_error_msg}), output.shift
assert_equal true, output.empty?
end
diff --git a/test/rubygems/test_gem_ext_ext_conf_builder.rb b/test/rubygems/test_gem_ext_ext_conf_builder.rb
index fb21fa0755..d178c1f737 100644
--- a/test/rubygems/test_gem_ext_ext_conf_builder.rb
+++ b/test/rubygems/test_gem_ext_ext_conf_builder.rb
@@ -1,4 +1,3 @@
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/ext'
@@ -55,7 +54,7 @@ class TestGemExtExtConfBuilder < RubyGemTestCase
output = []
- error = assert_raise Gem::InstallError do
+ error = assert_raises Gem::InstallError do
Dir.chdir @ext do
Gem::Ext::ExtConfBuilder.build 'extconf.rb', nil, @dest_path, output
end
@@ -103,7 +102,7 @@ install:
end
def test_class_make_no_Makefile
- error = assert_raise Gem::InstallError do
+ error = assert_raises Gem::InstallError do
Dir.chdir @ext do
Gem::Ext::ExtConfBuilder.make @ext, ['output']
end
diff --git a/test/rubygems/test_gem_ext_rake_builder.rb b/test/rubygems/test_gem_ext_rake_builder.rb
index 6d9184e804..18d74c382a 100644
--- a/test/rubygems/test_gem_ext_rake_builder.rb
+++ b/test/rubygems/test_gem_ext_rake_builder.rb
@@ -1,4 +1,3 @@
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/ext'
@@ -32,6 +31,8 @@ class TestGemExtRakeBuilder < RubyGemTestCase
end
end
+ output = output.join "\n"
+
expected = [
"#{@@ruby} mkrf_conf.rb",
"",
@@ -39,7 +40,9 @@ class TestGemExtRakeBuilder < RubyGemTestCase
"(in #{realdir})\n"
]
- assert_equal expected, output
+ refute_match %r%^rake failed:%, output
+ assert_match %r%^#{Regexp.escape @@ruby} mkrf_conf\.rb%, output
+ assert_match %r%^#{Regexp.escape @@rake} RUBYARCHDIR=#{Regexp.escape @dest_path} RUBYLIBDIR=#{Regexp.escape @dest_path}%, output
end
def test_class_build_fail
@@ -53,7 +56,7 @@ class TestGemExtRakeBuilder < RubyGemTestCase
output = []
- error = assert_raise Gem::InstallError do
+ error = assert_raises Gem::InstallError do
build_rake_in do
Dir.chdir @ext do
Gem::Ext::RakeBuilder.build "mkrf_conf.rb", nil, @dest_path, output
@@ -69,7 +72,9 @@ rake failed:
#{@@rake} RUBYARCHDIR=#{@dest_path} RUBYLIBDIR=#{@dest_path}
EOF
- assert_equal expected, error.message.split("\n")[0..4].join("\n")
+ assert_match %r%^rake failed:%, error.message
+ assert_match %r%^#{Regexp.escape @@ruby} mkrf_conf\.rb%, error.message
+ assert_match %r%^#{Regexp.escape @@rake} RUBYARCHDIR=#{Regexp.escape @dest_path} RUBYLIBDIR=#{Regexp.escape @dest_path}%, error.message
end
end
diff --git a/test/rubygems/test_gem_format.rb b/test/rubygems/test_gem_format.rb
index 4014acfed9..4d8a38a062 100644
--- a/test/rubygems/test_gem_format.rb
+++ b/test/rubygems/test_gem_format.rb
@@ -4,7 +4,6 @@
# See LICENSE.txt for permissions.
#++
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require File.join(File.expand_path(File.dirname(__FILE__)), 'simple_gem')
require 'rubygems/format'
@@ -36,27 +35,27 @@ class TestGemFormat < RubyGemTestCase
end
def test_from_file_by_path_nonexistent
- assert_raise Gem::Exception do
+ assert_raises Gem::Exception do
Gem::Format.from_file_by_path '/nonexistent'
end
end
def test_from_io_garbled
- e = assert_raise Gem::Package::FormatError do
+ e = assert_raises Gem::Package::FormatError do
# subtly bogus input
Gem::Format.from_io(StringIO.new(@simple_gem.upcase))
end
assert_equal 'No metadata found!', e.message
- e = assert_raise Gem::Package::FormatError do
+ e = assert_raises Gem::Package::FormatError do
# Totally bogus input
Gem::Format.from_io(StringIO.new(@simple_gem.reverse))
end
assert_equal 'No metadata found!', e.message
- e = assert_raise Gem::Package::FormatError do
+ e = assert_raises Gem::Package::FormatError do
# This was intentionally screws up YAML parsing.
Gem::Format.from_io(StringIO.new(@simple_gem.gsub(/:/, "boom")))
end
@@ -66,4 +65,3 @@ class TestGemFormat < RubyGemTestCase
end
-
diff --git a/test/rubygems/test_gem_gem_path_searcher.rb b/test/rubygems/test_gem_gem_path_searcher.rb
index c9da4d2b05..d69de4d22a 100644
--- a/test/rubygems/test_gem_gem_path_searcher.rb
+++ b/test/rubygems/test_gem_gem_path_searcher.rb
@@ -1,14 +1,9 @@
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/gem_path_searcher'
class Gem::GemPathSearcher
attr_accessor :gemspecs
attr_accessor :lib_dirs
-
- public :init_gemspecs
- public :matching_file
- public :lib_dirs_for
end
class TestGemGemPathSearcher < RubyGemTestCase
@@ -40,6 +35,10 @@ class TestGemGemPathSearcher < RubyGemTestCase
assert_equal @foo1, @gps.find('foo')
end
+ def test_find_all
+ assert_equal [@foo1], @gps.find_all('foo')
+ end
+
def test_init_gemspecs
assert_equal [@bar2, @bar1, @foo2, @foo1], @gps.init_gemspecs
end
@@ -51,9 +50,17 @@ class TestGemGemPathSearcher < RubyGemTestCase
assert_equal expected, lib_dirs
end
- def test_matching_file
- assert !@gps.matching_file(@foo1, 'bar')
- assert @gps.matching_file(@foo1, 'foo')
+ def test_matching_file_eh
+ assert !@gps.matching_file?(@foo1, 'bar')
+ assert @gps.matching_file?(@foo1, 'foo')
+ end
+
+ def test_matching_files
+ assert_equal [], @gps.matching_files(@foo1, 'bar')
+
+ expected = File.join @foo1.full_gem_path, 'lib', 'foo.rb'
+
+ assert_equal [expected], @gps.matching_files(@foo1, 'foo')
end
end
diff --git a/test/rubygems/test_gem_gem_runner.rb b/test/rubygems/test_gem_gem_runner.rb
index 4e3239f015..2b4889e015 100644
--- a/test/rubygems/test_gem_gem_runner.rb
+++ b/test/rubygems/test_gem_gem_runner.rb
@@ -1,4 +1,3 @@
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/gem_runner'
diff --git a/test/rubygems/test_gem_indexer.rb b/test/rubygems/test_gem_indexer.rb
index 9d68a7f34d..b1932c7335 100644
--- a/test/rubygems/test_gem_indexer.rb
+++ b/test/rubygems/test_gem_indexer.rb
@@ -4,7 +4,6 @@
# See LICENSE.txt for permissions.
#++
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/indexer'
@@ -217,8 +216,8 @@ Compressing indicies
assert_same specs[0].last, specs[1].last,
'identical platforms not identical'
- assert_not_same specs[1][1], specs[5][1],
- 'different versions not different'
+ refute_same specs[1][1], specs[5][1],
+ 'different versions not different'
end
def test_generate_index_latest_specs
diff --git a/test/rubygems/test_gem_install_update_options.rb b/test/rubygems/test_gem_install_update_options.rb
index 3638a0670a..8610a79cdf 100644
--- a/test/rubygems/test_gem_install_update_options.rb
+++ b/test/rubygems/test_gem_install_update_options.rb
@@ -1,4 +1,3 @@
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require File.join(File.expand_path(File.dirname(__FILE__)),
'gem_installer_test_case')
@@ -31,7 +30,7 @@ class TestGemInstallUpdateOptions < GemInstallerTestCase
def test_security_policy_unknown
@cmd.add_install_update_options
- assert_raise OptionParser::InvalidArgument do
+ assert_raises OptionParser::InvalidArgument do
@cmd.handle_options %w[-P UnknownSecurity]
end
end
@@ -41,8 +40,8 @@ class TestGemInstallUpdateOptions < GemInstallerTestCase
@installer = Gem::Installer.new @gem, @cmd.options
@installer.install
- assert File.exist?(File.join(@userhome, '.gem', 'gems'))
- assert File.exist?(File.join(@userhome, '.gem', 'gems',
+ assert File.exist?(File.join(Gem.user_dir, 'gems'))
+ assert File.exist?(File.join(Gem.user_dir, 'gems',
@spec.full_name))
end
diff --git a/test/rubygems/test_gem_installer.rb b/test/rubygems/test_gem_installer.rb
index eb9743dd42..3df9dbc28c 100644
--- a/test/rubygems/test_gem_installer.rb
+++ b/test/rubygems/test_gem_installer.rb
@@ -52,7 +52,7 @@ load 'my_exec'
def test_build_extensions_extconf_bad
@spec.extensions << 'extconf.rb'
- e = assert_raise Gem::Installer::ExtensionBuildError do
+ e = assert_raises Gem::Installer::ExtensionBuildError do
use_ui @ui do
@installer.build_extensions
end
@@ -70,13 +70,16 @@ load 'my_exec'
#{Gem.ruby}: No such file or directory -- extconf.rb (LoadError)
EOF
- assert_equal expected, File.read(gem_make_out)
+ assert_match %r%#{Regexp.escape Gem.ruby} extconf.rb%,
+ File.read(gem_make_out)
+ assert_match %r%#{Regexp.escape Gem.ruby}: No such file%,
+ File.read(gem_make_out)
end
def test_build_extensions_unsupported
@spec.extensions << nil
- e = assert_raise Gem::Installer::ExtensionBuildError do
+ e = assert_raises Gem::Installer::ExtensionBuildError do
use_ui @ui do
@installer.build_extensions
end
@@ -98,7 +101,7 @@ load 'my_exec'
assert @installer.ensure_dependency(@spec, dep)
dep = Gem::Dependency.new 'b', '> 2'
- e = assert_raise Gem::InstallError do
+ e = assert_raises Gem::InstallError do
@installer.ensure_dependency @spec, dep
end
@@ -139,7 +142,7 @@ load 'my_exec'
def test_extract_files_bad_dest
@installer.gem_dir = 'somedir'
@installer.format = nil
- e = assert_raise ArgumentError do
+ e = assert_raises ArgumentError do
@installer.extract_files
end
@@ -154,7 +157,7 @@ load 'my_exec'
@installer.format = format
- e = assert_raise Gem::InstallError do
+ e = assert_raises Gem::InstallError do
@installer.extract_files
end
@@ -172,7 +175,7 @@ load 'my_exec'
@installer.format = format
- e = assert_raise Gem::InstallError do
+ e = assert_raises Gem::InstallError do
@installer.extract_files
end
@@ -339,8 +342,8 @@ load 'my_exec'
assert_match %r|generated by RubyGems|, File.read(installed_exec)
- assert_no_match %r|generated by RubyGems|, File.read(real_exec),
- 'real executable overwritten'
+ refute_match %r|generated by RubyGems|, File.read(real_exec),
+ 'real executable overwritten'
end
def test_generate_bin_symlink
@@ -529,6 +532,16 @@ load 'my_exec'
Dir.mkdir util_inst_bindir
util_setup_gem
+ cache_file = File.join @gemhome, 'cache', "#{@spec.full_name}.gem"
+
+ Gem.pre_install do |installer|
+ assert !File.exist?(cache_file), 'cache file should not exist yet'
+ end
+
+ Gem.post_install do |installer|
+ assert File.exist?(cache_file), 'cache file should exist'
+ end
+
build_rake_in do
use_ui @ui do
assert_equal @spec, @installer.install
@@ -552,6 +565,9 @@ load 'my_exec'
assert_equal spec_file, @spec.loaded_from
assert File.exist?(spec_file)
+
+ assert_same @installer, @pre_install_hook_arg
+ assert_same @installer, @post_install_hook_arg
end
def test_install_bad_gem
@@ -565,7 +581,7 @@ load 'my_exec'
gem_data = File.open gem, 'rb' do |fp| fp.read 1024 end
File.open gem, 'wb' do |fp| fp.write gem_data end
- e = assert_raise Gem::InstallError do
+ e = assert_raises Gem::InstallError do
use_ui @ui do
@installer = Gem::Installer.new gem
@installer.install
@@ -580,10 +596,35 @@ load 'my_exec'
util_setup_gem
use_ui @ui do
- assert_raise Gem::InstallError do
+ assert_raises Gem::InstallError do
+ @installer.install
+ end
+ end
+ end
+
+ def test_install_check_dependencies_install_dir
+ gemhome2 = "#{@gemhome}2"
+ @spec.add_dependency 'b'
+
+ b2 = quick_gem 'b', 2
+
+ FileUtils.mv @gemhome, gemhome2
+ Gem.source_index.gems.delete b2.full_name
+ source_index = Gem::SourceIndex.from_gems_in File.join(gemhome2,
+ 'specifications')
+
+ util_setup_gem
+
+ @installer = Gem::Installer.new @gem, :install_dir => gemhome2,
+ :source_index => source_index
+
+ build_rake_in do
+ use_ui @ui do
@installer.install
end
end
+
+ assert File.exist?(File.join(gemhome2, 'gems', @spec.full_name))
end
def test_install_force
@@ -641,13 +682,13 @@ load 'my_exec'
assert File.exist?(File.join(@gemhome, 'specifications',
"#{@spec.full_name}.gemspec"))
end
+
unless win_platform? # File.chmod doesn't work
def test_install_user_local_fallback
Dir.mkdir util_inst_bindir
File.chmod 0755, @userhome
File.chmod 0000, util_inst_bindir
File.chmod 0000, Gem.dir
- install_dir = File.join @userhome, '.gem', 'gems', @spec.full_name
@spec.executables = ["executable"]
build_rake_in do
@@ -656,9 +697,10 @@ load 'my_exec'
@installer.install
end
end
-
- assert File.exist?(File.join(install_dir, 'lib', 'code.rb'))
- assert File.exist?(File.join(@userhome, '.gem', 'bin', 'executable'))
+
+ assert File.exist?(File.join(Gem.user_dir, 'gems',
+ @spec.full_name, 'lib', 'code.rb'))
+ assert File.exist?(File.join(Gem.user_dir, 'bin', 'executable'))
ensure
File.chmod 0755, Gem.dir
File.chmod 0755, util_inst_bindir
@@ -671,18 +713,17 @@ load 'my_exec'
build_rake_in do
use_ui @ui do
- setup
util_setup_gem
@installer.install
end
end
-
- assert File.exist?(File.join(@userhome, '.gem', 'bin', 'executable'))
+
+ assert File.exist?(File.join(Gem.user_dir, 'bin', 'executable'))
ensure
File.chmod 0755, util_inst_bindir
end
end
-
+
def test_install_with_message
@spec.post_install_message = 'I am a shiny gem!'
@@ -698,7 +739,7 @@ load 'my_exec'
def test_install_wrong_ruby_version
use_ui @ui do
installer = Gem::Installer.new old_ruby_required
- e = assert_raise Gem::InstallError do
+ e = assert_raises Gem::InstallError do
installer.install
end
assert_equal 'old_ruby_required requires Ruby version = 1.4.6',
@@ -717,7 +758,7 @@ load 'my_exec'
use_ui @ui do
@installer = Gem::Installer.new gem
- e = assert_raise Gem::InstallError do
+ e = assert_raises Gem::InstallError do
@installer.install
end
assert_equal 'old_rubygems_required requires RubyGems version < 0',
diff --git a/test/rubygems/test_gem_local_remote_options.rb b/test/rubygems/test_gem_local_remote_options.rb
index e676c94f21..e920972fd9 100644
--- a/test/rubygems/test_gem_local_remote_options.rb
+++ b/test/rubygems/test_gem_local_remote_options.rb
@@ -1,4 +1,3 @@
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/local_remote_options'
require 'rubygems/command'
@@ -19,6 +18,18 @@ class TestGemLocalRemoteOptions < RubyGemTestCase
assert @cmd.handles?(args)
end
+ def test_both_eh
+ assert_equal false, @cmd.both?
+
+ @cmd.options[:domain] = :local
+
+ assert_equal false, @cmd.both?
+
+ @cmd.options[:domain] = :both
+
+ assert_equal true, @cmd.both?
+ end
+
def test_local_eh
assert_equal false, @cmd.local?
@@ -74,7 +85,7 @@ class TestGemLocalRemoteOptions < RubyGemTestCase
s1 = 'htp://more-gems.example.com'
- assert_raise OptionParser::InvalidArgument do
+ assert_raises OptionParser::InvalidArgument do
@cmd.handle_options %W[--source #{s1}]
end
diff --git a/test/rubygems/test_gem_package_tar_reader_entry.rb b/test/rubygems/test_gem_package_tar_reader_entry.rb
index 7e25143a85..66f885b250 100644
--- a/test/rubygems/test_gem_package_tar_reader_entry.rb
+++ b/test/rubygems/test_gem_package_tar_reader_entry.rb
@@ -36,19 +36,19 @@ class TestGemPackageTarReaderEntry < TarTestCase
assert @entry.bytes_read
- e = assert_raise IOError do @entry.eof? end
+ e = assert_raises IOError do @entry.eof? end
assert_equal 'closed Gem::Package::TarReader::Entry', e.message
- e = assert_raise IOError do @entry.getc end
+ e = assert_raises IOError do @entry.getc end
assert_equal 'closed Gem::Package::TarReader::Entry', e.message
- e = assert_raise IOError do @entry.pos end
+ e = assert_raises IOError do @entry.pos end
assert_equal 'closed Gem::Package::TarReader::Entry', e.message
- e = assert_raise IOError do @entry.read end
+ e = assert_raises IOError do @entry.read end
assert_equal 'closed Gem::Package::TarReader::Entry', e.message
- e = assert_raise IOError do @entry.rewind end
+ e = assert_raises IOError do @entry.rewind end
assert_equal 'closed Gem::Package::TarReader::Entry', e.message
end
diff --git a/test/rubygems/test_gem_package_tar_writer.rb b/test/rubygems/test_gem_package_tar_writer.rb
index e066c2967f..4c2b475bf1 100644
--- a/test/rubygems/test_gem_package_tar_writer.rb
+++ b/test/rubygems/test_gem_package_tar_writer.rb
@@ -61,7 +61,7 @@ class TestTarWriter < TarTestCase
end
def test_add_file_simple_size
- assert_raise Gem::Package::TarWriter::FileOverflow do
+ assert_raises Gem::Package::TarWriter::FileOverflow do
@tar_writer.add_file_simple("lib/foo/bar", 0, 10) do |io|
io.write "1" * 11
end
@@ -69,7 +69,7 @@ class TestTarWriter < TarTestCase
end
def test_add_file_unseekable
- assert_raise Gem::Package::NonSeekableIO do
+ assert_raises Gem::Package::NonSeekableIO do
Gem::Package::TarWriter.new(Object.new).add_file 'x', 0
end
end
@@ -79,27 +79,27 @@ class TestTarWriter < TarTestCase
assert_equal "\0" * 1024, @io.string
- e = assert_raise IOError do
+ e = assert_raises IOError do
@tar_writer.close
end
assert_equal 'closed Gem::Package::TarWriter', e.message
- e = assert_raise IOError do
+ e = assert_raises IOError do
@tar_writer.flush
end
assert_equal 'closed Gem::Package::TarWriter', e.message
- e = assert_raise IOError do
+ e = assert_raises IOError do
@tar_writer.add_file 'x', 0
end
assert_equal 'closed Gem::Package::TarWriter', e.message
- e = assert_raise IOError do
+ e = assert_raises IOError do
@tar_writer.add_file_simple 'x', 0, 0
end
assert_equal 'closed Gem::Package::TarWriter', e.message
- e = assert_raise IOError do
+ e = assert_raises IOError do
@tar_writer.mkdir 'x', 0
end
assert_equal 'closed Gem::Package::TarWriter', e.message
@@ -125,7 +125,7 @@ class TestTarWriter < TarTestCase
name = File.join 'a', 'b' * 100
assert_equal ['b' * 100, 'a'], @tar_writer.split_name(name)
- assert_raise Gem::Package::TooLongFileName do
+ assert_raises Gem::Package::TooLongFileName do
name = File.join 'a', 'b' * 101
@tar_writer.split_name name
end
@@ -135,14 +135,14 @@ class TestTarWriter < TarTestCase
name = File.join 'a' * 155, 'b'
assert_equal ['b', 'a' * 155], @tar_writer.split_name(name)
- assert_raise Gem::Package::TooLongFileName do
+ assert_raises Gem::Package::TooLongFileName do
name = File.join 'a' * 156, 'b'
@tar_writer.split_name name
end
end
def test_split_name_too_long_total
- assert_raise Gem::Package::TooLongFileName do
+ assert_raises Gem::Package::TooLongFileName do
@tar_writer.split_name 'a' * 257
end
end
diff --git a/test/rubygems/test_gem_platform.rb b/test/rubygems/test_gem_platform.rb
index 648c2a9f36..fdb8fb11ed 100644
--- a/test/rubygems/test_gem_platform.rb
+++ b/test/rubygems/test_gem_platform.rb
@@ -1,23 +1,9 @@
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
-require 'test/unit'
require 'rubygems/platform'
require 'rbconfig'
class TestGemPlatform < RubyGemTestCase
- def test_self_const_missing
- consts = [:DARWIN, :LINUX_586, :MSWIN32, :PPC_DARWIN, :WIN32, :X86_LINUX]
-
- consts.each do |const|
- e = assert_raise NameError do
- Gem::Platform.const_missing const
- end
-
- assert_equal "#{const} has been removed, use CURRENT instead",
- e.message
- end
- end
-
def test_self_local
util_set_arch 'i686-darwin8.10.1'
@@ -105,6 +91,12 @@ class TestGemPlatform < RubyGemTestCase
platform = Gem::Platform.new 'i386-mswin32-80'
assert_equal expected, platform.to_a, 'i386-mswin32-80'
+
+ expected = ['x86', 'solaris', '2.10']
+
+ platform = Gem::Platform.new 'i386-solaris-2.10'
+
+ assert_equal expected, platform.to_a, 'i386-solaris-2.10'
end
def test_initialize_mswin32_vc6
@@ -154,8 +146,8 @@ class TestGemPlatform < RubyGemTestCase
other = Gem::Platform.new %w[cpu other_platform 1]
assert_equal my, my
- assert_not_equal my, other
- assert_not_equal other, my
+ refute_equal my, other
+ refute_equal other, my
end
def test_equals3
@@ -212,10 +204,10 @@ class TestGemPlatform < RubyGemTestCase
# oddballs
assert_match 'i386-mswin32-mq5.3', Gem::Platform.local
assert_match 'i386-mswin32-mq6', Gem::Platform.local
- deny_match 'win32-1.8.2-VC7', Gem::Platform.local
- deny_match 'win32-1.8.4-VC6', Gem::Platform.local
- deny_match 'win32-source', Gem::Platform.local
- deny_match 'windows', Gem::Platform.local
+ refute_match 'win32-1.8.2-VC7', Gem::Platform.local
+ refute_match 'win32-1.8.4-VC6', Gem::Platform.local
+ refute_match 'win32-source', Gem::Platform.local
+ refute_match 'windows', Gem::Platform.local
util_set_arch 'i686-linux'
assert_match 'i486-linux', Gem::Platform.local
@@ -243,17 +235,5 @@ class TestGemPlatform < RubyGemTestCase
assert_match 'sparc-solaris2.8-mq5.3', Gem::Platform.local
end
- def assert_match(pattern, platform, message = '')
- full_message = build_message message, "<?> expected to be =~\n<?>.",
- platform, pattern
- assert_block(full_message) { platform =~ pattern }
- end
-
- def deny_match(pattern, platform, message = '')
- full_message = build_message message, "<?> expected to be !~\n<?>.",
- platform, pattern
- assert_block(full_message) { platform !~ pattern }
- end
-
end
diff --git a/test/rubygems/test_gem_remote_fetcher.rb b/test/rubygems/test_gem_remote_fetcher.rb
index 484104dd8f..3f135ba046 100644
--- a/test/rubygems/test_gem_remote_fetcher.rb
+++ b/test/rubygems/test_gem_remote_fetcher.rb
@@ -1,11 +1,9 @@
-#!/usr/bin/env ruby
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'webrick'
require 'zlib'
@@ -111,9 +109,14 @@ gems:
@fetcher = Gem::RemoteFetcher.fetcher
end
+ def teardown
+ super
+ Gem.configuration[:http_proxy] = nil
+ end
+
def test_self_fetcher
fetcher = Gem::RemoteFetcher.fetcher
- assert_not_nil fetcher
+ refute_nil fetcher
assert_kind_of Gem::RemoteFetcher, fetcher
end
@@ -124,7 +127,7 @@ gems:
fetcher = Gem::RemoteFetcher.fetcher
- assert_not_nil fetcher
+ refute_nil fetcher
assert_kind_of Gem::RemoteFetcher, fetcher
assert_equal proxy_uri, fetcher.instance_variable_get(:@proxy_uri).to_s
end
@@ -132,8 +135,11 @@ gems:
def test_self_fetcher_with_proxy_URI
proxy_uri = URI.parse 'http://proxy.example.com'
Gem.configuration[:http_proxy] = proxy_uri
+ Gem::RemoteFetcher.fetcher = nil
+
fetcher = Gem::RemoteFetcher.fetcher
- assert_not_nil fetcher
+ refute_nil fetcher
+
assert_kind_of Gem::RemoteFetcher, fetcher
assert_equal proxy_uri, fetcher.instance_variable_get(:@proxy_uri)
end
@@ -141,7 +147,7 @@ gems:
def test_fetch_size_bad_uri
fetcher = Gem::RemoteFetcher.new nil
- e = assert_raise ArgumentError do
+ e = assert_raises ArgumentError do
fetcher.fetch_size 'gems.example.com/yaml'
end
@@ -155,7 +161,7 @@ gems:
end
uri = 'http://gems.example.com/yaml'
- e = assert_raise Gem::RemoteFetcher::FetchError do
+ e = assert_raises Gem::RemoteFetcher::FetchError do
fetcher.fetch_size uri
end
@@ -268,15 +274,15 @@ gems:
ensure
File.chmod 0755, File.join(@gemhome, 'cache')
end
-
+
def test_download_read_only
File.chmod 0555, File.join(@gemhome, 'cache')
File.chmod 0555, File.join(@gemhome)
fetcher = util_fuck_with_fetcher File.read(@a1_gem)
fetcher.download(@a1, 'http://gems.example.com')
- assert File.exist?(File.join(@userhome, '.gem',
- 'cache', "#{@a1.full_name}.gem"))
+ assert File.exist?(File.join(Gem.user_dir, 'cache',
+ "#{@a1.full_name}.gem"))
ensure
File.chmod 0755, File.join(@gemhome)
File.chmod 0755, File.join(@gemhome, 'cache')
@@ -310,7 +316,7 @@ gems:
def test_download_unsupported
inst = Gem::RemoteFetcher.fetcher
- e = assert_raise Gem::InstallError do
+ e = assert_raises Gem::InstallError do
inst.download @a1, 'ftp://gems.rubyforge.org'
end
@@ -391,6 +397,16 @@ gems:
assert_equal 'foo', fetcher.fetch_path(@uri + 'foo.gz')
end
+ def test_fetch_path_gzip_unmodified
+ fetcher = Gem::RemoteFetcher.new nil
+
+ def fetcher.open_uri_or_path(uri, mtime, head = nil)
+ nil
+ end
+
+ assert_equal nil, fetcher.fetch_path(@uri + 'foo.gz', Time.at(0))
+ end
+
def test_fetch_path_io_error
fetcher = Gem::RemoteFetcher.new nil
@@ -398,7 +414,7 @@ gems:
raise EOFError
end
- e = assert_raise Gem::RemoteFetcher::FetchError do
+ e = assert_raises Gem::RemoteFetcher::FetchError do
fetcher.fetch_path 'uri'
end
@@ -413,7 +429,7 @@ gems:
raise SocketError
end
- e = assert_raise Gem::RemoteFetcher::FetchError do
+ e = assert_raises Gem::RemoteFetcher::FetchError do
fetcher.fetch_path 'uri'
end
@@ -428,7 +444,7 @@ gems:
raise Errno::ECONNREFUSED, 'connect(2)'
end
- e = assert_raise Gem::RemoteFetcher::FetchError do
+ e = assert_raises Gem::RemoteFetcher::FetchError do
fetcher.fetch_path 'uri'
end
@@ -441,10 +457,10 @@ gems:
fetcher = Gem::RemoteFetcher.new nil
def fetcher.open_uri_or_path(uri, mtime, head = nil)
- ''
+ nil
end
- assert_equal '', fetcher.fetch_path(URI.parse(@gem_repo), Time.at(0))
+ assert_equal nil, fetcher.fetch_path(URI.parse(@gem_repo), Time.at(0))
end
def test_get_proxy_from_env_empty
@@ -504,7 +520,7 @@ gems:
def conn.request(req)
unless defined? @requested then
@requested = true
- res = Net::HTTPRedirection.new nil, 301, nil
+ res = Net::HTTPMovedPermanently.new nil, 301, nil
res.add_field 'Location', 'http://gems.example.com/real_path'
res
else
@@ -528,7 +544,7 @@ gems:
conn = Object.new
def conn.started?() true end
def conn.request(req)
- res = Net::HTTPRedirection.new nil, 301, nil
+ res = Net::HTTPMovedPermanently.new nil, 301, nil
res.add_field 'Location', 'http://gems.example.com/redirect'
res
end
@@ -536,7 +552,7 @@ gems:
conn = { 'gems.example.com:80' => conn }
fetcher.instance_variable_set :@connections, conn
- e = assert_raise Gem::RemoteFetcher::FetchError do
+ e = assert_raises Gem::RemoteFetcher::FetchError do
fetcher.open_uri_or_path 'http://gems.example.com/redirect'
end
diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb
index c441bd16df..e1399bdaff 100644
--- a/test/rubygems/test_gem_requirement.rb
+++ b/test/rubygems/test_gem_requirement.rb
@@ -4,7 +4,6 @@
# See LICENSE.txt for permissions.
#++
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/version'
@@ -32,19 +31,19 @@ class TestGemRequirement < RubyGemTestCase
assert_equal @r1_2, @r1_2.dup
assert_equal @r1_2.dup, @r1_2
- assert_not_equal @r1_3, @r1_2
- assert_not_equal @r1_2, @r1_3
+ refute_equal @r1_3, @r1_2
+ refute_equal @r1_2, @r1_3
- assert_not_equal Object.new, @r1_2
- assert_not_equal @r1_2, Object.new
+ refute_equal Object.new, @r1_2
+ refute_equal @r1_2, Object.new
end
def test_hash
assert_equal @r1_2.hash, @r1_2.dup.hash
assert_equal @r1_2.dup.hash, @r1_2.hash
- assert_not_equal @r1_2.hash, @r1_3.hash
- assert_not_equal @r1_3.hash, @r1_2.hash
+ refute_equal @r1_2.hash, @r1_3.hash
+ refute_equal @r1_3.hash, @r1_2.hash
end
# We may get some old gems that have requirements in old formats.
@@ -80,13 +79,13 @@ class TestGemRequirement < RubyGemTestCase
end
def test_parse_illformed
- e = assert_raise ArgumentError do
+ e = assert_raises ArgumentError do
@r1_2.parse(nil)
end
assert_equal 'Illformed requirement [nil]', e.message
- e = assert_raise ArgumentError do
+ e = assert_raises ArgumentError do
@r1_2.parse('')
end
@@ -139,7 +138,7 @@ class TestGemRequirement < RubyGemTestCase
assert_equal false, r1_2.satisfied_by?(v1_2)
assert_equal true, r1_2.satisfied_by?(v1_3)
- assert_raise NoMethodError do
+ assert_raises NoMethodError do
assert_equal true, r1_2.satisfied_by?(nil)
end
end
@@ -154,7 +153,7 @@ class TestGemRequirement < RubyGemTestCase
assert_equal true, r1_2.satisfied_by?(v1_2)
assert_equal true, r1_2.satisfied_by?(v1_3)
- assert_raise NoMethodError do
+ assert_raises NoMethodError do
assert_equal true, r1_2.satisfied_by?(nil)
end
end
@@ -169,7 +168,7 @@ class TestGemRequirement < RubyGemTestCase
assert_equal true, r.satisfied_by?(v1_2)
assert_equal false, r.satisfied_by?(v1_3)
- assert_raise NoMethodError do
+ assert_raises NoMethodError do
assert_equal true, r.satisfied_by?(nil)
end
end
@@ -184,7 +183,7 @@ class TestGemRequirement < RubyGemTestCase
assert_equal false, r1_2.satisfied_by?(v1_2)
assert_equal false, r1_2.satisfied_by?(v1_3)
- assert_raise NoMethodError do
+ assert_raises NoMethodError do
assert_equal true, r1_2.satisfied_by?(nil)
end
end
@@ -199,7 +198,7 @@ class TestGemRequirement < RubyGemTestCase
assert_equal true, r1_2.satisfied_by?(v1_2)
assert_equal false, r1_2.satisfied_by?(v1_3)
- assert_raise NoMethodError do
+ assert_raises NoMethodError do
assert_equal true, r1_2.satisfied_by?(nil)
end
end
@@ -214,7 +213,7 @@ class TestGemRequirement < RubyGemTestCase
assert_equal true, r1_2.satisfied_by?(v1_2)
assert_equal true, r1_2.satisfied_by?(v1_3)
- assert_raise NoMethodError do
+ assert_raises NoMethodError do
assert_equal true, r1_2.satisfied_by?(nil)
end
end
diff --git a/test/rubygems/test_gem_server.rb b/test/rubygems/test_gem_server.rb
index dcdc766f0f..866a9e3c97 100644
--- a/test/rubygems/test_gem_server.rb
+++ b/test/rubygems/test_gem_server.rb
@@ -1,4 +1,3 @@
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/server'
require 'stringio'
diff --git a/test/rubygems/test_gem_source_index.rb b/test/rubygems/test_gem_source_index.rb
index 263826759a..48760292c0 100644
--- a/test/rubygems/test_gem_source_index.rb
+++ b/test/rubygems/test_gem_source_index.rb
@@ -4,7 +4,6 @@
# See LICENSE.txt for permissions.
#++
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/source_index'
require 'rubygems/config_file'
@@ -64,6 +63,54 @@ class TestGemSourceIndex < RubyGemTestCase
assert_equal a1.author, spec.author
end
+ def test_self_load_specification_utf_8
+ spec_dir = File.join @gemhome, 'specifications'
+
+ FileUtils.rm_r spec_dir
+
+ FileUtils.mkdir_p spec_dir
+
+ spec_file = File.join spec_dir, "utf-8.gemspec"
+ spec_data = <<-SPEC
+Gem::Specification.new do |s|
+ s.name = %q{utf}
+ s.version = "8"
+
+ s.required_rubygems_version = Gem::Requirement.new(">= 0")
+ s.authors = ["\317\200"]
+ s.date = %q{2008-09-10}
+ s.description = %q{This is a test description}
+ s.email = %q{example@example.com}
+ s.has_rdoc = true
+ s.homepage = %q{http://example.com}
+ s.require_paths = ["lib"]
+ s.rubygems_version = %q{1.2.0}
+ s.summary = %q{this is a summary}
+
+ if s.respond_to? :specification_version then
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
+ s.specification_version = 2
+
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
+ else
+ end
+ else
+ end
+end
+ SPEC
+
+ spec_data.force_encoding 'UTF-8'
+
+ File.open spec_file, 'w' do |io| io.write spec_data end
+
+ spec = Gem::SourceIndex.load_specification spec_file
+
+ pi = "\317\200"
+ pi.force_encoding 'UTF-8' if pi.respond_to? :force_encoding
+
+ assert_equal pi, spec.author
+ end if Gem.ruby_version > Gem::Version.new('1.9')
+
def test_self_load_specification_exception
spec_dir = File.join @gemhome, 'specifications'
@@ -102,7 +149,7 @@ WARNING: Invalid .gemspec format in '#{spec_file}'
end
use_ui @ui do
- assert_raise Interrupt do
+ assert_raises Interrupt do
Gem::SourceIndex.load_specification(spec_file)
end
end
@@ -144,7 +191,7 @@ WARNING: Invalid .gemspec format in '#{spec_file}'
end
use_ui @ui do
- assert_raise SystemExit do
+ assert_raises SystemExit do
Gem::SourceIndex.load_specification(spec_file)
end
end
@@ -184,7 +231,7 @@ WARNING: Invalid .gemspec format in '#{spec_file}'
@fetcher.data["#{@gem_repo}yaml.Z"] = proc { raise SocketError }
@fetcher.data["#{@gem_repo}yaml"] = proc { raise SocketError }
- e = assert_raise Gem::RemoteSourceException do
+ e = assert_raises Gem::RemoteSourceException do
use_ui @ui do
@source_index.fetch_bulk_index @uri
end
@@ -309,7 +356,7 @@ WARNING: Invalid .gemspec format in '#{spec_file}'
@fetcher.data["#{@gem_repo}quick/index.rz"] =
proc { raise Exception }
- e = assert_raise Gem::OperationNotSupportedError do
+ e = assert_raises Gem::OperationNotSupportedError do
@source_index.fetch_quick_index @uri, true
end
@@ -437,6 +484,27 @@ WARNING: Invalid .gemspec format in '#{spec_file}'
assert_equal [], missing
end
+ def test_find_name
+ assert_equal [@a1, @a2], @source_index.find_name('a')
+ assert_equal [@a2], @source_index.find_name('a', '= 2')
+ assert_equal [], @source_index.find_name('bogusstring')
+ assert_equal [], @source_index.find_name('a', '= 3')
+
+ source_index = Gem::SourceIndex.new
+ source_index.add_spec @a1
+ source_index.add_spec @a2
+
+ assert_equal [@a1], source_index.find_name(@a1.name, '= 1')
+
+ r1 = Gem::Requirement.create '= 1'
+ assert_equal [@a1], source_index.find_name(@a1.name, r1)
+ end
+
+ def test_find_name_empty_cache
+ empty_source_index = Gem::SourceIndex.new({})
+ assert_equal [], empty_source_index.find_name("foo")
+ end
+
def test_latest_specs
p1_ruby = quick_gem 'p', '1'
p1_platform = quick_gem 'p', '1' do |spec|
@@ -544,7 +612,7 @@ WARNING: Invalid .gemspec format in '#{spec_file}'
def test_refresh_bang_not_from_dir
source_index = Gem::SourceIndex.new
- e = assert_raise RuntimeError do
+ e = assert_raises RuntimeError do
source_index.refresh!
end
@@ -573,28 +641,12 @@ WARNING: Invalid .gemspec format in '#{spec_file}'
end
def test_search
- assert_equal [@a1, @a2, @a_evil9], @source_index.search('a')
- assert_equal [@a2], @source_index.search('a', '= 2')
-
- assert_equal [], @source_index.search('bogusstring')
- assert_equal [], @source_index.search('a', '= 3')
+ requirement = Gem::Requirement.create '= 9'
+ with_version = Gem::Dependency.new(/^a/, requirement)
+ assert_equal [@a_evil9], @source_index.search(with_version)
- source_index = Gem::SourceIndex.new
- source_index.add_spec @a1
- source_index.add_spec @a2
-
- assert_equal [@a1], source_index.search(@a1.name, '= 1')
-
- r1 = Gem::Requirement.create '= 1'
- assert_equal [@a1], source_index.search(@a1.name, r1)
-
- dep = Gem::Dependency.new @a1.name, r1
- assert_equal [@a1], source_index.search(dep)
- end
-
- def test_search_empty_cache
- empty_source_index = Gem::SourceIndex.new({})
- assert_equal [], empty_source_index.search("foo")
+ with_default = Gem::Dependency.new(/^a/, Gem::Requirement.default)
+ assert_equal [@a1, @a2, @a_evil9], @source_index.search(with_default)
end
def test_search_platform
diff --git a/test/rubygems/test_gem_source_info_cache.rb b/test/rubygems/test_gem_source_info_cache.rb
index 86866a8012..2a4ee6922a 100644
--- a/test/rubygems/test_gem_source_info_cache.rb
+++ b/test/rubygems/test_gem_source_info_cache.rb
@@ -1,11 +1,9 @@
-#!/usr/bin/env ruby
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/source_info_cache'
@@ -49,7 +47,7 @@ class TestGemSourceInfoCache < RubyGemTestCase
Gem.sources.replace %W[#{@gem_repo}]
use_ui @ui do
- assert_not_nil Gem::SourceInfoCache.cache
+ refute_nil Gem::SourceInfoCache.cache
assert_kind_of Gem::SourceInfoCache, Gem::SourceInfoCache.cache
assert_equal Gem::SourceInfoCache.cache.object_id,
Gem::SourceInfoCache.cache.object_id
@@ -68,11 +66,11 @@ class TestGemSourceInfoCache < RubyGemTestCase
Gem.sources.replace %w[#{@gem_repo}]
use_ui @ui do
- assert_not_nil Gem::SourceInfoCache.cache
+ refute_nil Gem::SourceInfoCache.cache
assert_kind_of Gem::SourceInfoCache, Gem::SourceInfoCache.cache
assert_equal Gem::SourceInfoCache.cache.object_id,
Gem::SourceInfoCache.cache.object_id
- assert_no_match %r|Bulk updating|, @ui.output
+ refute_match %r|Bulk updating|, @ui.output
end
end
@@ -147,7 +145,7 @@ class TestGemSourceInfoCache < RubyGemTestCase
def test_cache_data_none_writable
FileUtils.chmod 0444, @sic.system_cache_file
FileUtils.chmod 0444, @sic.user_cache_file
- e = assert_raise RuntimeError do
+ e = assert_raises RuntimeError do
@sic.cache_data
end
assert_equal 'unable to locate a writable cache file', e.message
@@ -202,7 +200,7 @@ class TestGemSourceInfoCache < RubyGemTestCase
def test_cache_file_none_writable
FileUtils.chmod 0444, @sic.system_cache_file
FileUtils.chmod 0444, @sic.user_cache_file
- e = assert_raise RuntimeError do
+ e = assert_raises RuntimeError do
@sic.cache_file
end
assert_equal 'unable to locate a writable cache file', e.message
@@ -224,7 +222,8 @@ class TestGemSourceInfoCache < RubyGemTestCase
@sic.set_cache_data @gem_repo => sice
latest = @sic.latest_cache_data
- gems = latest[@gem_repo].source_index.search('a').map { |s| s.full_name }
+ beginning_with_a = Gem::Dependency.new(/^a/, Gem::Requirement.default)
+ gems = latest[@gem_repo].source_index.search(beginning_with_a).map { |s| s.full_name }
assert_equal %w[a-2 a_evil-9], gems
end
diff --git a/test/rubygems/test_gem_source_info_cache_entry.rb b/test/rubygems/test_gem_source_info_cache_entry.rb
index 6986c9cd7f..e1d61b8f6f 100644
--- a/test/rubygems/test_gem_source_info_cache_entry.rb
+++ b/test/rubygems/test_gem_source_info_cache_entry.rb
@@ -1,4 +1,3 @@
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/source_info_cache_entry'
@@ -56,7 +55,7 @@ class TestGemSourceInfoCacheEntry < RubyGemTestCase
end
def test_refresh_bad_uri
- assert_raise URI::BadURIError do
+ assert_raises URI::BadURIError do
@sic_e.refresh 'gems.example.com', true
end
end
diff --git a/test/rubygems/test_gem_spec_fetcher.rb b/test/rubygems/test_gem_spec_fetcher.rb
index 2e9ce1b7eb..774785be08 100644
--- a/test/rubygems/test_gem_spec_fetcher.rb
+++ b/test/rubygems/test_gem_spec_fetcher.rb
@@ -1,4 +1,3 @@
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/spec_fetcher'
@@ -67,7 +66,7 @@ class TestGemSpecFetcher < RubyGemTestCase
end
def test_fetch_legacy_repo
- @fetcher.data["#{@gem_repo}specs.#{Gem.marshal_version}.gz"] = nil
+ @fetcher.data.delete "#{@gem_repo}specs.#{Gem.marshal_version}.gz"
@fetcher.data["#{@gem_repo}yaml"] = ''
util_setup_source_info_cache @a1, @a2
@@ -259,6 +258,16 @@ RubyGems will revert to legacy indexes degrading performance.
assert_equal specs, cached_specs
end
+ def test_list_latest_all
+ specs = @sf.list false
+
+ assert_equal [@latest_specs], specs.values
+
+ specs = @sf.list true
+
+ assert_equal [@specs], specs.values, 'specs file not loaded'
+ end
+
def test_load_specs
specs = @sf.load_specs @uri, 'specs'
@@ -280,7 +289,7 @@ RubyGems will revert to legacy indexes degrading performance.
end
def test_load_specs_cached
- @fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"] = ''
+ @fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"] = nil
@fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}"] =
' ' * Marshal.dump(@latest_specs).length
diff --git a/test/rubygems/test_gem_specification.rb b/test/rubygems/test_gem_specification.rb
index 57c3fdc158..d40e6787cd 100644
--- a/test/rubygems/test_gem_specification.rb
+++ b/test/rubygems/test_gem_specification.rb
@@ -5,7 +5,6 @@
#++
require 'stringio'
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/specification'
@@ -336,8 +335,8 @@ end
def test_equals2
assert_equal @a1, @a1
assert_equal @a1, @a1.dup
- assert_not_equal @a1, @a2
- assert_not_equal @a1, Object.new
+ refute_equal @a1, @a2
+ refute_equal @a1, Object.new
end
# The cgikit specification was reported to be causing trouble in at least
@@ -369,16 +368,16 @@ end
spec = @a1.dup
spec.default_executable = 'xx'
- assert_not_equal @a1, spec
- assert_not_equal spec, @a1
+ refute_equal @a1, spec
+ refute_equal spec, @a1
end
def test_equals2_extensions
spec = @a1.dup
spec.extensions = 'xx'
- assert_not_equal @a1, spec
- assert_not_equal spec, @a1
+ refute_equal @a1, spec
+ refute_equal spec, @a1
end
def test_executables
@@ -500,13 +499,13 @@ end
end
def test_has_rdoc_eh
- assert_equal true, @a1.has_rdoc?
+ assert @a1.has_rdoc?
end
def test_hash
assert_equal @a1.hash, @a1.hash
assert_equal @a1.hash, @a1.dup.hash
- assert_not_equal @a1.hash, @a2.hash
+ refute_equal @a1.hash, @a2.hash
end
def test_lib_files
@@ -634,7 +633,10 @@ end
ruby_code = @a2.to_ruby
- expected = "Gem::Specification.new do |s|
+ expected = <<-SPEC
+# -*- encoding: utf-8 -*-
+
+Gem::Specification.new do |s|
s.name = %q{a}
s.version = \"2\"
@@ -654,7 +656,7 @@ end
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
s.specification_version = #{Gem::Specification::CURRENT_SPECIFICATION_VERSION}
- if current_version >= 3 then
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
s.add_runtime_dependency(%q<b>, [\"= 1\"])
else
s.add_dependency(%q<b>, [\"= 1\"])
@@ -663,7 +665,7 @@ end
s.add_dependency(%q<b>, [\"= 1\"])
end
end
-"
+ SPEC
assert_equal expected, ruby_code
@@ -679,7 +681,10 @@ end
local = Gem::Platform.local
expected_platform = "[#{local.cpu.inspect}, #{local.os.inspect}, #{local.version.inspect}]"
- expected = "Gem::Specification.new do |s|
+ expected = <<-SPEC
+# -*- encoding: utf-8 -*-
+
+Gem::Specification.new do |s|
s.name = %q{a}
s.version = \"1\"
s.platform = Gem::Platform.new(#{expected_platform})
@@ -706,7 +711,7 @@ end
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
s.specification_version = 2
- if current_version >= 3 then
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
s.add_runtime_dependency(%q<rake>, [\"> 0.4\"])
s.add_runtime_dependency(%q<jabber4r>, [\"> 0.0.0\"])
s.add_runtime_dependency(%q<pqa>, [\"> 0.4\", \"<= 0.6\"])
@@ -721,7 +726,7 @@ end
s.add_dependency(%q<pqa>, [\"> 0.4\", \"<= 0.6\"])
end
end
-"
+ SPEC
assert_equal expected, ruby_code
@@ -809,7 +814,7 @@ end
@a1.authors = [Object.new]
- e = assert_raise Gem::InvalidSpecificationException do
+ e = assert_raises Gem::InvalidSpecificationException do
@a1.validate
end
@@ -843,7 +848,7 @@ end
end
def test_validate_empty
- e = assert_raise Gem::InvalidSpecificationException do
+ e = assert_raises Gem::InvalidSpecificationException do
Gem::Specification.new.validate
end
@@ -866,7 +871,7 @@ end
def test_validate_empty_require_paths
@a1.require_paths = []
- e = assert_raise Gem::InvalidSpecificationException do
+ e = assert_raises Gem::InvalidSpecificationException do
@a1.validate
end
@@ -926,7 +931,7 @@ end
def test_validate_rubygems_version
@a1.rubygems_version = "3"
- e = assert_raise Gem::InvalidSpecificationException do
+ e = assert_raises Gem::InvalidSpecificationException do
@a1.validate
end
diff --git a/test/rubygems/test_gem_stream_ui.rb b/test/rubygems/test_gem_stream_ui.rb
index a8564ba94f..ffab8844cf 100644
--- a/test/rubygems/test_gem_stream_ui.rb
+++ b/test/rubygems/test_gem_stream_ui.rb
@@ -1,4 +1,3 @@
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/user_interaction'
diff --git a/test/rubygems/test_gem_uninstaller.rb b/test/rubygems/test_gem_uninstaller.rb
index 7d7890c3ea..bb90f5cc5f 100644
--- a/test/rubygems/test_gem_uninstaller.rb
+++ b/test/rubygems/test_gem_uninstaller.rb
@@ -62,5 +62,26 @@ class TestGemUninstaller < GemInstallerTestCase
assert_equal true, uninstaller.path_ok?(@spec)
end
+ def test_uninstall
+ uninstaller = Gem::Uninstaller.new @spec.name, :executables => true
+
+ gem_dir = File.join @gemhome, 'gems', @spec.full_name
+
+ Gem.pre_uninstall do
+ assert File.exist?(gem_dir), 'gem_dir should exist'
+ end
+
+ Gem.post_uninstall do
+ assert !File.exist?(gem_dir), 'gem_dir should not exist'
+ end
+
+ uninstaller.uninstall
+
+ assert !File.exist?(gem_dir)
+
+ assert_same uninstaller, @pre_uninstall_hook_arg
+ assert_same uninstaller, @post_uninstall_hook_arg
+ end
+
end
diff --git a/test/rubygems/test_gem_validator.rb b/test/rubygems/test_gem_validator.rb
index c910cfdf11..77fdf2181a 100644
--- a/test/rubygems/test_gem_validator.rb
+++ b/test/rubygems/test_gem_validator.rb
@@ -4,7 +4,6 @@
# See LICENSE.txt for permissions.
#++
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require File.join(File.expand_path(File.dirname(__FILE__)), 'simple_gem')
require 'rubygems/validator'
@@ -26,7 +25,7 @@ class TestGemValidator < RubyGemTestCase
end
def test_verify_gem_file_empty
- e = assert_raise Gem::VerificationError do
+ e = assert_raises Gem::VerificationError do
@validator.verify_gem_file ''
end
@@ -35,7 +34,7 @@ class TestGemValidator < RubyGemTestCase
def test_verify_gem_file_nonexistent
file = '/nonexistent/nonexistent.gem'
- e = assert_raise Gem::VerificationError do
+ e = assert_raises Gem::VerificationError do
@validator.verify_gem_file file
end
@@ -47,7 +46,7 @@ class TestGemValidator < RubyGemTestCase
end
def test_verify_gem_empty
- e = assert_raise Gem::VerificationError do
+ e = assert_raises Gem::VerificationError do
@validator.verify_gem ''
end
@@ -55,7 +54,7 @@ class TestGemValidator < RubyGemTestCase
end
def test_verify_gem_invalid_checksum
- e = assert_raise Gem::VerificationError do
+ e = assert_raises Gem::VerificationError do
@validator.verify_gem @simple_gem.upcase
end
diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb
index 8d10700490..4f5f79eaad 100644
--- a/test/rubygems/test_gem_version.rb
+++ b/test/rubygems/test_gem_version.rb
@@ -4,7 +4,6 @@
# See LICENSE.txt for permissions.
#++
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/version'
@@ -29,10 +28,10 @@ class TestGemVersion < RubyGemTestCase
end
def test_class_create_malformed
- e = assert_raise ArgumentError do Gem::Version.create("junk") end
+ e = assert_raises ArgumentError do Gem::Version.create("junk") end
assert_equal "Malformed version number string junk", e.message
- e = assert_raise ArgumentError do Gem::Version.create("1.0\n2.0") end
+ e = assert_raises ArgumentError do Gem::Version.create("1.0\n2.0") end
assert_equal "Malformed version number string 1.0\n2.0", e.message
end
@@ -90,8 +89,8 @@ class TestGemVersion < RubyGemTestCase
assert_equal v, @v1_2
assert_equal @v1_2, v
- assert_not_equal @v1_2, @v1_3
- assert_not_equal @v1_3, @v1_2
+ refute_equal @v1_2, @v1_3
+ refute_equal @v1_3, @v1_2
end
def test_hash
@@ -100,16 +99,16 @@ class TestGemVersion < RubyGemTestCase
assert_equal v1_2.hash, @v1_2.hash
- assert_not_equal v1_2_0.hash, @v1_2.hash
+ refute_equal v1_2_0.hash, @v1_2.hash
- assert_not_equal @v1_2.hash, @v1_3.hash
+ refute_equal @v1_2.hash, @v1_3.hash
end
def test_illformed_requirements
[ ">>> 1.3.5", "> blah" ].each do |rq|
- assert_raises(ArgumentError, "req [#{rq}] should fail") {
- Gem::Version::Requirement.new(rq)
- }
+ assert_raises ArgumentError, "req [#{rq}] should fail" do
+ Gem::Version::Requirement.new rq
+ end
end
end
diff --git a/test/rubygems/test_gem_version_option.rb b/test/rubygems/test_gem_version_option.rb
index 30c73390fe..3fda36ed68 100644
--- a/test/rubygems/test_gem_version_option.rb
+++ b/test/rubygems/test_gem_version_option.rb
@@ -1,4 +1,3 @@
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/command'
require 'rubygems/version_option'
diff --git a/test/rubygems/test_kernel.rb b/test/rubygems/test_kernel.rb
index da31d772eb..ae594be65c 100644
--- a/test/rubygems/test_kernel.rb
+++ b/test/rubygems/test_kernel.rb
@@ -1,11 +1,9 @@
-#!/usr/bin/env ruby
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++
-require 'test/unit'
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
require 'rubygems/package'
@@ -48,7 +46,7 @@ class TestKernel < RubyGemTestCase
def test_gem_conflicting
assert gem('a', '= 1'), "Should load"
- ex = assert_raise Gem::Exception do
+ ex = assert_raises Gem::Exception do
gem 'a', '= 2'
end
diff --git a/test/runner.rb b/test/runner.rb
index f9ed25a931..3f1c8abc19 100644
--- a/test/runner.rb
+++ b/test/runner.rb
@@ -1,9 +1,25 @@
require 'rbconfig'
exit if CROSS_COMPILING
+
require 'test/unit'
-rcsid = %w$Id$
-Version = rcsid[2].scan(/\d+/).collect!(&method(:Integer)).freeze
-Release = rcsid[3].freeze
+src_testdir = File.dirname(File.expand_path(__FILE__))
+srcdir = File.dirname(src_testdir)
-exit Test::Unit::AutoRunner.run(true, File.dirname($0))
+Test::Unit.setup_argv {|files|
+ if files.empty?
+ [src_testdir]
+ else
+ files.map {|f|
+ if File.exist? "#{src_testdir}/#{f}"
+ "#{src_testdir}/#{f}"
+ elsif File.exist? "#{srcdir}/#{f}"
+ "#{srcdir}/#{f}"
+ elsif File.exist? f
+ f
+ else
+ raise ArgumentError, "not found: #{f}"
+ end
+ }
+ end
+}
diff --git a/test/scanf/test_scanf.rb b/test/scanf/test_scanf.rb
index 66ca629f54..2e9e10ba5d 100644
--- a/test/scanf/test_scanf.rb
+++ b/test/scanf/test_scanf.rb
@@ -16,7 +16,7 @@ class TestIOScanf < Test::Unit::TestCase;end
module ScanfTests
-def tests
+ def tests
[
# Scratchpad
@@ -284,8 +284,8 @@ def tests
[" [%d,%f", " [10,1.1", [10,1.1] ],
]
- end
end
+end
class TestStringScanf
include Scanf
diff --git a/test/sdbm/test_sdbm.rb b/test/sdbm/test_sdbm.rb
index 0c6df66fb2..b94e198e95 100644
--- a/test/sdbm/test_sdbm.rb
+++ b/test/sdbm/test_sdbm.rb
@@ -199,9 +199,9 @@ class TestSDBM < Test::Unit::TestCase
}
end
- def test_index
+ def test_key
assert_equal('bar', @sdbm['foo'] = 'bar')
- assert_equal('foo', @sdbm.index('bar'))
+ assert_equal('foo', @sdbm.key('bar'))
assert_nil(@sdbm['bar'])
end
@@ -277,7 +277,7 @@ class TestSDBM < Test::Unit::TestCase
n = 0
ret = @sdbm.each_value {|val|
- assert_not_nil(key = @sdbm.index(val))
+ assert_not_nil(key = @sdbm.key(val))
assert_not_nil(i = keys.index(key))
assert_equal(val, values[i])
@@ -365,14 +365,11 @@ class TestSDBM < Test::Unit::TestCase
def test_delete_with_block
key = 'no called block'
@sdbm[key] = 'foo'
- assert_equal('foo', @sdbm.delete(key) {|k| k.replace 'called block'})
- assert_equal('no called block', key)
+ assert_equal('foo', @sdbm.delete(key) {|k| k.replace 'called block'; :blockval})
assert_equal(0, @sdbm.size)
key = 'no called block'
- assert_equal(:blockval,
- @sdbm.delete(key) {|k| k.replace 'called block'; :blockval})
- assert_equal('called block', key)
+ assert_equal(:blockval, @sdbm.delete(key) {|k| k.replace 'called block'; :blockval})
assert_equal(0, @sdbm.size)
end
@@ -533,12 +530,6 @@ class TestSDBM < Test::Unit::TestCase
@sdbm = SDBM.new(@path)
end
- def test_index
- assert_equal(nil, @sdbm.index("foo"))
- @sdbm["bar"] = "foo"
- assert_equal("bar", @sdbm.index("foo"))
- end
-
def test_readonly
@sdbm["bar"] = "baz"
@sdbm.close
diff --git a/test/socket/test_tcp.rb b/test/socket/test_tcp.rb
index 3aa7be82c3..c623c1b58c 100644
--- a/test/socket/test_tcp.rb
+++ b/test/socket/test_tcp.rb
@@ -21,4 +21,23 @@ assert false, "TODO: doesn't work on mswin32/64" if /mswin/ =~ RUBY_PLATFORM
th.kill
th.join
end
+
+ def test_encoding
+ svr = TCPServer.new("localhost", 0)
+ th = Thread.new {
+ c = svr.accept
+ c.write "foo\r\n"
+ c.close
+ }
+ addr = svr.addr
+ sock = TCPSocket.open(addr[2], addr[1])
+ assert_equal(true, sock.binmode?)
+ s = sock.gets
+ assert_equal("foo\r\n", s)
+ assert_equal(Encoding.find("ASCII-8BIT"), s.encoding)
+ ensure
+ th.kill
+ th.join
+ sock.close if sock
+ end
end if defined?(TCPSocket)
diff --git a/test/strscan/test_stringscanner.rb b/test/strscan/test_stringscanner.rb
index ff1eb7a298..151e8928a4 100644
--- a/test/strscan/test_stringscanner.rb
+++ b/test/strscan/test_stringscanner.rb
@@ -31,8 +31,8 @@ class TestStringScanner < Test::Unit::TestCase
def test_s_allocate
s = StringScanner.allocate
assert_equal '#<StringScanner (uninitialized)>', s.inspect.sub(/StringScanner_C/, 'StringScanner')
- assert_raises(UNINIT_ERROR) { s.eos? }
- assert_raises(UNINIT_ERROR) { s.scan(/a/) }
+ assert_raise(UNINIT_ERROR) { s.eos? }
+ assert_raise(UNINIT_ERROR) { s.scan(/a/) }
s.string = 'test'
assert_equal '#<StringScanner 0/4 @ "test">', s.inspect.sub(/StringScanner_C/, 'StringScanner')
assert_nothing_raised(UNINIT_ERROR) { s.eos? }
diff --git a/test/test_delegate.rb b/test/test_delegate.rb
index 42abbb6f81..0b4c117ebd 100644
--- a/test/test_delegate.rb
+++ b/test/test_delegate.rb
@@ -17,4 +17,16 @@ class TestDelegateClass < Test::Unit::TestCase
e = SystemCallError.new(0)
assert((SimpleDelegator.new(e) == e) == (e == SimpleDelegator.new(e)), "[ruby-dev:34808]")
end
+
+ class Myclass < DelegateClass(Array);end
+
+ def test_delegateclass_class
+ myclass=Myclass.new([])
+ assert_equal(Myclass,myclass.class)
+ end
+
+ def test_simpledelegator_class
+ simple=SimpleDelegator.new([])
+ assert_equal(SimpleDelegator,simple.class)
+ end
end
diff --git a/test/test_shellwords.rb b/test/test_shellwords.rb
index ddb2d870b0..e6ee3d6b4d 100644
--- a/test/test_shellwords.rb
+++ b/test/test_shellwords.rb
@@ -18,21 +18,21 @@ class TestShellwords < Test::Unit::TestCase
def test_unmatched_double_quote
bad_cmd = 'one two "three'
- assert_raises ArgumentError do
+ assert_raise ArgumentError do
shellwords(bad_cmd)
end
end
def test_unmatched_single_quote
bad_cmd = "one two 'three"
- assert_raises ArgumentError do
+ assert_raise ArgumentError do
shellwords(bad_cmd)
end
end
def test_unmatched_quotes
bad_cmd = "one '"'"''""'""
- assert_raises ArgumentError do
+ assert_raise ArgumentError do
shellwords(bad_cmd)
end
end
diff --git a/test/test_tempfile.rb b/test/test_tempfile.rb
index c4234e551d..e7e6413f9b 100644
--- a/test/test_tempfile.rb
+++ b/test/test_tempfile.rb
@@ -10,5 +10,26 @@ class TestTempfile < Test::Unit::TestCase
o.extend M
assert(M === o, "[ruby-dev:32932]")
end
+ def test_tempfile_encoding_nooption
+ default_external=Encoding.default_external
+ t=Tempfile.new("TEST")
+ t.write("\xE6\x9D\xBE\xE6\xB1\x9F")
+ t.rewind
+ assert_equal(default_external,t.read.encoding)
+ end
+ def test_tempfile_encoding_ascii8bit
+ default_external=Encoding.default_external
+ t=Tempfile.new("TEST",:encoding=>"ascii-8bit")
+ t.write("\xE6\x9D\xBE\xE6\xB1\x9F")
+ t.rewind
+ assert_equal(Encoding::ASCII_8BIT,t.read.encoding)
+ end
+ def test_tempfile_encoding_ascii8bit2
+ default_external=Encoding.default_external
+ t=Tempfile.new("TEST",Dir::tmpdir,:encoding=>"ascii-8bit")
+ t.write("\xE6\x9D\xBE\xE6\xB1\x9F")
+ t.rewind
+ assert_equal(Encoding::ASCII_8BIT,t.read.encoding)
+ end
end
diff --git a/test/testunit/collector/test_dir.rb b/test/testunit/collector/test_dir.rb
deleted file mode 100644
index eb61f9e6b5..0000000000
--- a/test/testunit/collector/test_dir.rb
+++ /dev/null
@@ -1,411 +0,0 @@
-require 'test/unit'
-require 'test/unit/collector/dir'
-require 'pp'
-
-module Test
- module Unit
- module Collector
- class TestDir < TestCase
- class FileSystem
- class Directory
- def initialize(name, fs, parent=self, &block)
- @name = name
- @fs = fs
- @parent = parent
- @contents = {'.' => self, '..' => parent}
- instance_eval(&block) if(block)
- end
-
- def file(name, contents)
- @contents[name] = contents
- end
-
- def dir(name, &block)
- @contents[name] = self.class.new(name, @fs, self, &block)
- end
-
- def entries
- @contents.keys
- end
-
- def directory?(name)
- return true if(name.nil? || name.empty?)
- return false unless(@contents.include?(name))
- @contents[name].kind_of?(self.class)
- end
-
- def file?(name)
- return false unless(@contents.include?(name))
- !directory?(name)
- end
-
- def exist?(name)
- @contents.include?(name)
- end
-
- def [](name)
- raise Errno::ENOENT, name unless(@contents.include?(name))
- @contents[name]
- end
-
- def path_to(name=nil)
- if(!name)
- @parent.path_to(@name)
- elsif(@parent == self)
- @fs.join('/', name)
- else
- @fs.join(@parent.path_to(@name), name)
- end
- end
- end
-
- class ObjectSpace
- def initialize
- @objects = []
- end
-
- def each_object(klass, &block)
- @objects.find_all{|o| o.kind_of?(klass)}.each(&block)
- end
-
- def <<(object)
- @objects << object
- end
- end
-
- attr_reader :object_space
-
- def initialize(&block)
- @root = Directory.new('/', self, &block)
- @pwd = @root
- @object_space = ObjectSpace.new
- @required = []
- end
-
- def entries(dir)
- e = find(dir)
- require_directory(dir)
- e.entries
- end
-
- def directory?(name)
- return true if (base = basename(name)) == '/'
- e = find(dirname(name))
- return false unless(e)
- e.directory?(base)
- end
-
- def find(path)
- if(/\A\// =~ path)
- thing = @root
- else
- thing = @pwd
- end
- path.scan(/[^\/]+/) do |e|
- break thing = false unless(thing.kind_of?(Directory))
- thing = thing[e]
- end
- thing
- end
-
- def dirname(name)
- if (name = name.tr_s('/', '/')) == '/'
- name
- else
- name[%r"\A.+(?=/[^/]+/?\z)|\A/"] || "."
- end
- end
-
- def basename(name)
- name[%r"(\A/|[^/]+)/*\z", 1]
- end
-
- def split(name)
- [dirname(name), basename(name)]
- end
-
- def join(*parts)
- parts.join('/').gsub(%r{/+}, '/')
- end
-
- def file?(name)
- e = find(dirname(name))
- return false unless(e)
- e.file?(basename(name))
- end
-
- def pwd
- @pwd.path_to
- end
-
- def chdir(to)
- e = find(to)
- require_directory(to)
- @pwd = e
- end
-
- def expand_path(path, base = nil)
- until /\A\// =~ path
- base ||= pwd
- path = join(base, path)
- base = nil
- end
- path.gsub!(%r"(?:/\.)+(?=/)", '')
- nil while path.sub!(%r"/(?!\.\./)[^/]+/\.\.(?=/)", '')
- path.sub!(%r"\A(?:/\.\.)+(?=/)", '')
- path.sub!(%r"(?:\A(/)|/)\.\.?\z", '\1')
- path
- end
-
- def require_directory(path)
- raise Errno::ENOTDIR, path unless(directory?(path))
- end
-
- def require(file)
- return false if(@required.include?(file))
- begin
- e = find(file)
- rescue Errno::ENOENT => ex
- if(/\.rb\Z/ =~ file)
- raise LoadError, file
- end
- e = find(file + '.rb')
- end
- @required << file
- @object_space << e
- true
- rescue Errno::ENOENT
- raise LoadError, file
- end
- end
-
- def test_dir
- inner_dir = nil
- dirs = FileSystem::Directory.new('/', nil) do
- file 'a', nil
- inner_dir = dir 'b'
- end
- assert_equal(inner_dir, dirs['b'])
- end
-
- def test_fs
- fs = FileSystem.new do
- file 'a', nil
- dir 'b'
- end
- assert_equal(['.', '..', 'a', 'b'].sort, fs.entries('/').sort)
- assert(fs.directory?('/'))
- assert(!fs.directory?('/a'))
- assert(!fs.directory?('/bogus'))
- assert(fs.file?('/a'))
- assert(!fs.file?('/'))
- assert(!fs.file?('/bogus'))
- assert(fs.directory?('/b'))
- assert(fs.file?('a'))
- assert(fs.directory?('b'))
- end
-
- def test_fs_sub
- fs = FileSystem.new do
- dir 'a' do
- file 'b', nil
- dir 'c' do
- file 'd', nil
- end
- end
- end
- assert(fs.file?('/a/b'))
- assert(!fs.file?('/a/b/c/d'))
- assert(fs.file?('/a/c/d'))
- end
-
- def test_fs_pwd
- fs = FileSystem.new do
- file 'a', nil
- dir 'b' do
- file 'c', nil
- dir 'd' do
- file 'e', nil
- end
- end
- end
- assert_equal('/', fs.pwd)
- assert_raise(Errno::ENOENT) do
- fs.chdir('bogus')
- end
- assert_raise(Errno::ENOTDIR) do
- fs.chdir('a')
- end
- fs.chdir('b')
- assert_equal('/b', fs.pwd)
- fs.chdir('d')
- assert_equal('/b/d', fs.pwd)
- fs.chdir('..')
- assert_equal('/b', fs.pwd)
- fs.chdir('..')
- assert_equal('/', fs.pwd)
- end
-
- def test_fs_entries
- fs = FileSystem.new do
- file 'a', nil
- dir 'b' do
- file 'c', nil
- file 'd', nil
- end
- file 'e', nil
- dir 'f' do
- file 'g', nil
- dir 'h' do
- file 'i', nil
- end
- end
- end
- assert_equal(['.', '..', 'a', 'b', 'e', 'f'], fs.entries('/').sort)
- assert_equal(['.', '..', 'a', 'b', 'e', 'f'], fs.entries('.').sort)
- assert_equal(['.', '..', 'a', 'b', 'e', 'f'], fs.entries('b/..').sort)
- assert_equal(['.', '..', 'c', 'd'], fs.entries('b').sort)
- assert_raise(Errno::ENOENT) do
- fs.entries('z')
- end
- assert_raise(Errno::ENOTDIR) do
- fs.entries('a')
- end
- fs.chdir('f')
- assert_equal(['.', '..', 'i'], fs.entries('h').sort)
- end
-
- class TestClass1
- end
- class TestClass2
- end
- def test_fs_require
- fs = FileSystem.new do
- file 'test_class1.rb', TestClass1
- dir 'dir' do
- file 'test_class2.rb', TestClass2
- end
- end
- c = []
- fs.object_space.each_object(Class) do |o|
- c << o
- end
- assert_equal([], c)
-
- assert_raise(LoadError) do
- fs.require('bogus')
- end
-
- assert(fs.require('test_class1.rb'))
- assert(!fs.require('test_class1.rb'))
- c = []
- fs.object_space.each_object(Class) do |o|
- c << o
- end
- assert_equal([TestClass1], c)
-
- fs.require('dir/test_class2')
- c = []
- fs.object_space.each_object(Class) do |o|
- c << o
- end
- assert_equal([TestClass1, TestClass2], c)
-
- c = []
- fs.object_space.each_object(Time) do |o|
- c << o
- end
- assert_equal([], c)
- end
-
- def setup
- @t1 = t1 = create_test(1)
- @t2 = t2 = create_test(2)
- @t3 = t3 = create_test(3)
- @t4 = t4 = create_test(4)
- @t5 = t5 = create_test(5)
- @t6 = t6 = create_test(6)
- fs = FileSystem.new do
- file 'test_1.rb', t1
- file 'test_2.rb', t2
- dir 'd1' do
- file 'test_3.rb', t3
- end
- file 't4.rb', t4
- dir 'd2' do
- file 'test_5', t5
- file 'test_6.rb', Time
- end
- file 't6.rb', t6
- end
- fs.require('t6')
- @c = Dir.new(fs, fs, fs.object_space, fs)
- end
-
- def create_test(name)
- t = Class.new(TestCase)
- t.class_eval <<-EOC
- def self.name
- "T\#{#{name}}"
- end
- def test_#{name}a
- end
- def test_#{name}b
- end
- EOC
- t
- end
-
- def test_simple_collect
- expected = TestSuite.new('d1')
- expected << (@t3.suite)
- assert_equal(expected, @c.collect('d1'))
- end
-
- def test_multilevel_collect
- expected = TestSuite.new('.')
- expected << @t1.suite << @t2.suite
- expected << (TestSuite.new('d1') << @t3.suite)
- assert_equal(expected, @c.collect)
- end
-
- def test_collect_file
- expected = [@t1.suite]
- subsuites = []
- @c.collect_file('test_1.rb', subsuites, @c.find_test_cases)
- assert_equal(expected, subsuites)
-
- expected = [@t4.suite]
- subsuites = []
- @c.collect_file('t4.rb', subsuites, @c.find_test_cases)
- assert_equal(expected, subsuites)
- assert_raise(LoadError) do
- @c.collect_file('tloaderr.rb', [], [])
- end
- end
-
- def test_nil_pattern
- expected = TestSuite.new('d2')
- expected << @t5.suite
- @c.pattern.clear
- assert_equal(expected, @c.collect('d2'))
- end
-
- def test_filtering
- expected = TestSuite.new('.')
- expected << @t1.suite
- @c.filter = proc{|t| t.method_name == "test_1a" || t.method_name == "test_1b"}
- assert_equal(expected, @c.collect)
- end
-
- def test_collect_multi
- expected = TestSuite.new('[d1, d2]')
- expected << (TestSuite.new('d1') << @t3.suite)
- expected << (TestSuite.new('d2') << @t5.suite)
- @c.pattern.replace([/\btest_/])
- assert_equal(expected, @c.collect('d1', 'd2'))
- end
- end
- end
- end
-end
diff --git a/test/testunit/collector/test_objectspace.rb b/test/testunit/collector/test_objectspace.rb
deleted file mode 100644
index 74c796eb78..0000000000
--- a/test/testunit/collector/test_objectspace.rb
+++ /dev/null
@@ -1,98 +0,0 @@
-# Author:: Nathaniel Talbott.
-# Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
-# License:: Ruby license.
-
-require 'test/unit'
-require 'test/unit/collector/objectspace'
-
-module Test
- module Unit
- module Collector
- class TC_ObjectSpace < TestCase
- def setup
- @tc1 = Class.new(TestCase) do
- def self.name
- "tc_1"
- end
- def test_1
- end
- def test_2
- end
- end
-
- @tc2 = Class.new(TestCase) do
- def self.name
- "tc_2"
- end
- def test_0
- end
- end
-
- @no_tc = Class.new do
- def test_4
- end
- end
-
- @object_space = {Class => [@tc1, @tc2, @no_tc], String => ['']}
- def @object_space.each_object(type)
- self[type].each{|item| yield(item) }
- end
-
- @c = ObjectSpace.new(@object_space)
- end
-
- def full_suite(name=ObjectSpace::NAME)
- expected = TestSuite.new(name)
- expected << (TestSuite.new(@tc1.name) << @tc1.new("test_1") << @tc1.new("test_2"))
- expected << (TestSuite.new(@tc2.name) << @tc2.new("test_0"))
- end
-
- def empty_suite
- TestSuite.new(ObjectSpace::NAME)
- end
-
- def test_basic_collection
- assert_equal(full_suite("name"), @c.collect("name"))
-
- @c.filter = []
- assert_equal(full_suite("name"), @c.collect("name"))
- end
-
- def test_filtered_collection
- @c.filter = proc{false}
- assert_equal(empty_suite, @c.collect)
-
- @c.filter = proc{true}
- assert_equal(full_suite, @c.collect)
-
- @c.filter = proc{nil}
- assert_equal(full_suite, @c.collect)
-
- @c.filter = [proc{false}, proc{true}]
- assert_equal(empty_suite, @c.collect)
-
- @c.filter = [proc{true}, proc{false}]
- assert_equal(full_suite, @c.collect)
-
- @c.filter = [proc{nil}, proc{false}]
- assert_equal(empty_suite, @c.collect)
-
- @c.filter = [proc{nil}, proc{true}]
- assert_equal(full_suite, @c.collect)
-
- expected = TestSuite.new(ObjectSpace::NAME)
- expected << (TestSuite.new(@tc1.name) << @tc1.new("test_1"))
- expected << (TestSuite.new(@tc2.name) << @tc2.new("test_0"))
- @c.filter = proc{|test| ["test_1", "test_0"].include?(test.method_name)}
- assert_equal(expected, @c.collect)
-
- expected = TestSuite.new(ObjectSpace::NAME)
- expected << (TestSuite.new(@tc1.name) << @tc1.new("test_1"))
- expected << (TestSuite.new(@tc2.name) << @tc2.new("test_0"))
- @c.filter = [proc{|t| t.method_name == "test_1" ? true : nil}, proc{|t| t.method_name == "test_0" ? true : nil}, proc{false}]
- assert_equal(expected, @c.collect)
- end
- end
- end
- end
-end
diff --git a/test/testunit/test_assertions.rb b/test/testunit/test_assertions.rb
deleted file mode 100644
index d39c089b39..0000000000
--- a/test/testunit/test_assertions.rb
+++ /dev/null
@@ -1,543 +0,0 @@
-# Author:: Nathaniel Talbott.
-# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
-# License:: Ruby license.
-
-require 'test/unit'
-
-module Test
- module Unit
- class TC_Assertions < TestCase
- def check(value, message="")
- add_assertion
- if (!value)
- raise AssertionFailedError.new(message)
- end
- end
-
- def check_assertions(expect_fail, expected_message="", return_value_expected=false)
- @actual_assertion_count = 0
- failed = true
- actual_message = nil
- @catch_assertions = true
- return_value = nil
- begin
- return_value = yield
- failed = false
- rescue AssertionFailedError => error
- actual_message = error.message
- end
- @catch_assertions = false
- check(expect_fail == failed, (expect_fail ? "Should have failed, but didn't" : "Should not have failed, but did with message\n<#{actual_message}>"))
- check(1 == @actual_assertion_count, "Should have made one assertion but made <#{@actual_assertion_count}>")
- if (expect_fail)
- case expected_message
- when String
- check(actual_message == expected_message, "Should have the correct message.\n<#{expected_message.inspect}> expected but was\n<#{actual_message.inspect}>")
- when Regexp
- check(actual_message =~ expected_message, "The message should match correctly.\n</#{expected_message.source}/> expected to match\n<#{actual_message.inspect}>")
- else
- check(false, "Incorrect expected message type in assert_nothing_failed")
- end
- else
- if (!return_value_expected)
- check(return_value.nil?, "Should not return a value but returned <#{return_value}>")
- else
- check(!return_value.nil?, "Should return a value")
- end
- end
- return return_value
- end
-
- def check_nothing_fails(return_value_expected=false, &proc)
- check_assertions(false, "", return_value_expected, &proc)
- end
-
- def check_fails(expected_message="", &proc)
- check_assertions(true, expected_message, &proc)
- end
-
- def test_assert_block
- check_nothing_fails {
- assert_block {true}
- }
- check_nothing_fails {
- assert_block("successful assert_block") {true}
- }
- check_nothing_fails {
- assert_block("successful assert_block") {true}
- }
- check_fails("assert_block failed.") {
- assert_block {false}
- }
- check_fails("failed assert_block") {
- assert_block("failed assert_block") {false}
- }
- end
-
- def test_assert
- check_nothing_fails{assert("a")}
- check_nothing_fails{assert(true)}
- check_nothing_fails{assert(true, "successful assert")}
- check_fails("<nil> is not true."){assert(nil)}
- check_fails("<false> is not true."){assert(false)}
- check_fails("failed assert.\n<false> is not true."){assert(false, "failed assert")}
- end
-
- def test_assert_equal
- check_nothing_fails {
- assert_equal("string1", "string1")
- }
- check_nothing_fails {
- assert_equal( "string1", "string1", "successful assert_equal")
- }
- check_nothing_fails {
- assert_equal("string1", "string1", "successful assert_equal")
- }
- check_fails(%Q{<"string1"> expected but was\n<"string2">.}) {
- assert_equal("string1", "string2")
- }
- check_fails(%Q{failed assert_equal.\n<"string1"> expected but was\n<"string2">.}) {
- assert_equal("string1", "string2", "failed assert_equal")
- }
- check_fails(%Q{<"1"> expected but was\n<1>.}) do
- assert_equal("1", 1)
- end
- end
-
- def test_assert_raise
- return_value = nil
- check_nothing_fails(true) {
- return_value = assert_raise(RuntimeError) {
- raise "Error"
- }
- }
- check(return_value.kind_of?(Exception), "Should have returned the exception from a successful assert_raise")
- check(return_value.message == "Error", "Should have returned the correct exception from a successful assert_raise")
- check_nothing_fails(true) {
- assert_raise(ArgumentError, "successful assert_raise") {
- raise ArgumentError.new("Error")
- }
- }
- check_nothing_fails(true) {
- assert_raise(RuntimeError) {
- raise "Error"
- }
- }
- check_nothing_fails(true) {
- assert_raise(RuntimeError, "successful assert_raise") {
- raise "Error"
- }
- }
- check_fails("<RuntimeError> exception expected but none was thrown.") {
- assert_raise(RuntimeError) {
- 1 + 1
- }
- }
- check_fails(%r{\Afailed assert_raise.\n<ArgumentError> exception expected but was\nClass: <RuntimeError>\nMessage: <"Error">\n---Backtrace---\n.+\n---------------\Z}m) {
- assert_raise(ArgumentError, "failed assert_raise") {
- raise "Error"
- }
- }
- check_fails("Should expect a class of exception, Object.\n<false> is not true.") {
- assert_nothing_raised(Object) {
- 1 + 1
- }
- }
-
- exceptions = [ArgumentError, TypeError]
- modules = [Math, Comparable]
- rescues = exceptions + modules
- exceptions.each do |exc|
- check_nothing_fails(true) {
- return_value = assert_raise(*rescues) {
- raise exc, "Error"
- }
- }
- check(return_value.instance_of?(exc), "Should have returned #{exc} but was #{return_value.class}")
- check(return_value.message == "Error", "Should have returned the correct exception from a successful assert_raise")
- end
- modules.each do |mod|
- check_nothing_fails(true) {
- return_value = assert_raise(*rescues) {
- raise Exception.new("Error").extend(mod)
- }
- }
- check(mod === return_value, "Should have returned #{mod}")
- check(return_value.message == "Error", "Should have returned the correct exception from a successful assert_raise")
- end
- check_fails("<[ArgumentError, TypeError, Math, Comparable]> exception expected but none was thrown.") {
- assert_raise(*rescues) {
- 1 + 1
- }
- }
- check_fails(%r{\Afailed assert_raise.
-<\[ArgumentError, TypeError\]> exception expected but was
-Class: <RuntimeError>
-Message: <"Error">
----Backtrace---
-.+
----------------\Z}m) {
- assert_raise(ArgumentError, TypeError, "failed assert_raise") {
- raise "Error"
- }
- }
- end
-
- def test_assert_instance_of
- check_nothing_fails {
- assert_instance_of(String, "string")
- }
- check_nothing_fails {
- assert_instance_of(String, "string", "successful assert_instance_of")
- }
- check_nothing_fails {
- assert_instance_of(String, "string", "successful assert_instance_of")
- }
- check_fails(%Q{<"string"> expected to be an instance of\n<Hash> but was\n<String>.}) {
- assert_instance_of(Hash, "string")
- }
- check_fails(%Q{failed assert_instance_of.\n<"string"> expected to be an instance of\n<Hash> but was\n<String>.}) {
- assert_instance_of(Hash, "string", "failed assert_instance_of")
- }
- end
-
- def test_assert_nil
- check_nothing_fails {
- assert_nil(nil)
- }
- check_nothing_fails {
- assert_nil(nil, "successful assert_nil")
- }
- check_nothing_fails {
- assert_nil(nil, "successful assert_nil")
- }
- check_fails(%Q{<nil> expected but was\n<"string">.}) {
- assert_nil("string")
- }
- check_fails(%Q{failed assert_nil.\n<nil> expected but was\n<"string">.}) {
- assert_nil("string", "failed assert_nil")
- }
- end
-
- def test_assert_not_nil
- check_nothing_fails{assert_not_nil(false)}
- check_nothing_fails{assert_not_nil(false, "message")}
- check_fails("<nil> expected to not be nil."){assert_not_nil(nil)}
- check_fails("message.\n<nil> expected to not be nil.") {assert_not_nil(nil, "message")}
- end
-
- def test_assert_kind_of
- check_nothing_fails {
- assert_kind_of(Module, Array)
- }
- check_nothing_fails {
- assert_kind_of(Object, "string", "successful assert_kind_of")
- }
- check_nothing_fails {
- assert_kind_of(Object, "string", "successful assert_kind_of")
- }
- check_nothing_fails {
- assert_kind_of(Comparable, 1)
- }
- check_fails(%Q{<"string">\nexpected to be kind_of?\n<Class> but was\n<String>.}) {
- assert_kind_of(Class, "string")
- }
- check_fails(%Q{failed assert_kind_of.\n<"string">\nexpected to be kind_of?\n<Class> but was\n<String>.}) {
- assert_kind_of(Class, "string", "failed assert_kind_of")
- }
- end
-
- def test_assert_match
- check_nothing_fails {
- assert_match(/strin./, "string")
- }
- check_nothing_fails {
- assert_match("strin", "string")
- }
- check_nothing_fails {
- assert_match(/strin./, "string", "successful assert_match")
- }
- check_nothing_fails {
- assert_match(/strin./, "string", "successful assert_match")
- }
- check_fails(%Q{<"string"> expected to be =~\n</slin./>.}) {
- assert_match(/slin./, "string")
- }
- check_fails(%Q{<"string"> expected to be =~\n</strin\\./>.}) {
- assert_match("strin.", "string")
- }
- check_fails(%Q{failed assert_match.\n<"string"> expected to be =~\n</slin./>.}) {
- assert_match(/slin./, "string", "failed assert_match")
- }
- end
-
- def test_assert_same
- thing = "thing"
- check_nothing_fails {
- assert_same(thing, thing)
- }
- check_nothing_fails {
- assert_same(thing, thing, "successful assert_same")
- }
- check_nothing_fails {
- assert_same(thing, thing, "successful assert_same")
- }
- thing2 = "thing"
- check_fails(%Q{<"thing">\nwith id <#{thing.__id__}> expected to be equal? to\n<"thing">\nwith id <#{thing2.__id__}>.}) {
- assert_same(thing, thing2)
- }
- check_fails(%Q{failed assert_same.\n<"thing">\nwith id <#{thing.__id__}> expected to be equal? to\n<"thing">\nwith id <#{thing2.__id__}>.}) {
- assert_same(thing, thing2, "failed assert_same")
- }
- end
-
- def test_assert_nothing_raised
- check_nothing_fails {
- assert_nothing_raised {
- 1 + 1
- }
- }
- check_nothing_fails {
- assert_nothing_raised("successful assert_nothing_raised") {
- 1 + 1
- }
- }
- check_nothing_fails {
- assert_nothing_raised("successful assert_nothing_raised") {
- 1 + 1
- }
- }
- check_nothing_fails {
- begin
- assert_nothing_raised(RuntimeError, StandardError, Comparable, "successful assert_nothing_raised") {
- raise ZeroDivisionError.new("ArgumentError")
- }
- rescue ZeroDivisionError
- end
- }
- check_fails("Should expect a class of exception, Object.\n<false> is not true.") {
- assert_nothing_raised(Object) {
- 1 + 1
- }
- }
- check_fails(%r{\AException raised:\nClass: <RuntimeError>\nMessage: <"Error">\n---Backtrace---\n.+\n---------------\Z}m) {
- assert_nothing_raised {
- raise "Error"
- }
- }
- check_fails(%r{\Afailed assert_nothing_raised\.\nException raised:\nClass: <RuntimeError>\nMessage: <"Error">\n---Backtrace---\n.+\n---------------\Z}m) {
- assert_nothing_raised("failed assert_nothing_raised") {
- raise "Error"
- }
- }
- check_fails(%r{\AException raised:\nClass: <RuntimeError>\nMessage: <"Error">\n---Backtrace---\n.+\n---------------\Z}m) {
- assert_nothing_raised(StandardError, RuntimeError) {
- raise "Error"
- }
- }
- check_fails("Failure.") do
- assert_nothing_raised do
- flunk("Failure")
- end
- end
- end
-
- def test_flunk
- check_fails("Flunked.") {
- flunk
- }
- check_fails("flunk message.") {
- flunk("flunk message")
- }
- end
-
- def test_assert_not_same
- thing = "thing"
- thing2 = "thing"
- check_nothing_fails {
- assert_not_same(thing, thing2)
- }
- check_nothing_fails {
- assert_not_same(thing, thing2, "message")
- }
- check_fails(%Q{<"thing">\nwith id <#{thing.__id__}> expected to not be equal? to\n<"thing">\nwith id <#{thing.__id__}>.}) {
- assert_not_same(thing, thing)
- }
- check_fails(%Q{message.\n<"thing">\nwith id <#{thing.__id__}> expected to not be equal? to\n<"thing">\nwith id <#{thing.__id__}>.}) {
- assert_not_same(thing, thing, "message")
- }
- end
-
- def test_assert_not_equal
- check_nothing_fails {
- assert_not_equal("string1", "string2")
- }
- check_nothing_fails {
- assert_not_equal("string1", "string2", "message")
- }
- check_fails(%Q{<"string"> expected to be != to\n<"string">.}) {
- assert_not_equal("string", "string")
- }
- check_fails(%Q{message.\n<"string"> expected to be != to\n<"string">.}) {
- assert_not_equal("string", "string", "message")
- }
- end
-
- def test_assert_no_match
- check_nothing_fails{assert_no_match(/sling/, "string")}
- check_nothing_fails{assert_no_match(/sling/, "string", "message")}
- check_fails(%Q{The first argument to assert_no_match should be a Regexp.\n<"asdf"> expected to be an instance of\n<Regexp> but was\n<String>.}) do
- assert_no_match("asdf", "asdf")
- end
- check_fails(%Q{</string/> expected to not match\n<"string">.}) do
- assert_no_match(/string/, "string")
- end
- check_fails(%Q{message.\n</string/> expected to not match\n<"string">.}) do
- assert_no_match(/string/, "string", "message")
- end
- end
-
- def test_assert_throws
- check_nothing_fails {
- assert_throws(:thing, "message") {
- throw :thing
- }
- }
- check_nothing_fails {
- assert_throws(0, "message") {
- throw 0
- }
- }
- obj = Object.new
- check_nothing_fails {
- assert_throws(obj, "message") {
- throw obj
- }
- }
- check_fails("message.\n<\"string\"> expected to be thrown but\n<\"string\"> was thrown.") {
- assert_throws("string", "message") {
- throw "string"
- }
- }
- check_fails("message.\n<:thing> expected to be thrown but\n<:thing2> was thrown.") {
- assert_throws(:thing, "message") {
- throw :thing2
- }
- }
- check_fails("message.\n<:thing> should have been thrown.") {
- assert_throws(:thing, "message") {
- 1 + 1
- }
- }
- end
-
- def test_assert_nothing_thrown
- check_nothing_fails {
- assert_nothing_thrown("message") {
- 1 + 1
- }
- }
- check_fails("message.\n<:thing> was thrown when nothing was expected.") {
- assert_nothing_thrown("message") {
- throw :thing
- }
- }
- end
-
- def test_assert_operator
- check_nothing_fails {
- assert_operator("thing", :==, "thing", "message")
- }
- check_fails(%Q{<0.15>\ngiven as the operator for #assert_operator must be a Symbol or #respond_to?(:to_str).}) do
- assert_operator("thing", 0.15, "thing")
- end
- check_fails(%Q{message.\n<"thing1"> expected to be\n==\n<"thing2">.}) {
- assert_operator("thing1", :==, "thing2", "message")
- }
- end
-
- def test_assert_respond_to
- check_nothing_fails {
- assert_respond_to("thing", :to_s, "message")
- }
- check_nothing_fails {
- assert_respond_to("thing", "to_s", "message")
- }
- check_fails("<0.15>\ngiven as the method name argument to #assert_respond_to must be a Symbol or #respond_to?(:to_str).") {
- assert_respond_to("thing", 0.15)
- }
- check_fails("message.\n<:symbol>\nof type <Symbol>\nexpected to respond_to?<:non_existent>.") {
- assert_respond_to(:symbol, :non_existent, "message")
- }
- end
-
- def test_assert_in_delta
- check_nothing_fails {
- assert_in_delta(1.4, 1.4, 0)
- }
- check_nothing_fails {
- assert_in_delta(0.5, 0.4, 0.1, "message")
- }
- check_nothing_fails {
- float_thing = Object.new
- def float_thing.to_f
- 0.2
- end
- assert_in_delta(0.1, float_thing, 0.1)
- }
- check_fails("message.\n<0.5> and\n<0.4> expected to be within\n<0.05> of each other.") {
- assert_in_delta(0.5, 0.4, 0.05, "message")
- }
- check_fails(%r{The arguments must respond to to_f; the first float did not\.\n<.+>\nof type <Object>\nexpected to respond_to\?<:to_f>.}) {
- assert_in_delta(Object.new, 0.4, 0.1)
- }
- check_fails("The delta should not be negative.\n<-0.1> expected to be\n>=\n<0.0>.") {
- assert_in_delta(0.5, 0.4, -0.1, "message")
- }
- end
-
- def test_assert_send
- object = Object.new
- class << object
- def return_argument(argument, bogus)
- return argument
- end
- end
- check_nothing_fails {
- assert_send([object, :return_argument, true, "bogus"], "message")
- }
- check_fails(%r{\Amessage\.\n<.+> expected to respond to\n<return_argument\(\[false, "bogus"\]\)> with a true value.\Z}) {
- assert_send([object, :return_argument, false, "bogus"], "message")
- }
- end
-
- def test_condition_invariant
- object = Object.new
- def object.inspect
- @changed = true
- end
- def object.==(other)
- @changed ||= false
- return (!@changed)
- end
- check_nothing_fails {
- assert_equal(object, object, "message")
- }
- end
-
- def add_failure(message, location=caller)
- if (!@catch_assertions)
- super
- end
- end
-
- def add_assertion
- if (!@catch_assertions)
- super
- else
- @actual_assertion_count += 1
- end
- end
- end
- end
-end
diff --git a/test/testunit/test_error.rb b/test/testunit/test_error.rb
deleted file mode 100644
index 56b275b362..0000000000
--- a/test/testunit/test_error.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# Author:: Nathaniel Talbott.
-# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
-# License:: Ruby license.
-
-require 'test/unit'
-
-module Test
- module Unit
- class TC_Error < TestCase
- TF_Exception = Struct.new('TF_Exception', :message, :backtrace)
- def test_display
- ex = TF_Exception.new("message1\nmessage2", ['line1', 'line2'])
- e = Error.new("name", ex)
- assert_equal("name: #{TF_Exception.name}: message1", e.short_display)
- assert_equal(<<EOM.strip, e.long_display)
-Error:
-name:
-Struct::TF_Exception: message1
-message2
- line1
- line2
-EOM
- end
- end
- end
-end
diff --git a/test/testunit/test_failure.rb b/test/testunit/test_failure.rb
deleted file mode 100644
index 164f942476..0000000000
--- a/test/testunit/test_failure.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# Author:: Nathaniel Talbott.
-# Copyright:: Copyright (c) 2003 Nathaniel Talbott. All rights reserved.
-# License:: Ruby license.
-
-require 'test/unit'
-require 'test/unit/failure'
-
-module Test::Unit
- class TestFailure < TestCase
- def test_display
- f = Failure.new("name", [%q{location:1 in 'l'}], "message1\nmessage2")
- assert_equal("name: message1", f.short_display)
- assert_equal(<<EOM.strip, f.long_display)
-Failure:
-name [location:1]:
-message1
-message2
-EOM
-
- f = Failure.new("name", [%q{location1:2 in 'l1'}, 'location2:1', %q{location3:3 in 'l3'}], "message1\nmessage2")
- assert_equal("name: message1", f.short_display)
- assert_equal(<<EOM.strip, f.long_display)
-Failure:
-name
- [location1:2 in 'l1'
- location2:1
- location3:3 in 'l3']:
-message1
-message2
-EOM
- end
- end
-end
diff --git a/test/testunit/test_testcase.rb b/test/testunit/test_testcase.rb
deleted file mode 100644
index 2934a92fef..0000000000
--- a/test/testunit/test_testcase.rb
+++ /dev/null
@@ -1,275 +0,0 @@
-# Author:: Nathaniel Talbott.
-# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
-# License:: Ruby license.
-
-require 'test/unit'
-
-module Test
- module Unit
- class TC_TestCase < TestCase
- def test_creation
- tc = Class.new(TestCase) do
- def test_with_arguments(arg1, arg2)
- end
- end
-
- caught = true
- catch(:invalid_test) do
- tc.new(:test_with_arguments)
- caught = false
- end
- check("Should have caught an invalid test when there are arguments", caught)
-
- caught = true
- catch(:invalid_test) do
- tc.new(:non_existent_test)
- caught = false
- end
- check("Should have caught an invalid test when the method does not exist", caught)
- end
-
- def setup
- @tc_failure_error = Class.new(TestCase) do
- def test_failure
- assert_block("failure") { false }
- end
- def test_error
- 1 / 0
- end
- def test_nested_failure
- nested
- end
- def nested
- assert_block("nested"){false}
- end
- def return_passed?
- return passed?
- end
- end
-
- def @tc_failure_error.name
- "TC_FailureError"
- end
- end
-
- def test_add_failed_assertion
- test_case = @tc_failure_error.new(:test_failure)
- check("passed? should start out true", test_case.return_passed?)
- result = TestResult.new
- called = false
- result.add_listener(TestResult::FAULT) {
- | fault |
- check("Should have a Failure", fault.instance_of?(Failure))
- check("The Failure should have the correct message", "failure" == fault.message)
- check("The Failure should have the correct test_name (was <#{fault.test_name}>)", fault.test_name == "test_failure(TC_FailureError)")
- r = /\A.*#{Regexp.escape(File.basename(__FILE__))}:\d+:in `test_failure'\Z/
-
- location = fault.location
- check("The location should be an array", location.kind_of?(Array))
- check("The location should have two lines (was: <#{location.inspect}>)", location.size == 2)
- check("The Failure should have the correct location (was <#{location[0].inspect}>, expected <#{r.inspect}>)", r =~ location[0])
- called = true
- }
- progress = []
- test_case.run(result) { |*arguments| progress << arguments }
- check("The failure should have triggered the listener", called)
- check("The failure should have set passed?", !test_case.return_passed?)
- check("The progress block should have been updated correctly", [[TestCase::STARTED, test_case.name], [TestCase::FINISHED, test_case.name]] == progress)
- end
-
- def test_add_failure_nested
- test_case = @tc_failure_error.new(:test_nested_failure)
- check("passed? should start out true", test_case.return_passed?)
-
- result = TestResult.new
- called = false
- result.add_listener(TestResult::FAULT) {
- | fault |
- check("Should have a Failure", fault.instance_of?(Failure))
- check("The Failure should have the correct message", "nested" == fault.message)
- check("The Failure should have the correct test_name (was <#{fault.test_name}>)", fault.test_name == "test_nested_failure(TC_FailureError)")
- r =
-
- location = fault.location
- check("The location should be an array", location.kind_of?(Array))
- check("The location should have the correct number of lines (was: <#{location.inspect}>)", location.size == 3)
- check("The Failure should have the correct location (was <#{location[0].inspect}>)", /\A.*#{Regexp.escape(File.basename(__FILE__))}:\d+:in `nested'\Z/ =~ location[0])
- check("The Failure should have the correct location (was <#{location[1].inspect}>)", /\A.*#{Regexp.escape(File.basename(__FILE__))}:\d+:in `test_nested_failure'\Z/ =~ location[1])
- called = true
- }
- test_case.run(result){}
- check("The failure should have triggered the listener", called)
- end
-
- def test_add_error
- test_case = @tc_failure_error.new(:test_error)
- check("passed? should start out true", test_case.return_passed?)
- result = TestResult.new
- called = false
- result.add_listener(TestResult::FAULT) {
- | fault |
- check("Should have a TestError", fault.instance_of?(Error))
- check("The Error should have the correct message", "ZeroDivisionError: divided by 0" == fault.message)
- check("The Error should have the correct test_name", "test_error(TC_FailureError)" == fault.test_name)
- check("The Error should have the correct exception", fault.exception.instance_of?(ZeroDivisionError))
- called = true
- }
- test_case.run(result) {}
- check("The error should have triggered the listener", called)
- check("The error should have set passed?", !test_case.return_passed?)
- end
-
- def test_no_tests
- suite = TestCase.suite
- check("Should have a test suite", suite.instance_of?(TestSuite))
- check("Should have one test", suite.size == 1)
- check("Should have the default test", suite.tests.first.name == "default_test(Test::Unit::TestCase)")
-
- result = TestResult.new
- suite.run(result) {}
- check("Should have had one test run", result.run_count == 1)
- check("Should have had one test failure", result.failure_count == 1)
- check("Should have had no errors", result.error_count == 0)
- end
-
- def test_suite
- tc = Class.new(TestCase) do
- def test_succeed
- assert_block {true}
- end
- def test_fail
- assert_block {false}
- end
- def test_error
- 1/0
- end
- def dont_run
- assert_block {true}
- end
- def test_dont_run(argument)
- assert_block {true}
- end
- def test
- assert_block {true}
- end
- end
-
- suite = tc.suite
- check("Should have a test suite", suite.instance_of?(TestSuite))
- check("Should have three tests", suite.size == 3)
-
- result = TestResult.new
- suite.run(result) {}
- check("Should have had three test runs", result.run_count == 3)
- check("Should have had one test failure", result.failure_count == 1)
- check("Should have had one test error", result.error_count == 1)
- end
-
-
- def test_setup_teardown
- tc = Class.new(TestCase) do
- attr_reader(:setup_called, :teardown_called)
- def initialize(test)
- super(test)
- @setup_called = false
- @teardown_called = false
- end
- def setup
- @setup_called = true
- end
- def teardown
- @teardown_called = true
- end
- def test_succeed
- assert_block {true}
- end
- def test_fail
- assert_block {false}
- end
- def test_error
- raise "Error!"
- end
- end
- result = TestResult.new
-
- test = tc.new(:test_succeed)
- test.run(result) {}
- check("Should have called setup the correct number of times", test.setup_called)
- check("Should have called teardown the correct number of times", test.teardown_called)
-
- test = tc.new(:test_fail)
- test.run(result) {}
- check("Should have called setup the correct number of times", test.setup_called)
- check("Should have called teardown the correct number of times", test.teardown_called)
-
- test = tc.new(:test_error)
- test.run(result) {}
- check("Should have called setup the correct number of times", test.setup_called)
- check("Should have called teardown the correct number of times", test.teardown_called)
-
- check("Should have had two test runs", result.run_count == 3)
- check("Should have had a test failure", result.failure_count == 1)
- check("Should have had a test error", result.error_count == 1)
- end
-
- def test_assertion_failed_not_called
- tc = Class.new(TestCase) do
- def test_thing
- raise AssertionFailedError.new
- end
- end
-
- suite = tc.suite
- check("Should have one test", suite.size == 1)
- result = TestResult.new
- suite.run(result) {}
- check("Should have had one test run", result.run_count == 1)
- check("Should have had one assertion failure", result.failure_count == 1)
- check("Should not have any assertion errors but had #{result.error_count}", result.error_count == 0)
- end
-
- def test_equality
- tc1 = Class.new(TestCase) do
- def test_1
- end
- def test_2
- end
- end
-
- tc2 = Class.new(TestCase) do
- def test_1
- end
- end
-
- test1 = tc1.new('test_1')
- test2 = tc1.new('test_1')
- check("Should be equal", test1 == test2)
- check("Should be equal", test2 == test1)
-
- test1 = tc1.new('test_2')
- check("Should not be equal", test1 != test2)
- check("Should not be equal", test2 != test1)
-
- test2 = tc1.new('test_2')
- check("Should be equal", test1 == test2)
- check("Should be equal", test2 == test1)
-
- test1 = tc1.new('test_1')
- test2 = tc2.new('test_1')
- check("Should not be equal", test1 != test2)
- check("Should not be equal", test2 != test1)
-
-
- check("Should not be equal", test1 != Object.new)
- check("Should not be equal", Object.new != test1)
- end
-
- def check(message, passed)
- @_result.add_assertion
- if ! passed
- raise AssertionFailedError.new(message)
- end
- end
- end
- end
-end
diff --git a/test/testunit/test_testresult.rb b/test/testunit/test_testresult.rb
deleted file mode 100644
index 95d631a082..0000000000
--- a/test/testunit/test_testresult.rb
+++ /dev/null
@@ -1,104 +0,0 @@
-# Author:: Nathaniel Talbott.
-# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
-# License:: Ruby license.
-
-require 'test/unit/testcase'
-require 'test/unit/testresult'
-
-module Test
- module Unit
- class TC_TestResult < TestCase
- def setup
- @my_result = TestResult.new
- @my_result.add_assertion()
- @my_result.add_failure("")
- @my_result.add_error("")
- end
- def test_result_changed_notification
- called1 = false
- @my_result.add_listener( TestResult::CHANGED) {
- |result|
- assert_block("The result should be correct") { result == @my_result }
- called1 = true
- }
- @my_result.add_assertion
- assert_block("Should have been notified when the assertion happened") { called1 }
-
- called1, called2 = false, false
- @my_result.add_listener( TestResult::CHANGED) {
- |result|
- assert_block("The result should be correct") { result == @my_result }
- called2 = true
- }
- @my_result.add_assertion
- assert_block("Both listeners should have been notified for a success") { called1 && called2 }
-
- called1, called2 = false, false
- @my_result.add_failure("")
- assert_block("Both listeners should have been notified for a failure") { called1 && called2 }
-
- called1, called2 = false, false
- @my_result.add_error("")
- assert_block("Both listeners should have been notified for an error") { called1 && called2 }
-
- called1, called2 = false, false
- @my_result.add_run
- assert_block("Both listeners should have been notified for a run") { called1 && called2 }
- end
- def test_fault_notification
- called1 = false
- fault = "fault"
- @my_result.add_listener(TestResult::FAULT) {
- | passed_fault |
- assert_block("The fault should be correct") { passed_fault == fault }
- called1 = true
- }
-
- @my_result.add_assertion
- assert_block("Should not have been notified when the assertion happened") { !called1 }
-
- @my_result.add_failure(fault)
- assert_block("Should have been notified when the failure happened") { called1 }
-
- called1, called2 = false, false
- @my_result.add_listener(TestResult::FAULT) {
- | passed_fault |
- assert_block("The fault should be correct") { passed_fault == fault }
- called2 = true
- }
-
- @my_result.add_assertion
- assert_block("Neither listener should have been notified for a success") { !(called1 || called2) }
-
- called1, called2 = false, false
- @my_result.add_failure(fault)
- assert_block("Both listeners should have been notified for a failure") { called1 && called2 }
-
- called1, called2 = false, false
- @my_result.add_error(fault)
- assert_block("Both listeners should have been notified for an error") { called1 && called2 }
-
- called1, called2 = false, false
- @my_result.add_run
- assert_block("Neither listener should have been notified for a run") { !(called1 || called2) }
- end
- def test_passed?
- result = TestResult.new
- assert(result.passed?, "An empty result should have passed")
-
- result.add_assertion
- assert(result.passed?, "Adding an assertion should not cause the result to not pass")
-
- result.add_run
- assert(result.passed?, "Adding a run should not cause the result to not pass")
-
- result.add_failure("")
- assert(!result.passed?, "Adding a failed assertion should cause the result to not pass")
-
- result = TestResult.new
- result.add_error("")
- assert(!result.passed?, "Adding an error should cause the result to not pass")
- end
- end
- end
-end
diff --git a/test/testunit/test_testsuite.rb b/test/testunit/test_testsuite.rb
deleted file mode 100644
index 5f6631d3eb..0000000000
--- a/test/testunit/test_testsuite.rb
+++ /dev/null
@@ -1,129 +0,0 @@
-# Author:: Nathaniel Talbott.
-# Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
-# License:: Ruby license.
-
-require 'test/unit'
-
-module Test
- module Unit
- class TC_TestSuite < TestCase
- def setup
- @testcase1 = Class.new(TestCase) do
- def test_succeed1
- assert_block { true }
- end
- def test_fail
- assert_block { false }
- end
- end
-
- @testcase2 = Class.new(TestCase) do
- def test_succeed2
- assert_block { true }
- end
- def test_error
- raise
- end
- end
- end
-
- def test_add
- s = TestSuite.new
- assert_equal(s, s << self.class.new("test_add"))
- end
-
- def test_delete
- s = TestSuite.new
- t1 = self.class.new("test_delete")
- s << t1
- t2 = self.class.new("test_add")
- s << t2
- assert_equal(t1, s.delete(t1))
- assert_nil(s.delete(t1))
- assert_equal(TestSuite.new << t2, s)
- end
-
- def test_size
- suite = TestSuite.new
- suite2 = TestSuite.new
- suite2 << self.class.new("test_size")
- suite << suite2
- suite << self.class.new("test_size")
- assert_equal(2, suite.size, "The count should be correct")
- end
-
- def test_run
- progress = []
- suite = @testcase1.suite
- result = TestResult.new
- suite.run(result) { |*values| progress << values }
-
- assert_equal(2, result.run_count, "Should have had four test runs")
- assert_equal(1, result.failure_count, "Should have had one test failure")
- assert_equal(0, result.error_count, "Should have had one test error")
- assert_equal([[TestSuite::STARTED, suite.name],
- [TestCase::STARTED, "test_fail(#{suite.name})"],
- [TestCase::FINISHED, "test_fail(#{suite.name})"],
- [TestCase::STARTED, "test_succeed1(#{suite.name})"],
- [TestCase::FINISHED, "test_succeed1(#{suite.name})"],
- [TestSuite::FINISHED, suite.name]],
- progress, "Should have had the correct progress")
-
- suite = TestSuite.new
- suite << @testcase1.suite
- suite << @testcase2.suite
- result = TestResult.new
- progress = []
- suite.run(result) { |*values| progress << values }
-
- assert_equal(4, result.run_count, "Should have had four test runs")
- assert_equal(1, result.failure_count, "Should have had one test failure")
- assert_equal(1, result.error_count, "Should have had one test error")
- assert_equal(14, progress.size, "Should have had the correct number of progress calls")
- end
-
- def test_empty?
- assert(TestSuite.new.empty?, "A new test suite should be empty?")
- assert(!@testcase2.suite.empty?, "A test suite with tests should not be empty")
- end
-
- def test_equality
- suite1 = TestSuite.new
- suite2 = TestSuite.new
- assert_equal(suite1, suite2)
- assert_equal(suite2, suite1)
-
- suite1 = TestSuite.new('name')
- assert_not_equal(suite1, suite2)
- assert_not_equal(suite2, suite1)
-
- suite2 = TestSuite.new('name')
- assert_equal(suite1, suite2)
- assert_equal(suite2, suite1)
-
- suite1 << 'test'
- assert_not_equal(suite1, suite2)
- assert_not_equal(suite2, suite1)
-
- suite2 << 'test'
- assert_equal(suite1, suite2)
- assert_equal(suite2, suite1)
-
- suite2 = Object.new
- class << suite2
- def name
- 'name'
- end
- def tests
- ['test']
- end
- end
- assert_not_equal(suite1, suite2)
- assert_not_equal(suite2, suite1)
-
- assert_not_equal(suite1, Object.new)
- assert_not_equal(Object.new, suite1)
- end
- end
- end
-end
diff --git a/test/testunit/util/test_backtracefilter.rb b/test/testunit/util/test_backtracefilter.rb
deleted file mode 100644
index d4e40ea6ab..0000000000
--- a/test/testunit/util/test_backtracefilter.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-require 'test/unit'
-
-require 'test/unit/util/backtracefilter'
-
-module Test::Unit::Util
- class TestBacktraceFilter < Test::Unit::TestCase
- include BacktraceFilter
-
- def test_filter_backtrace
- backtrace = [%q{C:\some\old\path/test/unit/assertions.rb:44:in 'assert'},
- %q{tc_thing.rb:4:in 'a'},
- %q{tc_thing.rb:4:in 'test_stuff'},
- %q{C:\some\old\path/test/unit/testcase.rb:44:in 'send'},
- %q{C:\some\old\path\test\unit\testcase.rb:44:in 'run'},
- %q{C:\some\old\path\test\unit.rb:44:in 'run'},
- %q{tc_thing.rb:3}]
- assert_equal(backtrace[1..2], filter_backtrace(backtrace, %q{C:\some\old\path\test\unit}), "Should filter out all TestUnit-specific lines")
-
-backtrace = [%q{tc_thing.rb:4:in 'a'},
- %q{tc_thing.rb:4:in 'test_stuff'},
- %q{tc_thing.rb:3}]
- assert_equal(backtrace, filter_backtrace(backtrace, %q{C:\some\old\path\test\unit}), "Shouldn't filter too much")
-
- backtrace = [%q{C:\some\old\path/test/unit/assertions.rb:44:in 'assert'},
- %q{tc_thing.rb:4:in 'a'},
- %q{tc_thing.rb:4:in 'test_stuff'},
- %q{tc_thing.rb:3}]
- assert_equal(backtrace[1..3], filter_backtrace(backtrace, %q{C:\some\old\path\test\unit}), "Should filter out all TestUnit-specific lines")
-
- backtrace = [%q{C:\some\old\path/test/unit/assertions.rb:44:in 'assert'},
- %q{C:\some\old\path/test/unit/testcase.rb:44:in 'send'},
- %q{C:\some\old\path\test\unit\testcase.rb:44:in 'run'},
- %q{C:\some\old\path\test\unit.rb:44:in 'run'}]
- assert_equal(backtrace, filter_backtrace(backtrace, %q{C:\some\old\path\test\unit}), "Should filter out all TestUnit-specific lines")
- end
-
- def test_nil_backtrace
- assert_equal(["No backtrace"], filter_backtrace(nil))
- end
- end
-end
diff --git a/test/testunit/util/test_observable.rb b/test/testunit/util/test_observable.rb
deleted file mode 100644
index 6cd10184f1..0000000000
--- a/test/testunit/util/test_observable.rb
+++ /dev/null
@@ -1,102 +0,0 @@
-# Author:: Nathaniel Talbott.
-# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
-# License:: Ruby license.
-
-require 'test/unit/util/observable'
-
-module Test
- module Unit
- module Util
- class TC_Observable < TestCase
-
- class TF_Observable
- include Observable
- end
-
- def setup
- @observable = TF_Observable.new
- end
-
- def test_simple_observation
- assert_raises(ArgumentError, "add_listener should throw an exception if no callback is supplied") do
- @observable.add_listener(:property, "a")
- end
-
- heard = false
- callback = proc { heard = true }
- assert_equal("a", @observable.add_listener(:property, "a", &callback), "add_listener should return the listener that was added")
-
- count = 0
- @observable.instance_eval do
- count = notify_listeners(:property)
- end
- assert_equal(1, count, "notify_listeners should have returned the number of listeners that were notified")
- assert(heard, "Should have heard the property changed")
-
- heard = false
- assert_equal(callback, @observable.remove_listener(:property, "a"), "remove_listener should return the callback")
-
- count = 1
- @observable.instance_eval do
- count = notify_listeners(:property)
- end
- assert_equal(0, count, "notify_listeners should have returned the number of listeners that were notified")
- assert(!heard, "Should not have heard the property change")
- end
-
- def test_value_observation
- value = nil
- @observable.add_listener(:property, "a") do |passed_value|
- value = passed_value
- end
- count = 0
- @observable.instance_eval do
- count = notify_listeners(:property, "stuff")
- end
- assert_equal(1, count, "Should have update the correct number of listeners")
- assert_equal("stuff", value, "Should have received the value as an argument to the listener")
- end
-
- def test_multiple_value_observation
- values = []
- @observable.add_listener(:property, "a") do |first_value, second_value|
- values = [first_value, second_value]
- end
- count = 0
- @observable.instance_eval do
- count = notify_listeners(:property, "stuff", "more stuff")
- end
- assert_equal(1, count, "Should have update the correct number of listeners")
- assert_equal(["stuff", "more stuff"], values, "Should have received the value as an argument to the listener")
- end
-
- def test_add_remove_with_default_listener
- assert_raises(ArgumentError, "add_listener should throw an exception if no callback is supplied") do
- @observable.add_listener(:property)
- end
-
- heard = false
- callback = proc { heard = true }
- assert_equal(callback, @observable.add_listener(:property, &callback), "add_listener should return the listener that was added")
-
- count = 0
- @observable.instance_eval do
- count = notify_listeners(:property)
- end
- assert_equal(1, count, "notify_listeners should have returned the number of listeners that were notified")
- assert(heard, "Should have heard the property changed")
-
- heard = false
- assert_equal(callback, @observable.remove_listener(:property, callback), "remove_listener should return the callback")
-
- count = 1
- @observable.instance_eval do
- count = notify_listeners(:property)
- end
- assert_equal(0, count, "notify_listeners should have returned the number of listeners that were notified")
- assert(!heard, "Should not have heard the property change")
- end
- end
- end
- end
-end
diff --git a/test/testunit/util/test_procwrapper.rb b/test/testunit/util/test_procwrapper.rb
deleted file mode 100644
index 3e552c7711..0000000000
--- a/test/testunit/util/test_procwrapper.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# Author:: Nathaniel Talbott.
-# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
-# License:: Ruby license.
-
-require 'test/unit'
-require 'test/unit/util/procwrapper'
-
-module Test
- module Unit
- module Util
- class TC_ProcWrapper < TestCase
- def munge_proc(&a_proc)
- return a_proc
- end
- def setup
- @original = proc {}
- @munged = munge_proc(&@original)
- @wrapped_original = ProcWrapper.new(@original)
- @wrapped_munged = ProcWrapper.new(@munged)
- end
- def test_wrapping
- assert_same(@original, @wrapped_original.to_proc, "The wrapper should return what was wrapped")
- end
- def test_hashing
-
- assert_equal(@wrapped_original.hash, @wrapped_munged.hash, "The original and munged should have the same hash when wrapped")
- assert_equal(@wrapped_original, @wrapped_munged, "The wrappers should be equivalent")
-
- a_hash = {@wrapped_original => @original}
- assert(a_hash[@wrapped_original], "Should be able to access the wrapper in the hash")
- assert_equal(a_hash[@wrapped_original], @original, "Should be able to access the wrapper in the hash")
- end
- end
- end
- end
-end
diff --git a/test/uri/test_ftp.rb b/test/uri/test_ftp.rb
index c27cf6165b..6311be81b7 100644
--- a/test/uri/test_ftp.rb
+++ b/test/uri/test_ftp.rb
@@ -52,7 +52,7 @@ class TestFTP < Test::Unit::TestCase
u = URI.parse('ftp://a.b.c/')
ary = u.component.collect {|c| u.send(c)}
assert_equal(ary, u.select(*u.component))
- assert_raises(ArgumentError) do
+ assert_raise(ArgumentError) do
u.select(:scheme, :host, :not_exist, :port)
end
end
diff --git a/test/uri/test_generic.rb b/test/uri/test_generic.rb
index 6661b4a5d2..0d481c369a 100644
--- a/test/uri/test_generic.rb
+++ b/test/uri/test_generic.rb
@@ -39,6 +39,17 @@ class URI::TestGeneric < Test::Unit::TestCase
]
ary = uri_to_ary(url)
assert_equal(exp, ary)
+ # 1'
+ url = URI.parse('ftp://ftp.is.co.za/%2Frfc/rfc1808.txt')
+ assert_kind_of(URI::FTP, url)
+
+ exp = [
+ 'ftp',
+ nil, 'ftp.is.co.za', URI::FTP.default_port,
+ '/rfc/rfc1808.txt', nil,
+ ]
+ ary = uri_to_ary(url)
+ assert_equal(exp, ary)
# 2
url = URI.parse('gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles')
@@ -110,8 +121,8 @@ class URI::TestGeneric < Test::Unit::TestCase
# 7
# reported by Mr. Kubota <em6t-kbt@asahi-net.or.jp>
- assert_raises(URI::InvalidURIError) { URI.parse('http://a_b:80/') }
- assert_raises(URI::InvalidURIError) { URI.parse('http://a_b/') }
+ assert_raise(URI::InvalidURIError) { URI.parse('http://a_b:80/') }
+ assert_raise(URI::InvalidURIError) { URI.parse('http://a_b/') }
# 8
# reported by m_seki
@@ -230,7 +241,7 @@ class URI::TestGeneric < Test::Unit::TestCase
assert_equal('', url.to_s)
end
- def test_rfc2396_examples
+ def test_rfc3986_examples
# http://a/b/c/d;p?q
# g:h = g:h
url = @base_url.merge('g:h')
@@ -306,11 +317,11 @@ class URI::TestGeneric < Test::Unit::TestCase
assert_equal('g?y', url.to_s)
# http://a/b/c/d;p?q
-# #s = (current document)#s
+# #s = http://a/b/c/d;p?q#s
url = @base_url.merge('#s')
assert_kind_of(URI::HTTP, url)
- assert_equal(@base_url.to_s + '#s', url.to_s)
- url = @base_url.route_to(@base_url.to_s + '#s')
+ assert_equal('http://a/b/c/d;p?q#s', url.to_s)
+ url = @base_url.route_to('http://a/b/c/d;p?q#s')
assert_kind_of(URI::Generic, url)
assert_equal('#s', url.to_s)
@@ -448,18 +459,18 @@ class URI::TestGeneric < Test::Unit::TestCase
url = @base_url.merge('/./g')
assert_kind_of(URI::HTTP, url)
assert_equal('http://a/g', url.to_s)
- url = @base_url.route_to('http://a/./g')
- assert_kind_of(URI::Generic, url)
- assert_equal('/./g', url.to_s)
+# url = @base_url.route_to('http://a/./g')
+# assert_kind_of(URI::Generic, url)
+# assert_equal('/./g', url.to_s)
# http://a/b/c/d;p?q
-# /../g = http://a/../g
+# /../g = http://a/g
url = @base_url.merge('/../g')
assert_kind_of(URI::HTTP, url)
assert_equal('http://a/g', url.to_s)
- url = @base_url.route_to('http://a/../g')
- assert_kind_of(URI::Generic, url)
- assert_equal('/../g', url.to_s)
+# url = @base_url.route_to('http://a/../g')
+# assert_kind_of(URI::Generic, url)
+# assert_equal('/../g', url.to_s)
# http://a/b/c/d;p?q
# g. = http://a/b/c/g.
@@ -502,20 +513,20 @@ class URI::TestGeneric < Test::Unit::TestCase
url = @base_url.merge('../../../g')
assert_kind_of(URI::HTTP, url)
assert_equal('http://a/g', url.to_s)
- url = @base_url.route_to('http://a/../g')
+ url = @base_url.route_to('http://a/g')
assert_kind_of(URI::Generic, url)
- assert('../../../g' != url.to_s) # ok? yes, it confuses you
- assert_equal('/../g', url.to_s) # and it is clearly
+ assert('../../../g' != url.to_s) # ok? yes, it confuses you
+ assert_equal('../../g', url.to_s) # and it is clearly
# http://a/b/c/d;p?q
-# ../../../../g = http://a/../../g
+# ../../../../g = http://a/g
url = @base_url.merge('../../../../g')
assert_kind_of(URI::HTTP, url)
assert_equal('http://a/g', url.to_s)
- url = @base_url.route_to('http://a/../../g')
+ url = @base_url.route_to('http://a/g')
assert_kind_of(URI::Generic, url)
assert('../../../../g' != url.to_s) # ok? yes, it confuses you
- assert_equal('/../../g', url.to_s) # and it is clearly
+ assert_equal('../../g', url.to_s) # and it is clearly
# http://a/b/c/d;p?q
# ./../g = http://a/b/g
@@ -644,9 +655,10 @@ class URI::TestGeneric < Test::Unit::TestCase
assert_equal(URI.parse('http://foo/hoge'), URI.join('http://foo', 'bar/baz', '/hoge'))
end
+ # ruby-dev:16728
def test_set_component
uri = URI.parse('http://foo:bar@baz')
- assert_equal('oof', uri.user = 'oof', "[ruby-dev:16728]")
+ assert_equal('oof', uri.user = 'oof')
assert_equal('http://oof:bar@baz', uri.to_s)
assert_equal('rab', uri.password = 'rab')
assert_equal('http://oof:rab@baz', uri.to_s)
@@ -668,72 +680,19 @@ class URI::TestGeneric < Test::Unit::TestCase
assert_equal('http://foo:bar@zab:8080/?a=1#b123', uri.to_s)
uri = URI.parse('http://example.com')
- assert_raises(URI::InvalidURIError) { uri.password = 'bar' }
+ assert_raise(URI::InvalidURIError) { uri.password = 'bar' }
uri.userinfo = 'foo:bar'
assert_equal('http://foo:bar@example.com', uri.to_s)
- assert_raises(URI::InvalidURIError) { uri.registry = 'bar' }
- assert_raises(URI::InvalidURIError) { uri.opaque = 'bar' }
+ assert_raise(URI::InvalidURIError) { uri.registry = 'bar' }
+ assert_raise(URI::InvalidURIError) { uri.opaque = 'bar' }
uri = URI.parse('mailto:foo@example.com')
- assert_raises(URI::InvalidURIError) { uri.user = 'bar' }
- assert_raises(URI::InvalidURIError) { uri.password = 'bar' }
- assert_raises(URI::InvalidURIError) { uri.userinfo = ['bar', 'baz'] }
- assert_raises(URI::InvalidURIError) { uri.host = 'bar' }
- assert_raises(URI::InvalidURIError) { uri.port = 'bar' }
- assert_raises(URI::InvalidURIError) { uri.path = 'bar' }
- assert_raises(URI::InvalidURIError) { uri.query = 'bar' }
- end
-
- def m(s)
- @base_url.merge(s).to_s
-end
-
- def test_rfc3986_examples
- assert_equal("g:h", m("g:h"))
- assert_equal("http://a/b/c/g", m("g"))
- assert_equal("http://a/b/c/g", m("./g"))
- assert_equal("http://a/b/c/g/", m("g/"))
- assert_equal("http://a/g", m("/g"))
- assert_equal("http://g", m("//g"))
- assert_equal("http://a/b/c/d;p?y", m("?y"))
- assert_equal("http://a/b/c/g?y", m("g?y"))
- assert_equal("http://a/b/c/d;p?q#s", m("#s"))
- assert_equal("http://a/b/c/g#s", m("g#s"))
- assert_equal("http://a/b/c/g?y#s", m("g?y#s"))
- assert_equal("http://a/b/c/;x", m(";x"))
- assert_equal("http://a/b/c/g;x", m("g;x"))
- assert_equal("http://a/b/c/g;x?y#s", m("g;x?y#s"))
- assert_equal("http://a/b/c/d;p?q", m(""))
- assert_equal("http://a/b/c/", m("."))
- assert_equal("http://a/b/c/", m("./"))
- assert_equal("http://a/b/", m(".."))
- assert_equal("http://a/b/", m("../"))
- assert_equal("http://a/b/g", m("../g"))
- assert_equal("http://a/", m("../.."))
- assert_equal("http://a/", m("../../"))
- assert_equal("http://a/g", m("../../g"))
- assert_equal("http://a/g", m("../../../g"))
- assert_equal("http://a/g", m("../../../../g"))
-
- assert_equal("http://a/g", m("/./g"))
- assert_equal("http://a/g", m("/../g"))
- assert_equal("http://a/b/c/g.", m("g."))
- assert_equal("http://a/b/c/.g", m(".g"))
- assert_equal("http://a/b/c/g..", m("g.."))
- assert_equal("http://a/b/c/..g", m("..g"))
-
- assert_equal("http://a/b/g", m("./../g"))
- assert_equal("http://a/b/c/g/", m("./g/."))
- assert_equal("http://a/b/c/g/h", m("g/./h"))
- assert_equal("http://a/b/c/h", m("g/../h"))
- assert_equal("http://a/b/c/g;x=1/y", m("g;x=1/./y"))
- assert_equal("http://a/b/c/y", m("g;x=1/../y"))
-
- assert_equal("http://a/b/c/g?y/./x", m("g?y/./x"))
- assert_equal("http://a/b/c/g?y/../x", m("g?y/../x"))
- assert_equal("http://a/b/c/g#s/./x", m("g#s/./x"))
- assert_equal("http://a/b/c/g#s/../x", m("g#s/../x"))
-
- assert_equal("http:g", m("http:g"))
+ assert_raise(URI::InvalidURIError) { uri.user = 'bar' }
+ assert_raise(URI::InvalidURIError) { uri.password = 'bar' }
+ assert_raise(URI::InvalidURIError) { uri.userinfo = ['bar', 'baz'] }
+ assert_raise(URI::InvalidURIError) { uri.host = 'bar' }
+ assert_raise(URI::InvalidURIError) { uri.port = 'bar' }
+ assert_raise(URI::InvalidURIError) { uri.path = 'bar' }
+ assert_raise(URI::InvalidURIError) { uri.query = 'bar' }
end
end
diff --git a/test/uri/test_http.rb b/test/uri/test_http.rb
index a6846141df..6c8e700b77 100644
--- a/test/uri/test_http.rb
+++ b/test/uri/test_http.rb
@@ -53,7 +53,7 @@ class TestHTTP < Test::Unit::TestCase
assert_equal(['http', 'a.b.c', 80], URI.parse('http://a.b.c/').select(:scheme, :host, :port))
u = URI.parse('http://a.b.c/')
assert_equal(uri_to_ary(u), u.select(*u.component))
- assert_raises(ArgumentError) do
+ assert_raise(ArgumentError) do
u.select(:scheme, :host, :not_exist, :port)
end
end
diff --git a/test/uri/test_ldap.rb b/test/uri/test_ldap.rb
index 866b7d8066..0eaa113c94 100644
--- a/test/uri/test_ldap.rb
+++ b/test/uri/test_ldap.rb
@@ -90,7 +90,7 @@ class TestLDAP < Test::Unit::TestCase
def test_select
u = URI.parse('ldap:///??sub??!bindname=cn=Manager%2co=Foo')
assert_equal(uri_to_ary(u), u.select(*u.component))
- assert_raises(ArgumentError) do
+ assert_raise(ArgumentError) do
u.select(:scheme, :host, :not_exist, :port)
end
end
diff --git a/test/uri/test_mailto.rb b/test/uri/test_mailto.rb
index ba437904f8..38715fcc9c 100644
--- a/test/uri/test_mailto.rb
+++ b/test/uri/test_mailto.rb
@@ -101,7 +101,7 @@ class TestMailTo < Test::Unit::TestCase
end
bad.each do |x|
- assert_raises(URI::InvalidComponentError) {
+ assert_raise(URI::InvalidComponentError) {
@u.build(x)
}
end
@@ -112,7 +112,7 @@ class TestMailTo < Test::Unit::TestCase
def test_select
u = URI.parse('mailto:joe@example.com?cc=bob@example.com&body=hello')
assert_equal(uri_to_ary(u), u.select(*u.component))
- assert_raises(ArgumentError) do
+ assert_raise(ArgumentError) do
u.select(:scheme, :host, :not_exist, :port)
end
end
diff --git a/test/uri/test_parser.rb b/test/uri/test_parser.rb
new file mode 100644
index 0000000000..adf8a1292c
--- /dev/null
+++ b/test/uri/test_parser.rb
@@ -0,0 +1,41 @@
+require 'test/unit'
+require 'uri'
+
+class URI::TestParser < Test::Unit::TestCase
+ def uri_to_ary(uri)
+ uri.class.component.collect {|c| uri.send(c)}
+ end
+
+ def test_compare
+ url = 'http://a/b/c/d;p?q'
+ u0 = URI.parse(url)
+ u1 = URI.parse(url)
+ p = URI::Parser.new
+ u2 = p.parse(url)
+ u3 = p.parse(url)
+
+ assert(u0 == u1)
+ assert(u0.eql?(u1))
+ assert(!u0.equal?(u1))
+
+ assert(u1 == u2)
+ assert(!u1.eql?(u2))
+ assert(!u1.equal?(u2))
+
+ assert(u2 == u3)
+ assert(u2.eql?(u3))
+ assert(!u2.equal?(u3))
+ end
+
+ def test_parse
+ escaped = URI::REGEXP::PATTERN::ESCAPED
+ hex = URI::REGEXP::PATTERN::HEX
+ p1 = URI::Parser.new(:ESCAPED => "(?:#{escaped}|%u[#{hex}]{4})")
+ u1 = p1.parse('http://a/b/%uABCD')
+ assert_equal(['http', nil, 'a', URI::HTTP.default_port, '/b/%uABCD', nil, nil],
+ uri_to_ary(u1))
+ u1.path = '/%uDCBA'
+ assert_equal(['http', nil, 'a', URI::HTTP.default_port, '/%uDCBA', nil, nil],
+ uri_to_ary(u1))
+ end
+end
diff --git a/test/webrick/test_cgi.rb b/test/webrick/test_cgi.rb
index b50038d84c..ff83919902 100644
--- a/test/webrick/test_cgi.rb
+++ b/test/webrick/test_cgi.rb
@@ -21,41 +21,41 @@ class TestWEBrickCGI < Test::Unit::TestCase
if RUBY_PLATFORM =~ /mswin32|mingw|cygwin|bccwin32/
config[:CGIPathEnv] = ENV['PATH'] # runtime dll may not be in system dir.
end
- TestWEBrick.start_httpserver(config){|server, addr, port|
- block.call(server, addr, port)
+ TestWEBrick.start_httpserver(config){|server, addr, port, log|
+ block.call(server, addr, port, log)
}
end
def test_cgi
- start_cgi_server{|server, addr, port|
+ start_cgi_server{|server, addr, port, log|
http = Net::HTTP.new(addr, port)
req = Net::HTTP::Get.new("/webrick.cgi")
- http.request(req){|res| assert_equal("/webrick.cgi", res.body)}
+ http.request(req){|res| assert_equal("/webrick.cgi", res.body, log.call)}
req = Net::HTTP::Get.new("/webrick.cgi/path/info")
- http.request(req){|res| assert_equal("/path/info", res.body)}
+ http.request(req){|res| assert_equal("/path/info", res.body, log.call)}
req = Net::HTTP::Get.new("/webrick.cgi/%3F%3F%3F?foo=bar")
- http.request(req){|res| assert_equal("/???", res.body)}
+ http.request(req){|res| assert_equal("/???", res.body, log.call)}
req = Net::HTTP::Get.new("/webrick.cgi/%A4%DB%A4%B2/%A4%DB%A4%B2")
http.request(req){|res|
- assert_equal("/\xA4\xDB\xA4\xB2/\xA4\xDB\xA4\xB2", res.body)}
+ assert_equal("/\xA4\xDB\xA4\xB2/\xA4\xDB\xA4\xB2", res.body, log.call)}
req = Net::HTTP::Get.new("/webrick.cgi?a=1;a=2;b=x")
- http.request(req){|res| assert_equal("a=1, a=2, b=x", res.body)}
+ http.request(req){|res| assert_equal("a=1, a=2, b=x", res.body, log.call)}
req = Net::HTTP::Get.new("/webrick.cgi?a=1&a=2&b=x")
- http.request(req){|res| assert_equal("a=1, a=2, b=x", res.body)}
+ http.request(req){|res| assert_equal("a=1, a=2, b=x", res.body, log.call)}
req = Net::HTTP::Post.new("/webrick.cgi?a=x;a=y;b=1")
req["Content-Type"] = "application/x-www-form-urlencoded"
http.request(req, "a=1;a=2;b=x"){|res|
- assert_equal("a=1, a=2, b=x", res.body)}
+ assert_equal("a=1, a=2, b=x", res.body, log.call)}
req = Net::HTTP::Post.new("/webrick.cgi?a=x&a=y&b=1")
req["Content-Type"] = "application/x-www-form-urlencoded"
http.request(req, "a=1&a=2&b=x"){|res|
- assert_equal("a=1, a=2, b=x", res.body)}
+ assert_equal("a=1, a=2, b=x", res.body, log.call)}
req = Net::HTTP::Get.new("/")
http.request(req){|res|
ary = res.body.lines.to_a
- assert_match(%r{/$}, ary[0])
- assert_match(%r{/webrick.cgi$}, ary[1])
+ assert_match(%r{/$}, ary[0], log.call)
+ assert_match(%r{/webrick.cgi$}, ary[1], log.call)
}
req = Net::HTTP::Get.new("/webrick.cgi")
@@ -63,7 +63,7 @@ class TestWEBrickCGI < Test::Unit::TestCase
http.request(req){|res|
assert_equal(
"CUSTOMER=WILE_E_COYOTE\nPART_NUMBER=ROCKET_LAUNCHER_0001\n",
- res.body)
+ res.body, log.call)
}
req = Net::HTTP::Get.new("/webrick.cgi")
@@ -74,16 +74,16 @@ class TestWEBrickCGI < Test::Unit::TestCase
req["Cookie"] = cookie
http.request(req){|res|
assert_equal("Customer=WILE_E_COYOTE, Shipping=FedEx",
- res["Set-Cookie"])
+ res["Set-Cookie"], log.call)
assert_equal("Customer=WILE_E_COYOTE\n" +
"Part_Number=Rocket_Launcher_0001\n" +
- "Shipping=FedEx\n", res.body)
+ "Shipping=FedEx\n", res.body, log.call)
}
}
end
def test_bad_request
- start_cgi_server{|server, addr, port|
+ start_cgi_server{|server, addr, port, log|
sock = TCPSocket.new(addr, port)
begin
sock << "POST /webrick.cgi HTTP/1.0" << CRLF
@@ -92,7 +92,7 @@ class TestWEBrickCGI < Test::Unit::TestCase
sock << CRLF
sock << "a=1&a=2&b=x"
sock.close_write
- assert_match(%r{\AHTTP/\d.\d 400 Bad Request}, sock.read)
+ assert_match(%r{\AHTTP/\d.\d 400 Bad Request}, sock.read, log.call)
ensure
sock.close
end
diff --git a/test/webrick/test_filehandler.rb b/test/webrick/test_filehandler.rb
index 371527e413..712ff7b1cd 100644
--- a/test/webrick/test_filehandler.rb
+++ b/test/webrick/test_filehandler.rb
@@ -75,19 +75,19 @@ class WEBrick::TestFileHandler < Test::Unit::TestCase
def test_filehandler
config = { :DocumentRoot => File.dirname(__FILE__), }
this_file = File.basename(__FILE__)
- TestWEBrick.start_httpserver(config) do |server, addr, port|
+ TestWEBrick.start_httpserver(config) do |server, addr, port, log|
http = Net::HTTP.new(addr, port)
req = Net::HTTP::Get.new("/")
http.request(req){|res|
- assert_equal("200", res.code)
- assert_equal("text/html", res.content_type)
- assert_match(/HREF="#{this_file}"/, res.body)
+ assert_equal("200", res.code, log.call)
+ assert_equal("text/html", res.content_type, log.call)
+ assert_match(/HREF="#{this_file}"/, res.body, log.call)
}
req = Net::HTTP::Get.new("/#{this_file}")
http.request(req){|res|
- assert_equal("200", res.code)
- assert_equal("text/plain", res.content_type)
- assert_equal(File.read(__FILE__), res.body)
+ assert_equal("200", res.code, log.call)
+ assert_equal("text/plain", res.content_type, log.call)
+ assert_equal(File.read(__FILE__), res.body, log.call)
}
end
end
@@ -95,23 +95,23 @@ class WEBrick::TestFileHandler < Test::Unit::TestCase
def test_non_disclosure_name
config = { :DocumentRoot => File.dirname(__FILE__), }
this_file = File.basename(__FILE__)
- TestWEBrick.start_httpserver(config) do |server, addr, port|
+ TestWEBrick.start_httpserver(config) do |server, addr, port, log|
http = Net::HTTP.new(addr, port)
doc_root_opts = server[:DocumentRootOptions]
doc_root_opts[:NondisclosureName] = %w(.ht* *~ test_*)
req = Net::HTTP::Get.new("/")
http.request(req){|res|
- assert_equal("200", res.code)
- assert_equal("text/html", res.content_type)
+ assert_equal("200", res.code, log.call)
+ assert_equal("text/html", res.content_type, log.call)
assert_no_match(/HREF="#{File.basename(__FILE__)}"/, res.body)
}
req = Net::HTTP::Get.new("/#{this_file}")
http.request(req){|res|
- assert_equal("404", res.code)
+ assert_equal("404", res.code, log.call)
}
doc_root_opts[:NondisclosureName] = %w(.ht* *~ TEST_*)
http.request(req){|res|
- assert_equal("404", res.code)
+ assert_equal("404", res.code, log.call)
}
end
end
@@ -119,14 +119,14 @@ class WEBrick::TestFileHandler < Test::Unit::TestCase
def test_directory_traversal
config = { :DocumentRoot => File.dirname(__FILE__), }
this_file = File.basename(__FILE__)
- TestWEBrick.start_httpserver(config) do |server, addr, port|
+ TestWEBrick.start_httpserver(config) do |server, addr, port, log|
http = Net::HTTP.new(addr, port)
req = Net::HTTP::Get.new("/../../")
- http.request(req){|res| assert_equal("400", res.code) }
+ http.request(req){|res| assert_equal("400", res.code, log.call) }
req = Net::HTTP::Get.new("/..%5c../#{File.basename(__FILE__)}")
- http.request(req){|res| assert_equal(windows? ? "200" : "404", res.code) }
+ http.request(req){|res| assert_equal(windows? ? "200" : "404", res.code, log.call) }
req = Net::HTTP::Get.new("/..%5c..%5cruby.c")
- http.request(req){|res| assert_equal("404", res.code) }
+ http.request(req){|res| assert_equal("404", res.code, log.call) }
end
end
@@ -134,10 +134,10 @@ class WEBrick::TestFileHandler < Test::Unit::TestCase
if windows?
config = { :DocumentRoot => File.dirname(__FILE__), }
this_file = File.basename(__FILE__)
- TestWEBrick.start_httpserver(config) do |server, addr, port|
+ TestWEBrick.start_httpserver(config) do |server, addr, port, log|
http = Net::HTTP.new(addr, port)
req = Net::HTTP::Get.new("/..%5c..")
- http.request(req){|res| assert_equal("301", res.code) }
+ http.request(req){|res| assert_equal("301", res.code, log.call) }
end
end
end
@@ -148,25 +148,25 @@ class WEBrick::TestFileHandler < Test::Unit::TestCase
:DocumentRoot => File.dirname(__FILE__),
:CGIPathEnv => ENV['PATH'],
}
- TestWEBrick.start_httpserver(config) do |server, addr, port|
+ TestWEBrick.start_httpserver(config) do |server, addr, port, log|
http = Net::HTTP.new(addr, port)
req = Net::HTTP::Get.new("/webric~1.cgi/test")
http.request(req) do |res|
if windows?
- assert_equal("200", res.code)
- assert_equal("/test", res.body)
+ assert_equal("200", res.code, log.call)
+ assert_equal("/test", res.body, log.call)
else
- assert_equal("404", res.code)
+ assert_equal("404", res.code, log.call)
end
end
req = Net::HTTP::Get.new("/.htaccess")
- http.request(req) {|res| assert_equal("404", res.code) }
+ http.request(req) {|res| assert_equal("404", res.code, log.call) }
req = Net::HTTP::Get.new("/htacce~1")
- http.request(req) {|res| assert_equal("404", res.code) }
+ http.request(req) {|res| assert_equal("404", res.code, log.call) }
req = Net::HTTP::Get.new("/HTACCE~1")
- http.request(req) {|res| assert_equal("404", res.code) }
+ http.request(req) {|res| assert_equal("404", res.code, log.call) }
end
end
@@ -176,21 +176,21 @@ class WEBrick::TestFileHandler < Test::Unit::TestCase
:DocumentRoot => File.dirname(__FILE__),
:CGIPathEnv => ENV['PATH'],
}
- TestWEBrick.start_httpserver(config) do |server, addr, port|
+ TestWEBrick.start_httpserver(config) do |server, addr, port, log|
http = Net::HTTP.new(addr, port)
req = Net::HTTP::Get.new("/webrick.cgi/test")
http.request(req) do |res|
- assert_equal("200", res.code)
- assert_equal("/test", res.body)
+ assert_equal("200", res.code, log.call)
+ assert_equal("/test", res.body, log.call)
end
response_assertion = Proc.new do |res|
if windows?
- assert_equal("200", res.code)
- assert_equal("/test", res.body)
+ assert_equal("200", res.code, log.call)
+ assert_equal("/test", res.body, log.call)
else
- assert_equal("404", res.code)
+ assert_equal("404", res.code, log.call)
end
end
req = Net::HTTP::Get.new("/webrick.cgi%20/test")
diff --git a/test/webrick/test_httpauth.rb b/test/webrick/test_httpauth.rb
index 75926b1624..a6e29474b3 100644
--- a/test/webrick/test_httpauth.rb
+++ b/test/webrick/test_httpauth.rb
@@ -7,7 +7,7 @@ require File.join(File.dirname(__FILE__), "utils.rb")
class TestWEBrickHTTPAuth < Test::Unit::TestCase
def test_basic_auth
- TestWEBrick.start_httpserver{|server, addr, port|
+ TestWEBrick.start_httpserver{|server, addr, port, log|
realm = "WEBrick's realm"
path = "/basic_auth"
@@ -20,14 +20,14 @@ class TestWEBrickHTTPAuth < Test::Unit::TestCase
http = Net::HTTP.new(addr, port)
g = Net::HTTP::Get.new(path)
g.basic_auth("webrick", "supersecretpassword")
- http.request(g){|res| assert_equal("hoge", res.body)}
+ http.request(g){|res| assert_equal("hoge", res.body, log.call)}
g.basic_auth("webrick", "not super")
- http.request(g){|res| assert_not_equal("hoge", res.body)}
+ http.request(g){|res| assert_not_equal("hoge", res.body, log.call)}
}
end
def test_basic_auth2
- TestWEBrick.start_httpserver{|server, addr, port|
+ TestWEBrick.start_httpserver{|server, addr, port, log|
realm = "WEBrick's realm"
path = "/basic_auth2"
@@ -41,9 +41,9 @@ class TestWEBrickHTTPAuth < Test::Unit::TestCase
htpasswd = WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path)
users = []
htpasswd.each{|user, pass| users << user }
- assert_equal(2, users.size)
- assert(users.member?("webrick"))
- assert(users.member?("foo"))
+ assert_equal(2, users.size, log.call)
+ assert(users.member?("webrick"), log.call)
+ assert(users.member?("foo"), log.call)
server.mount_proc(path){|req, res|
auth = WEBrick::HTTPAuth::BasicAuth.new(
@@ -56,9 +56,9 @@ class TestWEBrickHTTPAuth < Test::Unit::TestCase
http = Net::HTTP.new(addr, port)
g = Net::HTTP::Get.new(path)
g.basic_auth("webrick", "supersecretpassword")
- http.request(g){|res| assert_equal("hoge", res.body)}
+ http.request(g){|res| assert_equal("hoge", res.body, log.call)}
g.basic_auth("webrick", "not super")
- http.request(g){|res| assert_not_equal("hoge", res.body)}
+ http.request(g){|res| assert_not_equal("hoge", res.body, log.call)}
}
end
@@ -66,7 +66,7 @@ class TestWEBrickHTTPAuth < Test::Unit::TestCase
tmpfile = Tempfile.new("test_webrick_auth")
tmpfile.puts("webrick:{SHA}GJYFRpBbdchp595jlh3Bhfmgp8k=")
tmpfile.flush
- assert_raises(NotImplementedError){
+ assert_raise(NotImplementedError){
WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path)
}
tmpfile.close(true)
@@ -74,7 +74,7 @@ class TestWEBrickHTTPAuth < Test::Unit::TestCase
tmpfile = Tempfile.new("test_webrick_auth")
tmpfile.puts("webrick:$apr1$IOVMD/..$rmnOSPXr0.wwrLPZHBQZy0")
tmpfile.flush
- assert_raises(NotImplementedError){
+ assert_raise(NotImplementedError){
WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path)
}
tmpfile.close(true)
diff --git a/test/webrick/test_httpproxy.rb b/test/webrick/test_httpproxy.rb
index 67862543a8..1f914e3a99 100644
--- a/test/webrick/test_httpproxy.rb
+++ b/test/webrick/test_httpproxy.rb
@@ -35,7 +35,7 @@ class TestWEBrickHTTPProxy < Test::Unit::TestCase
:ProxyContentHandler => Proc.new{|req, res| proxy_handler_called += 1 },
:RequestHandler => Proc.new{|req, res| request_handler_called += 1 }
}
- TestWEBrick.start_httpproxy(config){|server, addr, port|
+ TestWEBrick.start_httpproxy(config){|server, addr, port, log|
server.mount_proc("/"){|req, res|
res.body = "#{req.request_method} #{req.path} #{req.body}"
}
@@ -43,28 +43,28 @@ class TestWEBrickHTTPProxy < Test::Unit::TestCase
req = Net::HTTP::Get.new("/")
http.request(req){|res|
- assert_equal("1.1 localhost.localdomain:#{port}", res["via"])
- assert_equal("GET / ", res.body)
+ assert_equal("1.1 localhost.localdomain:#{port}", res["via"], log.call)
+ assert_equal("GET / ", res.body, log.call)
}
- assert_equal(1, proxy_handler_called)
- assert_equal(2, request_handler_called)
+ assert_equal(1, proxy_handler_called, log.call)
+ assert_equal(2, request_handler_called, log.call)
req = Net::HTTP::Head.new("/")
http.request(req){|res|
- assert_equal("1.1 localhost.localdomain:#{port}", res["via"])
- assert_nil(res.body)
+ assert_equal("1.1 localhost.localdomain:#{port}", res["via"], log.call)
+ assert_nil(res.body, log.call)
}
- assert_equal(2, proxy_handler_called)
- assert_equal(4, request_handler_called)
+ assert_equal(2, proxy_handler_called, log.call)
+ assert_equal(4, request_handler_called, log.call)
req = Net::HTTP::Post.new("/")
req.body = "post-data"
http.request(req){|res|
- assert_equal("1.1 localhost.localdomain:#{port}", res["via"])
- assert_equal("POST / post-data", res.body)
+ assert_equal("1.1 localhost.localdomain:#{port}", res["via"], log.call)
+ assert_equal("POST / post-data", res.body, log.call)
}
- assert_equal(3, proxy_handler_called)
- assert_equal(6, request_handler_called)
+ assert_equal(3, proxy_handler_called, log.call)
+ assert_equal(6, request_handler_called, log.call)
}
end
@@ -80,7 +80,7 @@ class TestWEBrickHTTPProxy < Test::Unit::TestCase
:ProxyContentHandler => Proc.new{|req, res| proxy_handler_called += 1 },
:RequestHandler => Proc.new{|req, res| request_handler_called += 1 }
}
- TestWEBrick.start_httpproxy(config){|server, addr, port|
+ TestWEBrick.start_httpproxy(config){|server, addr, port, log|
server.mount_proc("/"){|req, res|
res.body = "#{req.request_method} #{req.path} #{req.body}"
}
@@ -88,28 +88,28 @@ class TestWEBrickHTTPProxy < Test::Unit::TestCase
req = Net::HTTP::Get.new("/")
http.request(req){|res|
- assert_nil(res["via"])
- assert_equal("GET / ", res.body)
+ assert_nil(res["via"], log.call)
+ assert_equal("GET / ", res.body, log.call)
}
- assert_equal(0, proxy_handler_called)
- assert_equal(1, request_handler_called)
+ assert_equal(0, proxy_handler_called, log.call)
+ assert_equal(1, request_handler_called, log.call)
req = Net::HTTP::Head.new("/")
http.request(req){|res|
- assert_nil(res["via"])
- assert_nil(res.body)
+ assert_nil(res["via"], log.call)
+ assert_nil(res.body, log.call)
}
- assert_equal(0, proxy_handler_called)
- assert_equal(2, request_handler_called)
+ assert_equal(0, proxy_handler_called, log.call)
+ assert_equal(2, request_handler_called, log.call)
req = Net::HTTP::Post.new("/")
req.body = "post-data"
http.request(req){|res|
- assert_nil(res["via"])
- assert_equal("POST / post-data", res.body)
+ assert_nil(res["via"], log.call)
+ assert_equal("POST / post-data", res.body, log.call)
}
- assert_equal(0, proxy_handler_called)
- assert_equal(3, request_handler_called)
+ assert_equal(0, proxy_handler_called, log.call)
+ assert_equal(3, request_handler_called, log.call)
}
end
@@ -147,11 +147,11 @@ class TestWEBrickHTTPProxy < Test::Unit::TestCase
assert_equal("CONNECT", req.request_method)
},
}
- TestWEBrick.start_httpserver(s_config){|s_server, s_addr, s_port|
+ TestWEBrick.start_httpserver(s_config){|s_server, s_addr, s_port, s_log|
s_server.mount_proc("/"){|req, res|
res.body = "SSL #{req.request_method} #{req.path} #{req.body}"
}
- TestWEBrick.start_httpproxy(config){|server, addr, port|
+ TestWEBrick.start_httpproxy(config){|server, addr, port, log|
http = Net::HTTP.new("127.0.0.1", s_port, addr, port)
http.use_ssl = true
http.verify_callback = Proc.new do |preverify_ok, store_ctx|
@@ -160,13 +160,13 @@ class TestWEBrickHTTPProxy < Test::Unit::TestCase
req = Net::HTTP::Get.new("/")
http.request(req){|res|
- assert_equal("SSL GET / ", res.body)
+ assert_equal("SSL GET / ", res.body, s_log.call + log.call)
}
req = Net::HTTP::Post.new("/")
req.body = "post-data"
http.request(req){|res|
- assert_equal("SSL POST / post-data", res.body)
+ assert_equal("SSL POST / post-data", res.body, s_log.call + log.call)
}
}
}
@@ -187,7 +187,7 @@ class TestWEBrickHTTPProxy < Test::Unit::TestCase
:ProxyContentHandler => Proc.new{|req, res| up_proxy_handler_called += 1},
:RequestHandler => Proc.new{|req, res| up_request_handler_called += 1}
}
- TestWEBrick.start_httpproxy(up_config){|up_server, up_addr, up_port|
+ TestWEBrick.start_httpproxy(up_config){|up_server, up_addr, up_port, up_log|
up_server.mount_proc("/"){|req, res|
res.body = "#{req.request_method} #{req.path} #{req.body}"
}
@@ -197,45 +197,45 @@ class TestWEBrickHTTPProxy < Test::Unit::TestCase
:ProxyContentHandler => Proc.new{|req, res| proxy_handler_called += 1},
:RequestHandler => Proc.new{|req, res| request_handler_called += 1},
}
- TestWEBrick.start_httpproxy(config){|server, addr, port|
+ TestWEBrick.start_httpproxy(config){|server, addr, port, log|
http = Net::HTTP.new(up_addr, up_port, addr, port)
req = Net::HTTP::Get.new("/")
http.request(req){|res|
via = res["via"].split(/,\s+/)
- assert(via.include?("1.1 localhost.localdomain:#{up_port}"))
- assert(via.include?("1.1 localhost.localdomain:#{port}"))
+ assert(via.include?("1.1 localhost.localdomain:#{up_port}"), up_log.call + log.call)
+ assert(via.include?("1.1 localhost.localdomain:#{port}"), up_log.call + log.call)
assert_equal("GET / ", res.body)
}
- assert_equal(1, up_proxy_handler_called)
- assert_equal(2, up_request_handler_called)
- assert_equal(1, proxy_handler_called)
- assert_equal(1, request_handler_called)
+ assert_equal(1, up_proxy_handler_called, up_log.call + log.call)
+ assert_equal(2, up_request_handler_called, up_log.call + log.call)
+ assert_equal(1, proxy_handler_called, up_log.call + log.call)
+ assert_equal(1, request_handler_called, up_log.call + log.call)
req = Net::HTTP::Head.new("/")
http.request(req){|res|
via = res["via"].split(/,\s+/)
- assert(via.include?("1.1 localhost.localdomain:#{up_port}"))
- assert(via.include?("1.1 localhost.localdomain:#{port}"))
- assert_nil(res.body)
+ assert(via.include?("1.1 localhost.localdomain:#{up_port}"), up_log.call + log.call)
+ assert(via.include?("1.1 localhost.localdomain:#{port}"), up_log.call + log.call)
+ assert_nil(res.body, up_log.call + log.call)
}
- assert_equal(2, up_proxy_handler_called)
- assert_equal(4, up_request_handler_called)
- assert_equal(2, proxy_handler_called)
- assert_equal(2, request_handler_called)
+ assert_equal(2, up_proxy_handler_called, up_log.call + log.call)
+ assert_equal(4, up_request_handler_called, up_log.call + log.call)
+ assert_equal(2, proxy_handler_called, up_log.call + log.call)
+ assert_equal(2, request_handler_called, up_log.call + log.call)
req = Net::HTTP::Post.new("/")
req.body = "post-data"
http.request(req){|res|
via = res["via"].split(/,\s+/)
- assert(via.include?("1.1 localhost.localdomain:#{up_port}"))
- assert(via.include?("1.1 localhost.localdomain:#{port}"))
- assert_equal("POST / post-data", res.body)
+ assert(via.include?("1.1 localhost.localdomain:#{up_port}"), up_log.call + log.call)
+ assert(via.include?("1.1 localhost.localdomain:#{port}"), up_log.call + log.call)
+ assert_equal("POST / post-data", res.body, up_log.call + log.call)
}
- assert_equal(3, up_proxy_handler_called)
- assert_equal(6, up_request_handler_called)
- assert_equal(3, proxy_handler_called)
- assert_equal(3, request_handler_called)
+ assert_equal(3, up_proxy_handler_called, up_log.call + log.call)
+ assert_equal(6, up_request_handler_called, up_log.call + log.call)
+ assert_equal(3, proxy_handler_called, up_log.call + log.call)
+ assert_equal(3, request_handler_called, up_log.call + log.call)
if defined?(OpenSSL)
# Testing CONNECT to the upstream proxy server
@@ -253,11 +253,11 @@ class TestWEBrickHTTPProxy < Test::Unit::TestCase
:SSLCertificate => cert,
:SSLPrivateKey => key,
}
- TestWEBrick.start_httpserver(s_config){|s_server, s_addr, s_port|
+ TestWEBrick.start_httpserver(s_config){|s_server, s_addr, s_port, s_log|
s_server.mount_proc("/"){|req, res|
res.body = "SSL #{req.request_method} #{req.path} #{req.body}"
}
- http = Net::HTTP.new("127.0.0.1", s_port, addr, port)
+ http = Net::HTTP.new("127.0.0.1", s_port, addr, port, up_log.call + log.call + s_log.call)
http.use_ssl = true
http.verify_callback = Proc.new do |preverify_ok, store_ctx|
store_ctx.current_cert.to_der == cert.to_der
@@ -265,13 +265,13 @@ class TestWEBrickHTTPProxy < Test::Unit::TestCase
req = Net::HTTP::Get.new("/")
http.request(req){|res|
- assert_equal("SSL GET / ", res.body)
+ assert_equal("SSL GET / ", res.body, up_log.call + log.call + s_log.call)
}
req = Net::HTTP::Post.new("/")
req.body = "post-data"
http.request(req){|res|
- assert_equal("SSL POST / post-data", res.body)
+ assert_equal("SSL POST / post-data", res.body, up_log.call + log.call + s_log.call)
}
}
end
diff --git a/test/webrick/test_httprequest.rb b/test/webrick/test_httprequest.rb
index f49bd59384..92ad1e79ca 100644
--- a/test/webrick/test_httprequest.rb
+++ b/test/webrick/test_httprequest.rb
@@ -61,7 +61,7 @@ class TestWEBrickHTTPRequest < Test::Unit::TestCase
GET /#{"a"*1024} HTTP/1.1
_end_of_message_
req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
- assert_raises(WEBrick::HTTPStatus::RequestURITooLarge){
+ assert_raise(WEBrick::HTTPStatus::RequestURITooLarge){
req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
}
end
@@ -314,7 +314,7 @@ class TestWEBrickHTTPRequest < Test::Unit::TestCase
#{param}
_end_of_message_
- assert_raises(WEBrick::HTTPStatus::LengthRequired){
+ assert_raise(WEBrick::HTTPStatus::LengthRequired){
req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
req.body
@@ -327,7 +327,7 @@ class TestWEBrickHTTPRequest < Test::Unit::TestCase
body is too short.
_end_of_message_
- assert_raises(WEBrick::HTTPStatus::BadRequest){
+ assert_raise(WEBrick::HTTPStatus::BadRequest){
req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
req.body
@@ -340,7 +340,7 @@ class TestWEBrickHTTPRequest < Test::Unit::TestCase
body is too short.
_end_of_message_
- assert_raises(WEBrick::HTTPStatus::NotImplemented){
+ assert_raise(WEBrick::HTTPStatus::NotImplemented){
req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
req.body
diff --git a/test/webrick/test_httpserver.rb b/test/webrick/test_httpserver.rb
index eb685f916d..6b0c419ad7 100644
--- a/test/webrick/test_httpserver.rb
+++ b/test/webrick/test_httpserver.rb
@@ -223,7 +223,7 @@ class TestWEBrickHTTPServer < Test::Unit::TestCase
:StopCallback => Proc.new{ stopped += 1 },
:RequestCallback => Proc.new{|req, res| requested0 += 1 },
}
- TestWEBrick.start_httpserver(config){|server, addr, port|
+ TestWEBrick.start_httpserver(config){|server, addr, port, log|
vhost_config = {
:ServerName => "myhostname",
:BindAddress => addr,
@@ -236,23 +236,23 @@ class TestWEBrickHTTPServer < Test::Unit::TestCase
server.virtual_host(WEBrick::HTTPServer.new(vhost_config))
true while server.status != :Running
- assert_equal(started, 1)
- assert_equal(stopped, 0)
- assert_equal(accepted, 0)
+ assert_equal(started, 1, log.call)
+ assert_equal(stopped, 0, log.call)
+ assert_equal(accepted, 0, log.call)
http = Net::HTTP.new(addr, port)
req = Net::HTTP::Get.new("/")
req["Host"] = "myhostname:#{port}"
- http.request(req){|res| assert_equal("404", res.code)}
- http.request(req){|res| assert_equal("404", res.code)}
- http.request(req){|res| assert_equal("404", res.code)}
+ http.request(req){|res| assert_equal("404", res.code, log.call)}
+ http.request(req){|res| assert_equal("404", res.code, log.call)}
+ http.request(req){|res| assert_equal("404", res.code, log.call)}
req["Host"] = "localhost:#{port}"
- http.request(req){|res| assert_equal("404", res.code)}
- http.request(req){|res| assert_equal("404", res.code)}
- http.request(req){|res| assert_equal("404", res.code)}
- assert_equal(6, accepted)
- assert_equal(3, requested0)
- assert_equal(3, requested1)
+ http.request(req){|res| assert_equal("404", res.code, log.call)}
+ http.request(req){|res| assert_equal("404", res.code, log.call)}
+ http.request(req){|res| assert_equal("404", res.code, log.call)}
+ assert_equal(6, accepted, log.call)
+ assert_equal(3, requested0, log.call)
+ assert_equal(3, requested1, log.call)
}
assert_equal(started, 1)
assert_equal(stopped, 1)
diff --git a/test/webrick/test_httputils.rb b/test/webrick/test_httputils.rb
index 9d39ff53ab..ebe8a2b8a5 100644
--- a/test/webrick/test_httputils.rb
+++ b/test/webrick/test_httputils.rb
@@ -30,24 +30,24 @@ class TestWEBrickHTTPUtils < Test::Unit::TestCase
assert_equal("/foo/bar/", normalize_path("//foo///.//bar/.///.//"))
assert_equal("/", normalize_path("//foo///..///bar/.///..//.//"))
- assert_raises(RuntimeError){ normalize_path("foo/bar") }
- assert_raises(RuntimeError){ normalize_path("..") }
- assert_raises(RuntimeError){ normalize_path("/..") }
- assert_raises(RuntimeError){ normalize_path("/./..") }
- assert_raises(RuntimeError){ normalize_path("/./../") }
- assert_raises(RuntimeError){ normalize_path("/./../..") }
- assert_raises(RuntimeError){ normalize_path("/./../../") }
- assert_raises(RuntimeError){ normalize_path("/./../") }
- assert_raises(RuntimeError){ normalize_path("/../..") }
- assert_raises(RuntimeError){ normalize_path("/../../") }
- assert_raises(RuntimeError){ normalize_path("/../../..") }
- assert_raises(RuntimeError){ normalize_path("/../../../") }
- assert_raises(RuntimeError){ normalize_path("/../foo/../") }
- assert_raises(RuntimeError){ normalize_path("/../foo/../../") }
- assert_raises(RuntimeError){ normalize_path("/foo/bar/../../../../") }
- assert_raises(RuntimeError){ normalize_path("/foo/../bar/../../") }
- assert_raises(RuntimeError){ normalize_path("/./../bar/") }
- assert_raises(RuntimeError){ normalize_path("/./../") }
+ assert_raise(RuntimeError){ normalize_path("foo/bar") }
+ assert_raise(RuntimeError){ normalize_path("..") }
+ assert_raise(RuntimeError){ normalize_path("/..") }
+ assert_raise(RuntimeError){ normalize_path("/./..") }
+ assert_raise(RuntimeError){ normalize_path("/./../") }
+ assert_raise(RuntimeError){ normalize_path("/./../..") }
+ assert_raise(RuntimeError){ normalize_path("/./../../") }
+ assert_raise(RuntimeError){ normalize_path("/./../") }
+ assert_raise(RuntimeError){ normalize_path("/../..") }
+ assert_raise(RuntimeError){ normalize_path("/../../") }
+ assert_raise(RuntimeError){ normalize_path("/../../..") }
+ assert_raise(RuntimeError){ normalize_path("/../../../") }
+ assert_raise(RuntimeError){ normalize_path("/../foo/../") }
+ assert_raise(RuntimeError){ normalize_path("/../foo/../../") }
+ assert_raise(RuntimeError){ normalize_path("/foo/bar/../../../../") }
+ assert_raise(RuntimeError){ normalize_path("/foo/../bar/../../") }
+ assert_raise(RuntimeError){ normalize_path("/./../bar/") }
+ assert_raise(RuntimeError){ normalize_path("/./../") }
end
def test_split_header_value
diff --git a/test/webrick/test_server.rb b/test/webrick/test_server.rb
index ce5ee85c6c..4c064fdb4b 100644
--- a/test/webrick/test_server.rb
+++ b/test/webrick/test_server.rb
@@ -13,12 +13,12 @@ class TestWEBrickServer < Test::Unit::TestCase
end
def test_server
- TestWEBrick.start_server(Echo){|server, addr, port|
+ TestWEBrick.start_server(Echo){|server, addr, port, log|
TCPSocket.open(addr, port){|sock|
- sock.puts("foo"); assert_equal("foo\n", sock.gets)
- sock.puts("bar"); assert_equal("bar\n", sock.gets)
- sock.puts("baz"); assert_equal("baz\n", sock.gets)
- sock.puts("qux"); assert_equal("qux\n", sock.gets)
+ sock.puts("foo"); assert_equal("foo\n", sock.gets, log.call)
+ sock.puts("bar"); assert_equal("bar\n", sock.gets, log.call)
+ sock.puts("baz"); assert_equal("baz\n", sock.gets, log.call)
+ sock.puts("qux"); assert_equal("qux\n", sock.gets, log.call)
}
}
end
@@ -30,15 +30,15 @@ class TestWEBrickServer < Test::Unit::TestCase
:StartCallback => Proc.new{ started += 1 },
:StopCallback => Proc.new{ stopped += 1 },
}
- TestWEBrick.start_server(Echo, config){|server, addr, port|
+ TestWEBrick.start_server(Echo, config){|server, addr, port, log|
true while server.status != :Running
- assert_equal(started, 1)
- assert_equal(stopped, 0)
- assert_equal(accepted, 0)
+ assert_equal(started, 1, log.call)
+ assert_equal(stopped, 0, log.call)
+ assert_equal(accepted, 0, log.call)
TCPSocket.open(addr, port){|sock| (sock << "foo\n").gets }
TCPSocket.open(addr, port){|sock| (sock << "foo\n").gets }
TCPSocket.open(addr, port){|sock| (sock << "foo\n").gets }
- assert_equal(accepted, 3)
+ assert_equal(accepted, 3, log.call)
}
assert_equal(started, 1)
assert_equal(stopped, 1)
diff --git a/test/webrick/test_utils.rb b/test/webrick/test_utils.rb
index ace4632547..e63e0ebbfd 100644
--- a/test/webrick/test_utils.rb
+++ b/test/webrick/test_utils.rb
@@ -16,9 +16,9 @@ class TestWEBrickUtils < Test::Unit::TestCase
assert_expired(true, m)
i = 0
- assert_raises(Timeout::Error){
+ assert_raise(Timeout::Error){
m.timeout(2){
- assert_raises(Timeout::Error){ m.timeout(1){ i += 1; sleep } }
+ assert_raise(Timeout::Error){ m.timeout(1){ i += 1; sleep } }
assert_expired(false, m)
i += 1
sleep
@@ -27,14 +27,14 @@ class TestWEBrickUtils < Test::Unit::TestCase
assert_equal(2, i)
assert_expired(true, m)
- assert_raises(Timeout::Error){ m.timeout(0.1){ sleep } }
+ assert_raise(Timeout::Error){ m.timeout(0.1){ sleep } }
assert_expired(true, m)
- assert_raises(ex){ m.timeout(0.1, ex){ sleep } }
+ assert_raise(ex){ m.timeout(0.1, ex){ sleep } }
assert_expired(true, m)
i = 0
- assert_raises(ex){
+ assert_raise(ex){
m.timeout(10){
m.timeout(1, ex){ i += 1; sleep }
}
@@ -44,7 +44,7 @@ class TestWEBrickUtils < Test::Unit::TestCase
assert_expired(true, m)
i = 0
- assert_raises(Timeout::Error){
+ assert_raise(Timeout::Error){
m.timeout(1){
m.timeout(10, ex){ i += 1; sleep }
}
diff --git a/test/webrick/utils.rb b/test/webrick/utils.rb
index 39cadcff54..82df9cde69 100644
--- a/test/webrick/utils.rb
+++ b/test/webrick/utils.rb
@@ -27,23 +27,30 @@ module TestWEBrick
module_function
def start_server(klass, config={}, &block)
+ log_string = ""
+ logger = Object.new
+ logger.instance_eval do
+ define_singleton_method(:<<) {|msg| log_string << msg }
+ end
+ log = proc { "webrick log start:\n" + log_string.gsub(/^/, " ").chomp + "\nwebrick log end" }
server = klass.new({
:BindAddress => "127.0.0.1", :Port => 0,
:ShutdownSocketWithoutClose =>true,
:ServerType => Thread,
- :Logger => WEBrick::Log.new(NullWriter),
- :AccessLog => [[NullWriter, ""]]
+ :Logger => WEBrick::Log.new(logger),
+ :AccessLog => [[logger, ""]]
}.update(config))
begin
server.start
addr = server.listeners[0].addr
- block.yield([server, addr[3], addr[1]])
+ block.yield([server, addr[3], addr[1], log])
ensure
server.shutdown
until server.status == :Stop
sleep 0.1
end
end
+ log_string
end
def start_httpserver(config={}, &block)
diff --git a/test/win32ole/err_in_callback.rb b/test/win32ole/err_in_callback.rb
index d09870c95d..fabb7bef0e 100644
--- a/test/win32ole/err_in_callback.rb
+++ b/test/win32ole/err_in_callback.rb
@@ -1,11 +1,9 @@
require 'win32ole'
-ie = WIN32OLE.new('InternetExplorer.Application')
-ie.visible = true
-WIN32OLE_EVENT.message_loop
-sleep 0.2
-ev = WIN32OLE_EVENT.new(ie)
-
-ev.on_event('BeforeNavigate2') {|*args|
+db = WIN32OLE.new('ADODB.Connection')
+db.connectionString = "Driver={Microsoft Text Driver (*.txt; *.csv)};DefaultDir=.;"
+ev = WIN32OLE_EVENT.new(db)
+ev.on_event('WillConnect') {|*args|
foo
}
-ie.navigate(ARGV.shift)
+db.open
+WIN32OLE_EVENT.message_loop
diff --git a/test/win32ole/orig_data.csv b/test/win32ole/orig_data.csv
new file mode 100644
index 0000000000..3931c6ad1b
--- /dev/null
+++ b/test/win32ole/orig_data.csv
@@ -0,0 +1,5 @@
+ID,VALUE
+1,"A"
+2,"B"
+3,"C"
+4,"B"
diff --git a/test/win32ole/test_err_in_callback.rb b/test/win32ole/test_err_in_callback.rb
index 11ea6273fd..bbbab719d6 100644
--- a/test/win32ole/test_err_in_callback.rb
+++ b/test/win32ole/test_err_in_callback.rb
@@ -21,27 +21,12 @@ if defined?(WIN32OLE)
" -I " + e
}.join("")
@script = File.dirname(__FILE__) + "/err_in_callback.rb"
- @param = create_temp_html
- @param = "file:///" + @param.gsub(/\\/, '/')
end
end
- def create_temp_html
- fso = WIN32OLE.new('Scripting.FileSystemObject')
- dummy_file = fso.GetTempName + ".html"
- cfolder = fso.getFolder(".")
- @str = "This is test HTML file for Win32OLE (#{Time.now})"
- f = cfolder.CreateTextFile(dummy_file)
- f.writeLine("<html><body><div id='str'>#{@str}</div></body></html>")
- f.close
- @f = dummy_file
- dummy_path = cfolder.path + "\\" + dummy_file
- dummy_path
- end
-
def test_err_in_callback
if @ruby
- cmd = "#{@ruby} -v #{@iopt} #{@script} #{@param} > test_err_in_callback.log 2>&1"
+ cmd = "#{@ruby} -v #{@iopt} #{@script} > test_err_in_callback.log 2>&1"
system(cmd)
str = ""
open("test_err_in_callback.log") {|ifs|
@@ -51,32 +36,9 @@ if defined?(WIN32OLE)
end
end
- def ie_quit
- sh = WIN32OLE.new('Shell.Application')
- sh.windows.each do |w|
- if w.ole_type.name == 'IWebBrowser2'
- 20.times do |i|
- if w.locationURL != "" && w.document
- break
- end
- WIN32OLE_EVENT.message_loop
- sleep 1
- end
- e = w.document.getElementById("str")
- if e && e.innerHTML == @str
- w.quit
- WIN32OLE_EVENT.message_loop
- sleep 0.2
- end
- end
- end
- end
-
def teardown
- WIN32OLE_EVENT.message_loop
- ie_quit
- File.unlink(@f)
File.unlink("test_err_in_callback.log")
end
+
end
end
diff --git a/test/win32ole/test_win32ole.rb b/test/win32ole/test_win32ole.rb
index 914610375c..b946aa6ff0 100644
--- a/test/win32ole/test_win32ole.rb
+++ b/test/win32ole/test_win32ole.rb
@@ -153,6 +153,15 @@ if defined?(WIN32OLE)
assert_instance_of(WIN32OLE, @dict2)
end
+ def test_s_new_exc
+ assert_raise(TypeError) {
+ WIN32OLE.new(1)
+ }
+ assert_raise(TypeError) {
+ WIN32OLE.new("Scripting.Dictionary", 1)
+ }
+ end
+
def test_s_new_DCOM
rshell = WIN32OLE.new("Shell.Application")
assert_instance_of(WIN32OLE, rshell)
@@ -172,6 +181,12 @@ if defined?(WIN32OLE)
assert_instance_of(WIN32OLE, obj)
end
+ def test_s_connect_exc
+ assert_raise(TypeError) {
+ WIN32OLE.connect(1)
+ }
+ end
+
def test_invoke_accept_symbol_hash_key
fso = WIN32OLE.new('Scripting.FileSystemObject')
afolder = fso.getFolder(".")
@@ -361,6 +376,22 @@ if defined?(WIN32OLE)
end
end
+ def test_cp51932
+ cp = WIN32OLE.codepage
+ begin
+ obj = WIN32OLE_VARIANT.new([0x3042].pack("U*").force_encoding("UTF-8"))
+ begin
+ WIN32OLE.codepage = 51932
+ rescue
+ end
+ if WIN32OLE.codepage == 51932
+ assert_equal("\xA4\xA2".force_encoding("CP51932"), obj.value)
+ end
+ ensure
+ WIN32OLE.codepage = cp
+ end
+ end
+
def test_s_locale
assert_equal(WIN32OLE::LOCALE_SYSTEM_DEFAULT, WIN32OLE.locale)
end
diff --git a/test/win32ole/test_win32ole_event.rb b/test/win32ole/test_win32ole_event.rb
index 5b2a1af420..dff9a68c9b 100644
--- a/test/win32ole/test_win32ole_event.rb
+++ b/test/win32ole/test_win32ole_event.rb
@@ -4,330 +4,331 @@ rescue LoadError
end
require 'test/unit'
-if defined?(WIN32OLE_EVENT)
- class TestWIN32OLE_EVENT < Test::Unit::TestCase
- module IE
- end
- def create_temp_html
- fso = WIN32OLE.new('Scripting.FileSystemObject')
- dummy_file = fso.GetTempName + ".html"
- cfolder = fso.getFolder(".")
- f = cfolder.CreateTextFile(dummy_file)
- f.writeLine("<html><body>This is test HTML file for Win32OLE.</body></html>")
- f.close
- dummy_path = cfolder.path + "\\" + dummy_file
- dummy_path
+def ado_installed?
+ installed = false
+ if defined?(WIN32OLE)
+ db = nil
+ begin
+ db = WIN32OLE.new('ADODB.Connection')
+ db.connectionString = "Driver={Microsoft Text Driver (*.txt; *.csv)};DefaultDir=.;"
+ db.open
+ db.close
+ db = nil
+ installed = true
+ rescue
end
+ end
+ installed
+end
- def message_loop
- WIN32OLE_EVENT.message_loop
- sleep 0.1
- end
+if defined?(WIN32OLE_EVENT)
+ dotest = ado_installed?
+ if !dotest
+ STDERR.puts("\n#{__FILE__} skipped(ActiveX Data Object Library not found.)")
+ end
+ if dotest
+ class TestWIN32OLE_EVENT < Test::Unit::TestCase
+ CONNSTR="Driver={Microsoft Text Driver (*.txt; *.csv)};DefaultDir=.;"
+ module ADO
+ end
+ def message_loop
+ WIN32OLE_EVENT.message_loop
+ end
- def wait_ie
- while @ie.readyState != IE::READYSTATE_COMPLETE
- message_loop
+ def default_handler(event, *args)
+ @event += event
end
- end
- def setup
- WIN32OLE_EVENT.message_loop
- @ie = WIN32OLE.new("InternetExplorer.Application")
- if !defined?(IE::READYSTATE_COMPLETE)
- WIN32OLE.const_load(@ie, IE)
- end
- @ie.visible = true
- message_loop
- @event = ""
- @event2 = ""
- @event3 = ""
- @f = create_temp_html
- end
+ def setup
+ @db = WIN32OLE.new('ADODB.Connection')
+ if !defined?(ADO::AdStateOpen)
+ WIN32OLE.const_load(@db, ADO)
+ end
+ @db.connectionString = CONNSTR
+ @event = ""
+ @event2 = ""
+ @event3 = ""
+ end
- def default_handler(event, *args)
- @event += event
- end
+ def test_s_new
+ assert_raise(TypeError) {
+ ev = WIN32OLE_EVENT.new("A")
+ }
+ end
- def test_s_new
- assert_raise(TypeError) {
- ev = WIN32OLE_EVENT.new("A")
- }
- end
+ def test_s_new_without_itf
+ ev = WIN32OLE_EVENT.new(@db)
+ ev.on_event {|*args| default_handler(*args)}
+ @db.open
+ @db.close
+ 10.times do |i|
+ WIN32OLE_EVENT.new(@db)
+ GC.start
+ message_loop
+ @db.open
+ message_loop
+ @db.close
+ end
+ assert_match(/WillConnect/, @event)
+ end
- def test_s_new_without_itf
- ev = WIN32OLE_EVENT.new(@ie)
- ev.on_event {|*args| default_handler(*args)}
- @ie.navigate("file:///#{@f}")
- while @ie.busy
- WIN32OLE_EVENT.new(@ie)
- GC.start
+ def test_on_event
+ ev = WIN32OLE_EVENT.new(@db, 'ConnectionEvents')
+ ev.on_event {|*args| default_handler(*args)}
+ @db.open
message_loop
+ assert_match(/WillConnect/, @event)
end
- assert_match(/BeforeNavigate/, @event)
- assert_match(/NavigateComplete/, @event)
- end
-
- def test_on_event
- ev = WIN32OLE_EVENT.new(@ie, 'DWebBrowserEvents')
- ev.on_event {|*args| default_handler(*args)}
- @ie.navigate("file:///#{@f}")
- wait_ie
- assert_match(/BeforeNavigate/, @event)
- assert_match(/NavigateComplete/, @event)
- end
- def test_on_event_symbol
- ev = WIN32OLE_EVENT.new(@ie)
- ev.on_event(:BeforeNavigate2) {|*args|
- handler1
- }
- @ie.navigate("file:///#{@f}")
- wait_ie
- assert_equal("handler1", @event2)
- end
-
- def test_on_event2
- ev = WIN32OLE_EVENT.new(@ie, 'DWebBrowserEvents')
- ev.on_event('BeforeNavigate') {|*args| handler1}
- ev.on_event('BeforeNavigate') {|*args| handler2}
- @ie.navigate("file:///#{@f}")
- wait_ie
- assert_equal("handler2", @event2)
- end
+ def test_on_event_symbol
+ ev = WIN32OLE_EVENT.new(@db)
+ ev.on_event(:WillConnect) {|*args|
+ handler1
+ }
+ @db.open
+ message_loop
+ assert_equal("handler1", @event2)
+ end
- def test_on_event3
- ev = WIN32OLE_EVENT.new(@ie, 'DWebBrowserEvents')
- ev.on_event {|*args| handler1}
- ev.on_event {|*args| handler2}
- @ie.navigate("file:///#{@f}")
- wait_ie
- assert_equal("handler2", @event2)
- end
+ def test_on_event2
+ ev = WIN32OLE_EVENT.new(@db, 'ConnectionEvents')
+ ev.on_event('WillConnect') {|*args| handler1}
+ ev.on_event('WillConnect') {|*args| handler2}
+ @db.open
+ message_loop
+ assert_equal("handler2", @event2)
+ end
- def test_on_event4
- ev = WIN32OLE_EVENT.new(@ie, 'DWebBrowserEvents')
- ev.on_event{|*args| handler1}
- ev.on_event{|*args| handler2}
- ev.on_event('NavigateComplete'){|*args| handler3(*args)}
- @ie.navigate("file:///#{@f}")
- wait_ie
- assert(@event3!="")
- assert("handler2", @event2)
- end
+ def test_on_event3
+ ev = WIN32OLE_EVENT.new(@db, 'ConnectionEvents')
+ ev.on_event('WillConnect') {|*args| handler1}
+ ev.on_event('WillConnect') {|*args| handler2}
+ @db.open
+ message_loop
+ assert_equal("handler2", @event2)
+ end
- def test_on_event5
- ev = WIN32OLE_EVENT.new(@ie, 'DWebBrowserEvents')
- ev.on_event {|*args| default_handler(*args)}
- ev.on_event('NavigateComplete'){|*args| handler3(*args)}
- @ie.navigate("file:///#{@f}")
- wait_ie
- assert_match(/BeforeNavigate/, @event)
- assert(/NavigateComplete/ !~ @event)
- assert(@event!="")
- end
+ def test_on_event4
+ ev = WIN32OLE_EVENT.new(@db, 'ConnectionEvents')
+ ev.on_event{|*args| handler1}
+ ev.on_event{|*args| handler2}
+ ev.on_event('WillConnect'){|*args| handler3(*args)}
+ @db.open
+ message_loop
+ assert_equal(CONNSTR, @event3)
+ assert("handler2", @event2)
+ end
- def test_unadvise
- ev = WIN32OLE_EVENT.new(@ie, 'DWebBrowserEvents')
- ev.on_event {|*args| default_handler(*args)}
- @ie.navigate("file:///#{@f}")
- wait_ie
- assert_match(/BeforeNavigate/, @event)
- ev.unadvise
- @event = ""
- @ie.navigate("file:///#{@f}")
- wait_ie
- assert_equal("", @event);
- assert_raise(WIN32OLERuntimeError) {
+ def test_on_event5
+ ev = WIN32OLE_EVENT.new(@db, 'ConnectionEvents')
ev.on_event {|*args| default_handler(*args)}
- }
- end
-
- def test_non_exist_event
- assert_raise(RuntimeError) {
- ev = WIN32OLE_EVENT.new(@ie, 'XXXX')
- }
- dict = WIN32OLE.new('Scripting.Dictionary')
- assert_raise(RuntimeError) {
- ev = WIN32OLE_EVENT.new(dict)
- }
- end
+ ev.on_event('WillConnect'){|*args| handler3(*args)}
+ @db.open
+ message_loop
+ assert_match(/ConnectComplete/, @event)
+ assert(/WillConnect/ !~ @event)
+ assert_equal(CONNSTR, @event3)
+ end
- def test_on_event_with_outargs
- ev = WIN32OLE_EVENT.new(@ie)
- # ev.on_event_with_outargs('BeforeNavigate'){|*args|
- # args.last[5] = true # Cancel = true
- # }
- ev.on_event_with_outargs('BeforeNavigate2'){|*args|
- args.last[6] = true # Cancel = true
- }
- bl = @ie.locationURL
- @ie.navigate("file:///#{@f}")
- wait_ie
- assert_equal(bl, @ie.locationURL)
- end
+ def test_unadvise
+ ev = WIN32OLE_EVENT.new(@db, 'ConnectionEvents')
+ ev.on_event {|*args| default_handler(*args)}
+ @db.open
+ message_loop
+ assert_match(/WillConnect/, @event)
+ ev.unadvise
+ @event = ""
+ @db.close
+ @db.open
+ message_loop
+ assert_equal("", @event);
+ assert_raise(WIN32OLERuntimeError) {
+ ev.on_event {|*args| default_handler(*args)}
+ }
+ end
- def test_on_event_hash_return
- ev = WIN32OLE_EVENT.new(@ie)
- ev.on_event('BeforeNavigate2'){|*args|
- {:return => 1, :Cancel => true}
- }
- bl = @ie.locationURL
- @ie.navigate("file:///#{@f}")
- wait_ie
- assert_equal(bl, @ie.locationURL)
- end
+ def test_non_exist_event
+ assert_raise(RuntimeError) {
+ ev = WIN32OLE_EVENT.new(@db, 'XXXX')
+ }
+ dict = WIN32OLE.new('Scripting.Dictionary')
+ assert_raise(RuntimeError) {
+ ev = WIN32OLE_EVENT.new(dict)
+ }
+ end
- def test_on_event_hash_return2
- ev = WIN32OLE_EVENT.new(@ie)
- ev.on_event('BeforeNavigate2'){|*args|
- {:Cancel => true}
- }
- bl = @ie.locationURL
- @ie.navigate("file:///#{@f}")
- wait_ie
- assert_equal(bl, @ie.locationURL)
- end
+ def test_on_event_with_outargs
+ ev = WIN32OLE_EVENT.new(@db)
+ @db.connectionString = 'XXX' # set illegal connection string
+ assert_raise(WIN32OLERuntimeError) {
+ @db.open
+ }
+ ev.on_event_with_outargs('WillConnect'){|*args|
+ args.last[0] = CONNSTR # ConnectionString = CONNSTR
+ }
+ @db.open
+ message_loop
+ assert(true)
+ end
- def test_on_event_hash_return3
- ev = WIN32OLE_EVENT.new(@ie)
- ev.on_event('BeforeNavigate2'){|*args|
- {'Cancel' => true}
- }
- bl = @ie.locationURL
- @ie.navigate("file:///#{@f}")
- wait_ie
- assert_equal(bl, @ie.locationURL)
- end
-
- def test_on_event_hash_return4
- ev = WIN32OLE_EVENT.new(@ie)
- ev.on_event('BeforeNavigate2'){|*args|
- {'return' => 2, 'Cancel' => true}
- }
- bl = @ie.locationURL
- @ie.navigate("file:///#{@f}")
- wait_ie
- assert_equal(bl, @ie.locationURL)
- end
+ def test_on_event_hash_return
+ ev = WIN32OLE_EVENT.new(@db)
+ ev.on_event('WillConnect'){|*args|
+ {:return => 1, :ConnectionString => CONNSTR}
+ }
+ @db.connectionString = 'XXX'
+ @db.open
+ assert(true)
+ end
- def test_on_event_hash_return5
- ev = WIN32OLE_EVENT.new(@ie)
- ev.on_event('BeforeNavigate2'){|*args|
- {6 => true}
- }
- bl = @ie.locationURL
- @ie.navigate("file:///#{@f}")
- wait_ie
- assert_equal(bl, @ie.locationURL)
- end
+ def test_on_event_hash_return2
+ ev = WIN32OLE_EVENT.new(@db)
+ ev.on_event('WillConnect'){|*args|
+ {:ConnectionString => CONNSTR}
+ }
+ @db.connectionString = 'XXX'
+ @db.open
+ assert(true)
+ end
- def test_off_event
- ev = WIN32OLE_EVENT.new(@ie)
- ev.on_event{handler1}
- ev.off_event
- @ie.navigate("file:///#{@f}")
- wait_ie
- assert_equal("", @event2)
- end
+ def test_on_event_hash_return3
+ ev = WIN32OLE_EVENT.new(@db)
+ ev.on_event('WillConnect'){|*args|
+ {'ConnectionString' => CONNSTR}
+ }
+ @db.connectionString = 'XXX'
+ @db.open
+ assert(true)
+ end
- def test_off_event_arg
- ev = WIN32OLE_EVENT.new(@ie)
- ev.on_event('BeforeNavigate2'){handler1}
- ev.off_event('BeforeNavigate2')
- @ie.navigate("file:///#{@f}")
- wait_ie
- assert_equal("", @event2)
- end
+ def test_on_event_hash_return4
+ ev = WIN32OLE_EVENT.new(@db)
+ ev.on_event('WillConnect'){|*args|
+ {'return' => 1, 'ConnectionString' => CONNSTR}
+ }
+ @db.connectionString = 'XXX'
+ @db.open
+ assert(true)
+ end
- def test_off_event_sym_arg
- ev = WIN32OLE_EVENT.new(@ie)
- ev.on_event('BeforeNavigate2'){handler1}
- ev.off_event(:BeforeNavigate2)
- @ie.navigate("file:///#{@f}")
- wait_ie
- assert_equal("", @event2)
- end
+ def test_on_event_hash_return5
+ ev = WIN32OLE_EVENT.new(@db)
+ ev.on_event('WillConnect'){|*args|
+ {0 => CONNSTR}
+ }
+ @db.connectionString = 'XXX'
+ @db.open
+ assert(true)
+ end
- def handler1
- @event2 = "handler1"
- end
+ def test_off_event
+ ev = WIN32OLE_EVENT.new(@db)
+ ev.on_event{handler1}
+ ev.off_event
+ @db.open
+ message_loop
+ assert_equal("", @event2)
+ end
- def handler2
- @event2 = "handler2"
- end
+ def test_off_event_arg
+ ev = WIN32OLE_EVENT.new(@db)
+ ev.on_event('WillConnect'){handler1}
+ ev.off_event('WillConnect')
+ @db.open
+ message_loop
+ assert_equal("", @event2)
+ end
- def handler3(url)
- @event3 += url
- end
+ def test_off_event_arg2
+ ev = WIN32OLE_EVENT.new(@db)
+ ev.on_event('WillConnect'){handler1}
+ ev.on_event('ConnectComplete'){handler1}
+ ev.off_event('WillConnect')
+ @db.open
+ message_loop
+ assert_equal("handler1", @event2)
+ end
- def teardown
- @ie.quit
- message_loop
- @ie = nil
- i = 0
- begin
- i += 1
- File.unlink(@f) if i < 10
- rescue Errno::EACCES
+ def test_off_event_sym_arg
+ ev = WIN32OLE_EVENT.new(@db)
+ ev.on_event('WillConnect'){handler1}
+ ev.off_event(:WillConnect)
+ @db.open
message_loop
- retry
+ assert_equal("", @event2)
end
- message_loop
- GC.start
- message_loop
- end
- class Handler1
- attr_reader :val1, :val2, :val3, :val4
- def initialize
- @val1 = nil
- @val2 = nil
- @val3 = nil
- @val4 = nil
+ def handler1
+ @event2 = "handler1"
end
- def onStatusTextChange(t)
- @val1 = t
+
+ def handler2
+ @event2 = "handler2"
end
- def onProgressChange(p, pmax)
- @val2 = p
- @val3 = pmax
+
+ def handler3(*arg)
+ @event3 += arg[0]
end
- def onPropertyChange(p)
- @val4 = p
+
+ def teardown
+ if @db && @db.state == ADO::AdStateOpen
+ @db.close
+ end
+ message_loop
+ @db = nil
end
- end
- class Handler2
- attr_reader :ev
- def initialize
- @ev = ""
+ class Handler1
+ attr_reader :val1, :val2, :val3, :val4
+ def initialize
+ @val1 = nil
+ @val2 = nil
+ @val3 = nil
+ @val4 = nil
+ end
+ def onWillConnect(conn, uid, pwd, opts, stat, pconn)
+ @val1 = conn
+ end
+ def onConnectComplete(err, stat, pconn)
+ @val2 = err
+ @val3 = stat
+ end
+ def onInfoMessage(err, stat, pconn)
+ @val4 = stat
+ end
end
- def method_missing(ev, *arg)
- @ev += ev
+
+ class Handler2
+ attr_reader :ev
+ def initialize
+ @ev = ""
+ end
+ def method_missing(ev, *arg)
+ @ev += ev
+ end
end
- end
- def test_handler1
- ev = WIN32OLE_EVENT.new(@ie)
- h1 = Handler1.new
- ev.handler = h1
- @ie.navigate("file:///#{@f}")
- wait_ie
- assert(h1.val1)
- assert_equal(h1.val1, ev.handler.val1)
- assert(h1.val2)
- assert(h1.val3)
- assert(h1.val4)
- end
+ def test_handler1
+ ev = WIN32OLE_EVENT.new(@db)
+ h1 = Handler1.new
+ ev.handler = h1
+ @db.open
+ message_loop
+ assert_equal(CONNSTR, h1.val1)
+ assert_equal(h1.val1, ev.handler.val1)
+ assert_equal(nil, h1.val2)
+ assert_equal(ADO::AdStateOpen, h1.val3)
+ assert_equal(ADO::AdStateOpen, h1.val4)
+ end
- def test_handler2
- ev = WIN32OLE_EVENT.new(@ie)
- h2 = Handler2.new
- ev.handler = h2
- @ie.navigate("file:///#{@f}")
- wait_ie
- assert(h2.ev != "")
+ def test_handler2
+ ev = WIN32OLE_EVENT.new(@db)
+ h2 = Handler2.new
+ ev.handler = h2
+ @db.open
+ message_loop
+ assert(h2.ev != "")
+ end
end
-
end
end
diff --git a/test/win32ole/test_win32ole_method.rb b/test/win32ole/test_win32ole_method.rb
index 161b10233f..f2ed0c622c 100644
--- a/test/win32ole/test_win32ole_method.rb
+++ b/test/win32ole/test_win32ole_method.rb
@@ -24,6 +24,9 @@ if defined?(WIN32OLE_METHOD)
def test_initialize
ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ assert_raise(TypeError) {
+ WIN32OLE_METHOD.new(1, 2)
+ }
assert_raise(ArgumentError) {
method = WIN32OLE_METHOD.new("foo")
}
diff --git a/test/win32ole/test_win32ole_typelib.rb b/test/win32ole/test_win32ole_typelib.rb
index a1c3891396..389a5e6fea 100644
--- a/test/win32ole/test_win32ole_typelib.rb
+++ b/test/win32ole/test_win32ole_typelib.rb
@@ -10,7 +10,7 @@ if defined?(WIN32OLE_TYPELIB)
tlibs = WIN32OLE_TYPELIB.typelibs
assert_instance_of(Array, tlibs)
assert(tlibs.size > 0)
- tlib = tlibs.find {|tlib| tlib.name == "Microsoft Shell Controls And Automation"}
+ tlib = tlibs.find {|t| t.name == "Microsoft Shell Controls And Automation"}
assert(tlib)
end
diff --git a/test/win32ole/test_win32ole_variant.rb b/test/win32ole/test_win32ole_variant.rb
index 1226e0de50..af3876837d 100644
--- a/test/win32ole/test_win32ole_variant.rb
+++ b/test/win32ole/test_win32ole_variant.rb
@@ -18,6 +18,12 @@ if defined?(WIN32OLE_VARIANT)
assert_instance_of(WIN32OLE_VARIANT, obj)
end
+ def test_s_new_exc
+ assert_raise(TypeError) {
+ WIN32OLE_VARIANT.new(/foo/)
+ }
+ end
+
def test_s_new_no_argument
ex = nil
begin
diff --git a/test/win32ole/test_win32ole_variant_outarg.rb b/test/win32ole/test_win32ole_variant_outarg.rb
new file mode 100644
index 0000000000..1e4892f7f1
--- /dev/null
+++ b/test/win32ole/test_win32ole_variant_outarg.rb
@@ -0,0 +1,69 @@
+begin
+ require 'win32ole'
+rescue LoadError
+end
+require 'test/unit'
+require 'fileutils'
+
+def ado_csv_installed?
+ installed = false
+ if defined?(WIN32OLE)
+ db = nil
+ begin
+ db = WIN32OLE.new('ADODB.Connection')
+ db.connectionString = "Driver={Microsoft Text Driver (*.txt; *.csv)};DefaultDir=.;"
+ db.open
+ db.close
+ db = nil
+ installed = true
+ rescue
+ end
+ end
+ installed
+end
+
+if defined?(WIN32OLE_VARIANT)
+ dotest = ado_csv_installed?
+ if !dotest
+ STDERR.puts("\n#{__FILE__} skipped(ActiveX Data Object Library not found.)")
+ end
+ if dotest
+ class TestWIN32OLE_VARIANT_OUTARG < Test::Unit::TestCase
+ module ADO
+ end
+ CONNSTR="Driver={Microsoft Text Driver (*.txt; *.csv)};DefaultDir=.;"
+ def setup
+ FileUtils.cp(File.dirname(__FILE__) + '/orig_data.csv', './data.csv')
+ @db = WIN32OLE.new('ADODB.Connection')
+ if !defined?(ADO::AdStateOpen)
+ WIN32OLE.const_load(@db, ADO)
+ end
+ @db.connectionString = CONNSTR
+ @db.open
+ end
+
+ def test_variant_ref_and_argv
+ sql = "INSERT INTO data.csv VALUES (5, 'E')"
+ @db.execute(sql, -1)
+ c = WIN32OLE::ARGV[1]
+ assert_equal(1, WIN32OLE::ARGV[1])
+ obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_VARIANT|WIN32OLE::VARIANT::VT_BYREF)
+ assert_equal(nil, obj.value)
+ @db.execute(sql , obj)
+ assert_equal(1, obj.value)
+ obj = WIN32OLE_VARIANT.new(-100, WIN32OLE::VARIANT::VT_VARIANT|WIN32OLE::VARIANT::VT_BYREF)
+ assert_equal(-100, obj.value)
+ @db.execute(sql, obj)
+ assert_equal(1, obj.value)
+ end
+
+ def teardown
+ if @db && @db.state == ADO::AdStateOpen
+ @db.close
+ end
+ File.unlink("data.csv")
+ end
+
+ end
+ end
+end
diff --git a/test/win32ole/test_win32ole_variant_with_ie.rb b/test/win32ole/test_win32ole_variant_with_ie.rb
deleted file mode 100644
index 680f17ff54..0000000000
--- a/test/win32ole/test_win32ole_variant_with_ie.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-# This is test script to check WIN32OLE_VARIANT using Internet Explorer
-begin
- require 'win32ole'
-rescue LoadError
-end
-require 'test/unit'
-
-if defined?(WIN32OLE)
- class TestWIN32OLE_VARIANT_WITH_IE < Test::Unit::TestCase
- def create_temp_html
- fso = WIN32OLE.new('Scripting.FileSystemObject')
- dummy_file = fso.GetTempName + ".html"
- cfolder = fso.getFolder(".")
- f = cfolder.CreateTextFile(dummy_file)
- f.writeLine("<html><body>This is test HTML file for Win32OLE.</body></html>")
- f.close
- dummy_path = cfolder.path + "\\" + dummy_file
- dummy_path
- end
- def setup
- @f = create_temp_html
- @ie = WIN32OLE.new('InternetExplorer.Application')
- @ie.visible = true
- @ie.navigate("file:///#{@f}")
- while @ie.busy
- sleep 0.5
- end
- end
- def test_variant_ref_and_argv
- @ie.execWB(19, 0, nil, -1)
- size = WIN32OLE::ARGV[3]
- assert(size >= 0)
-
- obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_VARIANT|WIN32OLE::VARIANT::VT_BYREF)
- @ie.execWb(19, 0, nil, obj)
- assert_equal(size, obj.value)
- assert_equal(size, WIN32OLE::ARGV[3])
-
- obj = WIN32OLE_VARIANT.new(-1, WIN32OLE::VARIANT::VT_VARIANT|WIN32OLE::VARIANT::VT_BYREF)
- @ie.execWb(19, 0, nil, obj)
- assert_equal(size, obj.value)
- assert_equal(size, WIN32OLE::ARGV[3])
- end
-
- def teardown
- File.unlink(@f)
- if @ie
- @ie.quit
- @ie = nil
- end
- end
- end
-end
diff --git a/test/xmlrpc/test_datetime.rb b/test/xmlrpc/test_datetime.rb
index e38cea6f74..528e0805fc 100644
--- a/test/xmlrpc/test_datetime.rb
+++ b/test/xmlrpc/test_datetime.rb
@@ -10,18 +10,18 @@ class Test_DateTime < Test::Unit::TestCase
end
def test_new_exception
- assert_raises(ArgumentError) { XMLRPC::DateTime.new(4.5, 13, 32, 25, 60, 60) }
- assert_raises(ArgumentError) { XMLRPC::DateTime.new(2001, 12, 32, 25, 60, 60) }
- assert_raises(ArgumentError) { XMLRPC::DateTime.new(2001, 12, 31, 25, 60, 60) }
- assert_raises(ArgumentError) { XMLRPC::DateTime.new(2001, 12, 31, 24, 60, 60) }
- assert_raises(ArgumentError) { XMLRPC::DateTime.new(2001, 12, 31, 24, 59, 60) }
+ assert_raise(ArgumentError) { XMLRPC::DateTime.new(4.5, 13, 32, 25, 60, 60) }
+ assert_raise(ArgumentError) { XMLRPC::DateTime.new(2001, 12, 32, 25, 60, 60) }
+ assert_raise(ArgumentError) { XMLRPC::DateTime.new(2001, 12, 31, 25, 60, 60) }
+ assert_raise(ArgumentError) { XMLRPC::DateTime.new(2001, 12, 31, 24, 60, 60) }
+ assert_raise(ArgumentError) { XMLRPC::DateTime.new(2001, 12, 31, 24, 59, 60) }
assert_nothing_raised(ArgumentError) { XMLRPC::DateTime.new(2001, 12, 31, 24, 59, 59) }
- assert_raises(ArgumentError) { XMLRPC::DateTime.new(2001, 0, 0, -1, -1, -1) }
- assert_raises(ArgumentError) { XMLRPC::DateTime.new(2001, 1, 0, -1, -1, -1) }
- assert_raises(ArgumentError) { XMLRPC::DateTime.new(2001, 1, 1, -1, -1, -1) }
- assert_raises(ArgumentError) { XMLRPC::DateTime.new(2001, 1, 1, 0, -1, -1) }
- assert_raises(ArgumentError) { XMLRPC::DateTime.new(2001, 1, 1, 0, 0, -1) }
+ assert_raise(ArgumentError) { XMLRPC::DateTime.new(2001, 0, 0, -1, -1, -1) }
+ assert_raise(ArgumentError) { XMLRPC::DateTime.new(2001, 1, 0, -1, -1, -1) }
+ assert_raise(ArgumentError) { XMLRPC::DateTime.new(2001, 1, 1, -1, -1, -1) }
+ assert_raise(ArgumentError) { XMLRPC::DateTime.new(2001, 1, 1, 0, -1, -1) }
+ assert_raise(ArgumentError) { XMLRPC::DateTime.new(2001, 1, 1, 0, 0, -1) }
assert_nothing_raised(ArgumentError) { XMLRPC::DateTime.new(2001, 1, 1, 0, 0, 0) }
end
@@ -68,31 +68,31 @@ class Test_DateTime < Test::Unit::TestCase
def test_set_exception
dt = createDateTime()
- assert_raises(ArgumentError) { dt.year = 4.5 }
+ assert_raise(ArgumentError) { dt.year = 4.5 }
assert_nothing_raised(ArgumentError) { dt.year = -2000 }
- assert_raises(ArgumentError) { dt.month = 0 }
- assert_raises(ArgumentError) { dt.month = 13 }
+ assert_raise(ArgumentError) { dt.month = 0 }
+ assert_raise(ArgumentError) { dt.month = 13 }
assert_nothing_raised(ArgumentError) { dt.month = 7 }
- assert_raises(ArgumentError) { dt.mon = 0 }
- assert_raises(ArgumentError) { dt.mon = 13 }
+ assert_raise(ArgumentError) { dt.mon = 0 }
+ assert_raise(ArgumentError) { dt.mon = 13 }
assert_nothing_raised(ArgumentError) { dt.mon = 7 }
- assert_raises(ArgumentError) { dt.day = 0 }
- assert_raises(ArgumentError) { dt.day = 32 }
+ assert_raise(ArgumentError) { dt.day = 0 }
+ assert_raise(ArgumentError) { dt.day = 32 }
assert_nothing_raised(ArgumentError) { dt.day = 16 }
- assert_raises(ArgumentError) { dt.hour = -1 }
- assert_raises(ArgumentError) { dt.hour = 25 }
+ assert_raise(ArgumentError) { dt.hour = -1 }
+ assert_raise(ArgumentError) { dt.hour = 25 }
assert_nothing_raised(ArgumentError) { dt.hour = 12 }
- assert_raises(ArgumentError) { dt.min = -1 }
- assert_raises(ArgumentError) { dt.min = 60 }
+ assert_raise(ArgumentError) { dt.min = -1 }
+ assert_raise(ArgumentError) { dt.min = 60 }
assert_nothing_raised(ArgumentError) { dt.min = 30 }
- assert_raises(ArgumentError) { dt.sec = -1 }
- assert_raises(ArgumentError) { dt.sec = 60 }
+ assert_raise(ArgumentError) { dt.sec = -1 }
+ assert_raise(ArgumentError) { dt.sec = 60 }
assert_nothing_raised(ArgumentError) { dt.sec = 30 }
end
diff --git a/test/xmlrpc/test_features.rb b/test/xmlrpc/test_features.rb
index 96a6313202..377d539f26 100644
--- a/test/xmlrpc/test_features.rb
+++ b/test/xmlrpc/test_features.rb
@@ -15,7 +15,7 @@ class Test_Features < Test::Unit::TestCase
XMLRPC::Config.module_eval {remove_const(:ENABLE_NIL_CREATE)}
XMLRPC::Config.const_set(:ENABLE_NIL_CREATE, false)
- assert_raises(RuntimeError) { str = c.methodCall("test", *@params) }
+ assert_raise(RuntimeError) { str = c.methodCall("test", *@params) }
XMLRPC::Config.module_eval {remove_const(:ENABLE_NIL_CREATE)}
XMLRPC::Config.const_set(:ENABLE_NIL_CREATE, true)
@@ -35,7 +35,7 @@ class Test_Features < Test::Unit::TestCase
XMLRPC::Config.module_eval {remove_const(:ENABLE_NIL_PARSER)}
XMLRPC::Config.const_set(:ENABLE_NIL_PARSER, false)
- assert_raises(RuntimeError) { para = parser.parseMethodCall(str) }
+ assert_raise(RuntimeError) { para = parser.parseMethodCall(str) }
XMLRPC::Config.module_eval {remove_const(:ENABLE_NIL_PARSER)}
XMLRPC::Config.const_set(:ENABLE_NIL_PARSER, true)
diff --git a/test/xmlrpc/test_webrick_server.rb b/test/xmlrpc/test_webrick_server.rb
index 4cd63cfa74..38cfe2f896 100644
--- a/test/xmlrpc/test_webrick_server.rb
+++ b/test/xmlrpc/test_webrick_server.rb
@@ -68,7 +68,7 @@ class Test_Webrick < Test::Unit::TestCase
assert_equal 9, @s.call('test.add', 4, 5)
# fault exception
- assert_raises(XMLRPC::FaultException) { @s.call('test.div', 1, 0) }
+ assert_raise(XMLRPC::FaultException) { @s.call('test.div', 1, 0) }
# fault exception via call2
ok, param = @s.call2('test.div', 1, 0)
diff --git a/test/yaml/test_yaml.rb b/test/yaml/test_yaml.rb
index 74a2fa851e..ed94705fcf 100644
--- a/test/yaml/test_yaml.rb
+++ b/test/yaml/test_yaml.rb
@@ -1107,6 +1107,30 @@ EOY
end
+ def test_ruby_rational
+ assert_to_yaml( Rational(1, 2), <<EOY )
+--- !ruby/object:Rational
+numerator: 1
+denominator: 2
+EOY
+
+ # Read YAML dumped by the ruby 1.8.3.
+ assert_to_yaml( Rational(1, 2), "!ruby/object:Rational 1/2\n" )
+ assert_raise( ArgumentError ) { YAML.load("!ruby/object:Rational INVALID/RATIONAL\n") }
+ end
+
+ def test_ruby_complex
+ assert_to_yaml( Complex(3, 4), <<EOY )
+--- !ruby/object:Complex
+image: 4
+real: 3
+EOY
+
+ # Read YAML dumped by the ruby 1.8.3.
+ assert_to_yaml( Complex(3, 4), "!ruby/object:Complex 3+4i\n" )
+ assert_raise( ArgumentError ) { YAML.load("!ruby/object:Complex INVALID+COMPLEXi\n") }
+ end
+
def test_emitting_indicators
assert_to_yaml( "Hi, from Object 1. You passed: please, pretty please", <<EOY
--- "Hi, from Object 1. You passed: please, pretty please"
diff --git a/test/zlib/test_zlib.rb b/test/zlib/test_zlib.rb
index fe8cee5622..9e4cf80033 100644
--- a/test/zlib/test_zlib.rb
+++ b/test/zlib/test_zlib.rb
@@ -470,17 +470,27 @@ if defined? Zlib
Zlib::GzipWriter.open(t.path) {|gz| gz.print("foobar") }
f = Zlib::GzipReader.open(t.path)
- "foobar".each_byte {|c| assert_equal(c, f.getc) }
+ "foobar".each_char {|c| assert_equal(c, f.getc) }
assert_nil(f.getc)
end
+ def test_getbyte
+ t = Tempfile.new("test_zlib_gzip_reader")
+ t.close
+ Zlib::GzipWriter.open(t.path) {|gz| gz.print("foobar") }
+
+ f = Zlib::GzipReader.open(t.path)
+ "foobar".each_byte {|c| assert_equal(c, f.getbyte) }
+ assert_nil(f.getbyte)
+ end
+
def test_readchar
t = Tempfile.new("test_zlib_gzip_reader")
t.close
Zlib::GzipWriter.open(t.path) {|gz| gz.print("foobar") }
f = Zlib::GzipReader.open(t.path)
- "foobar".each_byte {|c| assert_equal(c, f.readchar) }
+ "foobar".each_byte {|c| assert_equal(c, f.readchar.ord) }
assert_raise(EOFError) { f.readchar }
end
diff --git a/thread.c b/thread.c
index 563c4e4bac..24a5aace64 100644
--- a/thread.c
+++ b/thread.c
@@ -45,8 +45,8 @@
/* for model 2 */
#include "eval_intern.h"
-#include "vm.h"
#include "gc.h"
+#include "ruby/util.h"
#ifndef USE_NATIVE_THREAD_PRIORITY
#define USE_NATIVE_THREAD_PRIORITY 0
@@ -72,6 +72,7 @@ static void rb_check_deadlock(rb_vm_t *vm);
void rb_signal_exec(rb_thread_t *th, int sig);
void rb_disable_interrupt(void);
+void rb_thread_stop_timer_thread(void);
static const VALUE eKillSignal = INT2FIX(0);
static const VALUE eTerminateSignal = INT2FIX(1);
@@ -87,10 +88,19 @@ st_delete_wrap(st_table *table, st_data_t key)
#define THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION
+struct rb_blocking_region_buffer {
+ enum rb_thread_status prev_status;
+ struct rb_unblock_callback oldubf;
+};
+
static void set_unblock_function(rb_thread_t *th, rb_unblock_function_t *func, void *arg,
struct rb_unblock_callback *old);
static void reset_unblock_function(rb_thread_t *th, const struct rb_unblock_callback *old);
+static void inline blocking_region_begin(rb_thread_t *th, struct rb_blocking_region_buffer *region,
+ rb_unblock_function_t *func, void *arg);
+static void inline blocking_region_end(rb_thread_t *th, struct rb_blocking_region_buffer *region);
+
#define GVL_UNLOCK_BEGIN() do { \
rb_thread_t *_th_stored = GET_THREAD(); \
rb_gc_save_machine_context(_th_stored); \
@@ -110,18 +120,10 @@ static void reset_unblock_function(rb_thread_t *th, const struct rb_unblock_call
#define BLOCKING_REGION(exec, ubf, ubfarg) do { \
rb_thread_t *__th = GET_THREAD(); \
- enum rb_thread_status __prev_status = __th->status; \
- struct rb_unblock_callback __oldubf; \
- set_unblock_function(__th, ubf, ubfarg, &__oldubf); \
- __th->status = THREAD_STOPPED; \
- thread_debug("enter blocking region (%p)\n", __th); \
- BLOCKING_REGION_CORE(exec); \
- thread_debug("leave blocking region (%p)\n", __th); \
- remove_signal_thread_list(__th); \
- reset_unblock_function(__th, &__oldubf); \
- if (__th->status == THREAD_STOPPED) { \
- __th->status = __prev_status; \
- } \
+ struct rb_blocking_region_buffer __region; \
+ blocking_region_begin(__th, &__region, ubf, ubfarg); \
+ exec; \
+ blocking_region_end(__th, &__region); \
RUBY_VM_CHECK_INTS(); \
} while(0)
@@ -326,7 +328,7 @@ rb_vm_thread_terminate_all(rb_vm_t *vm)
}
POP_TAG();
}
- --system_working;
+ rb_thread_stop_timer_thread();
}
int
@@ -919,6 +921,15 @@ rb_thread_check_trap_pending(void)
return !rb_queue_empty_p(&GET_THREAD()->queue.signal);
}
+/* This function can be called in blocking region. */
+int
+rb_thread_interrupted(VALUE thval)
+{
+ rb_thread_t *th;
+ GetThreadPtr(thval, th);
+ return RUBY_VM_INTERRUPTED(th);
+}
+
struct timeval rb_time_timeval();
void
@@ -950,6 +961,79 @@ rb_thread_schedule(void)
}
}
+/* blocking region */
+static inline void
+blocking_region_begin(rb_thread_t *th, struct rb_blocking_region_buffer *region,
+ rb_unblock_function_t *func, void *arg)
+{
+ region->prev_status = th->status;
+ set_unblock_function(th, func, arg, &region->oldubf);
+ th->status = THREAD_STOPPED;
+ thread_debug("enter blocking region (%p)\n", th);
+ rb_gc_save_machine_context(th);
+ native_mutex_unlock(&th->vm->global_vm_lock);
+}
+
+static inline void
+blocking_region_end(rb_thread_t *th, struct rb_blocking_region_buffer *region)
+{
+ native_mutex_lock(&th->vm->global_vm_lock);
+ rb_thread_set_current(th);
+ thread_debug("leave blocking region (%p)\n", th);
+ remove_signal_thread_list(th);
+ reset_unblock_function(th, &region->oldubf);
+ if (th->status == THREAD_STOPPED) {
+ th->status = region->prev_status;
+ }
+}
+
+struct rb_blocking_region_buffer *
+rb_thread_blocking_region_begin(void)
+{
+ rb_thread_t *th = GET_THREAD();
+ struct rb_blocking_region_buffer *region = ALLOC(struct rb_blocking_region_buffer);
+ blocking_region_begin(th, region, ubf_select, th);
+ return region;
+}
+
+void
+rb_thread_blocking_region_end(struct rb_blocking_region_buffer *region)
+{
+ rb_thread_t *th = GET_THREAD();
+ blocking_region_end(th, region);
+ xfree(region);
+ RUBY_VM_CHECK_INTS();
+}
+
+/*
+ * rb_thread_blocking_region - permit concurrent/parallel execution.
+ *
+ * This function does:
+ * (1) release GVL.
+ * Other Ruby threads may run in parallel.
+ * (2) call func with data1.
+ * (3) aquire GVL.
+ * Other Ruby threads can not run in parallel any more.
+ *
+ * If another thread interrupts this thread (Thread#kill, signal deliverly,
+ * VM-shutdown request, and so on), `ubf()' is called (`ubf()' means
+ * "un-blocking function"). `ubf()' should interrupt `func()' execution.
+ *
+ * There are built-in ubfs and you can specify these ubfs.
+ * However, we can not guarantee our built-in ubfs interrupt
+ * your `func()' correctly. Be careful to use rb_thread_blocking_region().
+ *
+ * * RUBY_UBF_IO: ubf for IO operation
+ * * RUBY_UBF_PROCESS: ubf for process operation
+ *
+ * NOTE: You can not execute most of Ruby C API and touch Ruby objects
+ * in `func()' and `ubf()' because current thread doesn't acquire
+ * GVL (cause synchronization problem). If you need to do it,
+ * read source code of C APIs and confirm by yourself.
+ *
+ * Safe C API:
+ * * rb_thread_interrupted() - check interrupt flag
+ */
VALUE
rb_thread_blocking_region(
rb_blocking_function_t *func, void *data1,
@@ -2236,6 +2320,7 @@ rb_thread_wait_fd_rw(int fd, int read)
if (fd < 0) {
rb_raise(rb_eIOError, "closed stream");
}
+ if (rb_thread_alone()) return;
while (result <= 0) {
rb_fdset_t set;
rb_fd_init(&set);
@@ -2322,6 +2407,7 @@ int rb_get_next_signal(void);
static int
vm_set_timer_interrupt(rb_vm_t *vm, void *dummy)
{
+ /* for time slice */
RUBY_VM_SET_TIMER_INTERRUPT(vm->running_thread);
return Qtrue;
}
@@ -2388,7 +2474,7 @@ timer_thread_function(void *arg)
void
rb_thread_stop_timer_thread(void)
{
- if (timer_thread_id && --system_working == 0) {
+ if (timer_thread_id && native_stop_timer_thread()) {
native_thread_join(timer_thread_id);
timer_thread_id = 0;
}
@@ -3059,7 +3145,7 @@ mutex_sleep(int argc, VALUE *argv, VALUE self)
*/
VALUE
-rb_thread_synchronize(VALUE mutex, VALUE (*func)(VALUE arg), VALUE arg)
+rb_mutex_synchronize(VALUE mutex, VALUE (*func)(VALUE arg), VALUE arg)
{
rb_mutex_lock(mutex);
return rb_ensure(func, arg, rb_mutex_unlock, mutex);
@@ -3068,135 +3154,47 @@ rb_thread_synchronize(VALUE mutex, VALUE (*func)(VALUE arg), VALUE arg)
/*
* Document-class: Barrier
*/
-typedef struct rb_thread_list_struct rb_thread_list_t;
-
-struct rb_thread_list_struct {
- rb_thread_t *th;
- rb_thread_list_t *next;
-};
-
-static void
-thlist_mark(void *ptr)
-{
- rb_thread_list_t *q = ptr;
-
- for (; q; q = q->next) {
- rb_gc_mark(q->th->self);
- }
-}
-
-static void
-thlist_free(void *ptr)
-{
- rb_thread_list_t *q = ptr, *next;
-
- for (; q; q = next) {
- next = q->next;
- ruby_xfree(q);
- }
-}
-
-static int
-thlist_signal(rb_thread_list_t **list, unsigned int maxth, rb_thread_t **woken_thread)
-{
- int woken = 0;
- rb_thread_list_t *q;
-
- while ((q = *list) != NULL) {
- rb_thread_t *th = q->th;
-
- *list = q->next;
- ruby_xfree(q);
- if (th->status != THREAD_KILLED) {
- rb_thread_ready(th);
- if (!woken && woken_thread) *woken_thread = th;
- if (++woken >= maxth && maxth) break;
- }
- }
- return woken;
-}
-
-typedef struct {
- rb_thread_t *owner;
- rb_thread_list_t *waiting, **tail;
-} rb_barrier_t;
-
-static void
-barrier_mark(void *ptr)
-{
- rb_barrier_t *b = ptr;
-
- if (b->owner) rb_gc_mark(b->owner->self);
- thlist_mark(b->waiting);
-}
-
-static void
-barrier_free(void *ptr)
-{
- rb_barrier_t *b = ptr;
-
- b->owner = 0;
- thlist_free(b->waiting);
- b->waiting = 0;
- ruby_xfree(ptr);
-}
-
static VALUE
barrier_alloc(VALUE klass)
{
- VALUE volatile obj;
- rb_barrier_t *barrier;
-
- obj = Data_Make_Struct(klass, rb_barrier_t, barrier_mark, barrier_free, barrier);
- barrier->owner = GET_THREAD();
- barrier->waiting = 0;
- barrier->tail = &barrier->waiting;
- return obj;
+ return Data_Wrap_Struct(klass, rb_gc_mark, 0, (void *)mutex_alloc(0));
}
VALUE
rb_barrier_new(void)
{
- return barrier_alloc(rb_cBarrier);
+ VALUE barrier = barrier_alloc(rb_cBarrier);
+ rb_mutex_lock((VALUE)DATA_PTR(barrier));
+ return barrier;
}
VALUE
rb_barrier_wait(VALUE self)
{
- rb_barrier_t *barrier;
- rb_thread_list_t *q;
+ VALUE mutex = (VALUE)DATA_PTR(self);
+ mutex_t *m;
- Data_Get_Struct(self, rb_barrier_t, barrier);
- if (!barrier->owner || barrier->owner->status == THREAD_KILLED) {
- barrier->owner = 0;
- if (thlist_signal(&barrier->waiting, 1, &barrier->owner)) return Qfalse;
- return Qtrue;
- }
- else if (barrier->owner == GET_THREAD()) {
- return Qfalse;
- }
- else {
- *barrier->tail = q = ALLOC(rb_thread_list_t);
- q->th = GET_THREAD();
- q->next = 0;
- barrier->tail = &q->next;
- rb_thread_sleep_forever();
- return barrier->owner == GET_THREAD() ? Qtrue : Qfalse;
- }
+ if (!mutex) return Qfalse;
+ GetMutexPtr(mutex, m);
+ if (m->th == GET_THREAD()) return Qfalse;
+ rb_mutex_lock(mutex);
+ if (DATA_PTR(self)) return Qtrue;
+ rb_mutex_unlock(mutex);
+ return Qfalse;
}
VALUE
rb_barrier_release(VALUE self)
{
- rb_barrier_t *barrier;
- unsigned int n;
+ return rb_mutex_unlock((VALUE)DATA_PTR(self));
+}
- Data_Get_Struct(self, rb_barrier_t, barrier);
- if (barrier->owner != GET_THREAD()) {
- rb_raise(rb_eThreadError, "not owned");
- }
- n = thlist_signal(&barrier->waiting, 0, &barrier->owner);
- return n ? UINT2NUM(n) : Qfalse;
+VALUE
+rb_barrier_destroy(VALUE self)
+{
+ VALUE mutex = (VALUE)DATA_PTR(self);
+ DATA_PTR(self) = 0;
+ return rb_mutex_unlock(mutex);
}
/* variables for recursive traversals */
diff --git a/thread_pthread.c b/thread_pthread.c
index dd672babc4..50cb0a7d99 100644
--- a/thread_pthread.c
+++ b/thread_pthread.c
@@ -124,6 +124,12 @@ native_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
pthread_cond_wait(cond, mutex);
}
+static int
+native_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, struct timespec *ts)
+{
+ return pthread_cond_timedwait(cond, mutex, ts);
+}
+
#define native_cleanup_push pthread_cleanup_push
#define native_cleanup_pop pthread_cleanup_pop
@@ -621,6 +627,8 @@ ubf_select(void *ptr)
#define ubf_select 0
#endif
+#define PER_NANO 1000000000
+
static void
native_sleep(rb_thread_t *th, struct timeval *tv)
{
@@ -631,10 +639,10 @@ native_sleep(rb_thread_t *th, struct timeval *tv)
gettimeofday(&tvn, NULL);
ts.tv_sec = tvn.tv_sec + tv->tv_sec;
ts.tv_nsec = (tvn.tv_usec + tv->tv_usec) * 1000;
- if (ts.tv_nsec >= 1000000000){
+ if (ts.tv_nsec >= PER_NANO){
ts.tv_sec += 1;
- ts.tv_nsec -= 1000000000;
- }
+ ts.tv_nsec -= PER_NANO;
+ }
}
thread_debug("native_sleep %ld\n", tv ? tv->tv_sec : -1);
@@ -653,7 +661,7 @@ native_sleep(rb_thread_t *th, struct timeval *tv)
int r;
thread_debug("native_sleep: pthread_cond_wait start\n");
r = pthread_cond_wait(&th->native_thread_data.sleep_cond,
- &th->interrupt_lock);
+ &th->interrupt_lock);
if (r) rb_bug("pthread_cond_wait: %d", r);
thread_debug("native_sleep: pthread_cond_wait end\n");
}
@@ -765,22 +773,36 @@ remove_signal_thread_list(rb_thread_t *th)
}
static pthread_t timer_thread_id;
+static pthread_cond_t timer_thread_cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t timer_thread_lock = PTHREAD_MUTEX_INITIALIZER;
+
+static struct timespec *
+get_ts(struct timespec *ts, unsigned long nsec)
+{
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ ts->tv_sec = tv.tv_sec;
+ ts->tv_nsec = tv.tv_usec * 1000 + nsec;
+ if (ts->tv_nsec >= PER_NANO) {
+ ts->tv_sec++;
+ ts->tv_nsec -= PER_NANO;
+ }
+ return ts;
+}
static void *
thread_timer(void *dummy)
{
- while (system_working) {
-#ifdef HAVE_NANOSLEEP
- struct timespec req, rem;
- req.tv_sec = 0;
- req.tv_nsec = 10 * 1000 * 1000; /* 10 ms */
- nanosleep(&req, &rem);
-#else
- struct timeval tv;
- tv.tv_sec = 0;
- tv.tv_usec = 10000; /* 10 ms */
- select(0, NULL, NULL, NULL, &tv);
-#endif
+ struct timespec ts;
+ int err;
+
+ native_mutex_lock(&timer_thread_lock);
+ native_cond_broadcast(&timer_thread_cond);
+#define WAIT_FOR_10MS() native_cond_timedwait(&timer_thread_cond, &timer_thread_lock, get_ts(&ts, PER_NANO/100))
+ while (system_working > 0 && (err = WAIT_FOR_10MS()) != 0 && err != EINTR) {
+ if (err != ETIMEDOUT) {
+ rb_bug("thread_timer/timedwait: %d", err);
+ }
#ifndef __CYGWIN__
if (signal_thread_list_anchor.next) {
FGLOCK(&signal_thread_list_lock, {
@@ -795,6 +817,7 @@ thread_timer(void *dummy)
#endif
timer_thread_function(dummy);
}
+ native_mutex_unlock(&timer_thread_lock);
return NULL;
}
@@ -812,14 +835,31 @@ rb_thread_create_timer_thread(void)
pthread_attr_setstacksize(&attr,
PTHREAD_STACK_MIN + (THREAD_DEBUG ? BUFSIZ : 0));
#endif
- err = pthread_create(&timer_thread_id, &attr, thread_timer, GET_VM());
+ native_mutex_lock(&timer_thread_lock);
+ err = pthread_create(&timer_thread_id, &attr, thread_timer, 0);
if (err != 0) {
+ native_mutex_unlock(&timer_thread_lock);
rb_bug("rb_thread_create_timer_thread: return non-zero (%d)", err);
}
+ native_cond_wait(&timer_thread_cond, &timer_thread_lock);
+ native_mutex_unlock(&timer_thread_lock);
}
rb_disable_interrupt(); /* only timer thread recieve signal */
}
+static int
+native_stop_timer_thread(void)
+{
+ int stopped;
+ native_mutex_lock(&timer_thread_lock);
+ stopped = --system_working <= 0;
+ if (stopped) {
+ native_cond_signal(&timer_thread_cond);
+ }
+ native_mutex_unlock(&timer_thread_lock);
+ return stopped;
+}
+
#ifdef HAVE_SIGALTSTACK
int
ruby_stack_overflowed_p(const rb_thread_t *th, const void *addr)
diff --git a/thread_win32.c b/thread_win32.c
index 27a12654d0..71fd929b21 100644
--- a/thread_win32.c
+++ b/thread_win32.c
@@ -482,7 +482,6 @@ static unsigned long _stdcall
thread_start_func_1(void *th_ptr)
{
rb_thread_t *th = th_ptr;
- VALUE stack_start;
volatile HANDLE thread_id = th->thread_id;
native_thread_init_stack(th);
@@ -491,7 +490,8 @@ thread_start_func_1(void *th_ptr)
/* run */
thread_debug("thread created (th: %p, thid: %p, event: %p)\n", th,
th->thread_id, th->native_thread_data.interrupt_event);
- thread_start_func_2(th, &stack_start, 0);
+
+ thread_start_func_2(th, th->machine_stack_start, rb_ia64_bsp());
w32_close_handle(thread_id);
thread_debug("thread deleted (th: %p)\n", th);
@@ -558,27 +558,42 @@ ubf_handle(void *ptr)
}
static HANDLE timer_thread_id = 0;
+static HANDLE timer_thread_lock;
static unsigned long _stdcall
timer_thread_func(void *dummy)
{
thread_debug("timer_thread\n");
- while (system_working) {
- Sleep(WIN32_WAIT_TIMEOUT);
+ while (WaitForSingleObject(timer_thread_lock, WIN32_WAIT_TIMEOUT) ==
+ WAIT_TIMEOUT) {
timer_thread_function(dummy);
}
thread_debug("timer killed\n");
return 0;
}
-void
+static void
rb_thread_create_timer_thread(void)
{
if (timer_thread_id == 0) {
+ if (!timer_thread_lock) {
+ timer_thread_lock = CreateEvent(0, TRUE, FALSE, 0);
+ }
timer_thread_id = w32_create_thread(1024 + (THREAD_DEBUG ? BUFSIZ : 0),
- timer_thread_func, GET_VM());
+ timer_thread_func, 0);
w32_resume_thread(timer_thread_id);
}
}
+static int
+native_stop_timer_thread(void)
+{
+ int stopped = --system_working <= 0;
+ if (stopped) {
+ CloseHandle(timer_thread_lock);
+ timer_thread_lock = 0;
+ }
+ return stopped;
+}
+
#endif /* THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION */
diff --git a/tool/compile_prelude.rb b/tool/compile_prelude.rb
index 70197aebf3..72cf961bd8 100644
--- a/tool/compile_prelude.rb
+++ b/tool/compile_prelude.rb
@@ -64,7 +64,7 @@ tmp = ERB.new(<<'EOS', nil, '%').result(binding)
#include "vm_core.h"
% preludes.zip(lines_list).each_with_index {|(prelude, (setup_lines, lines)), i|
-static const char prelude_name<%=i%>[] = <%=c_esc(File.basename(prelude))%>;
+static const char prelude_name<%=i%>[] = <%=c_esc("<internal:" + File.basename(prelude, ".rb") + ">")%>;
static const char prelude_code<%=i%>[] =
% (setup_lines+lines).each {|line|
<%=line%>
diff --git a/tool/generic_erb.rb b/tool/generic_erb.rb
new file mode 100644
index 0000000000..3ddfd7f653
--- /dev/null
+++ b/tool/generic_erb.rb
@@ -0,0 +1,34 @@
+require 'erb'
+require 'optparse'
+require 'fileutils'
+
+timestamp = nil
+output = nil
+ifchange = nil
+opt = OptionParser.new do |o|
+ o.on('-t', '--timestamp[=PATH]') {|v| timestamp = v || true}
+ o.on('-o', '--output=PATH') {|v| output = v}
+ o.on('-c', '--[no-]if-change') {|v| ifchange = v}
+ o.order!(ARGV)
+end or abort opt.opt_s
+template = ARGV.shift
+erb = ERB.new(File.read(template), nil, '%')
+erb.filename = template
+result = erb.result
+if output
+ if ifchange and (IO.read(output) rescue nil) == result
+ puts "#{output} unchanged"
+ else
+ open(output, "wb") {|f| f.print result}
+ puts "#{output} updated"
+ end
+ if timestamp
+ if timestamp == true
+ dir, base = File.split(output)
+ timestamp = File.join(dir, ".time." + base)
+ end
+ FileUtils.touch(timestamp)
+ end
+else
+ print result
+end
diff --git a/tool/ifchange b/tool/ifchange
index 544513ad15..8bfca26703 100755
--- a/tool/ifchange
+++ b/tool/ifchange
@@ -1,6 +1,11 @@
#!/bin/sh
# usage: ifchange target temporary
+unset timestamp
+if [ "$1" = --timestamp ]; then
+ timestamp=yes
+ shift
+fi
target="$1"
temp="$2"
if [ "$temp" = - ]; then
@@ -15,3 +20,6 @@ else
echo "$target updated"
mv -f "$temp" "$target"
fi
+if [ $timestamp ]; then
+ touch `dirname "$target"`/.time.`basename "$target"`
+fi
diff --git a/tool/insns2vm.rb b/tool/insns2vm.rb
index 47aba50c1e..f518707f11 100755
--- a/tool/insns2vm.rb
+++ b/tool/insns2vm.rb
@@ -1,4 +1,4 @@
-#!ruby -Kn
+#!ruby
require 'optparse'
diff --git a/tool/instruction.rb b/tool/instruction.rb
index 5e5eb0b78a..7ecc84b26f 100644
--- a/tool/instruction.rb
+++ b/tool/instruction.rb
@@ -106,8 +106,8 @@ class RubyVM
load_insns_def opts[:"insns.def"] || 'insns.def'
- load_opt_operand_def opts[:"opope.def"] || 'opt_operand.def'
- load_insn_unification_def opts[:"unif.def"] || 'opt_insn_unif.def'
+ load_opt_operand_def opts[:"opope.def"] || 'defs/opt_operand.def'
+ load_insn_unification_def opts[:"unif.def"] || 'defs/opt_insn_unif.def'
make_stackcaching_insns if vm_opt?('STACK_CACHING')
end
@@ -1326,8 +1326,8 @@ class RubyVM
def self.def_options(opt)
opts = {
:"insns.def" => 'insns.def',
- :"opope.def" => 'opt_operand.def',
- :"unif.def" => 'opt_insn_unif.def',
+ :"opope.def" => 'defs/opt_operand.def',
+ :"unif.def" => 'defs/opt_insn_unif.def',
}
opt.on("-Dname", /\AOPT_(\w+)\z/, "enable VM option") {|s, v|
diff --git a/tool/make-snapshot b/tool/make-snapshot
index f6529d9c25..25d61a7954 100755
--- a/tool/make-snapshot
+++ b/tool/make-snapshot
@@ -1,4 +1,5 @@
#!/usr/bin/ruby -s
+# -*- coding: us-ascii -*-
require 'uri'
require 'digest/md5'
require 'digest/sha2'
@@ -6,6 +7,9 @@ require 'fileutils'
require 'tmpdir'
STDOUT.sync = true
+$exported = nil if $exported == ""
+$archname = nil if $archname == ""
+
ENV["LC_ALL"] = ENV["LANG"] = "C"
SVNURL = URI.parse("http://svn.ruby-lang.org/repos/ruby/")
RUBY_VERSION_PATTERN = /^\#define\s+RUBY_VERSION\s+"([\d.]+)"/
@@ -17,12 +21,17 @@ ENV["RUBY"] ||= "ruby"
ENV["MV"] ||= "mv"
ENV["MINIRUBY"] ||= "ruby"
+class String
+ # for older ruby
+ alias bytesize size unless method_defined?(:bytesize)
+end
+
$patch_file &&= File.expand_path($patch_file)
path = ENV["PATH"].split(File::PATH_SEPARATOR)
%w[YACC BASERUBY RUBY MV MINIRUBY].each do |var|
cmd = ENV[var]
unless path.any? {|dir|
- file = File.join(dir, cmd)
+ file = File.expand_path(cmd, dir)
File.file?(file) and File.executable?(file)
}
abort "#{File.basename $0}: #{var} command not found - #{cmd}"
@@ -53,7 +62,7 @@ def package(rev, destdir)
when /\Astable\z/
url = SVNURL + "branches/"
url = url + `svn ls #{url}`[/.*^(ruby_\d+_\d+)\//m, 1]
- when /\A(.*)\.(.*)\.(.*)-(p)?(.*)/
+ when /\A(.*)\.(.*)\.(.*)-((?!preview)p)?(.*)/
patchlevel = !!$4
tag = "#{$4}#{$5}"
url = SVNURL + "tags/v#{$1}_#{$2}_#{$3}_#{$5}"
@@ -74,9 +83,15 @@ def package(rev, destdir)
end
revision = `svn info #{url}`[/Last Changed Rev: (\d+)/, 1]
end
- unless $exported
+ v = nil
+ if $exported
+ if String === $exported
+ v = $exported
+ end
+ else
+ v = "ruby"
puts "Exporting #{rev}@#{revision}"
- IO.popen("svn export #{url} ruby") do |pipe|
+ IO.popen("svn export #{url} #{v}") do |pipe|
pipe.each {|line| /^A/ =~ line or print line}
end
unless $?.success?
@@ -85,7 +100,7 @@ def package(rev, destdir)
end
end
- if !File.directory?(v = "ruby")
+ if !File.directory?(v)
v = Dir.glob("ruby-*").select(&File.method(:directory?))
v.size == 1 or abort "not exported"
v = v[0]
@@ -100,8 +115,11 @@ def package(rev, destdir)
else
tag ||= "r#{revision}"
end
- v = "ruby-#{version}-#{tag}"
- File.directory?(v) or File.rename "ruby", v
+ unless v == $exported
+ n = "ruby-#{version}-#{tag}"
+ File.directory?(n) or File.rename v, n
+ v = n
+ end
system("patch -d #{v} -p0 -i #{$patch_file}") if $patch_file
def (clean = []).add(n) push(n); n end
Dir.chdir(v) do
@@ -154,11 +172,16 @@ def package(rev, destdir)
puts " done"
end
+ if v == "."
+ v = File.basename(Dir.pwd)
+ Dir.chdir ".."
+ end
+
return [["bzip tarball", ".tar.bz2", %w"tar cjf"],
["gzip tarball", ".tar.gz", %w"tar czf"],
["zip archive", ".zip", %w"zip -qr"]
].collect do |mesg, ext, cmd|
- file = "#{destdir}/#{v}#{ext}"
+ file = "#{destdir}/#{v||$archname}#{ext}"
print "creating #{mesg}... #{file}"
if system(*(cmd + [file, v]))
puts " done"
@@ -177,8 +200,11 @@ revisions.collect {|rev| package(rev, destdir)}.flatten.each do |name|
str = open(name, "rb") {|f| f.read}
md5 = Digest::MD5.hexdigest str
sha = Digest::SHA256.hexdigest str
- puts "MD5(#{name})= #{md5}"
- puts "SHA256(#{name})= #{sha}"
- puts "SIZE(name)= #{str.size}"
+ puts "* #{name}"
+ puts " SIZE: #{str.bytesize} bytes"
+ puts " MD5: #{md5}"
+ puts " SHA256: #{sha}"
puts
end
+
+# vim:fileencoding=US-ASCII sw=2 ts=4 noexpandtab ff=unix
diff --git a/mdoc2man.rb b/tool/mdoc2man.rb
index 910b2e5745..0922474b47 100755
--- a/mdoc2man.rb
+++ b/tool/mdoc2man.rb
@@ -190,7 +190,7 @@ class Mdoc2Man
next
when 'Xr'
retval << '\\fB' << words.shift <<
- '\\fP(' << words.shift << ')' << words.shift
+ '\\fP(' << words.shift << ')' << (words.shift||'')
break
when 'Rs'
@refauthors = []
diff --git a/tool/merge_from_trunk.rb b/tool/merge_from_trunk.rb
index e48ceb941d..0698a0f958 100755
--- a/tool/merge_from_trunk.rb
+++ b/tool/merge_from_trunk.rb
@@ -13,7 +13,7 @@ conflicts = []
old_revision = IO.read(".merged-trunk-revision").chomp
unless old_revision == new_revision
puts "merging r#{old_revision}:#{new_revision}"
- IO.foreach("|svn merge #{TRUNK}@#{old_revision} #{TRUNK}@#{new_revision} .") do |line|
+ IO.foreach("|svn merge --accept postpone #{TRUNK}@#{old_revision} #{TRUNK}@#{new_revision} .") do |line|
puts line
conflicts << line[5..-2] if /^C/ =~ line
end
diff --git a/tool/transcode-tblgen.rb b/tool/transcode-tblgen.rb
index 5395460ee5..870d971e9e 100644
--- a/tool/transcode-tblgen.rb
+++ b/tool/transcode-tblgen.rb
@@ -62,7 +62,8 @@ class StrSet
end
def hash
- @pat.hash
+ return @hash if defined? @hash
+ @hash = @pat.hash
end
def eql?(other)
@@ -196,11 +197,12 @@ class ActionMap
end
def hash
+ return @hash if defined? @hash
hash = 0
@map.each {|k,v|
hash ^= k.hash ^ v.hash
}
- hash
+ @hash = hash
end
def eql?(other)
@@ -305,7 +307,7 @@ class ActionMap
n = str_name(bytes)
@bytes_code.insert_at_last(1 + len,
"\#define #{n} makeSTR1(#{size})\n" +
- " #{len}," + bytes.gsub(/../, ' 0x\&,') + "\n\n")
+ " makeSTR1LEN(#{len})," + bytes.gsub(/../, ' 0x\&,') + "\n\n")
n
end
end
@@ -334,7 +336,7 @@ class ActionMap
"o3(0x#$1,0x#$2,0x#$3)"
when /\A(f[0-7])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])\z/i
"o4(0x#$1,0x#$2,0x#$3,0x#$4)"
- when /\A([0-9a-f][0-9a-f]){0,255}\z/i
+ when /\A([0-9a-f][0-9a-f]){4,259}\z/i
gen_str(info.upcase)
when /\A\/\*BYTE_LOOKUP\*\// # pointer to BYTE_LOOKUP structure
$'.to_s
@@ -724,27 +726,23 @@ ValidEncoding = {
{81-fe}{30-39}{81-fe}{30-39}',
}
-{
- 'ASCII-8BIT' => '1byte',
- 'ISO-8859-1' => '1byte',
- 'ISO-8859-2' => '1byte',
- 'ISO-8859-3' => '1byte',
- 'ISO-8859-4' => '1byte',
- 'ISO-8859-5' => '1byte',
- 'ISO-8859-6' => '1byte',
- 'ISO-8859-7' => '1byte',
- 'ISO-8859-8' => '1byte',
- 'ISO-8859-9' => '1byte',
- 'ISO-8859-10' => '1byte',
- 'ISO-8859-11' => '1byte',
- 'ISO-8859-13' => '1byte',
- 'ISO-8859-14' => '1byte',
- 'ISO-8859-15' => '1byte',
- 'Windows-31J' => 'Shift_JIS',
- 'eucJP-ms' => 'EUC-JP'
-}.each {|k, v|
- ValidEncoding[k] = ValidEncoding.fetch(v)
-}
+def set_valid_byte_pattern (encoding, pattern_or_label)
+ pattern =
+ if ValidEncoding[pattern_or_label]
+ ValidEncoding[pattern_or_label]
+ else
+ pattern_or_label
+ end
+ if ValidEncoding[encoding] and ValidEncoding[encoding]!=pattern
+ raise ArgumentError, "trying to change valid byte pattern for encoding #{encoding} from #{ValidEncoding[encoding]} to #{pattern}"
+ end
+ ValidEncoding[encoding] = pattern
+end
+
+# the following may be used in different places, so keep them here for the moment
+set_valid_byte_pattern 'ASCII-8BIT', '1byte'
+set_valid_byte_pattern 'Windows-31J', 'Shift_JIS'
+set_valid_byte_pattern 'eucJP-ms', 'EUC-JP'
def make_signature(filename, src)
"src=#{filename.dump}, len=#{src.length}, checksum=#{src.sum}"
diff --git a/transcode.c b/transcode.c
index fd41001689..26e0a022c2 100644
--- a/transcode.c
+++ b/transcode.c
@@ -12,19 +12,22 @@
#include "ruby/ruby.h"
#include "ruby/encoding.h"
#include "transcode_data.h"
+#include "private_object.h"
#include <ctype.h>
-VALUE rb_eConversionUndefined;
-VALUE rb_eInvalidByteSequence;
-VALUE rb_eNoConverter;
+#if 0
+VALUE rb_eUndefinedConversionError;
+VALUE rb_eInvalidByteSequenceError;
+VALUE rb_eConverterNotFoundError;
VALUE rb_cEncodingConverter;
+#endif
static VALUE sym_invalid, sym_undef, sym_ignore, sym_replace;
static VALUE sym_xml, sym_text, sym_attr;
-static VALUE sym_universal_newline_decoder;
-static VALUE sym_crlf_newline_encoder;
-static VALUE sym_cr_newline_encoder;
+static VALUE sym_universal_newline;
+static VALUE sym_crlf_newline;
+static VALUE sym_cr_newline;
static VALUE sym_partial_input;
static VALUE sym_invalid_byte_sequence;
@@ -32,7 +35,7 @@ static VALUE sym_undefined_conversion;
static VALUE sym_destination_buffer_full;
static VALUE sym_source_buffer_empty;
static VALUE sym_finished;
-static VALUE sym_output_followed_by_input;
+static VALUE sym_after_output;
static VALUE sym_incomplete_input;
static unsigned char *
@@ -52,6 +55,7 @@ typedef struct rb_transcoding {
unsigned int next_table;
VALUE next_info;
unsigned char next_byte;
+ unsigned int output_index;
int recognized_len; /* already interpreted */
int readagain_len; /* not yet interpreted */
@@ -67,7 +71,10 @@ typedef struct rb_transcoding {
unsigned char *ptr; /* length: max_output */
} writebuf;
- void *state; /* opaque data for stateful encoding */
+ union rb_transcoding_state_t { /* opaque data for stateful encoding */
+ void *ptr;
+ double dummy_for_alignment;
+ } state;
} rb_transcoding;
#define TRANSCODING_READBUF(tc) \
((tc)->transcoder->max_input <= sizeof((tc)->readbuf.ary) ? \
@@ -77,11 +84,15 @@ typedef struct rb_transcoding {
((tc)->transcoder->max_output <= sizeof((tc)->writebuf.ary) ? \
(tc)->writebuf.ary : \
(tc)->writebuf.ptr)
-#define TRANSCODING_STATE_EMBED_MAX sizeof(void *)
+#define TRANSCODING_WRITEBUF_SIZE(tc) \
+ ((tc)->transcoder->max_output <= sizeof((tc)->writebuf.ary) ? \
+ sizeof((tc)->writebuf.ary) : \
+ (tc)->transcoder->max_output)
+#define TRANSCODING_STATE_EMBED_MAX sizeof(union rb_transcoding_state_t)
#define TRANSCODING_STATE(tc) \
((tc)->transcoder->state_size <= sizeof((tc)->state) ? \
(void *)&(tc)->state : \
- (tc)->state)
+ (tc)->state.ptr)
typedef struct {
struct rb_transcoding *tc;
@@ -97,6 +108,8 @@ struct rb_econv_t {
const char *source_encoding_name;
const char *destination_encoding_name;
+ int started;
+
const unsigned char *replacement_str;
size_t replacement_len;
const char *replacement_enc;
@@ -107,9 +120,9 @@ struct rb_econv_t {
unsigned char *in_data_end;
unsigned char *in_buf_end;
rb_econv_elem_t *elems;
+ int num_allocated;
int num_trans;
int num_finished;
- int last_trans_index; /* last trans, not including universal newline */
struct rb_transcoding *last_tc;
/* last error */
@@ -133,7 +146,7 @@ struct rb_econv_t {
* Dispatch data and logic
*/
-#define SUPPLEMENTAL_CONVERSION(sname, dname) (*(sname) == '\0' || *(dname) == '\0')
+#define DECORATOR_P(sname, dname) (*(sname) == '\0')
typedef struct {
const char *sname;
@@ -267,7 +280,7 @@ transcode_search_path(const char *sname, const char *dname,
st_data_t val;
st_table *table2;
int found;
- int pathlen;
+ int pathlen = -1;
if (encoding_equal(sname, dname))
return -1;
@@ -339,10 +352,7 @@ transcode_search_path(const char *sname, const char *dname,
st_free_table(bfs.visited);
- if (found)
- return pathlen;
- else
- return -1;
+ return pathlen; /* is -1 if !found */
}
static const rb_transcoder *
@@ -373,44 +383,16 @@ load_transcoder_entry(transcoder_entry_t *entry)
}
static const char*
-get_replacement_character(rb_encoding *enc, size_t *len_ret, const char **repl_enc_ptr)
+get_replacement_character(const char *encname, size_t *len_ret, const char **repl_encname_ptr)
{
- static rb_encoding *utf16be_encoding, *utf16le_encoding;
- static rb_encoding *utf32be_encoding, *utf32le_encoding;
- if (!utf16be_encoding) {
- utf16be_encoding = rb_enc_find("UTF-16BE");
- utf16le_encoding = rb_enc_find("UTF-16LE");
- utf32be_encoding = rb_enc_find("UTF-32BE");
- utf32le_encoding = rb_enc_find("UTF-32LE");
- }
- if (rb_utf8_encoding() == enc) {
+ if (encoding_equal(encname, "UTF-8")) {
*len_ret = 3;
- *repl_enc_ptr = "UTF-8";
+ *repl_encname_ptr = "UTF-8";
return "\xEF\xBF\xBD";
}
- else if (utf16be_encoding == enc) {
- *len_ret = 2;
- *repl_enc_ptr = "UTF-16BE";
- return "\xFF\xFD";
- }
- else if (utf16le_encoding == enc) {
- *len_ret = 2;
- *repl_enc_ptr = "UTF-16LE";
- return "\xFD\xFF";
- }
- else if (utf32be_encoding == enc) {
- *len_ret = 4;
- *repl_enc_ptr = "UTF-32BE";
- return "\x00\x00\xFF\xFD";
- }
- else if (utf32le_encoding == enc) {
- *len_ret = 4;
- *repl_enc_ptr = "UTF-32LE";
- return "\xFD\xFF\x00\x00";
- }
else {
*len_ret = 1;
- *repl_enc_ptr = "US-ASCII";
+ *repl_encname_ptr = "US-ASCII";
return "?";
}
}
@@ -455,19 +437,6 @@ transcode_restartable0(const unsigned char **in_pos, unsigned char **out_pos,
unsigned char *out_p;
- unsigned char empty_buf;
- unsigned char *empty_ptr = &empty_buf;
-
- if (!in_pos) {
- in_pos = (const unsigned char **)&empty_ptr;
- in_stop = empty_ptr;
- }
-
- if (!out_pos) {
- out_pos = &empty_ptr;
- out_stop = empty_ptr;
- }
-
in_p = inchar_start = *in_pos;
out_p = *out_pos;
@@ -493,9 +462,9 @@ transcode_restartable0(const unsigned char **in_pos, unsigned char **out_pos,
while (out_stop - out_p < 1) { SUSPEND(econv_destination_buffer_full, num); } \
} while (0)
-#define SUSPEND_OUTPUT_FOLLOWED_BY_INPUT(num) \
- if ((opt & ECONV_OUTPUT_FOLLOWED_BY_INPUT) && *out_pos != out_p) { \
- SUSPEND(econv_output_followed_by_input, num); \
+#define SUSPEND_AFTER_OUTPUT(num) \
+ if ((opt & ECONV_AFTER_OUTPUT) && *out_pos != out_p) { \
+ SUSPEND(econv_after_output, num); \
}
#define next_table (tc->next_table)
@@ -541,7 +510,7 @@ transcode_restartable0(const unsigned char **in_pos, unsigned char **out_pos,
tc->recognized_len = 0;
next_table = tr->conv_tree_start;
- SUSPEND_OUTPUT_FOLLOWED_BY_INPUT(24);
+ SUSPEND_AFTER_OUTPUT(24);
if (in_stop <= in_p) {
if (!(opt & ECONV_PARTIAL_INPUT))
@@ -573,7 +542,7 @@ transcode_restartable0(const unsigned char **in_pos, unsigned char **out_pos,
continue;
case 0x00: case 0x04: case 0x08: case 0x0C:
case 0x10: case 0x14: case 0x18: case 0x1C:
- SUSPEND_OUTPUT_FOLLOWED_BY_INPUT(25);
+ SUSPEND_AFTER_OUTPUT(25);
while (in_p >= in_stop) {
if (!(opt & ECONV_PARTIAL_INPUT))
goto incomplete;
@@ -603,10 +572,10 @@ transcode_restartable0(const unsigned char **in_pos, unsigned char **out_pos,
SUSPEND_OBUF(19); *out_p++ = getBT3(next_info);
continue;
case STR1:
- next_byte = 0; /* index */
- while (next_byte < BYTE_ADDR(STR1_BYTEINDEX(next_info))[0]) {
- SUSPEND_OBUF(28); *out_p++ = BYTE_ADDR(STR1_BYTEINDEX(next_info))[1+next_byte];
- next_byte++;
+ tc->output_index = 0;
+ while (tc->output_index < STR1_LENGTH(BYTE_ADDR(STR1_BYTEINDEX(next_info)))) {
+ SUSPEND_OBUF(28); *out_p++ = BYTE_ADDR(STR1_BYTEINDEX(next_info))[1+tc->output_index];
+ tc->output_index++;
}
continue;
case FUNii:
@@ -623,9 +592,12 @@ transcode_restartable0(const unsigned char **in_pos, unsigned char **out_pos,
case FUNio:
SUSPEND_OBUF(13);
if (tr->max_output <= out_stop - out_p)
- out_p += (VALUE)(*tr->func_io)(TRANSCODING_STATE(tc), next_info, out_p);
+ out_p += tr->func_io(TRANSCODING_STATE(tc),
+ next_info, out_p, out_stop - out_p);
else {
- writebuf_len = (VALUE)(*tr->func_io)(TRANSCODING_STATE(tc), next_info, TRANSCODING_WRITEBUF(tc));
+ writebuf_len = tr->func_io(TRANSCODING_STATE(tc),
+ next_info,
+ TRANSCODING_WRITEBUF(tc), TRANSCODING_WRITEBUF_SIZE(tc));
writebuf_off = 0;
while (writebuf_off < writebuf_len) {
SUSPEND_OBUF(20);
@@ -640,11 +612,15 @@ transcode_restartable0(const unsigned char **in_pos, unsigned char **out_pos,
SUSPEND_OBUF(14);
if (tr->max_output <= out_stop - out_p) {
char_start = transcode_char_start(tc, *in_pos, inchar_start, in_p, &char_len);
- out_p += (VALUE)(*tr->func_so)(TRANSCODING_STATE(tc), char_start, (size_t)char_len, out_p);
+ out_p += tr->func_so(TRANSCODING_STATE(tc),
+ char_start, (size_t)char_len,
+ out_p, out_stop - out_p);
}
else {
char_start = transcode_char_start(tc, *in_pos, inchar_start, in_p, &char_len);
- writebuf_len = (VALUE)(*tr->func_so)(TRANSCODING_STATE(tc), char_start, (size_t)char_len, TRANSCODING_WRITEBUF(tc));
+ writebuf_len = tr->func_so(TRANSCODING_STATE(tc),
+ char_start, (size_t)char_len,
+ TRANSCODING_WRITEBUF(tc), TRANSCODING_WRITEBUF_SIZE(tc));
writebuf_off = 0;
while (writebuf_off < writebuf_len) {
SUSPEND_OBUF(22);
@@ -656,7 +632,7 @@ transcode_restartable0(const unsigned char **in_pos, unsigned char **out_pos,
case INVALID:
if (tc->recognized_len + (in_p - inchar_start) <= unitlen) {
if (tc->recognized_len + (in_p - inchar_start) < unitlen)
- SUSPEND_OUTPUT_FOLLOWED_BY_INPUT(26);
+ SUSPEND_AFTER_OUTPUT(26);
while ((opt & ECONV_PARTIAL_INPUT) && tc->recognized_len + (in_stop - inchar_start) < unitlen) {
in_p = in_stop;
SUSPEND(econv_source_buffer_empty, 8);
@@ -698,10 +674,12 @@ transcode_restartable0(const unsigned char **in_pos, unsigned char **out_pos,
if (tr->finish_func) {
SUSPEND_OBUF(4);
if (tr->max_output <= out_stop - out_p) {
- out_p += tr->finish_func(TRANSCODING_STATE(tc), out_p);
+ out_p += tr->finish_func(TRANSCODING_STATE(tc),
+ out_p, out_stop - out_p);
}
else {
- writebuf_len = tr->finish_func(TRANSCODING_STATE(tc), TRANSCODING_WRITEBUF(tc));
+ writebuf_len = tr->finish_func(TRANSCODING_STATE(tc),
+ TRANSCODING_WRITEBUF(tc), TRANSCODING_WRITEBUF_SIZE(tc));
writebuf_off = 0;
while (writebuf_off < writebuf_len) {
SUSPEND_OBUF(23);
@@ -754,7 +732,7 @@ rb_transcoding_open_by_transcoder(const rb_transcoder *tr, int flags)
tc->transcoder = tr;
tc->flags = flags;
if (TRANSCODING_STATE_EMBED_MAX < tr->state_size)
- tc->state = xmalloc(tr->state_size);
+ tc->state.ptr = xmalloc(tr->state_size);
if (tr->state_init_func) {
(tr->state_init_func)(TRANSCODING_STATE(tc)); /* xxx: check return value */
}
@@ -792,7 +770,7 @@ rb_transcoding_close(rb_transcoding *tc)
(tr->state_fini_func)(TRANSCODING_STATE(tc)); /* check return value? */
}
if (TRANSCODING_STATE_EMBED_MAX < tr->state_size)
- xfree(tc->state);
+ xfree(tc->state.ptr);
if (sizeof(tc->readbuf.ary) < tr->max_input)
xfree(tc->readbuf.ptr);
if (sizeof(tc->writebuf.ary) < tr->max_output)
@@ -801,34 +779,31 @@ rb_transcoding_close(rb_transcoding *tc)
}
static rb_econv_t *
-rb_econv_open_by_transcoder_entries(int n, transcoder_entry_t **entries)
+rb_econv_alloc(int n_hint)
{
rb_econv_t *ec;
- int i;
- for (i = 0; i < n; i++) {
- const rb_transcoder *tr;
- tr = load_transcoder_entry(entries[i]);
- if (!tr)
- return NULL;
- }
+ if (n_hint <= 0)
+ n_hint = 1;
ec = ALLOC(rb_econv_t);
ec->flags = 0;
ec->source_encoding_name = NULL;
ec->destination_encoding_name = NULL;
+ ec->started = 0;
ec->replacement_str = NULL;
ec->replacement_len = 0;
+ ec->replacement_enc = NULL;
ec->replacement_allocated = 0;
ec->in_buf_start = NULL;
ec->in_data_start = NULL;
ec->in_data_end = NULL;
ec->in_buf_end = NULL;
- ec->num_trans = n;
- ec->elems = ALLOC_N(rb_econv_elem_t, ec->num_trans);
+ ec->num_allocated = n_hint;
+ ec->num_trans = 0;
+ ec->elems = ALLOC_N(rb_econv_elem_t, ec->num_allocated);
ec->num_finished = 0;
ec->last_tc = NULL;
- ec->last_trans_index = -1;
ec->last_error.result = econv_source_buffer_empty;
ec->last_error.error_tc = NULL;
ec->last_error.source_encoding = NULL;
@@ -838,27 +813,70 @@ rb_econv_open_by_transcoder_entries(int n, transcoder_entry_t **entries)
ec->last_error.readagain_len = 0;
ec->source_encoding = NULL;
ec->destination_encoding = NULL;
- for (i = 0; i < ec->num_trans; i++) {
+ return ec;
+}
+
+static int
+rb_econv_add_transcoder_at(rb_econv_t *ec, const rb_transcoder *tr, int i)
+{
+ int n, j;
+ int bufsize = 4096;
+ unsigned char *p;
+
+ if (ec->num_trans == ec->num_allocated) {
+ n = ec->num_allocated * 2;
+ REALLOC_N(ec->elems, rb_econv_elem_t, n);
+ ec->num_allocated = n;
+ }
+
+ p = xmalloc(bufsize);
+
+ MEMMOVE(ec->elems+i+1, ec->elems+i, rb_econv_elem_t, ec->num_trans-i);
+
+ ec->elems[i].tc = rb_transcoding_open_by_transcoder(tr, 0);
+ ec->elems[i].out_buf_start = p;
+ ec->elems[i].out_buf_end = p + bufsize;
+ ec->elems[i].out_data_start = p;
+ ec->elems[i].out_data_end = p;
+ ec->elems[i].last_result = econv_source_buffer_empty;
+
+ ec->num_trans++;
+
+ if (!DECORATOR_P(tr->src_encoding, tr->dst_encoding))
+ for (j = ec->num_trans-1; i <= j; j--) {
+ rb_transcoding *tc = ec->elems[j].tc;
+ const rb_transcoder *tr2 = tc->transcoder;
+ if (!DECORATOR_P(tr2->src_encoding, tr2->dst_encoding)) {
+ ec->last_tc = tc;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static rb_econv_t *
+rb_econv_open_by_transcoder_entries(int n, transcoder_entry_t **entries)
+{
+ rb_econv_t *ec;
+ int i, ret;
+
+ for (i = 0; i < n; i++) {
+ const rb_transcoder *tr;
+ tr = load_transcoder_entry(entries[i]);
+ if (!tr)
+ return NULL;
+ }
+
+ ec = rb_econv_alloc(n);
+
+ for (i = 0; i < n; i++) {
const rb_transcoder *tr = load_transcoder_entry(entries[i]);
- ec->elems[i].tc = rb_transcoding_open_by_transcoder(tr, 0);
- ec->elems[i].out_buf_start = NULL;
- ec->elems[i].out_data_start = NULL;
- ec->elems[i].out_data_end = NULL;
- ec->elems[i].out_buf_end = NULL;
- ec->elems[i].last_result = econv_source_buffer_empty;
- }
- if (ec->num_trans)
- ec->last_tc = ec->elems[ec->num_trans-1].tc;
- ec->last_trans_index = ec->num_trans-1;
-
- for (i = 0; i < ec->num_trans-1; i++) {
- int bufsize = 4096;
- unsigned char *p;
- p = xmalloc(bufsize);
- ec->elems[i].out_buf_start = p;
- ec->elems[i].out_buf_end = p + bufsize;
- ec->elems[i].out_data_start = p;
- ec->elems[i].out_data_end = p;
+ ret = rb_econv_add_transcoder_at(ec, tr, ec->num_trans);
+ if (ret == -1) {
+ rb_econv_close(ec);
+ return NULL;
+ }
}
return ec;
@@ -880,53 +898,16 @@ trans_open_i(const char *sname, const char *dname, int depth, void *arg)
toarg->entries[depth] = get_transcoder_entry(sname, dname);
}
-rb_econv_t *
-rb_econv_open(const char *sname, const char *dname, int ecflags)
+static rb_econv_t *
+rb_econv_open0(const char *sname, const char *dname, int ecflags)
{
transcoder_entry_t **entries = NULL;
int num_trans;
- static rb_econv_t *ec;
+ rb_econv_t *ec;
rb_encoding *senc, *denc;
int sidx, didx;
- int num_encoders, num_decoders;
- transcoder_entry_t *encoders[4], *decoders[1];
-
- if ((ecflags & ECONV_CRLF_NEWLINE_ENCODER) &&
- (ecflags & ECONV_CR_NEWLINE_ENCODER))
- return NULL;
-
- if ((ecflags & (ECONV_CRLF_NEWLINE_ENCODER|ECONV_CR_NEWLINE_ENCODER)) &&
- (ecflags & ECONV_UNIVERSAL_NEWLINE_DECODER))
- return NULL;
-
- if ((ecflags & ECONV_XML_TEXT_ENCODER) &&
- (ecflags & ECONV_XML_ATTR_CONTENT_ENCODER))
- return NULL;
-
- num_encoders = 0;
- if (ecflags & ECONV_CRLF_NEWLINE_ENCODER)
- if (!(encoders[num_encoders++] = get_transcoder_entry("", "crlf_newline")))
- return NULL;
- if (ecflags & ECONV_CR_NEWLINE_ENCODER)
- if (!(encoders[num_encoders++] = get_transcoder_entry("", "cr_newline")))
- return NULL;
- if (ecflags & ECONV_XML_TEXT_ENCODER)
- if (!(encoders[num_encoders++] = get_transcoder_entry("", "xml-text-escaped")))
- return NULL;
- if (ecflags & ECONV_XML_ATTR_CONTENT_ENCODER)
- if (!(encoders[num_encoders++] = get_transcoder_entry("", "xml-attr-content-escaped")))
- return NULL;
- if (ecflags & ECONV_XML_ATTR_QUOTE_ENCODER)
- if (!(encoders[num_encoders++] = get_transcoder_entry("", "xml-attr-quoted")))
- return NULL;
-
- num_decoders = 0;
- if (ecflags & ECONV_UNIVERSAL_NEWLINE_DECODER)
- if (!(decoders[num_decoders++] = get_transcoder_entry("universal_newline", "")))
- return NULL;
-
senc = NULL;
if (*sname) {
sidx = rb_enc_find_index(sname);
@@ -943,35 +924,22 @@ rb_econv_open(const char *sname, const char *dname, int ecflags)
}
}
- if (*sname && (!senc || !rb_enc_asciicompat(senc)) && num_encoders)
- return NULL;
-
- if (*dname && (!denc || !rb_enc_asciicompat(denc)) && num_decoders)
- return NULL;
-
if (*sname == '\0' && *dname == '\0') {
num_trans = 0;
- entries = ALLOC_N(transcoder_entry_t *, num_encoders+num_decoders);
+ entries = NULL;
}
else {
struct trans_open_t toarg;
toarg.entries = NULL;
- toarg.num_additional = num_encoders+num_decoders;
+ toarg.num_additional = 0;
num_trans = transcode_search_path(sname, dname, trans_open_i, (void *)&toarg);
entries = toarg.entries;
+ if (num_trans < 0) {
+ xfree(entries);
+ return NULL;
+ }
}
- if (num_trans < 0 || !entries) {
- xfree(entries);
- return NULL;
- }
-
- MEMMOVE(entries+num_encoders, entries, transcoder_entry_t *, num_trans);
- MEMMOVE(entries, encoders, transcoder_entry_t *, num_encoders);
- MEMMOVE(entries+num_encoders+num_trans, decoders, transcoder_entry_t *, num_decoders);
-
- num_trans += num_encoders + num_decoders;
-
ec = rb_econv_open_by_transcoder_entries(num_trans, entries);
xfree(entries);
if (!ec)
@@ -981,14 +949,70 @@ rb_econv_open(const char *sname, const char *dname, int ecflags)
ec->source_encoding_name = sname;
ec->destination_encoding_name = dname;
- if (num_trans == num_encoders + num_decoders) {
- ec->last_tc = NULL;
- ec->last_trans_index = -1;
- }
- else {
- ec->last_trans_index = ec->num_trans-1-num_decoders;
- ec->last_tc = ec->elems[ec->last_trans_index].tc;
- }
+ return ec;
+}
+
+#define MAX_ECFLAGS_DECORATORS 32
+
+static int
+decorator_names(int ecflags, const char **decorators_ret)
+{
+ int num_decorators;
+
+ if ((ecflags & ECONV_CRLF_NEWLINE_DECORATOR) &&
+ (ecflags & ECONV_CR_NEWLINE_DECORATOR))
+ return -1;
+
+ if ((ecflags & (ECONV_CRLF_NEWLINE_DECORATOR|ECONV_CR_NEWLINE_DECORATOR)) &&
+ (ecflags & ECONV_UNIVERSAL_NEWLINE_DECORATOR))
+ return -1;
+
+ if ((ecflags & ECONV_XML_TEXT_DECORATOR) &&
+ (ecflags & ECONV_XML_ATTR_CONTENT_DECORATOR))
+ return -1;
+
+ num_decorators = 0;
+
+ if (ecflags & ECONV_XML_TEXT_DECORATOR)
+ decorators_ret[num_decorators++] = "xml_text_escape";
+ if (ecflags & ECONV_XML_ATTR_CONTENT_DECORATOR)
+ decorators_ret[num_decorators++] = "xml_attr_content_escape";
+ if (ecflags & ECONV_XML_ATTR_QUOTE_DECORATOR)
+ decorators_ret[num_decorators++] = "xml_attr_quote";
+
+ if (ecflags & ECONV_CRLF_NEWLINE_DECORATOR)
+ decorators_ret[num_decorators++] = "crlf_newline";
+ if (ecflags & ECONV_CR_NEWLINE_DECORATOR)
+ decorators_ret[num_decorators++] = "cr_newline";
+ if (ecflags & ECONV_UNIVERSAL_NEWLINE_DECORATOR)
+ decorators_ret[num_decorators++] = "universal_newline";
+
+ return num_decorators;
+}
+
+rb_econv_t *
+rb_econv_open(const char *sname, const char *dname, int ecflags)
+{
+ rb_econv_t *ec;
+ int num_decorators;
+ const char *decorators[MAX_ECFLAGS_DECORATORS];
+ int i;
+
+ num_decorators = decorator_names(ecflags, decorators);
+ if (num_decorators == -1)
+ return NULL;
+
+ ec = rb_econv_open0(sname, dname, ecflags & ECONV_ERROR_HANDLER_MASK);
+ if (!ec)
+ return NULL;
+
+ for (i = 0; i < num_decorators; i++)
+ if (rb_econv_decorate_at_last(ec, decorators[i]) == -1) {
+ rb_econv_close(ec);
+ return NULL;
+ }
+
+ ec->flags |= ecflags & ~ECONV_ERROR_HANDLER_MASK;
return ec;
}
@@ -1042,12 +1066,12 @@ trans_sweep(rb_econv_t *ec,
f = flags;
if (ec->num_finished != i)
f |= ECONV_PARTIAL_INPUT;
- if (i == 0 && (flags & ECONV_OUTPUT_FOLLOWED_BY_INPUT)) {
+ if (i == 0 && (flags & ECONV_AFTER_OUTPUT)) {
start = 1;
- flags &= ~ECONV_OUTPUT_FOLLOWED_BY_INPUT;
+ flags &= ~ECONV_AFTER_OUTPUT;
}
if (i != 0)
- f &= ~ECONV_OUTPUT_FOLLOWED_BY_INPUT;
+ f &= ~ECONV_AFTER_OUTPUT;
iold = *ipp;
oold = *opp;
te->last_result = res = rb_transcoding_convert(te->tc, ipp, is, opp, os, f);
@@ -1058,7 +1082,7 @@ trans_sweep(rb_econv_t *ec,
case econv_invalid_byte_sequence:
case econv_incomplete_input:
case econv_undefined_conversion:
- case econv_output_followed_by_input:
+ case econv_after_output:
return i;
case econv_destination_buffer_full:
@@ -1098,7 +1122,7 @@ rb_trans_conv(rb_econv_t *ec,
output_stop = empty_ptr;
}
- if (ec->elems[0].last_result == econv_output_followed_by_input)
+ if (ec->elems[0].last_result == econv_after_output)
ec->elems[0].last_result = econv_source_buffer_empty;
needreport_index = -1;
@@ -1107,7 +1131,7 @@ rb_trans_conv(rb_econv_t *ec,
case econv_invalid_byte_sequence:
case econv_incomplete_input:
case econv_undefined_conversion:
- case econv_output_followed_by_input:
+ case econv_after_output:
case econv_finished:
sweep_start = i+1;
needreport_index = i;
@@ -1125,15 +1149,15 @@ rb_trans_conv(rb_econv_t *ec,
/* /^[sd]+$/ is confirmed. but actually /^s*d*$/. */
if (ec->elems[ec->num_trans-1].last_result == econv_destination_buffer_full &&
- (flags & ECONV_OUTPUT_FOLLOWED_BY_INPUT)) {
+ (flags & ECONV_AFTER_OUTPUT)) {
rb_econv_result_t res;
res = rb_trans_conv(ec, NULL, NULL, output_ptr, output_stop,
- (flags & ~ECONV_OUTPUT_FOLLOWED_BY_INPUT)|ECONV_PARTIAL_INPUT,
+ (flags & ~ECONV_AFTER_OUTPUT)|ECONV_PARTIAL_INPUT,
result_position_ptr);
if (res == econv_source_buffer_empty)
- return econv_output_followed_by_input;
+ return econv_after_output;
return res;
}
@@ -1152,7 +1176,7 @@ rb_trans_conv(rb_econv_t *ec,
if (res == econv_invalid_byte_sequence ||
res == econv_incomplete_input ||
res == econv_undefined_conversion ||
- res == econv_output_followed_by_input) {
+ res == econv_after_output) {
ec->elems[i].last_result = econv_source_buffer_empty;
}
if (result_position_ptr)
@@ -1192,8 +1216,8 @@ rb_econv_convert0(rb_econv_t *ec,
memcpy(*output_ptr, ec->in_data_start, len);
*output_ptr += len;
ec->in_data_start = ec->in_data_end = ec->in_buf_start;
- if (flags & ECONV_OUTPUT_FOLLOWED_BY_INPUT) {
- res = econv_output_followed_by_input;
+ if (flags & ECONV_AFTER_OUTPUT) {
+ res = econv_after_output;
goto gotresult;
}
}
@@ -1203,9 +1227,9 @@ rb_econv_convert0(rb_econv_t *ec,
else {
len = input_stop - *input_ptr;
}
- if (0 < len && (flags & ECONV_OUTPUT_FOLLOWED_BY_INPUT)) {
+ if (0 < len && (flags & ECONV_AFTER_OUTPUT)) {
*(*output_ptr)++ = *(*input_ptr)++;
- res = econv_output_followed_by_input;
+ res = econv_after_output;
goto gotresult;
}
memcpy(*output_ptr, *input_ptr, len);
@@ -1246,28 +1270,28 @@ rb_econv_convert0(rb_econv_t *ec,
if (ec->in_buf_start &&
ec->in_data_start != ec->in_data_end) {
res = rb_trans_conv(ec, (const unsigned char **)&ec->in_data_start, ec->in_data_end, output_ptr, output_stop,
- (flags&~ECONV_OUTPUT_FOLLOWED_BY_INPUT)|ECONV_PARTIAL_INPUT, &result_position);
+ (flags&~ECONV_AFTER_OUTPUT)|ECONV_PARTIAL_INPUT, &result_position);
if (res != econv_source_buffer_empty)
goto gotresult;
}
if (has_output &&
- (flags & ECONV_OUTPUT_FOLLOWED_BY_INPUT) &&
+ (flags & ECONV_AFTER_OUTPUT) &&
*input_ptr != input_stop) {
input_stop = *input_ptr;
res = rb_trans_conv(ec, input_ptr, input_stop, output_ptr, output_stop, flags, &result_position);
if (res == econv_source_buffer_empty)
- res = econv_output_followed_by_input;
+ res = econv_after_output;
}
- else if ((flags & ECONV_OUTPUT_FOLLOWED_BY_INPUT) ||
+ else if ((flags & ECONV_AFTER_OUTPUT) ||
ec->num_trans == 1) {
res = rb_trans_conv(ec, input_ptr, input_stop, output_ptr, output_stop, flags, &result_position);
}
else {
- flags |= ECONV_OUTPUT_FOLLOWED_BY_INPUT;
+ flags |= ECONV_AFTER_OUTPUT;
do {
res = rb_trans_conv(ec, input_ptr, input_stop, output_ptr, output_stop, flags, &result_position);
- } while (res == econv_output_followed_by_input);
+ } while (res == econv_after_output);
}
gotresult:
@@ -1356,6 +1380,8 @@ rb_econv_convert(rb_econv_t *ec,
unsigned char empty_buf;
unsigned char *empty_ptr = &empty_buf;
+ ec->started = 1;
+
if (!input_ptr) {
input_ptr = (const unsigned char **)&empty_ptr;
input_stop = empty_ptr;
@@ -1493,6 +1519,7 @@ rb_econv_insert_output(rb_econv_t *ec,
const unsigned char *insert_str = NULL;
size_t insert_len;
+ int last_trans_index;
rb_transcoding *tc;
unsigned char **buf_start_p;
@@ -1502,6 +1529,8 @@ rb_econv_insert_output(rb_econv_t *ec,
size_t need;
+ ec->started = 1;
+
if (len == 0)
return 0;
@@ -1518,25 +1547,27 @@ rb_econv_insert_output(rb_econv_t *ec,
need = insert_len;
- tc = ec->last_tc;
- if (!tc) {
+ last_trans_index = ec->num_trans-1;
+ if (ec->num_trans == 0) {
+ tc = NULL;
buf_start_p = &ec->in_buf_start;
data_start_p = &ec->in_data_start;
data_end_p = &ec->in_data_end;
buf_end_p = &ec->in_buf_end;
}
- else if (tc->transcoder->asciicompat_type == asciicompat_encoder) {
+ else if (ec->elems[last_trans_index].tc->transcoder->asciicompat_type == asciicompat_encoder) {
+ tc = ec->elems[last_trans_index].tc;
need += tc->readagain_len;
if (need < insert_len)
goto fail;
- if (ec->last_trans_index == 0) {
+ if (last_trans_index == 0) {
buf_start_p = &ec->in_buf_start;
data_start_p = &ec->in_data_start;
data_end_p = &ec->in_data_end;
buf_end_p = &ec->in_buf_end;
}
else {
- rb_econv_elem_t *ee = &ec->elems[ec->last_trans_index-1];
+ rb_econv_elem_t *ee = &ec->elems[last_trans_index-1];
buf_start_p = &ee->out_buf_start;
data_start_p = &ee->out_data_start;
data_end_p = &ee->out_data_end;
@@ -1544,11 +1575,12 @@ rb_econv_insert_output(rb_econv_t *ec,
}
}
else {
- rb_econv_elem_t *ee = &ec->elems[ec->last_trans_index];
+ rb_econv_elem_t *ee = &ec->elems[last_trans_index];
buf_start_p = &ee->out_buf_start;
data_start_p = &ee->out_data_start;
data_end_p = &ee->out_data_end;
buf_end_p = &ee->out_buf_end;
+ tc = ec->elems[last_trans_index].tc;
}
if (*buf_start_p == NULL) {
@@ -1642,7 +1674,7 @@ asciicompat_encoding_i(st_data_t key, st_data_t val, st_data_t arg)
transcoder_entry_t *entry = (transcoder_entry_t *)val;
const rb_transcoder *tr;
- if (SUPPLEMENTAL_CONVERSION(entry->sname, entry->dname))
+ if (DECORATOR_P(entry->sname, entry->dname))
return ST_CONTINUE;
tr = load_transcoder_entry(entry);
if (tr && tr->asciicompat_type == asciicompat_decoder) {
@@ -1741,39 +1773,97 @@ rb_econv_str_convert(rb_econv_t *ec, VALUE src, int flags)
return rb_econv_substr_append(ec, src, 0, RSTRING_LEN(src), Qnil, flags);
}
+static int
+rb_econv_add_converter(rb_econv_t *ec, const char *sname, const char *dname, int n)
+{
+ transcoder_entry_t *entry;
+ const rb_transcoder *tr;
+
+ if (ec->started != 0)
+ return -1;
+
+ entry = get_transcoder_entry(sname, dname);
+ if (!entry)
+ return -1;
+
+ tr = load_transcoder_entry(entry);
+
+ return rb_econv_add_transcoder_at(ec, tr, n);
+}
+
+static int
+rb_econv_decorate_at(rb_econv_t *ec, const char *decorator_name, int n)
+{
+ return rb_econv_add_converter(ec, "", decorator_name, n);
+}
+
+int
+rb_econv_decorate_at_first(rb_econv_t *ec, const char *decorator_name)
+{
+ const rb_transcoder *tr;
+
+ if (ec->num_trans == 0)
+ return rb_econv_decorate_at(ec, decorator_name, 0);
+
+ tr = ec->elems[0].tc->transcoder;
+
+ if (!DECORATOR_P(tr->src_encoding, tr->dst_encoding) &&
+ tr->asciicompat_type == asciicompat_decoder)
+ return rb_econv_decorate_at(ec, decorator_name, 1);
+
+ return rb_econv_decorate_at(ec, decorator_name, 0);
+}
+
+int
+rb_econv_decorate_at_last(rb_econv_t *ec, const char *decorator_name)
+{
+ const rb_transcoder *tr;
+
+ if (ec->num_trans == 0)
+ return rb_econv_decorate_at(ec, decorator_name, 0);
+
+ tr = ec->elems[ec->num_trans-1].tc->transcoder;
+
+ if (!DECORATOR_P(tr->src_encoding, tr->dst_encoding) &&
+ tr->asciicompat_type == asciicompat_encoder)
+ return rb_econv_decorate_at(ec, decorator_name, ec->num_trans-1);
+
+ return rb_econv_decorate_at(ec, decorator_name, ec->num_trans);
+}
+
void
rb_econv_binmode(rb_econv_t *ec)
{
const rb_transcoder *trs[3];
int n, i, j;
transcoder_entry_t *entry;
+ int num_trans;
n = 0;
- if (ec->flags & ECONV_UNIVERSAL_NEWLINE_DECODER) {
- entry = get_transcoder_entry("universal_newline", "");
+ if (ec->flags & ECONV_UNIVERSAL_NEWLINE_DECORATOR) {
+ entry = get_transcoder_entry("", "universal_newline");
if (entry->transcoder)
trs[n++] = entry->transcoder;
}
- if (ec->flags & ECONV_CRLF_NEWLINE_ENCODER) {
+ if (ec->flags & ECONV_CRLF_NEWLINE_DECORATOR) {
entry = get_transcoder_entry("", "crlf_newline");
if (entry->transcoder)
trs[n++] = entry->transcoder;
}
- if (ec->flags & ECONV_CR_NEWLINE_ENCODER) {
+ if (ec->flags & ECONV_CR_NEWLINE_DECORATOR) {
entry = get_transcoder_entry("", "cr_newline");
if (entry->transcoder)
trs[n++] = entry->transcoder;
}
+ num_trans = ec->num_trans;
j = 0;
- for (i = 0; i < ec->num_trans; i++) {
+ for (i = 0; i < num_trans; i++) {
int k;
for (k = 0; k < n; k++)
if (trs[k] == ec->elems[i].tc->transcoder)
break;
if (k == n) {
- if (ec->last_tc == ec->elems[i].tc)
- ec->last_trans_index = j;
ec->elems[j] = ec->elems[i];
j++;
}
@@ -1784,7 +1874,7 @@ rb_econv_binmode(rb_econv_t *ec)
}
}
- ec->flags &= ~(ECONV_UNIVERSAL_NEWLINE_DECODER|ECONV_CRLF_NEWLINE_ENCODER|ECONV_CR_NEWLINE_ENCODER);
+ ec->flags &= ~(ECONV_UNIVERSAL_NEWLINE_DECORATOR|ECONV_CRLF_NEWLINE_DECORATOR|ECONV_CR_NEWLINE_DECORATOR);
}
@@ -1806,38 +1896,38 @@ econv_description(const char *sname, const char *dname, int ecflags, VALUE mesg)
has_description = 1;
}
- if (ecflags & (ECONV_UNIVERSAL_NEWLINE_DECODER|
- ECONV_CRLF_NEWLINE_ENCODER|
- ECONV_CR_NEWLINE_ENCODER|
- ECONV_XML_TEXT_ENCODER|
- ECONV_XML_ATTR_CONTENT_ENCODER|
- ECONV_XML_ATTR_QUOTE_ENCODER)) {
+ if (ecflags & (ECONV_UNIVERSAL_NEWLINE_DECORATOR|
+ ECONV_CRLF_NEWLINE_DECORATOR|
+ ECONV_CR_NEWLINE_DECORATOR|
+ ECONV_XML_TEXT_DECORATOR|
+ ECONV_XML_ATTR_CONTENT_DECORATOR|
+ ECONV_XML_ATTR_QUOTE_DECORATOR)) {
const char *pre = "";
if (has_description)
rb_str_cat2(mesg, " with ");
- if (ecflags & ECONV_UNIVERSAL_NEWLINE_DECODER) {
+ if (ecflags & ECONV_UNIVERSAL_NEWLINE_DECORATOR) {
rb_str_cat2(mesg, pre); pre = ",";
- rb_str_cat2(mesg, "universal-newline");
+ rb_str_cat2(mesg, "universal_newline");
}
- if (ecflags & ECONV_CRLF_NEWLINE_ENCODER) {
+ if (ecflags & ECONV_CRLF_NEWLINE_DECORATOR) {
rb_str_cat2(mesg, pre); pre = ",";
- rb_str_cat2(mesg, "CRLF-newline");
+ rb_str_cat2(mesg, "crlf_newline");
}
- if (ecflags & ECONV_CR_NEWLINE_ENCODER) {
+ if (ecflags & ECONV_CR_NEWLINE_DECORATOR) {
rb_str_cat2(mesg, pre); pre = ",";
- rb_str_cat2(mesg, "CR-newline");
+ rb_str_cat2(mesg, "cr_newline");
}
- if (ecflags & ECONV_XML_TEXT_ENCODER) {
+ if (ecflags & ECONV_XML_TEXT_DECORATOR) {
rb_str_cat2(mesg, pre); pre = ",";
- rb_str_cat2(mesg, "XML-text");
+ rb_str_cat2(mesg, "xml_text");
}
- if (ecflags & ECONV_XML_ATTR_CONTENT_ENCODER) {
+ if (ecflags & ECONV_XML_ATTR_CONTENT_DECORATOR) {
rb_str_cat2(mesg, pre); pre = ",";
- rb_str_cat2(mesg, "XML-attr-content");
+ rb_str_cat2(mesg, "xml_attr_content");
}
- if (ecflags & ECONV_XML_ATTR_QUOTE_ENCODER) {
+ if (ecflags & ECONV_XML_ATTR_QUOTE_DECORATOR) {
rb_str_cat2(mesg, pre); pre = ",";
- rb_str_cat2(mesg, "XML-attr-quote");
+ rb_str_cat2(mesg, "xml_attr_quote");
}
has_description = 1;
}
@@ -1852,10 +1942,10 @@ VALUE
rb_econv_open_exc(const char *sname, const char *dname, int ecflags)
{
VALUE mesg, exc;
- mesg = rb_str_new_cstr("code converter open failed (");
+ mesg = rb_str_new_cstr("code converter not found (");
econv_description(sname, dname, ecflags, mesg);
rb_str_cat2(mesg, ")");
- exc = rb_exc_new3(rb_eNoConverter, mesg);
+ exc = rb_exc_new3(rb_eConverterNotFoundError, mesg);
return exc;
}
@@ -1892,7 +1982,7 @@ make_econv_exception(rb_econv_t *ec)
ec->last_error.source_encoding);
}
- exc = rb_exc_new3(rb_eInvalidByteSequence, mesg);
+ exc = rb_exc_new3(rb_eInvalidByteSequenceError, mesg);
rb_ivar_set(exc, rb_intern("error_bytes"), bytes);
rb_ivar_set(exc, rb_intern("readagain_bytes"), bytes2);
rb_ivar_set(exc, rb_intern("incomplete_input"), ec->last_error.result == econv_incomplete_input ? Qtrue : Qfalse);
@@ -1918,7 +2008,7 @@ make_econv_exception(rb_econv_t *ec)
StringValueCStr(dumped),
ec->last_error.source_encoding,
ec->last_error.destination_encoding);
- exc = rb_exc_new3(rb_eConversionUndefined, mesg);
+ exc = rb_exc_new3(rb_eUndefinedConversionError, mesg);
idx = rb_enc_find_index(ec->last_error.source_encoding);
if (0 <= idx)
rb_enc_associate_index(bytes, idx);
@@ -1954,16 +2044,17 @@ make_replacement(rb_econv_t *ec)
const char *repl_enc;
const char *ins_enc;
size_t len;
- int allocated = 0;
if (ec->replacement_str)
return 0;
+ ins_enc = rb_econv_encoding_to_insert_output(ec);
+
tc = ec->last_tc;
- if (tc) {
+ if (*ins_enc) {
tr = tc->transcoder;
enc = rb_enc_find(tr->dst_encoding);
- replacement = (const unsigned char *)get_replacement_character(enc, &len, &repl_enc);
+ replacement = (const unsigned char *)get_replacement_character(ins_enc, &len, &repl_enc);
}
else {
replacement = (unsigned char *)"?";
@@ -1971,18 +2062,10 @@ make_replacement(rb_econv_t *ec)
repl_enc = "";
}
- ins_enc = rb_econv_encoding_to_insert_output(ec);
- if (*repl_enc && !encoding_equal(repl_enc, ins_enc)) {
- replacement = allocate_converted_string(repl_enc, ins_enc, replacement, len, NULL, 0, &len);
- if (!replacement)
- return -1;
- allocated = 1;
- repl_enc = ins_enc;
- }
ec->replacement_str = replacement;
ec->replacement_len = len;
ec->replacement_enc = repl_enc;
- ec->replacement_allocated = allocated;
+ ec->replacement_allocated = 0;
return 0;
}
@@ -2173,7 +2256,6 @@ econv_opts(VALUE opt)
}
else if (v==sym_replace) {
ecflags |= ECONV_INVALID_REPLACE;
- v = rb_hash_aref(opt, sym_replace);
}
else {
rb_raise(rb_eArgError, "unknown value for invalid character option");
@@ -2191,29 +2273,31 @@ econv_opts(VALUE opt)
v = rb_hash_aref(opt, sym_xml);
if (!NIL_P(v)) {
- v = rb_convert_type(v, T_SYMBOL, "Symbol", "to_sym");
if (v==sym_text) {
- ecflags |= ECONV_XML_TEXT_ENCODER|ECONV_UNDEF_HEX_CHARREF;
+ ecflags |= ECONV_XML_TEXT_DECORATOR|ECONV_UNDEF_HEX_CHARREF;
}
else if (v==sym_attr) {
- ecflags |= ECONV_XML_ATTR_CONTENT_ENCODER|ECONV_XML_ATTR_QUOTE_ENCODER|ECONV_UNDEF_HEX_CHARREF;
+ ecflags |= ECONV_XML_ATTR_CONTENT_DECORATOR|ECONV_XML_ATTR_QUOTE_DECORATOR|ECONV_UNDEF_HEX_CHARREF;
}
- else {
+ else if (TYPE(v) == T_SYMBOL) {
rb_raise(rb_eArgError, "unexpected value for xml option: %s", rb_id2name(SYM2ID(v)));
}
+ else {
+ rb_raise(rb_eArgError, "unexpected value for xml option");
+ }
}
- v = rb_hash_aref(opt, sym_universal_newline_decoder);
+ v = rb_hash_aref(opt, sym_universal_newline);
if (RTEST(v))
- ecflags |= ECONV_UNIVERSAL_NEWLINE_DECODER;
+ ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
- v = rb_hash_aref(opt, sym_crlf_newline_encoder);
+ v = rb_hash_aref(opt, sym_crlf_newline);
if (RTEST(v))
- ecflags |= ECONV_CRLF_NEWLINE_ENCODER;
+ ecflags |= ECONV_CRLF_NEWLINE_DECORATOR;
- v = rb_hash_aref(opt, sym_cr_newline_encoder);
+ v = rb_hash_aref(opt, sym_cr_newline);
if (RTEST(v))
- ecflags |= ECONV_CR_NEWLINE_ENCODER;
+ ecflags |= ECONV_CR_NEWLINE_DECORATOR;
return ecflags;
}
@@ -2223,20 +2307,27 @@ rb_econv_prepare_opts(VALUE opthash, VALUE *opts)
{
int ecflags;
VALUE newhash = Qnil;
- if (NIL_P(opthash))
- return Qnil;
- ecflags = econv_opts(opthash);
+ VALUE v;
- if ((ecflags & ECONV_INVALID_MASK) == ECONV_INVALID_REPLACE ||
- (ecflags & ECONV_UNDEF_MASK) == ECONV_UNDEF_REPLACE) {
- VALUE v = rb_hash_aref(opthash, sym_replace);
- if (!NIL_P(v)) {
- StringValue(v);
- v = rb_str_new_frozen(v);
- newhash = rb_hash_new();
- rb_hash_aset(newhash, sym_replace, v);
- }
+ if (NIL_P(opthash)) {
+ *opts = Qnil;
+ return 0;
+ }
+ ecflags = econv_opts(opthash);
+ v = rb_hash_aref(opthash, sym_replace);
+ if (!NIL_P(v)) {
+ StringValue(v);
+ if (rb_enc_str_coderange(v) == ENC_CODERANGE_BROKEN) {
+ VALUE dumped = rb_str_dump(v);
+ rb_raise(rb_eArgError, "replacement string is broken: %s as %s",
+ StringValueCStr(dumped),
+ rb_enc_name(rb_enc_get(v)));
+ }
+ v = rb_str_new_frozen(v);
+ newhash = rb_hash_new();
+ rb_hash_aset(newhash, sym_replace, v);
}
+
if (!NIL_P(newhash))
rb_hash_freeze(newhash);
*opts = newhash;
@@ -2270,7 +2361,7 @@ rb_econv_open_opts(const char *source_encoding, const char *destination_encoding
ret = rb_econv_set_replacement(ec,
(const unsigned char *)RSTRING_PTR(replacement),
RSTRING_LEN(replacement),
- enc->name);
+ rb_enc_name(enc));
if (ret == -1) {
rb_econv_close(ec);
return NULL;
@@ -2280,17 +2371,17 @@ rb_econv_open_opts(const char *source_encoding, const char *destination_encoding
}
static int
-enc_arg(VALUE arg, const char **name_p, rb_encoding **enc_p)
+enc_arg(volatile VALUE *arg, const char **name_p, rb_encoding **enc_p)
{
rb_encoding *enc;
const char *n;
int encidx;
VALUE encval;
- if ((encidx = rb_to_encoding_index(encval = arg)) < 0) {
+ if ((encidx = rb_to_encoding_index(encval = *arg)) < 0) {
enc = NULL;
encidx = 0;
- n = StringValueCStr(encval);
+ n = StringValueCStr(*arg);
}
else {
enc = rb_enc_from_index(encidx);
@@ -2304,7 +2395,7 @@ enc_arg(VALUE arg, const char **name_p, rb_encoding **enc_p)
}
static int
-str_transcode_enc_args(VALUE str, VALUE arg1, VALUE arg2,
+str_transcode_enc_args(VALUE str, volatile VALUE *arg1, volatile VALUE *arg2,
const char **sname_p, rb_encoding **senc_p,
const char **dname_p, rb_encoding **denc_p)
{
@@ -2314,7 +2405,7 @@ str_transcode_enc_args(VALUE str, VALUE arg1, VALUE arg2,
dencidx = enc_arg(arg1, &dname, &denc);
- if (NIL_P(arg2)) {
+ if (NIL_P(*arg2)) {
sencidx = rb_enc_get_index(str);
senc = rb_enc_from_index(sencidx);
sname = rb_enc_name(senc);
@@ -2335,6 +2426,7 @@ str_transcode0(int argc, VALUE *argv, VALUE *self, int ecflags, VALUE ecopts)
{
VALUE dest;
VALUE str = *self;
+ volatile VALUE arg1, arg2;
long blen, slen;
unsigned char *buf, *bp, *sp;
const unsigned char *fromp;
@@ -2342,18 +2434,29 @@ str_transcode0(int argc, VALUE *argv, VALUE *self, int ecflags, VALUE ecopts)
const char *sname, *dname;
int dencidx;
- if (argc < 1 || argc > 2) {
- rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..2)", argc);
+ if (argc <0 || argc > 2) {
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 0..2)", argc);
}
- dencidx = str_transcode_enc_args(str, argv[0], argc==1 ? Qnil : argv[1], &sname, &senc, &dname, &denc);
+ if (argc == 0) {
+ arg1 = rb_enc_default_internal();
+ if (NIL_P(arg1)) {
+ return -1;
+ }
+ ecflags |= ECONV_INVALID_REPLACE | ECONV_UNDEF_REPLACE;
+ }
+ else {
+ arg1 = argv[0];
+ }
+ arg2 = argc<=1 ? Qnil : argv[1];
+ dencidx = str_transcode_enc_args(str, &arg1, &arg2, &sname, &senc, &dname, &denc);
- if ((ecflags & (ECONV_UNIVERSAL_NEWLINE_DECODER|
- ECONV_CRLF_NEWLINE_ENCODER|
- ECONV_CR_NEWLINE_ENCODER|
- ECONV_XML_TEXT_ENCODER|
- ECONV_XML_ATTR_CONTENT_ENCODER|
- ECONV_XML_ATTR_QUOTE_ENCODER)) == 0) {
+ if ((ecflags & (ECONV_UNIVERSAL_NEWLINE_DECORATOR|
+ ECONV_CRLF_NEWLINE_DECORATOR|
+ ECONV_CR_NEWLINE_DECORATOR|
+ ECONV_XML_TEXT_DECORATOR|
+ ECONV_XML_ATTR_CONTENT_DECORATOR|
+ ECONV_XML_ATTR_QUOTE_DECORATOR)) == 0) {
if (senc && senc == denc) {
return -1;
}
@@ -2460,6 +2563,7 @@ str_encode_bang(int argc, VALUE *argv, VALUE str)
* call-seq:
* str.encode(encoding [, options] ) => str
* str.encode(dst_encoding, src_encoding [, options] ) => str
+ * str.encode([options]) => str
*
* The first form returns a copy of <i>str</i> transcoded
* to encoding +encoding+.
@@ -2467,6 +2571,8 @@ str_encode_bang(int argc, VALUE *argv, VALUE str)
* from src_encoding to dst_encoding.
* The options Hash gives details for conversion. Details
* to be added.
+ * The last form returns a copy of <i>str</i> transcoded to
+ * <code>Encoding.default_internal</code>.
*/
static VALUE
@@ -2476,12 +2582,17 @@ str_encode(int argc, VALUE *argv, VALUE str)
int encidx = str_transcode(argc, argv, &newstr);
if (encidx < 0) return rb_str_dup(str);
- RBASIC(newstr)->klass = rb_obj_class(str);
+ if (newstr == str) {
+ newstr = rb_str_dup(str);
+ }
+ else {
+ RBASIC(newstr)->klass = rb_obj_class(str);
+ }
return str_encode_associate(newstr, encidx);
}
VALUE
-rb_str_transcode(VALUE str, VALUE to, int ecflags, VALUE ecopts)
+rb_str_encode(VALUE str, VALUE to, int ecflags, VALUE ecopts)
{
int argc = 1;
VALUE *argv = &to;
@@ -2515,6 +2626,22 @@ make_dummy_encoding(const char *name)
return enc;
}
+static rb_encoding *
+make_encoding(const char *name)
+{
+ rb_encoding *enc;
+ enc = rb_enc_find(name);
+ if (!enc)
+ enc = make_dummy_encoding(name);
+ return enc;
+}
+
+static VALUE
+make_encobj(const char *name)
+{
+ return rb_enc_from_encoding(make_encoding(name));
+}
+
/*
* call-seq:
* Encoding::Converter.asciicompat_encoding(string) => encoding or nil
@@ -2540,72 +2667,33 @@ econv_s_asciicompat_encoding(VALUE klass, VALUE arg)
const char *arg_name, *result_name;
rb_encoding *arg_enc, *result_enc;
- enc_arg(arg, &arg_name, &arg_enc);
+ enc_arg(&arg, &arg_name, &arg_enc);
result_name = rb_econv_asciicompat_encoding(arg_name);
if (result_name == NULL)
return Qnil;
- result_enc = rb_enc_find(result_name);
-
- if (!result_enc)
- result_enc = make_dummy_encoding(result_name);
+ result_enc = make_encoding(result_name);
return rb_enc_from_encoding(result_enc);
}
-/*
- * call-seq:
- * Encoding::Converter.new(source_encoding, destination_encoding)
- * Encoding::Converter.new(source_encoding, destination_encoding, opt)
- *
- * possible options elements:
- * hash form:
- * :universal_newline_decoder => true # convert CRLF and CR to LF at last
- * :crlf_newline_encoder => true # convert LF to CRLF at first
- * :cr_newline_encoder => true # convert LF to CR at first
- * :invalid => nil # error on invalid byte sequence (default)
- * :invalid => :replace # replace invalid byte sequence
- * :undef => nil # error on undefined conversion (default)
- * :undef => :replace # replace undefined conversion
- * :replace => string # replacement string ("?" or "\uFFFD" if not specified)
- * integer form:
- * Encoding::Converter::UNIVERSAL_NEWLINE_DECODER
- * Encoding::Converter::CRLF_NEWLINE_ENCODER
- * Encoding::Converter::CR_NEWLINE_ENCODER
- *
- * Encoding::Converter.new creates an instance of Encoding::Converter.
- *
- * source_encoding and destination_encoding should be a string or
- * Encoding object.
- *
- * opt should be nil, a hash or an integer.
- *
- * example:
- * # UTF-16BE to UTF-8
- * ec = Encoding::Converter.new("UTF-16BE", "UTF-8")
- *
- * # (1) convert UTF-16BE to UTF-8
- * # (2) convert CRLF and CR to LF
- * ec = Encoding::Converter.new("UTF-16BE", "UTF-8", :universal_newline_decoder => true)
- *
- * # (1) convert LF to CRLF
- * # (2) convert UTF-8 to UTF-16BE
- * ec = Encoding::Converter.new("UTF-8", "UTF-16BE", :crlf_newline_encoder => true)
- *
- */
-static VALUE
-econv_init(int argc, VALUE *argv, VALUE self)
-{
- VALUE source_encoding, destination_encoding, opt, opthash, flags_v, ecopts;
+static void
+econv_args(int argc, VALUE *argv,
+ volatile VALUE *snamev_p, volatile VALUE *dnamev_p,
+ const char **sname_p, const char **dname_p,
+ rb_encoding **senc_p, rb_encoding **denc_p,
+ int *ecflags_p,
+ VALUE *ecopts_p)
+{
+ VALUE opt, opthash, flags_v, ecopts;
int sidx, didx;
const char *sname, *dname;
rb_encoding *senc, *denc;
- rb_econv_t *ec;
int ecflags;
- rb_scan_args(argc, argv, "21", &source_encoding, &destination_encoding, &opt);
+ rb_scan_args(argc, argv, "21", snamev_p, dnamev_p, &opt);
if (NIL_P(opt)) {
ecflags = 0;
@@ -2621,36 +2709,367 @@ econv_init(int argc, VALUE *argv, VALUE self)
}
senc = NULL;
- sidx = rb_to_encoding_index(source_encoding);
+ sidx = rb_to_encoding_index(*snamev_p);
if (0 <= sidx) {
senc = rb_enc_from_index(sidx);
}
else {
- StringValue(source_encoding);
+ StringValue(*snamev_p);
}
denc = NULL;
- didx = rb_to_encoding_index(destination_encoding);
+ didx = rb_to_encoding_index(*dnamev_p);
if (0 <= didx) {
denc = rb_enc_from_index(didx);
}
else {
- StringValue(destination_encoding);
+ StringValue(*dnamev_p);
}
- sname = senc ? senc->name : StringValueCStr(source_encoding);
- dname = denc ? denc->name : StringValueCStr(destination_encoding);
+ sname = senc ? rb_enc_name(senc) : StringValueCStr(*snamev_p);
+ dname = denc ? rb_enc_name(denc) : StringValueCStr(*dnamev_p);
+
+ *sname_p = sname;
+ *dname_p = dname;
+ *senc_p = senc;
+ *denc_p = denc;
+ *ecflags_p = ecflags;
+ *ecopts_p = ecopts;
+}
+
+static int
+decorate_convpath(VALUE convpath, int ecflags)
+{
+ int num_decorators;
+ const char *decorators[MAX_ECFLAGS_DECORATORS];
+ int i;
+ int n, len;
+
+ num_decorators = decorator_names(ecflags, decorators);
+ if (num_decorators == -1)
+ return -1;
+
+ len = n = RARRAY_LEN(convpath);
+ if (n != 0) {
+ VALUE pair = RARRAY_PTR(convpath)[n-1];
+ const char *sname = rb_enc_name(rb_to_encoding(RARRAY_PTR(pair)[0]));
+ const char *dname = rb_enc_name(rb_to_encoding(RARRAY_PTR(pair)[1]));
+ transcoder_entry_t *entry = get_transcoder_entry(sname, dname);
+ const rb_transcoder *tr = load_transcoder_entry(entry);
+ if (!tr)
+ return -1;
+ if (!DECORATOR_P(tr->src_encoding, tr->dst_encoding) &&
+ tr->asciicompat_type == asciicompat_encoder) {
+ n--;
+ rb_ary_store(convpath, len + num_decorators - 1, pair);
+ }
+ }
+
+ for (i = 0; i < num_decorators; i++)
+ rb_ary_store(convpath, n + i, rb_str_new_cstr(decorators[i]));
+
+ return 0;
+}
+
+static void
+search_convpath_i(const char *sname, const char *dname, int depth, void *arg)
+{
+ VALUE *ary_p = arg;
+ VALUE v;
+
+ if (*ary_p == Qnil) {
+ *ary_p = rb_ary_new();
+ }
+
+ if (DECORATOR_P(sname, dname)) {
+ v = rb_str_new_cstr(dname);
+ }
+ else {
+ v = rb_assoc_new(make_encobj(sname), make_encobj(dname));
+ }
+ rb_ary_store(*ary_p, depth, v);
+}
+
+/*
+ * call-seq:
+ * Encoding::Converter.search_convpath(source_encoding, destination_encoding) -> ary
+ * Encoding::Converter.search_convpath(source_encoding, destination_encoding, opt) -> ary
+ *
+ * returns the conversion path.
+ *
+ * p Encoding::Converter.search_convpath("ISO-8859-1", "EUC-JP")
+ * #=> [[#<Encoding:ISO-8859-1>, #<Encoding:UTF-8>],
+ * # [#<Encoding:UTF-8>, #<Encoding:EUC-JP>]]
+ *
+ * p Encoding::Converter.search_convpath("ISO-8859-1", "EUC-JP", universal_newline: true)
+ * #=> [[#<Encoding:ISO-8859-1>, #<Encoding:UTF-8>],
+ * # [#<Encoding:UTF-8>, #<Encoding:EUC-JP>],
+ * # "universal_newline"]
+ *
+ * p Encoding::Converter.search_convpath("ISO-8859-1", "UTF-32BE", universal_newline: true)
+ * #=> [[#<Encoding:ISO-8859-1>, #<Encoding:UTF-8>],
+ * # "universal_newline",
+ * # [#<Encoding:UTF-8>, #<Encoding:UTF-32BE>]]
+ */
+static VALUE
+econv_s_search_convpath(int argc, VALUE *argv, VALUE klass)
+{
+ volatile VALUE snamev, dnamev;
+ const char *sname, *dname;
+ rb_encoding *senc, *denc;
+ int ecflags;
+ VALUE ecopts;
+ VALUE convpath;
+
+ econv_args(argc, argv, &snamev, &dnamev, &sname, &dname, &senc, &denc, &ecflags, &ecopts);
+
+ convpath = Qnil;
+ transcode_search_path(sname, dname, search_convpath_i, &convpath);
+
+ if (NIL_P(convpath))
+ rb_exc_raise(rb_econv_open_exc(sname, dname, ecflags));
+
+ if (decorate_convpath(convpath, ecflags) == -1)
+ rb_exc_raise(rb_econv_open_exc(sname, dname, ecflags));
+
+ return convpath;
+}
+
+/*
+ * check the existance of converter.
+ * returns the count of the converting paths.
+ * result: >=0:success -1:failure
+ */
+int
+rb_econv_has_convpath_p(const char* from_encoding, const char* to_encoding)
+{
+ VALUE convpath = Qnil;
+ transcode_search_path(from_encoding, to_encoding, search_convpath_i,
+ &convpath);
+ return RTEST(convpath);
+}
+
+struct rb_econv_init_by_convpath_t {
+ rb_econv_t *ec;
+ int index;
+ int ret;
+};
+
+void rb_econv_init_by_convpath_i(const char *sname, const char *dname, int depth, void *arg)
+{
+ struct rb_econv_init_by_convpath_t *a = (struct rb_econv_init_by_convpath_t *)arg;
+ int ret;
+
+ if (a->ret == -1)
+ return;
+
+ ret = rb_econv_add_converter(a->ec, sname, dname, a->index);
+
+ a->ret = ret;
+ return;
+}
+
+static rb_econv_t *
+rb_econv_init_by_convpath(VALUE self, VALUE convpath,
+ const char **sname_p, const char **dname_p,
+ rb_encoding **senc_p, rb_encoding**denc_p)
+{
+ rb_econv_t *ec;
+ long i;
+ int ret, first=1;
+ VALUE elt;
+ rb_encoding *senc = 0, *denc = 0;
+ const char *sname, *dname;
+
+ ec = rb_econv_alloc(RARRAY_LEN(convpath));
+ DATA_PTR(self) = ec;
+
+ for (i = 0; i < RARRAY_LEN(convpath); i++) {
+ volatile VALUE snamev, dnamev;
+ VALUE pair;
+ elt = rb_ary_entry(convpath, i);
+ if (!NIL_P(pair = rb_check_array_type(elt))) {
+ if (RARRAY_LEN(pair) != 2)
+ rb_raise(rb_eArgError, "not a 2-element array in convpath");
+ snamev = rb_ary_entry(pair, 0);
+ enc_arg(&snamev, &sname, &senc);
+ dnamev = rb_ary_entry(pair, 1);
+ enc_arg(&dnamev, &dname, &denc);
+ }
+ else {
+ sname = "";
+ dname = StringValueCStr(elt);
+ }
+ if (DECORATOR_P(sname, dname)) {
+ ret = rb_econv_add_converter(ec, sname, dname, ec->num_trans);
+ if (ret == -1)
+ rb_raise(rb_eArgError, "decoration failed: %s", dname);
+ }
+ else {
+ int j = ec->num_trans;
+ struct rb_econv_init_by_convpath_t arg;
+ arg.ec = ec;
+ arg.index = ec->num_trans;
+ arg.ret = 0;
+ ret = transcode_search_path(sname, dname, rb_econv_init_by_convpath_i, &arg);
+ if (ret == -1 || arg.ret == -1)
+ rb_raise(rb_eArgError, "conversion add failed: %s to %s", sname, dname);
+ if (first) {
+ first = 0;
+ *senc_p = senc;
+ *sname_p = ec->elems[j].tc->transcoder->src_encoding;
+ }
+ *denc_p = denc;
+ *dname_p = ec->elems[ec->num_trans-1].tc->transcoder->dst_encoding;
+ }
+ }
+
+ if (first) {
+ *senc_p = NULL;
+ *denc_p = NULL;
+ *sname_p = "";
+ *dname_p = "";
+ }
+
+ ec->source_encoding_name = *sname_p;
+ ec->destination_encoding_name = *dname_p;
+
+ return ec;
+}
+
+/*
+ * call-seq:
+ * Encoding::Converter.new(source_encoding, destination_encoding)
+ * Encoding::Converter.new(source_encoding, destination_encoding, opt)
+ * Encoding::Converter.new(convpath)
+ *
+ * possible options elements:
+ * hash form:
+ * :invalid => nil # raise error on invalid byte sequence (default)
+ * :invalid => :replace # replace invalid byte sequence
+ * :undef => nil # raise error on undefined conversion (default)
+ * :undef => :replace # replace undefined conversion
+ * :replace => string # replacement string ("?" or "\uFFFD" if not specified)
+ * :universal_newline => true # decorator for converting CRLF and CR to LF
+ * :crlf_newline => true # decorator for converting LF to CRLF
+ * :cr_newline => true # decorator for converting LF to CR
+ * :xml => :text # escape as XML CharData.
+ * :xml => :attr # escape as XML AttValue
+ * integer form:
+ * Encoding::Converter::INVALID_REPLACE
+ * Encoding::Converter::UNDEF_REPLACE
+ * Encoding::Converter::UNDEF_HEX_CHARREF
+ * Encoding::Converter::UNIVERSAL_NEWLINE_DECORATOR
+ * Encoding::Converter::CRLF_NEWLINE_DECORATOR
+ * Encoding::Converter::CR_NEWLINE_DECORATOR
+ * Encoding::Converter::XML_TEXT_DECORATOR
+ * Encoding::Converter::XML_ATTR_CONTENT_DECORATOR
+ * Encoding::Converter::XML_ATTR_QUOTE_DECORATOR
+ *
+ * Encoding::Converter.new creates an instance of Encoding::Converter.
+ *
+ * source_encoding and destination_encoding should be a string or
+ * Encoding object.
+ *
+ * opt should be nil, a hash or an integer.
+ *
+ * convpath should be an array.
+ * convpath should contains
+ * - two-element array which contains encoding or encoding name, or
+ * - a string of decorator name.
+ *
+ * Encoding::Converter.new optionally takes an option.
+ * The option should be a hash or an integer.
+ * The option hash can contain :invalid => nil, etc.
+ * The option integer should be logical-or of constants such as
+ * Encoding::Converter::INVALID_REPLACE, etc.
+ *
+ * [:invalid => nil]
+ * raise error on invalid byte sequence. This is a default behavior.
+ * [:invalid => :replace]
+ * replace invalid byte sequence as a replacement string.
+ * [:undef => nil]
+ * raise error on conversion failure due to an character in source_encoding is not defined in destination_encoding.
+ * This is a default behavior.
+ * [:undef => :replace]
+ * replace undefined character in destination_encoding as a replacement string.
+ * [:replace => string]
+ * specify the replacement string.
+ * If not specified, "\uFFFD" is used for Unicode encodings and "?" for others.
+ * [:universal_newline => true]
+ * convert CRLF and CR to LF.
+ * [:crlf_newline => true]
+ * convert LF to CRLF.
+ * [:cr_newline => true]
+ * convert LF to CR.
+ * [:xml => :text]
+ * escape as XML CharData.
+ * This form can be used as a HTML 4.0 #PCDATA.
+ * - '&' -> '&amp;'
+ * - '<' -> '&lt;'
+ * - '>' -> '&gt;'
+ * - undefined characters in destination_encoding -> hexadecimal CharRef such as &#xHH;
+ * [:xml => :attr]
+ * escape as XML AttValue.
+ * The converted result is quoted as "...".
+ * This form can be used as a HTML 4.0 attribute value.
+ * - '&' -> '&amp;'
+ * - '<' -> '&lt;'
+ * - '>' -> '&gt;'
+ * - '"' -> '&quot;'
+ * - undefined characters in destination_encoding -> hexadecimal CharRef such as &#xHH;
+ *
+ * example:
+ * # UTF-16BE to UTF-8
+ * ec = Encoding::Converter.new("UTF-16BE", "UTF-8")
+ *
+ * # Usually, decorators such as newline conversion are inserted at last.
+ * ec = Encoding::Converter.new("UTF-16BE", "UTF-8", :universal_newline => true)
+ * p ec.convpath #=> [[#<Encoding:UTF-16BE>, #<Encoding:UTF-8>],
+ * # "universal_newline"]
+ *
+ * # But, if the last encoding is ASCII incompatible,
+ * # decorators are inserted before the last conversion.
+ * ec = Encoding::Converter.new("UTF-8", "UTF-16BE", :crlf_newline => true)
+ * p ec.convpath #=> ["crlf_newline",
+ * # [#<Encoding:UTF-8>, #<Encoding:UTF-16BE>]]
+ *
+ * # conversion path can be specified directly.
+ * ec = Encoding::Converter.new(["universal_newline", ["EUC-JP", "UTF-8"], ["UTF-8", "UTF-16BE"]])
+ * p ec.convpath #=> ["universal_newline",
+ * # [#<Encoding:EUC-JP>, #<Encoding:UTF-8>],
+ * # [#<Encoding:UTF-8>, #<Encoding:UTF-16BE>]]
+ */
+static VALUE
+econv_init(int argc, VALUE *argv, VALUE self)
+{
+ VALUE ecopts;
+ volatile VALUE snamev, dnamev;
+ const char *sname, *dname;
+ rb_encoding *senc, *denc;
+ rb_econv_t *ec;
+ int ecflags;
+ VALUE convpath;
if (DATA_PTR(self)) {
rb_raise(rb_eTypeError, "already initialized");
}
- ec = rb_econv_open_opts(sname, dname, ecflags, ecopts);
+ if (argc == 1 && !NIL_P(convpath = rb_check_array_type(argv[0]))) {
+ ec = rb_econv_init_by_convpath(self, convpath, &sname, &dname, &senc, &denc);
+ ecflags = 0;
+ ecopts = Qnil;
+ }
+ else {
+ econv_args(argc, argv, &snamev, &dnamev, &sname, &dname, &senc, &denc, &ecflags, &ecopts);
+ ec = rb_econv_open_opts(sname, dname, ecflags, ecopts);
+ }
+
if (!ec) {
rb_exc_raise(rb_econv_open_exc(sname, dname, ecflags));
}
- if (*sname && *dname) { /* check "" to "universal_newline" */
+ if (!DECORATOR_P(sname, dname)) {
if (!senc)
senc = make_dummy_encoding(sname);
if (!denc)
@@ -2660,15 +3079,6 @@ econv_init(int argc, VALUE *argv, VALUE self)
ec->source_encoding = senc;
ec->destination_encoding = denc;
- if (ec->last_tc) {
- ec->source_encoding_name = ec->elems[0].tc->transcoder->src_encoding;
- ec->destination_encoding_name = ec->last_tc->transcoder->dst_encoding;
- }
- else {
- ec->source_encoding_name = "";
- ec->destination_encoding_name = "";
- }
-
DATA_PTR(self) = ec;
return self;
@@ -2749,6 +3159,48 @@ econv_destination_encoding(VALUE self)
return rb_enc_from_encoding(ec->destination_encoding);
}
+/*
+ * call-seq:
+ * ec.convpath -> ary
+ *
+ * returns the conversion path of ec.
+ *
+ * The result is an array of conversions.
+ *
+ * ec = Encoding::Converter.new("ISo-8859-1", "EUC-JP", crlf_newline: true)
+ * p ec.convpath
+ * #=> [[#<Encoding:ISO-8859-1>, #<Encoding:UTF-8>],
+ * # [#<Encoding:UTF-8>, #<Encoding:EUC-JP>],
+ * # "crlf_newline"]
+ *
+ * A element of the array is a pair of encodings or a string.
+ * The pair means encoding conversion.
+ * The string means decorator.
+ *
+ * In the above example, [#<Encoding:ISO-8859-1>, #<Encoding:UTF-8>] means
+ * a converter from ISO-8859-1 to UTF-8.
+ * "crlf_newline" means newline converter from LF to CRLF.
+ */
+static VALUE
+econv_convpath(VALUE self)
+{
+ rb_econv_t *ec = check_econv(self);
+ VALUE result;
+ int i;
+
+ result = rb_ary_new();
+ for (i = 0; i < ec->num_trans; i++) {
+ const rb_transcoder *tr = ec->elems[i].tc->transcoder;
+ VALUE v;
+ if (DECORATOR_P(tr->src_encoding, tr->dst_encoding))
+ v = rb_str_new_cstr(tr->dst_encoding);
+ else
+ v = rb_assoc_new(make_encobj(tr->src_encoding), make_encobj(tr->dst_encoding));
+ rb_ary_push(result, v);
+ }
+ return result;
+}
+
static VALUE
econv_result_to_symbol(rb_econv_result_t res)
{
@@ -2759,7 +3211,7 @@ econv_result_to_symbol(rb_econv_result_t res)
case econv_destination_buffer_full: return sym_destination_buffer_full;
case econv_source_buffer_empty: return sym_source_buffer_empty;
case econv_finished: return sym_finished;
- case econv_output_followed_by_input: return sym_output_followed_by_input;
+ case econv_after_output: return sym_after_output;
default: return INT2NUM(res); /* should not be reached */
}
}
@@ -2774,16 +3226,16 @@ econv_result_to_symbol(rb_econv_result_t res)
* possible opt elements:
* hash form:
* :partial_input => true # source buffer may be part of larger source
- * output_followed_by_input => true # stop conversion after output before input
+ * :after_output => true # stop conversion after output before input
* integer form:
* Encoding::Converter::PARTIAL_INPUT
- * Encoding::Converter::OUTPUT_FOLLOWED_BY_INPUT
+ * Encoding::Converter::AFTER_OUTPUT
*
* possible results:
* :invalid_byte_sequence
* :incomplete_input
* :undefined_conversion
- * :output_followed_by_input
+ * :after_output
* :destination_buffer_full
* :source_buffer_empty
* :finished
@@ -2831,8 +3283,8 @@ econv_result_to_symbol(rb_econv_result_t res)
* - unexpected end of source buffer (:incomplete_input)
* this occur only when :partial_input is not specified.
* - character not representable in output encoding (:undefined_conversion)
- * - after some output is generated, before input is done (:output_followed_by_input)
- * this occur only when :output_followed_by_input is specified.
+ * - after some output is generated, before input is done (:after_output)
+ * this occur only when :after_output is specified.
* - destination buffer is full (:destination_buffer_full)
* this occur only when destination_bytesize is non-nil.
* - source buffer is empty (:source_buffer_empty)
@@ -2892,9 +3344,9 @@ econv_primitive_convert(int argc, VALUE *argv, VALUE self)
v = rb_hash_aref(opt, sym_partial_input);
if (RTEST(v))
flags |= ECONV_PARTIAL_INPUT;
- v = rb_hash_aref(opt, sym_output_followed_by_input);
+ v = rb_hash_aref(opt, sym_after_output);
if (RTEST(v))
- flags |= ECONV_OUTPUT_FOLLOWED_BY_INPUT;
+ flags |= ECONV_AFTER_OUTPUT;
}
StringValue(output);
@@ -2989,8 +3441,8 @@ econv_primitive_convert(int argc, VALUE *argv, VALUE self)
* puts ec.finish.dump #=> "\e(B".force_encoding("ISO-2022-JP")
*
* If a conversion error occur,
- * Encoding::ConversionUndefined or
- * Encoding::InvalidByteSequence is raised.
+ * Encoding::UndefinedConversionError or
+ * Encoding::InvalidByteSequenceError is raised.
*
*/
static VALUE
@@ -3220,7 +3672,7 @@ econv_insert_output(VALUE self, VALUE string)
StringValue(string);
insert_enc = rb_econv_encoding_to_insert_output(ec);
- string = rb_str_transcode(string, rb_enc_from_encoding(rb_enc_find(insert_enc)), 0, Qnil);
+ string = rb_str_encode(string, rb_enc_from_encoding(rb_enc_find(insert_enc)), 0, Qnil);
ret = rb_econv_insert_output(ec, (const unsigned char *)RSTRING_PTR(string), RSTRING_LEN(string), insert_enc);
if (ret == -1) {
@@ -3242,7 +3694,7 @@ econv_insert_output(VALUE self, VALUE string)
* some bytes are buffered to be converted later.
* The latter bytes can be put back.
* It can be observed by
- * Encoding::InvalidByteSequence#readagain_bytes and
+ * Encoding::InvalidByteSequenceError#readagain_bytes and
* Encoding::Converter#primitive_errinfo.
*
* ec = Encoding::Converter.new("utf-16le", "iso-8859-1")
@@ -3291,14 +3743,14 @@ econv_putback(int argc, VALUE *argv, VALUE self)
* It returns nil if the last conversion is not an error.
*
* "error" means that
- * Encoding::InvalidByteSequence and Encoding::ConversionUndefined for
+ * Encoding::InvalidByteSequenceError and Encoding::UndefinedConversionError for
* Encoding::Converter#convert and
* :invalid_byte_sequence, :incomplete_input and :undefined_conversion for
* Encoding::Converter#primitive_convert.
*
* ec = Encoding::Converter.new("utf-8", "iso-8859-1")
* p ec.primitive_convert(src="\xf1abcd", dst="") #=> :invalid_byte_sequence
- * p ec.last_error #=> #<Encoding::InvalidByteSequence: "\xF1" followed by "a" on UTF-8>
+ * p ec.last_error #=> #<Encoding::InvalidByteSequenceError: "\xF1" followed by "a" on UTF-8>
* p ec.primitive_convert(src, dst, nil, 1) #=> :destination_buffer_full
* p ec.last_error #=> nil
*
@@ -3336,7 +3788,7 @@ econv_get_replacement(VALUE self)
ret = make_replacement(ec);
if (ret == -1) {
- rb_raise(rb_eConversionUndefined, "replacement character setup failed");
+ rb_raise(rb_eUndefinedConversionError, "replacement character setup failed");
}
enc = rb_enc_find(ec->replacement_enc);
@@ -3367,11 +3819,11 @@ econv_set_replacement(VALUE self, VALUE arg)
ret = rb_econv_set_replacement(ec,
(const unsigned char *)RSTRING_PTR(string),
RSTRING_LEN(string),
- enc->name);
+ rb_enc_name(enc));
if (ret == -1) {
- /* xxx: rb_eInvalidByteSequence? */
- rb_raise(rb_eConversionUndefined, "replacement character setup failed");
+ /* xxx: rb_eInvalidByteSequenceError? */
+ rb_raise(rb_eUndefinedConversionError, "replacement character setup failed");
}
return arg;
@@ -3412,7 +3864,7 @@ ecerr_source_encoding_name(VALUE self)
* ec = Encoding::Converter.new("ISO-8859-1", "EUC-JP") # ISO-8859-1 -> UTF-8 -> EUC-JP
* begin
* ec.convert("\xa0") # NO-BREAK SPACE, which is available in UTF-8 but not in EUC-JP.
- * rescue Encoding::ConversionUndefined
+ * rescue Encoding::UndefinedConversionError
* p $!.source_encoding #=> #<Encoding:UTF-8>
* p $!.destination_encoding #=> #<Encoding:EUC-JP>
* p $!.source_encoding_name #=> "UTF-8"
@@ -3454,12 +3906,12 @@ ecerr_destination_encoding(VALUE self)
* call-seq:
* ecerr.error_char -> string
*
- * returns the one-character string which cause Encoding::ConversionUndefined.
+ * returns the one-character string which cause Encoding::UndefinedConversionError.
*
* ec = Encoding::Converter.new("ISO-8859-1", "EUC-JP")
* begin
* ec.convert("\xa0")
- * rescue Encoding::ConversionUndefined
+ * rescue Encoding::UndefinedConversionError
* puts $!.error_char.dump #=> "\xC2\xA0"
* p $!.error_char.encoding #=> #<Encoding:UTF-8>
* end
@@ -3475,13 +3927,13 @@ ecerr_error_char(VALUE self)
* call-seq:
* ecerr.error_bytes -> string
*
- * returns the discarded bytes when Encoding::InvalidByteSequence occur.
+ * returns the discarded bytes when Encoding::InvalidByteSequenceError occur.
*
* ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1")
* begin
* ec.convert("abc\xA1\xFFdef")
- * rescue Encoding::InvalidByteSequence
- * p $! #=> #<Encoding::InvalidByteSequence: "\xA1" followed by "\xFF" on EUC-JP>
+ * rescue Encoding::InvalidByteSequenceError
+ * p $! #=> #<Encoding::InvalidByteSequenceError: "\xA1" followed by "\xFF" on EUC-JP>
* puts $!.error_bytes.dump #=> "\xA1"
* puts $!.readagain_bytes.dump #=> "\xFF"
* end
@@ -3496,7 +3948,7 @@ ecerr_error_bytes(VALUE self)
* call-seq:
* ecerr.readagain_bytes -> string
*
- * returns the bytes to be read again when Encoding::InvalidByteSequence occur.
+ * returns the bytes to be read again when Encoding::InvalidByteSequenceError occur.
*/
static VALUE
ecerr_readagain_bytes(VALUE self)
@@ -3515,16 +3967,16 @@ ecerr_readagain_bytes(VALUE self)
*
* begin
* ec.convert("abc\xA1z")
- * rescue Encoding::InvalidByteSequence
- * p $! #=> #<Encoding::InvalidByteSequence: "\xA1" followed by "z" on EUC-JP>
+ * rescue Encoding::InvalidByteSequenceError
+ * p $! #=> #<Encoding::InvalidByteSequenceError: "\xA1" followed by "z" on EUC-JP>
* p $!.incomplete_input? #=> false
* end
*
* begin
* ec.convert("abc\xA1")
* ec.finish
- * rescue Encoding::InvalidByteSequence
- * p $! #=> #<Encoding::InvalidByteSequence: incomplete "\xA1" on EUC-JP>
+ * rescue Encoding::InvalidByteSequenceError
+ * p $! #=> #<Encoding::InvalidByteSequenceError: incomplete "\xA1" on EUC-JP>
* p $!.incomplete_input? #=> true
* end
*/
@@ -3539,7 +3991,6 @@ extern void Init_newline(void);
void
Init_transcode(void)
{
-
transcoder_table = st_init_strcasetable();
sym_invalid = ID2SYM(rb_intern("invalid"));
@@ -3555,11 +4006,11 @@ Init_transcode(void)
sym_destination_buffer_full = ID2SYM(rb_intern("destination_buffer_full"));
sym_source_buffer_empty = ID2SYM(rb_intern("source_buffer_empty"));
sym_finished = ID2SYM(rb_intern("finished"));
- sym_output_followed_by_input = ID2SYM(rb_intern("output_followed_by_input"));
+ sym_after_output = ID2SYM(rb_intern("after_output"));
sym_incomplete_input = ID2SYM(rb_intern("incomplete_input"));
- sym_universal_newline_decoder = ID2SYM(rb_intern("universal_newline_decoder"));
- sym_crlf_newline_encoder = ID2SYM(rb_intern("crlf_newline_encoder"));
- sym_cr_newline_encoder = ID2SYM(rb_intern("cr_newline_encoder"));
+ sym_universal_newline = ID2SYM(rb_intern("universal_newline"));
+ sym_crlf_newline = ID2SYM(rb_intern("crlf_newline"));
+ sym_cr_newline = ID2SYM(rb_intern("cr_newline"));
sym_partial_input = ID2SYM(rb_intern("partial_input"));
Init_newline();
@@ -3568,9 +4019,9 @@ Init_transcode(void)
void
InitVM_transcode(rb_vm_t *vm)
{
- rb_eConversionUndefined = rb_define_class_under(rb_cEncoding, "ConversionUndefined", rb_eStandardError);
- rb_eInvalidByteSequence = rb_define_class_under(rb_cEncoding, "InvalidByteSequence", rb_eStandardError);
- rb_eNoConverter = rb_define_class_under(rb_cEncoding, "NoConverter", rb_eStandardError);
+ rb_eUndefinedConversionError = rb_define_class_under(rb_cEncoding, "UndefinedConversionError", rb_eEncodingError);
+ rb_eInvalidByteSequenceError = rb_define_class_under(rb_cEncoding, "InvalidByteSequenceError", rb_eEncodingError);
+ rb_eConverterNotFoundError = rb_define_class_under(rb_cEncoding, "ConverterNotFoundError", rb_eEncodingError);
rb_define_method(rb_cString, "encode", str_encode, -1);
rb_define_method(rb_cString, "encode!", str_encode_bang, -1);
@@ -3578,8 +4029,10 @@ InitVM_transcode(rb_vm_t *vm)
rb_cEncodingConverter = rb_define_class_under(rb_cEncoding, "Converter", rb_cData);
rb_define_alloc_func(rb_cEncodingConverter, econv_s_allocate);
rb_define_singleton_method(rb_cEncodingConverter, "asciicompat_encoding", econv_s_asciicompat_encoding, 1);
+ rb_define_singleton_method(rb_cEncodingConverter, "search_convpath", econv_s_search_convpath, -1);
rb_define_method(rb_cEncodingConverter, "initialize", econv_init, -1);
rb_define_method(rb_cEncodingConverter, "inspect", econv_inspect, 0);
+ rb_define_method(rb_cEncodingConverter, "convpath", econv_convpath, 0);
rb_define_method(rb_cEncodingConverter, "source_encoding", econv_source_encoding, 0);
rb_define_method(rb_cEncodingConverter, "destination_encoding", econv_destination_encoding, 0);
rb_define_method(rb_cEncodingConverter, "primitive_convert", econv_primitive_convert, -1);
@@ -3598,25 +4051,25 @@ InitVM_transcode(rb_vm_t *vm)
rb_define_const(rb_cEncodingConverter, "UNDEF_REPLACE", INT2FIX(ECONV_UNDEF_REPLACE));
rb_define_const(rb_cEncodingConverter, "UNDEF_HEX_CHARREF", INT2FIX(ECONV_UNDEF_HEX_CHARREF));
rb_define_const(rb_cEncodingConverter, "PARTIAL_INPUT", INT2FIX(ECONV_PARTIAL_INPUT));
- rb_define_const(rb_cEncodingConverter, "OUTPUT_FOLLOWED_BY_INPUT", INT2FIX(ECONV_OUTPUT_FOLLOWED_BY_INPUT));
- rb_define_const(rb_cEncodingConverter, "UNIVERSAL_NEWLINE_DECODER", INT2FIX(ECONV_UNIVERSAL_NEWLINE_DECODER));
- rb_define_const(rb_cEncodingConverter, "CRLF_NEWLINE_ENCODER", INT2FIX(ECONV_CRLF_NEWLINE_ENCODER));
- rb_define_const(rb_cEncodingConverter, "CR_NEWLINE_ENCODER", INT2FIX(ECONV_CR_NEWLINE_ENCODER));
- rb_define_const(rb_cEncodingConverter, "XML_TEXT_ENCODER", INT2FIX(ECONV_XML_TEXT_ENCODER));
- rb_define_const(rb_cEncodingConverter, "XML_ATTR_CONTENT_ENCODER", INT2FIX(ECONV_XML_ATTR_CONTENT_ENCODER));
- rb_define_const(rb_cEncodingConverter, "XML_ATTR_QUOTE_ENCODER", INT2FIX(ECONV_XML_ATTR_QUOTE_ENCODER));
-
- rb_define_method(rb_eConversionUndefined, "source_encoding_name", ecerr_source_encoding_name, 0);
- rb_define_method(rb_eConversionUndefined, "destination_encoding_name", ecerr_destination_encoding_name, 0);
- rb_define_method(rb_eConversionUndefined, "source_encoding", ecerr_source_encoding, 0);
- rb_define_method(rb_eConversionUndefined, "destination_encoding", ecerr_destination_encoding, 0);
- rb_define_method(rb_eConversionUndefined, "error_char", ecerr_error_char, 0);
-
- rb_define_method(rb_eInvalidByteSequence, "source_encoding_name", ecerr_source_encoding_name, 0);
- rb_define_method(rb_eInvalidByteSequence, "destination_encoding_name", ecerr_destination_encoding_name, 0);
- rb_define_method(rb_eInvalidByteSequence, "source_encoding", ecerr_source_encoding, 0);
- rb_define_method(rb_eInvalidByteSequence, "destination_encoding", ecerr_destination_encoding, 0);
- rb_define_method(rb_eInvalidByteSequence, "error_bytes", ecerr_error_bytes, 0);
- rb_define_method(rb_eInvalidByteSequence, "readagain_bytes", ecerr_readagain_bytes, 0);
- rb_define_method(rb_eInvalidByteSequence, "incomplete_input?", ecerr_incomplete_input, 0);
+ rb_define_const(rb_cEncodingConverter, "AFTER_OUTPUT", INT2FIX(ECONV_AFTER_OUTPUT));
+ rb_define_const(rb_cEncodingConverter, "UNIVERSAL_NEWLINE_DECORATOR", INT2FIX(ECONV_UNIVERSAL_NEWLINE_DECORATOR));
+ rb_define_const(rb_cEncodingConverter, "CRLF_NEWLINE_DECORATOR", INT2FIX(ECONV_CRLF_NEWLINE_DECORATOR));
+ rb_define_const(rb_cEncodingConverter, "CR_NEWLINE_DECORATOR", INT2FIX(ECONV_CR_NEWLINE_DECORATOR));
+ rb_define_const(rb_cEncodingConverter, "XML_TEXT_DECORATOR", INT2FIX(ECONV_XML_TEXT_DECORATOR));
+ rb_define_const(rb_cEncodingConverter, "XML_ATTR_CONTENT_DECORATOR", INT2FIX(ECONV_XML_ATTR_CONTENT_DECORATOR));
+ rb_define_const(rb_cEncodingConverter, "XML_ATTR_QUOTE_DECORATOR", INT2FIX(ECONV_XML_ATTR_QUOTE_DECORATOR));
+
+ rb_define_method(rb_eUndefinedConversionError, "source_encoding_name", ecerr_source_encoding_name, 0);
+ rb_define_method(rb_eUndefinedConversionError, "destination_encoding_name", ecerr_destination_encoding_name, 0);
+ rb_define_method(rb_eUndefinedConversionError, "source_encoding", ecerr_source_encoding, 0);
+ rb_define_method(rb_eUndefinedConversionError, "destination_encoding", ecerr_destination_encoding, 0);
+ rb_define_method(rb_eUndefinedConversionError, "error_char", ecerr_error_char, 0);
+
+ rb_define_method(rb_eInvalidByteSequenceError, "source_encoding_name", ecerr_source_encoding_name, 0);
+ rb_define_method(rb_eInvalidByteSequenceError, "destination_encoding_name", ecerr_destination_encoding_name, 0);
+ rb_define_method(rb_eInvalidByteSequenceError, "source_encoding", ecerr_source_encoding, 0);
+ rb_define_method(rb_eInvalidByteSequenceError, "destination_encoding", ecerr_destination_encoding, 0);
+ rb_define_method(rb_eInvalidByteSequenceError, "error_bytes", ecerr_error_bytes, 0);
+ rb_define_method(rb_eInvalidByteSequenceError, "readagain_bytes", ecerr_readagain_bytes, 0);
+ rb_define_method(rb_eInvalidByteSequenceError, "incomplete_input?", ecerr_incomplete_input, 0);
}
diff --git a/transcode_data.h b/transcode_data.h
index 98f48a4de9..497eb3c51b 100644
--- a/transcode_data.h
+++ b/transcode_data.h
@@ -34,10 +34,12 @@
#define FUNsi (PType 0x0D) /* function from start to info */
#define FUNio (PType 0x0E) /* function from info to output */
#define FUNso (PType 0x0F) /* function from start to output */
-#define STR1 (PType 0x11) /* string up to 255 bytes: 1byte length + content */
+#define STR1 (PType 0x11) /* string 4 <= len <= 259 bytes: 1byte length + content */
+#define STR1_LENGTH(byte_addr) (*(byte_addr) + 4)
#define STR1_BYTEINDEX(w) ((w) >> 6)
#define makeSTR1(bi) (((bi) << 6) | STR1)
+#define makeSTR1LEN(len) ((len)-4)
#define o1(b1) (PType((((unsigned char)(b1))<<8)|ONEbt))
#define o2(b1,b2) (PType((((unsigned char)(b1))<<8)|(((unsigned char)(b2))<<16)|TWObt))
@@ -84,11 +86,11 @@ struct rb_transcoder {
int (*state_fini_func)(void*); /* ret==0:success ret!=0:failure(errno) */
VALUE (*func_ii)(void*, VALUE); /* info -> info */
VALUE (*func_si)(void*, const unsigned char*, size_t); /* start -> info */
- int (*func_io)(void*, VALUE, const unsigned char*); /* info -> output */
- int (*func_so)(void*, const unsigned char*, size_t, unsigned char*); /* start -> output */
- int (*finish_func)(void*, unsigned char*); /* -> output */
- int (*resetsize_func)(void*); /* -> len */
- int (*resetstate_func)(void*, unsigned char*); /* -> output */
+ ssize_t (*func_io)(void*, VALUE, const unsigned char*, size_t); /* info -> output */
+ ssize_t (*func_so)(void*, const unsigned char*, size_t, unsigned char*, size_t); /* start -> output */
+ ssize_t (*finish_func)(void*, unsigned char*, size_t); /* -> output */
+ ssize_t (*resetsize_func)(void*); /* -> len */
+ ssize_t (*resetstate_func)(void*, unsigned char*, size_t); /* -> output */
};
void rb_declare_transcoder(const char *enc1, const char *enc2, const char *lib);
diff --git a/util.c b/util.c
index 6df83fcedb..a55c28d502 100644
--- a/util.c
+++ b/util.c
@@ -191,7 +191,7 @@ ruby_strtoul(const char *str, char **endptr, int base)
# define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR)
#endif
-#if defined(MSDOS) || defined(__CYGWIN32__) || defined(_WIN32)
+#if defined(__CYGWIN32__) || defined(_WIN32)
/*
* Copyright (c) 1993, Intergraph Corporation
*
@@ -283,15 +283,11 @@ ruby_add_suffix(VALUE str, const char *suffix)
rb_fatal("Cannot do inplace edit on long filename (%ld characters)",
RSTRING_LEN(str));
-#if defined(DJGPP) || defined(__CYGWIN32__) || defined(_WIN32)
+#if defined(__CYGWIN32__) || defined(_WIN32)
/* Style 0 */
slen = RSTRING_LEN(str);
rb_str_cat(str, suffix, extlen);
-#if defined(DJGPP)
- if (_USE_LFN) return;
-#else
if (valid_filename(RSTRING_PTR(str))) return;
-#endif
/* Fooey, style 0 failed. Fix str before continuing. */
rb_str_resize(str, slen);
@@ -363,136 +359,6 @@ valid_filename(const char *s)
#endif
#endif
-#if defined __DJGPP__
-
-#include <dpmi.h>
-
-static char dbcs_table[256];
-
-int
-make_dbcs_table()
-{
- __dpmi_regs r;
- struct {
- unsigned char start;
- unsigned char end;
- } vec;
- int offset;
-
- memset(&r, 0, sizeof(r));
- r.x.ax = 0x6300;
- __dpmi_int(0x21, &r);
- offset = r.x.ds * 16 + r.x.si;
-
- for (;;) {
- int i;
- dosmemget(offset, sizeof vec, &vec);
- if (!vec.start && !vec.end)
- break;
- for (i = vec.start; i <= vec.end; i++)
- dbcs_table[i] = 1;
- offset += 2;
- }
-}
-
-int
-mblen(const char *s, size_t n)
-{
- static int need_init = 1;
- if (need_init) {
- make_dbcs_table();
- need_init = 0;
- }
- if (s) {
- if (n == 0 || *s == 0)
- return 0;
- else if (!s[1])
- return 1;
- return dbcs_table[(unsigned char)*s] + 1;
- }
- else
- return 1;
-}
-
-struct PathList {
- struct PathList *next;
- char *path;
-};
-
-struct PathInfo {
- struct PathList *head;
- int count;
-};
-
-static int
-push_element(const char *path, VALUE vinfo)
-{
- struct PathList *p;
- struct PathInfo *info = (struct PathInfo *)vinfo;
-
- p = ALLOC(struct PathList);
- MEMZERO(p, struct PathList, 1);
- p->path = ruby_strdup(path);
- p->next = info->head;
- info->head = p;
- info->count++;
-
- return 0;
-}
-
-#include <dirent.h>
-int __opendir_flags = __OPENDIR_PRESERVE_CASE;
-
-char **
-__crt0_glob_function(char *path)
-{
- int len = strlen(path);
- int i;
- char **rv;
- char path_buffer[PATH_MAX];
- char *buf = path_buffer;
- char *p;
- struct PathInfo info;
- struct PathList *plist;
-
- if (PATH_MAX <= len)
- buf = ruby_xmalloc(len + 1);
-
- strncpy(buf, path, len);
- buf[len] = '\0';
-
- for (p = buf; *p; p += mblen(p, RUBY_MBCHAR_MAXSIZE))
- if (*p == '\\')
- *p = '/';
-
- info.count = 0;
- info.head = 0;
-
- ruby_glob(buf, 0, push_element, (VALUE)&info);
-
- if (buf != path_buffer)
- ruby_xfree(buf);
-
- if (info.count == 0)
- return 0;
-
- rv = ruby_xmalloc((info.count + 1) * sizeof (char *));
-
- plist = info.head;
- i = 0;
- while (plist) {
- struct PathList *cur;
- rv[i] = plist->path;
- cur = plist;
- plist = plist->next;
- ruby_xfree(cur);
- i++;
- }
- rv[i] = 0;
- return rv;
-}
-
-#endif
/* mm.c */
@@ -3220,23 +3086,21 @@ nrv_alloc(const char *s, char **rve, int n)
return rv;
}
+#ifndef MULTIPLE_THREADS
/* freedtoa(s) must be used to free values s returned by dtoa
* when MULTIPLE_THREADS is #defined. It should be used in all cases,
* but for consistency with earlier versions of dtoa, it is optional
* when MULTIPLE_THREADS is not defined.
*/
-void
+static void
freedtoa(char *s)
{
Bigint *b = (Bigint *)((int *)s - 1);
b->maxwds = 1 << (b->k = *(int*)b);
Bfree(b);
-#ifndef MULTIPLE_THREADS
- if (s == dtoa_result)
- dtoa_result = 0;
-#endif
}
+#endif
/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
*
@@ -3273,7 +3137,7 @@ freedtoa(char *s)
*/
char *
-dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve)
+ruby_dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve)
{
/* Arguments ndigits, decpt, sign are similar to those
of ecvt and fcvt; trailing zeros are suppressed from
diff --git a/variable.c b/variable.c
index 5e706add22..c133f4149e 100644
--- a/variable.c
+++ b/variable.c
@@ -12,10 +12,10 @@
**********************************************************************/
#include "ruby/ruby.h"
-#include "ruby/node.h"
#include "ruby/st.h"
#include "ruby/util.h"
#include "vm_core.h"
+#include "node.h"
void rb_vm_change_state(void);
#define rb_global_tbl GET_VM()->global_tbl
@@ -146,6 +146,7 @@ classname(VALUE klass)
if (RCLASS_IV_TBL(klass)) {
if (!st_lookup(RCLASS_IV_TBL(klass), classpath, &path)) {
ID classid;
+ st_data_t n;
CONST_ID(classid, "__classid__");
@@ -155,7 +156,8 @@ classname(VALUE klass)
path = rb_str_dup(rb_id2str(SYM2ID(path)));
OBJ_FREEZE(path);
st_insert(RCLASS_IV_TBL(klass), classpath, path);
- st_delete(RCLASS_IV_TBL(klass), (st_data_t*)&classid, 0);
+ n = classid;
+ st_delete(RCLASS_IV_TBL(klass), &n, 0);
}
if (TYPE(path) != T_STRING) {
rb_bug("class path is not set properly");
@@ -287,9 +289,15 @@ rb_obj_classname(VALUE obj)
return rb_class2name(CLASS_OF(obj));
}
+#define global_variable rb_global_variable
+
+#define gvar_getter_t rb_gvar_getter_t
+#define gvar_setter_t rb_gvar_setter_t
+#define gvar_marker_t rb_gvar_marker_t
+
struct trace_var {
int removed;
- void (*func)();
+ void (*func)(VALUE arg, VALUE val);
VALUE data;
struct trace_var *next;
};
@@ -302,24 +310,29 @@ struct global_variable {
int counter;
int flags;
void *data;
- VALUE (*getter)();
- void (*setter)();
- void (*marker)();
+ gvar_getter_t *getter;
+ gvar_setter_t *setter;
+ gvar_marker_t *marker;
int block_trace;
struct trace_var *trace;
};
-static VALUE undef_getter(ID id);
-static void undef_setter(VALUE val, ID id, void *data, struct global_variable *var);
-static void undef_marker(void);
+#define undef_getter rb_gvar_undef_getter
+#define undef_setter rb_gvar_undef_setter
+#define undef_marker rb_gvar_undef_marker
+
+#define val_getter rb_gvar_val_getter
+#define val_setter rb_gvar_val_setter
+#define val_marker rb_gvar_val_marker
+
+#define var_getter rb_gvar_var_getter
+#define var_setter rb_gvar_var_setter
+#define var_marker rb_gvar_var_marker
-static VALUE val_getter(ID id, VALUE val);
-static void val_setter(VALUE val, ID id, void *data, struct global_variable *var);
-static void val_marker(VALUE data);
+#define readonly_setter rb_gvar_readonly_setter
-static VALUE var_getter(ID id, VALUE *var);
-static void var_setter(VALUE val, ID id, VALUE *var);
-static void var_marker(VALUE *var);
+#define global_entry rb_global_entry
+#define global_variable rb_global_variable
struct global_entry*
rb_global_entry(ID id)
@@ -350,15 +363,15 @@ rb_global_entry(ID id)
return entry;
}
-static VALUE
-undef_getter(ID id)
+VALUE
+undef_getter(ID id, void *data, struct global_variable *var)
{
rb_warning("global variable `%s' not initialized", rb_id2name(id));
return Qnil;
}
-static void
+void
undef_setter(VALUE val, ID id, void *data, struct global_variable *var)
{
var->getter = val_getter;
@@ -368,56 +381,58 @@ undef_setter(VALUE val, ID id, void *data, struct global_variable *var)
var->data = (void*)val;
}
-static void
-undef_marker(void)
+void
+undef_marker(VALUE *var)
{
}
-static VALUE
-val_getter(ID id, VALUE val)
+VALUE
+val_getter(ID id, void *data, struct global_variable *var)
{
- return val;
+ return (VALUE)data;
}
-static void
+void
val_setter(VALUE val, ID id, void *data, struct global_variable *var)
{
var->data = (void*)val;
}
-static void
-val_marker(VALUE data)
+void
+val_marker(VALUE *var)
{
+ VALUE data = (VALUE)var;
if (data) rb_gc_mark_maybe(data);
}
-static VALUE
-var_getter(ID id, VALUE *var)
+VALUE
+var_getter(ID id, void *data, struct global_variable *gvar)
{
+ VALUE *var = data;
if (!var) return Qnil;
return *var;
}
-static void
-var_setter(VALUE val, ID id, VALUE *var)
+void
+var_setter(VALUE val, ID id, void *data, struct global_variable *gvar)
{
- *var = val;
+ *(VALUE *)data = val;
}
-static void
+void
var_marker(VALUE *var)
{
if (var) rb_gc_mark_maybe(*var);
}
static void
-vm_marker(void *var)
+vm_marker(VALUE *var)
{
rb_gc_mark(*rb_vm_specific_ptr((int)(VALUE)var));
}
-static void
-readonly_setter(VALUE val, ID id, void *var)
+void
+readonly_setter(VALUE val, ID id, void *data, struct global_variable *gvar)
{
rb_name_error(id, "%s is a read-only variable", rb_id2name(id));
}
@@ -495,8 +510,8 @@ rb_define_hooked_variable(
gvar->data = (void*)var;
gvar->marker = var_marker;
}
- gvar->getter = getter?getter:var_getter;
- gvar->setter = setter?setter:var_setter;
+ gvar->getter = getter?(gvar_getter_t *)getter:var_getter;
+ gvar->setter = setter?(gvar_setter_t *)setter:var_setter;
RB_GC_GUARD(tmp);
}
@@ -1310,7 +1325,8 @@ VALUE
rb_obj_remove_instance_variable(VALUE obj, VALUE name)
{
VALUE val = Qnil;
- ID id = rb_to_id(name);
+ const ID id = rb_to_id(name);
+ st_data_t n, v;
struct st_table *iv_index_tbl;
st_data_t index;
@@ -1335,8 +1351,9 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name)
break;
case T_CLASS:
case T_MODULE:
- if (RCLASS_IV_TBL(obj) && st_delete(RCLASS_IV_TBL(obj), (st_data_t*)&id, &val)) {
- return val;
+ n = id;
+ if (RCLASS_IV_TBL(obj) && st_delete(RCLASS_IV_TBL(obj), &n, &v)) {
+ return (VALUE)v;
}
break;
default:
@@ -1454,22 +1471,17 @@ rb_autoload(VALUE mod, ID id, const char *file)
static NODE*
autoload_delete(VALUE mod, ID id)
{
- VALUE val;
- st_data_t load = 0;
+ st_data_t val, load = 0, n = id;
- st_delete(RCLASS_IV_TBL(mod), (st_data_t*)&id, 0);
+ st_delete(RCLASS_IV_TBL(mod), &n, 0);
if (st_lookup(RCLASS_IV_TBL(mod), autoload, &val)) {
- struct st_table *tbl = check_autoload_table(val);
+ struct st_table *tbl = check_autoload_table((VALUE)val);
- st_delete(tbl, (st_data_t*)&id, &load);
+ st_delete(tbl, &n, &load);
if (tbl->num_entries == 0) {
- DATA_PTR(val) = 0;
- st_free_table(tbl);
- id = autoload;
- if (st_delete(RCLASS_IV_TBL(mod), (st_data_t*)&id, &val)) {
- rb_gc_force_recycle(val);
- }
+ n = autoload;
+ st_delete(RCLASS_IV_TBL(mod), &n, &val);
}
}
@@ -1491,12 +1503,12 @@ rb_autoload_load(VALUE klass, ID id)
static VALUE
autoload_file(VALUE mod, ID id)
{
- VALUE val, file;
+ VALUE file;
struct st_table *tbl;
- st_data_t load;
+ st_data_t val, load, n = id;
if (!st_lookup(RCLASS_IV_TBL(mod), autoload, &val) ||
- !(tbl = check_autoload_table(val)) || !st_lookup(tbl, id, &load)) {
+ !(tbl = check_autoload_table((VALUE)val)) || !st_lookup(tbl, n, &load)) {
return Qnil;
}
file = ((NODE *)load)->nd_lit;
@@ -1509,14 +1521,10 @@ autoload_file(VALUE mod, ID id)
}
/* already loaded but not defined */
- st_delete(tbl, (st_data_t*)&id, 0);
+ st_delete(tbl, &n, 0);
if (!tbl->num_entries) {
- DATA_PTR(val) = 0;
- st_free_table(tbl);
- id = autoload;
- if (st_delete(RCLASS_IV_TBL(mod), (st_data_t*)&id, &val)) {
- rb_gc_force_recycle(val);
- }
+ n = autoload;
+ st_delete(RCLASS_IV_TBL(mod), &n, &val);
}
return Qnil;
}
@@ -1595,8 +1603,9 @@ rb_const_get_at(VALUE klass, ID id)
VALUE
rb_mod_remove_const(VALUE mod, VALUE name)
{
- ID id = rb_to_id(name);
+ const ID id = rb_to_id(name);
VALUE val;
+ st_data_t v, n = id;
rb_vm_change_state();
@@ -1607,7 +1616,8 @@ rb_mod_remove_const(VALUE mod, VALUE name)
rb_raise(rb_eSecurityError, "Insecure: can't remove constant");
if (OBJ_FROZEN(mod)) rb_error_frozen("class/module");
- if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), (st_data_t*)&id, &val)) {
+ if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), &n, &v)) {
+ val = (VALUE)v;
if (val == Qundef) {
autoload_delete(mod, id);
val = Qnil;
@@ -2002,7 +2012,7 @@ rb_mod_class_variables(VALUE obj)
* @@var = 99
* puts @@var
* remove_class_variable(:@@var)
- * puts(defined? @@var)
+ * p(defined? @@var)
* end
*
* <em>produces:</em>
@@ -2014,8 +2024,8 @@ rb_mod_class_variables(VALUE obj)
VALUE
rb_mod_remove_cvar(VALUE mod, VALUE name)
{
- ID id = rb_to_id(name);
- VALUE val;
+ const ID id = rb_to_id(name);
+ st_data_t val, n = id;
if (!rb_is_class_id(id)) {
rb_name_error(id, "wrong class variable name %s", rb_id2name(id));
@@ -2024,8 +2034,8 @@ rb_mod_remove_cvar(VALUE mod, VALUE name)
rb_raise(rb_eSecurityError, "Insecure: can't remove class variable");
if (OBJ_FROZEN(mod)) rb_error_frozen("class/module");
- if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), (st_data_t*)&id, &val)) {
- return val;
+ if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), &n, &val)) {
+ return (VALUE)val;
}
if (rb_cvar_defined(mod, id)) {
rb_name_error(id, "cannot remove %s for %s",
diff --git a/version.h b/version.h
index 74e946997c..8f337afa7f 100644
--- a/version.h
+++ b/version.h
@@ -1,7 +1,7 @@
#define RUBY_VERSION "1.9.0"
-#define RUBY_RELEASE_DATE "2008-11-07"
+#define RUBY_RELEASE_DATE "2008-11-19"
#define RUBY_VERSION_CODE 190
-#define RUBY_RELEASE_CODE 20081107
+#define RUBY_RELEASE_CODE 20081119
#define RUBY_PATCHLEVEL 0
#define RUBY_VERSION_MAJOR 1
@@ -9,7 +9,7 @@
#define RUBY_VERSION_TEENY 0
#define RUBY_RELEASE_YEAR 2008
#define RUBY_RELEASE_MONTH 11
-#define RUBY_RELEASE_DAY 7
+#define RUBY_RELEASE_DAY 19
#ifdef RUBY_EXTERN
RUBY_EXTERN const char ruby_version[];
diff --git a/vm.c b/vm.c
index 25a7b914a2..434ebfb208 100644
--- a/vm.c
+++ b/vm.c
@@ -9,13 +9,20 @@
**********************************************************************/
#include "ruby/ruby.h"
-#include "ruby/node.h"
#include "ruby/st.h"
#include "ruby/encoding.h"
+#include "ruby/util.h"
+
#include "gc.h"
+#include "vm_core.h"
+#include "iseq.h"
+#include "eval_intern.h"
-#include "insnhelper.h"
#include "vm_insnhelper.c"
+#include "vm_exec.h"
+#include "vm_exec.c"
+
+#include "vm_method.c"
#include "vm_eval.c"
#define BUFSIZE 0x100
@@ -29,14 +36,6 @@ void vm_analysis_operand(int insn, int n, VALUE op);
void vm_analysis_register(int reg, int isset);
void vm_analysis_insn(int insn);
-#if OPT_STACK_CACHING
-static VALUE finish_insn_seq[1] = { BIN(finish_SC_ax_ax) };
-#elif OPT_CALL_THREADED_CODE
-static VALUE const finish_insn_seq[1] = { 0 };
-#else
-static VALUE finish_insn_seq[1] = { BIN(finish) };
-#endif
-
void
rb_vm_change_state(void)
{
@@ -127,6 +126,18 @@ vm_get_ruby_level_caller_cfp(rb_thread_t *th, rb_control_frame_t *cfp)
/* Env */
+/*
+ env{
+ env[0] // special (block or prev env)
+ env[1] // env object
+ env[2] // prev env val
+ };
+ */
+
+#define ENV_IN_HEAP_P(th, env) \
+ (!((th)->stack < (env) && (env) < ((th)->stack + (th)->stack_size)))
+#define ENV_VAL(env) ((env)[1])
+
static void
env_free(void * const ptr)
{
@@ -466,7 +477,7 @@ invoke_block_from_c(rb_thread_t *th, const rb_block_t *block,
th->cfp->dfp[-1] = (VALUE)cref;
}
- return vm_eval_body(th);
+ return vm_exec(th);
}
else {
return vm_yield_with_cfunc(th, block, self, argc, argv, blockptr);
@@ -738,37 +749,6 @@ debug_cref(NODE *cref)
}
#endif
-static NODE *
-vm_cref_push(rb_thread_t *th, VALUE klass, int noex)
-{
- rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(th, th->cfp);
- NODE *cref = NEW_BLOCK(klass);
- cref->nd_file = 0;
- cref->nd_visi = noex;
-
- if (cfp) {
- cref->nd_next = vm_get_cref(cfp->iseq, cfp->lfp, cfp->dfp);
- }
-
- return cref;
-}
-
-static inline VALUE
-vm_get_cbase(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp)
-{
- NODE *cref = vm_get_cref(iseq, lfp, dfp);
- VALUE klass = Qundef;
-
- while (cref) {
- if ((klass = cref->nd_clss) != 0) {
- break;
- }
- cref = cref->nd_next;
- }
-
- return klass;
-}
-
VALUE
rb_vm_cbase(void)
{
@@ -853,8 +833,8 @@ vm_make_jump_tag_but_local_jump(int state, VALUE val)
void
vm_jump_tag_but_local_jump(int state, VALUE val)
{
- VALUE exc = vm_make_jump_tag_but_local_jump(state, val);
if (val != Qnil) {
+ VALUE exc = vm_make_jump_tag_but_local_jump(state, val);
rb_exc_raise(exc);
}
JUMP_TAG(state);
@@ -881,21 +861,23 @@ rb_iter_break(void)
/* optimization: redefine management */
-#define vm_opt_method_table GET_VM()->opt_method_table
+#define vm_opt_method_table vm->opt_method_table
static void
rb_vm_check_redefinition_opt_method(const NODE *node)
{
- VALUE bop;
+ rb_vm_t *vm = GET_VM();
+ st_data_t bop;
if (st_lookup(vm_opt_method_table, (st_data_t)node, &bop)) {
- ruby_vm_redefined_flag |= bop;
+ vm->redefined_flag[(VALUE)bop] = 1;
}
}
static void
add_opt_method(VALUE klass, ID mid, VALUE bop)
{
+ rb_vm_t *vm = GET_VM();
NODE *node;
if (st_lookup(RCLASS_M_TBL(klass), mid, (void *)&node) &&
nd_type(node->nd_body->nd_body) == NODE_CFUNC) {
@@ -914,7 +896,7 @@ vm_init_redefined_flag(rb_vm_t *vm)
vm->opt_method_table = st_init_numtable();
-#define OP(mid_, bop_) (mid = id##mid_, bop = BOP_##bop_)
+#define OP(mid_, bop_) (mid = id##mid_, bop = BOP_##bop_, vm->redefined_flag[bop] = 0)
#define C(k) add_opt_method(rb_c##k, mid, bop)
OP(PLUS, PLUS), (C(Fixnum), C(Float), C(String), C(Array));
OP(MINUS, MINUS), (C(Fixnum));
@@ -937,8 +919,6 @@ vm_init_redefined_flag(rb_vm_t *vm)
/* evaluator body */
-#include "vm_evalbody.c"
-
/* finish
VMe (h1) finish
VM finish F1 F2
@@ -1041,7 +1021,7 @@ vm_init_redefined_flag(rb_vm_t *vm)
static VALUE
-vm_eval_body(rb_thread_t *th)
+vm_exec(rb_thread_t *th)
{
int state;
VALUE result, err;
@@ -1052,7 +1032,7 @@ vm_eval_body(rb_thread_t *th)
_tag.retval = Qnil;
if ((state = EXEC_TAG()) == 0) {
vm_loop_start:
- result = vm_eval(th, initial);
+ result = vm_exec_core(th, initial);
if ((state = th->state) != 0) {
err = result;
th->state = 0;
@@ -1257,7 +1237,7 @@ rb_iseq_eval(VALUE iseqval)
if (!rb_const_defined(rb_cObject, rb_intern("TOPLEVEL_BINDING"))) {
rb_define_global_const("TOPLEVEL_BINDING", rb_binding_new());
}
- val = vm_eval_body(th);
+ val = vm_exec(th);
tmp = iseqval; /* prohibit tail call optimization */
return val;
}
@@ -1808,7 +1788,7 @@ InitVM_VM(rb_vm_t *vm)
rb_define_method_id(klass, id_core_define_singleton_method, m_core_define_singleton_method, 3);
rb_define_method_id(klass, id_core_set_postexe, m_core_set_postexe, 1);
rb_obj_freeze(fcore);
- rb_global_variable(&rb_mRubyVMFrozenCore);
+ rb_gc_register_mark_object(fcore);
rb_mRubyVMFrozenCore = fcore;
/* ::VM::Env */
@@ -1889,7 +1869,7 @@ InitVM_VM(rb_vm_t *vm)
vm->living_threads = st_init_numtable();
st_insert(vm->living_threads, th_self, (st_data_t) th->thread_id);
- rb_register_mark_object(iseqval);
+ rb_gc_register_mark_object(iseqval);
GetISeqPtr(iseqval, iseq);
th->cfp->iseq = iseq;
th->cfp->pc = iseq->iseq_encoded;
@@ -1963,4 +1943,7 @@ InitVM_top_self(rb_vm_t *vm)
{
vm->top_self = rb_obj_alloc(rb_cObject);
rb_define_singleton_method(rb_vm_top_self(), "to_s", main_to_s, 0);
+
+ /* initialize mark object array */
+ vm->mark_object_ary = rb_ary_new();
}
diff --git a/vm_core.h b/vm_core.h
index d5f195e83f..1afaab59c9 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -14,14 +14,13 @@
#define RUBY_VM_THREAD_MODEL 2
-#include <setjmp.h>
-
#include "ruby/ruby.h"
-#include "ruby/mvm.h"
#include "ruby/st.h"
-#include "ruby/node.h"
+
+#include "vm_insnhelper.h"
#include "private_object.h"
+#include "node.h"
#include "debug.h"
#include "vm_opts.h"
#include "id.h"
@@ -34,20 +33,23 @@
#error "unsupported thread type"
#endif
+#include <setjmp.h>
#include <signal.h>
#ifndef NSIG
-# ifdef DJGPP
-# define NSIG SIGMAX
-# elif defined MACOS_UNUSE_SIGNAL
-# define NSIG 1
-# else
-# define NSIG (_SIGMAX + 1) /* For QNX */
-# endif
+# define NSIG (_SIGMAX + 1) /* For QNX */
#endif
#define RUBY_NSIG NSIG
+#ifdef HAVE_STDARG_PROTOTYPES
+#include <stdarg.h>
+#define va_init_list(a,b) va_start(a,b)
+#else
+#include <varargs.h>
+#define va_init_list(a,b) va_start(a)
+#endif
+
/*****************/
/* configuration */
/*****************/
@@ -93,46 +95,6 @@
typedef unsigned long rb_num_t;
-#define ISEQ_TYPE_TOP INT2FIX(1)
-#define ISEQ_TYPE_METHOD INT2FIX(2)
-#define ISEQ_TYPE_BLOCK INT2FIX(3)
-#define ISEQ_TYPE_CLASS INT2FIX(4)
-#define ISEQ_TYPE_RESCUE INT2FIX(5)
-#define ISEQ_TYPE_ENSURE INT2FIX(6)
-#define ISEQ_TYPE_EVAL INT2FIX(7)
-#define ISEQ_TYPE_DEFINED_GUARD INT2FIX(8)
-
-#define CATCH_TYPE_RESCUE INT2FIX(1)
-#define CATCH_TYPE_ENSURE INT2FIX(2)
-#define CATCH_TYPE_RETRY INT2FIX(3)
-#define CATCH_TYPE_BREAK INT2FIX(4)
-#define CATCH_TYPE_REDO INT2FIX(5)
-#define CATCH_TYPE_NEXT INT2FIX(6)
-
-struct iseq_insn_info_entry {
- unsigned short position;
- unsigned short line_no;
- unsigned short sp;
-};
-
-struct iseq_catch_table_entry {
- VALUE type;
- VALUE iseq;
- unsigned long start;
- unsigned long end;
- unsigned long cont;
- unsigned long sp;
-};
-
-#define INITIAL_ISEQ_COMPILE_DATA_STORAGE_BUFF_SIZE (512)
-
-struct iseq_compile_data_storage {
- struct iseq_compile_data_storage *next;
- unsigned long pos;
- unsigned long size;
- char *buff;
-};
-
struct iseq_compile_data_ensure_node_stack;
typedef struct rb_compile_option_struct {
@@ -147,31 +109,6 @@ typedef struct rb_compile_option_struct {
int debug_level;
} rb_compile_option_t;
-struct iseq_compile_data {
- /* GC is needed */
- VALUE err_info;
- VALUE mark_ary;
- VALUE catch_table_ary; /* Array */
-
- /* GC is not needed */
- struct iseq_label_data *start_label;
- struct iseq_label_data *end_label;
- struct iseq_label_data *redo_label;
- VALUE current_block;
- VALUE loopval_popped; /* used by NODE_BREAK */
- VALUE ensure_node;
- VALUE for_iseq;
- struct iseq_compile_data_ensure_node_stack *ensure_node_stack;
- int cached_const;
- struct iseq_compile_data_storage *storage_head;
- struct iseq_compile_data_storage *storage_current;
- int last_line;
- int flip_cnt;
- int label_no;
- int node_level;
- const rb_compile_option_t *option;
-};
-
#if 1
#define GetCoreDataFromValue(obj, type, ptr) do { \
ptr = (type*)DATA_PTR(obj); \
@@ -183,12 +120,6 @@ struct iseq_compile_data {
#define GetISeqPtr(obj, ptr) \
GetCoreDataFromValue(obj, rb_iseq_t, ptr)
-typedef struct rb_iseq_profile_struct {
- VALUE count;
- VALUE time_self;
- VALUE time_cumu; /* cumulative */
-} rb_iseq_profile_t;
-
struct rb_iseq_struct;
struct rb_iseq_struct {
@@ -279,7 +210,6 @@ struct rb_iseq_struct {
/* misc */
ID defined_method_id; /* for define_method */
- rb_iseq_profile_t profile;
/* used at compile time */
struct iseq_compile_data *compile_data;
@@ -299,14 +229,13 @@ enum end_proc_type {
#define ENABLE_VM_OBJSPACE 1
-struct rb_vm_struct
-{
+struct rb_vm_struct {
VALUE self;
rb_thread_lock_t global_vm_lock;
VALUE global_state_version;
- VALUE redefined_flag;
+ char redefined_flag[BOP_LAST_];
st_table *opt_method_table;
struct rb_thread_struct *main_thread;
@@ -376,8 +305,6 @@ typedef struct {
VALUE proc; /* cfp[9] / block[4] */
ID method_id; /* cfp[10] saved in special case */
VALUE method_class; /* cfp[11] saved in special case */
- VALUE prof_time_self; /* cfp[12] */
- VALUE prof_time_chld; /* cfp[13] */
} rb_control_frame_t;
typedef struct rb_block_struct {
@@ -446,7 +373,7 @@ int rb_queue_push(rb_queue_t *, void *);
int rb_queue_shift(rb_queue_t *, void **);
int rb_queue_empty_p(const rb_queue_t *);
-struct rb_thread_struct
+typedef struct rb_thread_struct
{
VALUE self;
rb_vm_t *vm;
@@ -557,25 +484,24 @@ struct rb_thread_struct
/* misc */
int method_missing_reason;
int abort_on_exception;
-};
-
-typedef struct rb_thread_struct rb_thread_t;
+} 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_with_bopt(NODE*, VALUE, VALUE, VALUE, VALUE, VALUE);
VALUE rb_iseq_new_with_opt(NODE*, VALUE, VALUE, VALUE, VALUE, const rb_compile_option_t*);
VALUE rb_iseq_compile(VALUE src, VALUE file, VALUE line);
VALUE ruby_iseq_disasm(VALUE self);
VALUE ruby_iseq_disasm_insn(VALUE str, VALUE *iseqval, int pos, rb_iseq_t *iseq, VALUE child);
const char *ruby_node_name(int node);
-VALUE rb_iseq_clone(VALUE iseqval, VALUE newcbase);
+int rb_iseq_first_lineno(rb_iseq_t *iseq);
/* each thread has this size stack : 128KB */
#define RUBY_VM_THREAD_STACK_SIZE (128 * 1024)
-struct global_entry {
- struct global_variable *var;
+struct rb_global_entry {
+ struct rb_global_variable *var;
ID id;
};
@@ -671,8 +597,6 @@ typedef rb_control_frame_t *
#define GC_GUARDED_PTR_REF(p) ((void *)(((VALUE)p) & ~0x03))
#define GC_GUARDED_PTR_P(p) (((VALUE)p) & 0x01)
-#define RUBY_VM_METHOD_NODE NODE_METHOD
-
#define RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp) (cfp+1)
#define RUBY_VM_NEXT_CONTROL_FRAME(cfp) (cfp-1)
#define RUBY_VM_END_CONTROL_FRAME(th) \
@@ -692,20 +616,7 @@ typedef rb_control_frame_t *
#define RUBY_VM_GET_CFP_FROM_BLOCK_PTR(b) \
((rb_control_frame_t *)((VALUE *)(b) - 5))
-/* defined? */
-#define DEFINED_IVAR INT2FIX(1)
-#define DEFINED_IVAR2 INT2FIX(2)
-#define DEFINED_GVAR INT2FIX(3)
-#define DEFINED_CVAR INT2FIX(4)
-#define DEFINED_CONST INT2FIX(5)
-#define DEFINED_METHOD INT2FIX(6)
-#define DEFINED_YIELD INT2FIX(7)
-#define DEFINED_REF INT2FIX(8)
-#define DEFINED_ZSUPER INT2FIX(9)
-#define DEFINED_FUNC INT2FIX(10)
-
/* VM related object allocate functions */
-/* TODO: should be static functions */
VALUE rb_thread_alloc(VALUE klass);
VALUE rb_proc_alloc(VALUE klass);
@@ -768,8 +679,7 @@ int ruby_thread_set_native(rb_thread_t *th);
void rb_thread_execute_interrupts(rb_thread_t *);
#define RUBY_VM_CHECK_INTS_TH(th) do { \
- if (th->interrupt_flag) { \
- /* TODO: trap something event */ \
+ if (UNLIKELY(th->interrupt_flag)) { \
rb_thread_execute_interrupts(th); \
} \
} while (0)
diff --git a/vm_dump.c b/vm_dump.c
index 9d31037fc2..5813f6ba32 100644
--- a/vm_dump.c
+++ b/vm_dump.c
@@ -10,13 +10,13 @@
#include "ruby/ruby.h"
-#include "ruby/node.h"
-
#include "vm_core.h"
-#include "vm.h"
#define MAX_POSBUF 128
+#define VM_CFP_CNT(th, cfp) \
+ ((rb_control_frame_t *)(th->stack + th->stack_size) - (rb_control_frame_t *)(cfp))
+
static void
control_frame_dump(rb_thread_t *th, rb_control_frame_t *cfp)
{
@@ -25,6 +25,7 @@ control_frame_dump(rb_thread_t *th, rb_control_frame_t *cfp)
ptrdiff_t dfp = cfp->dfp - th->stack;
char lfp_in_heap = ' ', dfp_in_heap = ' ';
char posbuf[MAX_POSBUF+1];
+ int nopos = 0;
const char *magic, *iseq_name = "-", *selfstr = "-", *biseq_name = "-";
VALUE tmp;
@@ -60,6 +61,7 @@ control_frame_dump(rb_thread_t *th, rb_control_frame_t *cfp)
break;
case VM_FRAME_MAGIC_FINISH:
magic = "FINISH";
+ nopos = 1;
break;
case VM_FRAME_MAGIC_CFUNC:
magic = "CFUNC";
@@ -92,7 +94,10 @@ control_frame_dump(rb_thread_t *th, rb_control_frame_t *cfp)
selfstr = "";
}
- if (cfp->iseq != 0) {
+ if (nopos) {
+ /* no name */
+ }
+ else if (cfp->iseq != 0) {
if (RUBY_VM_IFUNC_P(cfp->iseq)) {
iseq_name = "<ifunc>";
}
@@ -103,9 +108,7 @@ control_frame_dump(rb_thread_t *th, rb_control_frame_t *cfp)
iseq_name = RSTRING_PTR(cfp->iseq->name);
line = vm_get_sourceline(cfp);
if (line) {
- char fn[MAX_POSBUF+1];
- snprintf(fn, MAX_POSBUF, "%s", RSTRING_PTR(cfp->iseq->filename));
- snprintf(posbuf, MAX_POSBUF, "%s:%d", fn, line);
+ snprintf(posbuf, MAX_POSBUF, "%s:%d", RSTRING_PTR(cfp->iseq->filename), line);
}
}
}
@@ -126,12 +129,12 @@ control_frame_dump(rb_thread_t *th, rb_control_frame_t *cfp)
fprintf(stderr, "s:%04"PRIdPTRDIFF" b:%04d ", (cfp->sp - th->stack), bp);
fprintf(stderr, lfp_in_heap == ' ' ? "l:%06"PRIdPTRDIFF" " : "l:%06"PRIxPTRDIFF" ", lfp % 10000);
fprintf(stderr, dfp_in_heap == ' ' ? "d:%06"PRIdPTRDIFF" " : "d:%06"PRIxPTRDIFF" ", dfp % 10000);
- fprintf(stderr, "%-6s ", magic);
- if (line) {
- fprintf(stderr, "%s", posbuf);
+ fprintf(stderr, "%-6s", magic);
+ if (line && !nopos) {
+ fprintf(stderr, " %s", posbuf);
}
if (0) {
- fprintf(stderr, " \t");
+ fprintf(stderr, " \t");
fprintf(stderr, "iseq: %-24s ", iseq_name);
fprintf(stderr, "self: %-24s ", selfstr);
fprintf(stderr, "%-1s ", biseq_name);
diff --git a/vm_eval.c b/vm_eval.c
index c309145b7f..edf2b7b739 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -11,19 +11,13 @@
**********************************************************************/
-#include "ruby/ruby.h"
-#include "ruby/node.h"
-#include "ruby/st.h"
-
-#include "vm_method.c"
-
static inline VALUE method_missing(VALUE obj, ID id, int argc, const VALUE *argv, int call_status);
static inline VALUE rb_vm_set_finish_env(rb_thread_t * th);
static inline VALUE vm_yield_with_cref(rb_thread_t *th, int argc, const VALUE *argv, const NODE *cref);
static inline VALUE vm_yield(rb_thread_t *th, int argc, const VALUE *argv);
static inline VALUE vm_backtrace(rb_thread_t *th, int lev);
static NODE *vm_cref_push(rb_thread_t *th, VALUE klass, int noex);
-static VALUE vm_eval_body(rb_thread_t *th);
+static VALUE vm_exec(rb_thread_t *th);
static void vm_set_eval_stack(rb_thread_t * th, VALUE iseqval, const NODE *cref);
static inline VALUE
@@ -58,7 +52,7 @@ vm_call0(rb_thread_t * th, VALUE klass, VALUE recv, VALUE id, ID oid,
}
vm_setup_method(th, reg_cfp, argc, blockptr, 0, iseqval, recv, klass);
- val = vm_eval_body(th);
+ val = vm_exec(th);
break;
}
case NODE_CFUNC: {
@@ -742,7 +736,7 @@ eval_string_with_cref(VALUE self, VALUE src, VALUE scope, NODE *cref, const char
/* kick */
CHECK_STACK_OVERFLOW(th->cfp, iseq->stack_max);
- result = vm_eval_body(th);
+ result = vm_exec(th);
}
POP_TAG();
th->mild_compile_error = mild_compile_error;
@@ -1327,6 +1321,7 @@ rb_make_backtrace(void)
void
Init_vm_eval(void)
{
+ rb_define_global_function("eval", rb_f_eval, -1);
rb_define_global_function("catch", rb_f_catch, -1);
rb_define_global_function("throw", rb_f_throw, -1);
@@ -1342,6 +1337,8 @@ Init_vm_eval(void)
rb_define_method(rb_cModule, "module_exec", rb_mod_module_exec, -1);
rb_define_method(rb_cModule, "class_exec", rb_mod_module_exec, -1);
+ rb_define_method(rb_cModule, "module_eval", rb_mod_module_eval, -1);
+ rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval, -1);
rb_define_global_function("caller", rb_f_caller, -1);
}
diff --git a/vm_evalbody.c b/vm_exec.c
index 65f2964180..e82ff08fcf 100644
--- a/vm_evalbody.c
+++ b/vm_exec.c
@@ -1,7 +1,7 @@
/* -*-c-*- */
/**********************************************************************
- vm_evalbody.c -
+ vm_exec.c -
$Author$
@@ -25,9 +25,17 @@
#endif
/* #define DECL_SC_REG(r, reg) VALUE reg_##r */
+#if OPT_STACK_CACHING
+static VALUE finish_insn_seq[1] = { BIN(finish_SC_ax_ax) };
+#elif OPT_CALL_THREADED_CODE
+static VALUE const finish_insn_seq[1] = { 0 };
+#else
+static VALUE finish_insn_seq[1] = { BIN(finish) };
+#endif
+
#if !OPT_CALL_THREADED_CODE
static VALUE
-vm_eval(rb_thread_t *th, VALUE initial)
+vm_exec_core(rb_thread_t *th, VALUE initial)
{
#if OPT_STACK_CACHING
@@ -75,7 +83,7 @@ vm_eval(rb_thread_t *th, VALUE initial)
#if OPT_TOKEN_THREADED_CODE || OPT_DIRECT_THREADED_CODE
#include "vmtc.inc"
- if (th == 0) {
+ if (UNLIKELY(th == 0)) {
#if OPT_STACK_CACHING
finish_insn_seq[0] = (VALUE)&&LABEL (finish_SC_ax_ax);
#else
@@ -104,19 +112,25 @@ vm_eval(rb_thread_t *th, VALUE initial)
goto first;
}
+const void **
+vm_get_insns_address_table(void)
+{
+ return (const void **)vm_exec_core(0, 0);
+}
+
#else
#include "vm.inc"
#include "vmtc.inc"
const void *const *
-get_insns_address_table()
+vm_get_insns_address_table(void)
{
return insns_address_table;
}
-VALUE
-vm_eval(rb_thread_t *th, VALUE initial)
+static VALUE
+vm_exec_core(rb_thread_t *th, VALUE initial)
{
register rb_control_frame_t *reg_cfp = th->cfp;
VALUE ret;
@@ -140,9 +154,3 @@ vm_eval(rb_thread_t *th, VALUE initial)
return ret;
}
#endif
-
-const void **
-vm_get_insns_address_table(void)
-{
- return (const void **)vm_eval(0, 0);
-}
diff --git a/vm.h b/vm_exec.h
index 6e82a29fc5..d669800f8e 100644
--- a/vm.h
+++ b/vm_exec.h
@@ -9,8 +9,8 @@
**********************************************************************/
-#ifndef RUBY_VM_H
-#define RUBY_VM_H
+#ifndef RUBY_VM_EXEC_H
+#define RUBY_VM_EXEC_H
typedef long OFFSET;
typedef unsigned long lindex_t;
@@ -18,33 +18,6 @@ typedef unsigned long dindex_t;
typedef rb_num_t GENTRY;
typedef rb_iseq_t *ISEQ;
-#define ruby_vm_global_state_version (GET_VM()->global_state_version)
-#define ruby_vm_redefined_flag (GET_VM()->redefined_flag)
-
-
-/**
- * VM Debug Level
- *
- * debug level:
- * 0: no debug output
- * 1: show instruction name
- * 2: show stack frame when control stack frame is changed
- * 3: show stack status
- * 4: show register
- * 5:
- * 10: gc check
- */
-
-
-#ifndef VMDEBUG
-#define VMDEBUG 0
-#endif
-
-#if 0
-#undef VMDEBUG
-#define VMDEBUG 3
-#endif
-
#ifdef COLLECT_USAGE_ANALYSIS
#define USAGE_ANALYSIS_INSN(insn) vm_analysis_insn(insn)
#define USAGE_ANALYSIS_OPERAND(insn, n, op) vm_analysis_operand(insn, n, (VALUE)op)
@@ -198,26 +171,8 @@ default: \
#endif
-
-/************************************************/
-/************************************************/
-
-#define VM_CFP_CNT(th, cfp) \
- ((rb_control_frame_t *)(th->stack + th->stack_size) - (rb_control_frame_t *)(cfp))
#define VM_SP_CNT(th, sp) ((sp) - (th)->stack)
-/*
- env{
- env[0] // special (block or prev env)
- env[1] // env object
- env[2] // prev env val
- };
- */
-
-#define ENV_IN_HEAP_P(th, env) \
- (!((th)->stack < (env) && (env) < ((th)->stack + (th)->stack_size)))
-#define ENV_VAL(env) ((env)[1])
-
#if OPT_CALL_THREADED_CODE
#define THROW_EXCEPTION(exc) do { \
th->errinfo = (VALUE)(exc); \
@@ -229,28 +184,4 @@ default: \
#define SCREG(r) (reg_##r)
-/* VM state version */
-
-#define GET_VM_STATE_VERSION() (ruby_vm_global_state_version)
-#define INC_VM_STATE_VERSION() \
- (ruby_vm_global_state_version = (ruby_vm_global_state_version+1) & 0x8fffffff)
-
-#define BOP_PLUS 0x01
-#define BOP_MINUS 0x02
-#define BOP_MULT 0x04
-#define BOP_DIV 0x08
-#define BOP_MOD 0x10
-#define BOP_EQ 0x20
-#define BOP_LT 0x40
-#define BOP_LE 0x80
-#define BOP_LTLT 0x100
-#define BOP_AREF 0x200
-#define BOP_ASET 0x400
-#define BOP_LENGTH 0x800
-#define BOP_SUCC 0x1000
-#define BOP_GT 0x2000
-#define BOP_GE 0x4000
-#define BOP_NOT 0x8000
-#define BOP_NEQ 0x10000
-
-#endif /* RUBY_VM_H */
+#endif /* RUBY_VM_EXEC_H */
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index c9397f8ecf..39b379429f 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -1,6 +1,6 @@
/**********************************************************************
- insnhelper.c - instruction helper functions.
+ vm_insnhelper.c - instruction helper functions.
$Author$
@@ -10,12 +10,10 @@
/* finish iseq array */
#include "insns.inc"
-
#include <math.h>
/* control stack frame */
-
#ifndef INLINE
#define INLINE inline
#endif
@@ -680,124 +678,174 @@ vm_yield_with_cfunc(rb_thread_t *th, const rb_block_t *block,
return val;
}
+
+/*--
+ * @brief on supplied all of optional, rest and post parameters.
+ * @pre iseq is block style (not lambda style)
+ */
static inline int
-vm_yield_setup_args(rb_thread_t * const th, const rb_iseq_t *iseq,
- int orig_argc, VALUE *argv,
- const rb_block_t *blockptr, int lambda)
+vm_yield_setup_block_args_complex(rb_thread_t *th, const rb_iseq_t * iseq,
+ int argc, VALUE * argv)
{
- if (0) { /* for debug */
- printf(" argc: %d\n", orig_argc);
- printf("iseq argc: %d\n", iseq->argc);
- printf("iseq opts: %d\n", iseq->arg_opts);
- printf("iseq rest: %d\n", iseq->arg_rest);
- printf("iseq post: %d\n", iseq->arg_post_len);
- printf("iseq blck: %d\n", iseq->arg_block);
- printf("iseq smpl: %d\n", iseq->arg_simple);
- printf(" lambda: %s\n", lambda ? "true" : "false");
+ int opt_pc = 0;
+ int i;
+ const int m = iseq->argc;
+ const int r = iseq->arg_rest;
+ int len = iseq->arg_post_len;
+ int start = iseq->arg_post_start;
+ int rsize = argc > m ? argc - m : 0; /* # of arguments which did not consumed yet */
+ int psize = rsize > len ? len : rsize; /* # of post arguments */
+ int osize = 0; /* # of opt arguments */
+ VALUE ary;
+
+ /* reserves arguments for post parameters */
+ rsize -= psize;
+
+ if (iseq->arg_opts) {
+ const int opts = iseq->arg_opts - 1;
+ if (rsize > opts) {
+ osize = opts;
+ opt_pc = iseq->arg_opt_table[opts];
+ }
+ else {
+ osize = rsize;
+ opt_pc = iseq->arg_opt_table[rsize];
+ }
}
+ rsize -= osize;
- if (lambda) {
- /* call as method */
- int opt_pc;
- VM_CALLEE_SETUP_ARG(opt_pc, th, iseq, orig_argc, argv, &blockptr);
- return opt_pc;
+ if (0) {
+ printf(" argc: %d\n", argc);
+ printf(" len: %d\n", len);
+ printf("start: %d\n", start);
+ printf("rsize: %d\n", rsize);
+ }
+
+ if (r == -1) {
+ /* copy post argument */
+ MEMMOVE(&argv[start], &argv[m+osize], VALUE, psize);
}
else {
- int i;
- int argc = orig_argc;
- const int m = iseq->argc;
- VALUE ary;
+ ary = rb_ary_new4(rsize, &argv[r]);
- th->mark_stack_len = argc;
+ /* copy post argument */
+ MEMMOVE(&argv[start], &argv[m+rsize+osize], VALUE, psize);
+ argv[r] = ary;
+ }
- /*
- * yield [1, 2]
- * => {|a|} => a = [1, 2]
- * => {|a, b|} => a, b = [1, 2]
- */
- if (!(iseq->arg_simple & 0x02) &&
- (m + iseq->arg_post_len) > 0 &&
- argc == 1 && !NIL_P(ary = rb_check_array_type(argv[0]))) {
- th->mark_stack_len = argc = RARRAY_LEN(ary);
+ for (i=psize; i<len; i++) {
+ argv[start + i] = Qnil;
+ }
- CHECK_STACK_OVERFLOW(th->cfp, argc);
+ return opt_pc;
+}
- MEMCPY(argv, RARRAY_PTR(ary), VALUE, argc);
- }
+static inline int
+vm_yield_setup_block_args(rb_thread_t *th, const rb_iseq_t * iseq,
+ int orig_argc, VALUE * argv,
+ const rb_block_t *blockptr)
+{
+ int i;
+ int argc = orig_argc;
+ const int m = iseq->argc;
+ VALUE ary;
+ int opt_pc = 0;
- for (i=argc; i<m; i++) {
- argv[i] = Qnil;
- }
+ th->mark_stack_len = argc;
- if (iseq->arg_rest == -1) {
- if (m < argc) {
- /*
- * yield 1, 2
- * => {|a|} # truncate
- */
- th->mark_stack_len = argc = m;
- }
- }
- else {
- int r = iseq->arg_rest;
+ /*
+ * yield [1, 2]
+ * => {|a|} => a = [1, 2]
+ * => {|a, b|} => a, b = [1, 2]
+ */
+ if (!(iseq->arg_simple & 0x02) && /* exclude {|a|} */
+ (m + iseq->arg_post_len) > 0 && /* this process is meaningful */
+ argc == 1 && !NIL_P(ary = rb_check_array_type(argv[0]))) { /* rhs is only an array */
+ th->mark_stack_len = argc = RARRAY_LEN(ary);
- if (iseq->arg_post_len) {
- int len = iseq->arg_post_len;
- int start = iseq->arg_post_start;
- int rsize = argc > m ? argc - m : 0;
- int psize = rsize;
- VALUE ary;
+ CHECK_STACK_OVERFLOW(th->cfp, argc);
- if (psize > len) psize = len;
+ MEMCPY(argv, RARRAY_PTR(ary), VALUE, argc);
+ }
- ary = rb_ary_new4(rsize - psize, &argv[r]);
+ for (i=argc; i<m; i++) {
+ argv[i] = Qnil;
+ }
- if (0) {
- printf(" argc: %d\n", argc);
- printf(" len: %d\n", len);
- printf("start: %d\n", start);
- printf("rsize: %d\n", rsize);
- }
+ if (iseq->arg_rest == -1 && iseq->arg_opts == 0) {
+ const int arg_size = iseq->arg_size;
+ if (arg_size < argc) {
+ /*
+ * yield 1, 2
+ * => {|a|} # truncate
+ */
+ th->mark_stack_len = argc = arg_size;
+ }
+ }
+ else {
+ int r = iseq->arg_rest;
- /* copy post argument */
- MEMMOVE(&argv[start], &argv[r + rsize - psize], VALUE, psize);
+ if (iseq->arg_post_len ||
+ iseq->arg_opts) { /* TODO: implement simple version for (iseq->arg_post_len==0 && iseq->arg_opts > 0) */
+ opt_pc = vm_yield_setup_block_args_complex(th, iseq, argc, argv);
+ }
+ else {
+ if (argc < r) {
+ /* yield 1
+ * => {|a, b, *r|}
+ */
+ for (i=argc; i<r; i++) {
+ argv[i] = Qnil;
+ }
+ argv[r] = rb_ary_new();
+ }
+ else {
+ argv[r] = rb_ary_new4(argc-r, &argv[r]);
+ }
+ }
- for (i=psize; i<len; i++) {
- argv[start + i] = Qnil;
- }
- argv[r] = ary;
- }
- else {
- if (argc < r) {
- /* yield 1
- * => {|a, b, *r|}
- */
- for (i=argc; i<r; i++) {
- argv[i] = Qnil;
- }
- argv[r] = rb_ary_new();
- }
- else {
- argv[r] = rb_ary_new4(argc-r, &argv[r]);
- }
- }
+ th->mark_stack_len = iseq->arg_size;
+ }
- th->mark_stack_len = iseq->arg_size;
- }
+ /* {|&b|} */
+ if (iseq->arg_block != -1) {
+ VALUE procval = Qnil;
- /* {|&b|} */
- if (iseq->arg_block != -1) {
- VALUE procval = Qnil;
+ if (blockptr) {
+ procval = blockptr->proc;
+ }
- if (blockptr) {
- procval = blockptr->proc;
- }
+ argv[iseq->arg_block] = procval;
+ }
- argv[iseq->arg_block] = procval;
- }
+ th->mark_stack_len = 0;
+ return opt_pc;
+}
- th->mark_stack_len = 0;
- return 0;
+static inline int
+vm_yield_setup_args(rb_thread_t * const th, const rb_iseq_t *iseq,
+ int argc, VALUE *argv,
+ const rb_block_t *blockptr, int lambda)
+{
+ if (0) { /* for debug */
+ printf(" argc: %d\n", argc);
+ printf("iseq argc: %d\n", iseq->argc);
+ printf("iseq opts: %d\n", iseq->arg_opts);
+ printf("iseq rest: %d\n", iseq->arg_rest);
+ printf("iseq post: %d\n", iseq->arg_post_len);
+ printf("iseq blck: %d\n", iseq->arg_block);
+ printf("iseq smpl: %d\n", iseq->arg_simple);
+ printf(" lambda: %s\n", lambda ? "true" : "false");
+ }
+
+ if (lambda) {
+ /* call as method */
+ int opt_pc;
+ VM_CALLEE_SETUP_ARG(opt_pc, th, iseq, argc, argv, &blockptr);
+ return opt_pc;
+ }
+ else {
+ return vm_yield_setup_block_args(th, iseq, argc, argv, blockptr);
}
}
@@ -967,6 +1015,36 @@ vm_get_cref(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp)
return cref;
}
+static NODE *
+vm_cref_push(rb_thread_t *th, VALUE klass, int noex)
+{
+ rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(th, th->cfp);
+ NODE *cref = NEW_BLOCK(klass);
+ cref->nd_file = 0;
+ cref->nd_visi = noex;
+
+ if (cfp) {
+ cref->nd_next = vm_get_cref(cfp->iseq, cfp->lfp, cfp->dfp);
+ }
+
+ return cref;
+}
+
+static inline VALUE
+vm_get_cbase(const rb_iseq_t *iseq, const VALUE *lfp, const VALUE *dfp)
+{
+ NODE *cref = vm_get_cref(iseq, lfp, dfp);
+ VALUE klass = Qundef;
+
+ while (cref) {
+ if ((klass = cref->nd_clss) != 0) {
+ break;
+ }
+ cref = cref->nd_next;
+ }
+
+ return klass;
+}
static inline void
vm_check_if_namespace(VALUE klass)
diff --git a/insnhelper.h b/vm_insnhelper.h
index a862f2672e..7a1d056b53 100644
--- a/insnhelper.h
+++ b/vm_insnhelper.h
@@ -12,11 +12,57 @@
#ifndef RUBY_INSNHELPER_H
#define RUBY_INSNHELPER_H
-#include "ruby/ruby.h"
-#include "ruby/node.h"
-#include "eval_intern.h"
-#include "vm_core.h"
-#include "vm.h"
+/**
+ * VM Debug Level
+ *
+ * debug level:
+ * 0: no debug output
+ * 1: show instruction name
+ * 2: show stack frame when control stack frame is changed
+ * 3: show stack status
+ * 4: show register
+ * 5:
+ * 10: gc check
+ */
+
+#ifndef VMDEBUG
+#define VMDEBUG 0
+#endif
+
+#if 0
+#undef VMDEBUG
+#define VMDEBUG 3
+#endif
+
+enum {
+ BOP_PLUS,
+ BOP_MINUS,
+ BOP_MULT,
+ BOP_DIV,
+ BOP_MOD,
+ BOP_EQ,
+ BOP_LT,
+ BOP_LE,
+ BOP_LTLT,
+ BOP_AREF,
+ BOP_ASET,
+ BOP_LENGTH,
+ BOP_SUCC,
+ BOP_GT,
+ BOP_GE,
+ BOP_NOT,
+ BOP_NEQ,
+
+ BOP_LAST_,
+};
+
+#define ruby_vm_redefined_flag GET_VM()->redefined_flag
+#define ruby_vm_global_state_version GET_VM()->global_state_version
+
+#define GET_VM_STATE_VERSION() (ruby_vm_global_state_version)
+#define INC_VM_STATE_VERSION() \
+ (ruby_vm_global_state_version = (ruby_vm_global_state_version+1) & 0x8fffffff)
+
/**********************************************************/
/* deal with stack */
@@ -90,8 +136,8 @@
#define GET_PREV_DFP(dfp) ((VALUE *)((dfp)[0] & ~0x03))
-#define GET_GLOBAL(entry) rb_gvar_get((struct global_entry*)entry)
-#define SET_GLOBAL(entry, val) rb_gvar_set((struct global_entry*)entry, val)
+#define GET_GLOBAL(entry) rb_gvar_get((struct rb_global_entry*)entry)
+#define SET_GLOBAL(entry, val) rb_gvar_set((struct rb_global_entry*)entry, val)
#define GET_CONST_INLINE_CACHE(dst) ((IC) * (GET_PC() + (dst) + 1))
@@ -137,7 +183,7 @@
/* optimize insn */
#define FIXNUM_2_P(a, b) ((a) & (b) & 1)
-#define BASIC_OP_UNREDEFINED_P(op) ((ruby_vm_redefined_flag & (op)) == 0)
+#define BASIC_OP_UNREDEFINED_P(op) (LIKELY(ruby_vm_redefined_flag[op] == 0))
#define HEAP_CLASS_OF(obj) RBASIC(obj)->klass
#define CALL_SIMPLE_METHOD(num, id, recv) do { \
diff --git a/vm_method.c b/vm_method.c
index 004b038795..fcf6a3353e 100644
--- a/vm_method.c
+++ b/vm_method.c
@@ -1,6 +1,5 @@
-/* -*-c-*- */
/*
- * This file is included by vm_eval.c
+ * This file is included by vm.h
*/
#define CACHE_SIZE 0x800
@@ -1035,7 +1034,7 @@ rb_mod_modfunc(int argc, VALUE *argv, VALUE module)
fbody = search_method(rb_cObject, id, &m);
}
if (fbody == 0 || fbody->nd_body == 0) {
- rb_bug("undefined method `%s'; can't happen", rb_id2name(id));
+ rb_print_undef(module, id, 0);
}
if (nd_type(fbody->nd_body->nd_body) != NODE_ZSUPER) {
break; /* normal case: need not to follow 'super' link */
diff --git a/vms/config.h b/vms/config.h
deleted file mode 100644
index 55b0c36803..0000000000
--- a/vms/config.h
+++ /dev/null
@@ -1,123 +0,0 @@
-#define HAVE_ACOSH 1
-/* #define HAVE_ALLOCA_H 1 */
-/* #define HAVE_CHROOT 1 */
-#define HAVE_COSH 1
-/* #define HAVE_CRYPT 1 */
-#define HAVE_DAYLIGHT 1
-#define HAVE_DECL_SYS_NERR 1
-#define HAVE_DIRENT_H 1
-#define HAVE_DLOPEN 1
-#define HAVE_DUP2 1
-/* #define HAVE_FCHMOD 1 */
-#define HAVE_FCNTL 1
-#define HAVE_FCNTL_H 1
-#define HAVE_FINITE 1
-#define HAVE_FLOCK 1
-#define HAVE_FMOD 1
-#define HAVE_FREXP 1
-/* #define HAVE_FSEEKO 1 */
-#define HAVE_FSYNC 1
-/* #define HAVE_FTELLO 1 */
-#define HAVE_GETCWD 1
-/* #define HAVE_GETPGID 1 xxxx */
-#define HAVE_GETPGRP 1
-/* #define HAVE_GETPRIORITY 1 */
-/* #define HAVE_GETRLIMIT 1 */
-#define HAVE_PID_T 1
-#define HAVE_GID_T 1
-#define HAVE_UID_T 1
-#define HAVE_HYPOT 1
-#define HAVE_ISASCII 1
-/* #define HAVE_ISINF 1 */
-#define HAVE_ISNAN 1
-/* #define HAVE_LCHMOD 1 */
-/* #define HAVE_LCHOWN 1 */
-#define HAVE_LONG_LONG 1
-/* #define HAVE_LSTAT 1 */
-#define HAVE_MEMCMP 1
-#define HAVE_MEMMOVE 1
-#define HAVE_MKDIR 1
-#define HAVE_MKTIME 1
-#define HAVE_MODF 1
-#define HAVE_OFF_T 1
-#define HAVE_PAUSE 1
-/* #define HAVE_PROTOTYPES 1 */
-/* #define HAVE_PWD_H 1 */
-/* #define HAVE_READLINK 1 */
-#define HAVE_SEEKDIR 1
-/* #define HAVE_SETITIMER 1 */
-/* #define HAVE_SETPGID 1 xxxx */
-/* #define HAVE_SETRESGID 1 */
-/* #define HAVE_SETRESUID 1 */
-/* #define HAVE_SETSID 1 xxxx */
-#define HAVE_SIGPROCMASK 1
-#define HAVE_SINH 1
-#define HAVE_STDARG_PROTOTYPES 1
-#define HAVE_STDLIB_H 1
-#define HAVE_STRCASECMP 1
-#define HAVE_STRCHR 1
-#define HAVE_STRERROR 1
-#define HAVE_STRFTIME 1
-#define HAVE_STRING_H 1
-#define HAVE_STRNCASECMP 1
-#define HAVE_STRSTR 1
-#define HAVE_STRTOD 1
-#define HAVE_STRTOL 1
-#define HAVE_STRTOUL 1
-#define HAVE_STRUCT_TM_TM_GMTOFF 1
-/* #define HAVE_ST_BLKSIZE 1 */
-/* #define HAVE_ST_BLOCKS 1 */
-#define HAVE_ST_RDEV 1
-/* #define HAVE_SYMLINK 1 */
-/* #define HAVE_SYSCALL 1 */
-#define HAVE_SYS_FILE_H 1
-/* #define HAVE_SYS_MKDEV_H 1 */
-/* #define HAVE_SYS_PARAM_H 1 */
-#define HAVE_SYS_RESOURCE_H 1
-/* #define HAVE_SYS_SELECT_H 1 */
-#define HAVE_SYS_TIMES_H 1
-#define HAVE_SYS_TIME_H 1
-#define HAVE_SYS_WAIT_H 1
-#define HAVE_TANH 1
-#define HAVE_TELLDIR 1
-/* #define HAVE_TIMEGM 1 */
-#define HAVE_TIMES 1
-#define HAVE_TM_ZONE 1
-#define HAVE_TRUNCATE 1
-#define HAVE_TZNAME 1
-#define HAVE_UNISTD_H 1
-#define HAVE_UTIMES 1
-#define HAVE_UTIME_H 1
-/* #define HAVE_VSNPRINTF 1 */
-#define HAVE_WAIT4 1
-#define HAVE_WAITPID 1
- #define HAVE__SETJMP 1
-
-#define GETGROUPS_T gid_t
-#define RETSIGTYPE void
-
-#define RSHIFT(x,y) ((x)>>y)
-#define DEFAULT_KCODE KCODE_EUC
-#define DLEXT ".EXE"
-#define DLEXT2 ""
-#define RUBY_LIB "/RUBY_LIB"
-#define RUBY_SITE_LIB "/RUBY_SYSLIB"
-#define RUBY_SITE_LIB2 "/SYS$SHARE"
-#define RUBY_ARCHLIB ""
-#define RUBY_SITE_ARCHLIB ""
-#define SIZEOF_INT 4
-#define SIZEOF_SHORT 2
-#define SIZEOF_LONG 4
-#define SIZEOF_VOIDP 4
-#define SIZEOF_FLOAT 4
-#define SIZEOF_DOUBLE 8
-
-#if defined(__vax)
-#define RUBY_PLATFORM "vax-vms"
-#elif defined(__alpha)
-#define RUBY_PLATFORM "alpha-vms"
-#elif defined(__ia-64)
-#define RUBY_PLATFORM "ia64-vms"
-#else
-#define RUBY_PLATFORM "vms"
-#endif
diff --git a/vms/vms.h b/vms/vms.h
deleted file mode 100644
index 8eaa88cde3..0000000000
--- a/vms/vms.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __FAST_SETJMP
-#define __FAST_SETJMP /* use decc$setjmp/decc$longjmp */
-#endif
-
-extern int isinf(double);
-extern int isnan(double);
-extern int flock(int fd, int oper);
-
-extern int vsnprintf();
-extern int snprintf();
-
-#define LONG_LONG long long
-#define SIZEOF_LONG_LONG sizeof(long long)
diff --git a/vms/vmsruby_private.c b/vms/vmsruby_private.c
deleted file mode 100644
index c1cbfcebec..0000000000
--- a/vms/vmsruby_private.c
+++ /dev/null
@@ -1,52 +0,0 @@
-#include "vmsruby_private.h"
-#include <stdio.h>
-#include <stdlib.h>
-
-void _vmsruby_init(void)
-{
- _vmsruby_set_switch("DECC$WLS", "TRUE");
-}
-
-
-#include <starlet.h>
-#include <string.h>
-#include <descrip.h>
-#include <lnmdef.h>
-
-struct item_list_3 {
- short buflen;
- short itmcod;
- void *bufadr;
- void *retlen;
-};
-
-long _vmsruby_set_switch(char *name, char *value)
-{
- long status;
- struct item_list_3 itemlist[20];
- int i;
-
- i = 0;
- itemlist[i].itmcod = LNM$_STRING;
- itemlist[i].buflen = strlen(value);
- itemlist[i].bufadr = value;
- itemlist[i].retlen = NULL;
- i++;
- itemlist[i].itmcod = 0;
- itemlist[i].buflen = 0;
-
- $DESCRIPTOR(TABLE_d, "LNM$PROCESS");
- $DESCRIPTOR(lognam_d, "");
-
- lognam_d.dsc$a_pointer = name;
- lognam_d.dsc$w_length = strlen(name);
-
- status = sys$crelnm (
- 0,
- &TABLE_d,
- &lognam_d,
- 0, /* usermode */
- itemlist);
-
- return status;
-}
diff --git a/vms/vmsruby_private.h b/vms/vmsruby_private.h
deleted file mode 100644
index 24703dc7fc..0000000000
--- a/vms/vmsruby_private.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef VMSRUBY_H_INCLUDED
-#define VMSRUBY_H_INCLUDED
-
-void _vmsruby_init(void);
-long _vmsruby_set_switch(char *, char *);
-
-#endif /* VMSRUBY_H_INCLUDED */
diff --git a/win32/Makefile.sub b/win32/Makefile.sub
index 1e394eeceb..de10bfa3e7 100644
--- a/win32/Makefile.sub
+++ b/win32/Makefile.sub
@@ -31,7 +31,7 @@ LIB = $(pathlist:;=/lib;)
srcdir = ..
!endif
!ifndef RUBY_INSTALL_NAME
-RUBY_INSTALL_NAME = ruby$(RUBY_SUFFIX)
+RUBY_INSTALL_NAME = $(PROGRAM_PREFIX)ruby$(RUBY_SUFFIX)
!endif
!if !defined(RUBYW_INSTALL_NAME) || "$(RUBYW_INSTALL_NAME)" == "$(RUBY_INSTALL_NAME)"
RUBYW_INSTALL_NAME = $(RUBY_INSTALL_NAME:ruby=rubyw)
@@ -214,10 +214,10 @@ MINIRUBY = $(RUBY) -I$(MAKEDIR) -rfake
RUNRUBY = $(MINIRUBY)
!else
MINIRUBY = .\miniruby$(EXEEXT) -I$(srcdir)/lib
-RUNRUBY = .\$(PROGRAM) -I"$(EXTOUT)/$(arch)"
+RUNRUBY = .\$(PROGRAM) -I$(srcdir)/lib -I"$(EXTOUT)/$(arch)"
!endif
MINIRUBY = $(MINIRUBY) $(MINIRUBYOPT)
-RUNRUBY = $(RUNRUBY) "$(srcdir)/runruby.rb" --extout="$(EXTOUT)" --
+RUNRUBY = $(RUNRUBY) "$(srcdir)/runruby.rb" --extout="$(EXTOUT)" $(RUNRUBYOPT) --
!ifndef RUBY
RUBY = ruby
!endif
@@ -373,9 +373,7 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/win32/Makefile.sub $(win_srcdir)/Makefile.sub
#define FUNC_FASTCALL(x) __fastcall x
#define RUBY_EXTERN extern __declspec(dllimport)
#define HAVE_DECL_SYS_NERR 1
-!if !defined(WIN32_WCE)
#define HAVE_LIMITS_H 1
-!endif
#define HAVE_FCNTL_H 1
#define HAVE_SYS_UTIME_H 1
#define HAVE_FLOAT_H 1
@@ -409,9 +407,7 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/win32/Makefile.sub $(win_srcdir)/Makefile.sub
!endif
#define GETGROUPS_T int
#define RETSIGTYPE void
-!if !defined(WIN32_WCE)
#define HAVE_ALLOCA 1
-!endif
#define HAVE_DUP2 1
#define HAVE_MEMCMP 1
#define HAVE_MEMMOVE 1
@@ -444,9 +440,7 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/win32/Makefile.sub $(win_srcdir)/Makefile.sub
#define HAVE_TIMES 1
#define HAVE_FCNTL 1
#define HAVE_LINK 1
-!if !defined(WIN32_WCE)
#define HAVE__SETJMP 1
-!endif
#define HAVE_TELLDIR 1
#define HAVE_SEEKDIR 1
#define HAVE_MKTIME 1
@@ -470,44 +464,21 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/win32/Makefile.sub $(win_srcdir)/Makefile.sub
#define THREAD_SPECIFIC __declspec(thread)
#define DEFAULT_KCODE KCODE_NONE
#define DLEXT ".so"
-#define RUBY_LIB "/lib/ruby/$(ruby_version)"
-#define RUBY_SITE_LIB "/lib/ruby/site_ruby"
-#define RUBY_SITE_LIB2 "/lib/ruby/site_ruby/$(ruby_version)"
-#define RUBY_VENDOR_LIB "/lib/ruby/vendor_ruby"
-#define RUBY_VENDOR_LIB2 "/lib/ruby/vendor_ruby/$(ruby_version)"
+#define RUBY_LIB "/lib/$(RUBY_INSTALL_NAME)/$(ruby_version)"
+#define RUBY_SITE_LIB "/lib/$(RUBY_INSTALL_NAME)/site_ruby"
+#define RUBY_SITE_LIB2 "/lib/$(RUBY_INSTALL_NAME)/site_ruby/$(ruby_version)"
+#define RUBY_VENDOR_LIB "/lib/$(RUBY_INSTALL_NAME)/vendor_ruby"
+#define RUBY_VENDOR_LIB2 "/lib/$(RUBY_INSTALL_NAME)/vendor_ruby/$(ruby_version)"
#define RUBY_PLATFORM "$(arch)"
-#define RUBY_ARCHLIB "/lib/ruby/$(ruby_version)/$(ARCH)-$(PLATFORM)"
-#define RUBY_SITE_ARCHLIB "/lib/ruby/site_ruby/$(ruby_version)/$(ARCH)-$(RT)"
-#define RUBY_VENDOR_ARCHLIB "/lib/ruby/vendor_ruby/$(ruby_version)/$(ARCH)-$(RT)"
+#define RUBY_ARCHLIB "/lib/$(RUBY_INSTALL_NAME)/$(ruby_version)/$(ARCH)-$(PLATFORM)"
+#define RUBY_SITE_ARCHLIB "/lib/$(RUBY_INSTALL_NAME)/site_ruby/$(ruby_version)/$(ARCH)-$(RT)"
+#define RUBY_VENDOR_ARCHLIB "/lib/$(RUBY_INSTALL_NAME)/vendor_ruby/$(ruby_version)/$(ARCH)-$(RT)"
#define LIBRUBY_SO "$(LIBRUBY_SO)"
#if 0
$(BANG)if "$(RUBY_SO_NAME)"!="$$(RUBY_SO_NAME)" || "$(ARCH)-$(PLATFORM)"!="$$(ARCH)-$$(PLATFORM)"
config.h: nul
$(BANG)endif
#endif
-!if defined(WIN32_WCE)
-#define GC_MALLOC_LIMIT 4000000
-#define stricmp _stricmp
-#define fopen wce_fopen
-#define open _open
-#define read _read
-#define write _write
-#define lseek _lseek
-
-#if _WIN32_WCE < 300
- #define isascii(c) ( (c>=0x00&&c<=0x7f)?1:0 )
- #define isspace(c) ( ((c>=0x09&&c<=0x0d)||c==0x20)?1:0 )
- #define isdigit(c) ( (c>=0x30&&c<=0x39)?1:0 )
- #define isupper(c) ( (c>='A'&&c<='Z')?1:0 )
- #define isalpha(c) ( ((c>='A'&&c<='Z')||(c>='a'&&c<='z'))?1:0 )
- #define isprint(c) ( (c>=0x20&&c<=0x7e)?1:0 )
- #define isalnum(c) ( (isalpha(c)||isdigit(c))?1:0 )
- #define iscntrl(c) ( ((c>=0x00&&c<=0x1f)||c==0x7f)?1:0 )
- #define islower(c) ( (c>='a'&&c<='z')?1:0 )
- #define ispunct(c) ( !(isalnum(c)||isspace(c))?1:0 )
- #define isxdigit(c) ( ((c>=0&&c<=9)||(c>='A'&&c<='F')||(c>='a'&&c<='f'))?1:0 )
-#endif
-!endif
<<
@exit > $(@:/=\)
@@ -530,9 +501,6 @@ config.status: $(MKFILES) $(srcdir)/win32/Makefile.sub $(win_srcdir)/Makefile.su
@exit <<$@
# Generated automatically by Makefile.sub.
s,@SHELL@,$$(COMSPEC),;t t
-!if defined(WIN32_WCE)
-s,@MAIN_DOES_NOTHING@,int WinMain(HINSTANCE h, HINSTANCE hp, LPWSTR s, int n) {return 0;},;t t
-!endif
s,@BUILD_FILE_SEPARATOR@,\,;t t
s,@PATH_SEPARATOR@,;,;t t
s,@CFLAGS@,$(CFLAGS),;t t
@@ -544,7 +512,7 @@ s,@LDFLAGS@,,;t t
s,@LIBS@,$(LIBS),;t t
s,@exec_prefix@,$${prefix},;t t
s,@prefix@,$(prefix),;t t
-s,@program_transform_name@,s,$$,$(RUBY_SUFFIX),,;t t
+s,@program_transform_name@,s,.*,$(RUBY_PREFIX)&$(RUBY_SUFFIX),,;t t
s,@bindir@,$${exec_prefix}/bin,;t t
s,@sbindir@,$${exec_prefix}/sbin,;t t
s,@libexecdir@,$${exec_prefix}/libexec,;t t
@@ -650,9 +618,9 @@ s,@EXPORT_PREFIX@, ,;t t
s,@arch@,$(ARCH)-$(PLATFORM),;t t
s,@sitearch@,$(ARCH)-$(RT),;t t
s,@ruby_version@,$(ruby_version),;t t
-s,@sitedir@,$${prefix}/lib/ruby/site_ruby,;t t
-s,@vendordir@,$${prefix}/lib/ruby/vendor_ruby,;t t
-s,@rubyhdrdir@,$$(includedir)/ruby-$$(ruby_version),;t t
+s,@sitedir@,$${prefix}/lib/$${RUBY_INSTALL_NAME}/site_ruby,;t t
+s,@vendordir@,$${prefix}/lib/$${RUBY_INSTALL_NAME}/vendor_ruby,;t t
+s,@rubyhdrdir@,$$(includedir)/$${RUBY_INSTALL_NAME}-$$(ruby_version),;t t
s,@sitehdrdir@,$$(rubyhdrdir)/site_ruby,;t t
s,@vendorhdrdir@,$$(rubyhdrdir)/vendor_ruby,;t t
s,@configure_args@,--with-make-prog=nmake --enable-shared $(configure_args),;t t
@@ -734,9 +702,6 @@ $(RUBY_INSTALL_NAME).rc $(RUBYW_INSTALL_NAME).rc $(RUBY_SO_NAME).rc: $(RBCONFIG)
-ruby_name=$(RUBY_INSTALL_NAME) \
-rubyw_name=$(RUBYW_INSTALL_NAME) \
-so_name=$(RUBY_SO_NAME) \
-!if defined(WIN32_WCE)
- -wce_ver=$(SUBSYSVERSION) \
-!endif
. $(icondirs) $(win_srcdir)
fake.rb: $(MKFILES)
diff --git a/win32/configure.bat b/win32/configure.bat
index 0ec9fde9a6..f9d287b21c 100755
--- a/win32/configure.bat
+++ b/win32/configure.bat
@@ -18,6 +18,7 @@ if "%1" == "srcdir" goto :srcdir
if "%1" == "--target" goto :target
if "%1" == "target" goto :target
if "%1" == "--with-static-linked-ext" goto :extstatic
+if "%1" == "--program-prefix" goto :pprefix
if "%1" == "--program-suffix" goto :suffix
if "%1" == "--program-name" goto :installname
if "%1" == "--install-name" goto :installname
@@ -44,6 +45,12 @@ goto :loop
shift
shift
goto :loop
+:pprefix
+ echo>> ~tmp~.mak "RUBY_PREFIX=%2" \
+ echo>>confargs.tmp %1=%2 \
+ shift
+ shift
+goto :loop
:suffix
echo>> ~tmp~.mak "RUBY_SUFFIX=%2" \
echo>>confargs.tmp %1=%2 \
diff --git a/win32/ifchange.bat b/win32/ifchange.bat
index 8411099020..9f6092747b 100755
--- a/win32/ifchange.bat
+++ b/win32/ifchange.bat
@@ -3,6 +3,11 @@
if "%1" == "" goto :end
+set timestamp=
+if "%1" == "--timestamp" (
+ set timestamp=yes
+ shift
+)
set dest=%1
set src=%2
set dest=%dest:/=\%
@@ -47,13 +52,18 @@ goto :end
if not exist %src% goto :end
if exist %dest% (
fc.exe %dest% %src% > nul && (
- echo %dest% unchanged.
+ echo %1 unchanged.
del %src%
- goto :end
+ goto :nt_end
)
)
-echo %dest% updated.
+echo %1 updated.
copy %src% %dest% > nul
del %src%
+:nt_end
+if "%timestamp%" == "" goto :end
+ for %%I in ("%dest%") do set timestamp=%%~dpI\.time.%%~nxI
+ if not exist "%timestamp%" copy nul "%timestamp%" > nul
+ goto :end >> "%timestamp%"
:end
diff --git a/win32/setup.mak b/win32/setup.mak
index 9ca6daa5c6..39a00e8fae 100644
--- a/win32/setup.mak
+++ b/win32/setup.mak
@@ -154,6 +154,9 @@ MSC_VER = _MSC_VER
-program-name-:
@type << >>$(MAKEFILE)
+!ifdef RUBY_PREFIX
+RUBY_PREFIX = $(RUBY_PREFIX)
+!endif
!ifdef RUBY_SUFFIX
RUBY_SUFFIX = $(RUBY_SUFFIX)
!endif
diff --git a/win32/win32.c b/win32/win32.c
index 5774d0c503..f2129afac8 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -33,9 +33,6 @@
#endif
#include "ruby/win32.h"
#include "win32/dir.h"
-#ifdef _WIN32_WCE
-#include "wince.h"
-#endif
#ifndef index
#define index(x, y) strchr((x), (y))
#endif
@@ -46,7 +43,7 @@
#undef close
#undef setsockopt
-#if defined __BORLANDC__ || defined _WIN32_WCE
+#if defined __BORLANDC__
# define _filbuf _fgetc
# define _flsbuf _fputc
# define enough_to_get(n) (--(n) >= 0)
@@ -67,11 +64,7 @@
static struct ChildRecord *CreateChild(const char *, const char *, SECURITY_ATTRIBUTES *, HANDLE, HANDLE, HANDLE);
static int has_redirection(const char *);
int rb_w32_wait_events(HANDLE *events, int num, DWORD timeout);
-#if !defined(_WIN32_WCE)
static int rb_w32_open_osfhandle(intptr_t osfhandle, int flags);
-#else
-#define rb_w32_open_osfhandle(osfhandle, flags) _open_osfhandle(osfhandle, flags)
-#endif
#define RUBY_CRITICAL(expr) do { expr; } while (0)
@@ -508,11 +501,6 @@ rb_w32_sysinit(int *argc, char ***argv)
// Initialize Winsock
StartSockets();
-
-#ifdef _WIN32_WCE
- // free commandline buffer
- wce_FreeCommandLine();
-#endif
}
char *
@@ -776,9 +764,8 @@ rb_w32_pipe_exec(const char *cmd, const char *prog, int mode, int *pipe,
reading = TRUE;
writing = FALSE;
}
- mode &= ~(O_RDWR|O_RDONLY|O_WRONLY);
- if (!(mode & O_BINARY))
- mode |= O_TEXT;
+ mode &= ~(O_RDWR|O_RDONLY|O_WRONLY|O_TEXT);
+ mode |= O_BINARY;
sa.nLength = sizeof (SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
@@ -1698,7 +1685,7 @@ typedef struct {
#define _CRTIMP __declspec(dllimport)
#endif
-#if !defined(__BORLANDC__) && !defined(_WIN32_WCE)
+#if !defined(__BORLANDC__)
EXTERN_C _CRTIMP ioinfo * __pioinfo[];
#define IOINFO_L2E 5
@@ -2157,6 +2144,9 @@ do_select(int nfds, fd_set *rd, fd_set *wr, fd_set *ex,
static inline int
subtract(struct timeval *rest, const struct timeval *wait)
{
+ if (rest->tv_sec < wait->tv_sec) {
+ return 0;
+ }
while (rest->tv_usec < wait->tv_usec) {
if (rest->tv_sec <= wait->tv_sec) {
return 0;
@@ -2306,25 +2296,33 @@ int WSAAPI
rb_w32_accept(int s, struct sockaddr *addr, int *addrlen)
{
SOCKET r;
+ int fd;
if (!NtSocketsInitialized) {
StartSockets();
}
RUBY_CRITICAL({
- r = accept(TO_SOCKET(s), addr, addrlen);
- if (r == INVALID_SOCKET) {
- errno = map_errno(WSAGetLastError());
- s = -1;
- }
- else {
- s = rb_w32_open_osfhandle(r, O_RDWR|O_BINARY|O_NOINHERIT);
- if (s != -1)
+ HANDLE h = CreateFile("NUL", 0, 0, NULL, OPEN_ALWAYS, 0, NULL);
+ fd = rb_w32_open_osfhandle((intptr_t)h, O_RDWR|O_BINARY|O_NOINHERIT);
+ if (fd != -1) {
+ r = accept(TO_SOCKET(s), addr, addrlen);
+ if (r != INVALID_SOCKET) {
+ MTHREAD_ONLY(EnterCriticalSection(&(_pioinfo(fd)->lock)));
+ _set_osfhnd(fd, r);
+ MTHREAD_ONLY(LeaveCriticalSection(&_pioinfo(fd)->lock));
+ CloseHandle(h);
st_insert(socklist, (st_data_t)r, (st_data_t)0);
- else
- closesocket(r);
+ }
+ else {
+ errno = map_errno(WSAGetLastError());
+ close(fd);
+ fd = -1;
+ }
}
+ else
+ CloseHandle(h);
});
- return s;
+ return fd;
}
#undef bind
@@ -2652,6 +2650,8 @@ open_ifs_socket(int af, int type, int protocol)
WSA_FLAG_OVERLAPPED);
break;
}
+ if (out == INVALID_SOCKET)
+ out = WSASocket(af, type, protocol, NULL, 0, 0);
}
free(proto_buffers);
@@ -3756,7 +3756,7 @@ catch_interrupt(void)
RUBY_CRITICAL(rb_w32_wait_events(NULL, 0, 0));
}
-#if defined __BORLANDC__ || defined _WIN32_WCE
+#if defined __BORLANDC__
#undef read
int
read(int fd, void *buf, size_t size)
@@ -3776,15 +3776,13 @@ int
rb_w32_getc(FILE* stream)
{
int c;
-#ifndef _WIN32_WCE
if (enough_to_get(stream->FILE_COUNT)) {
c = (unsigned char)*stream->FILE_READPTR++;
}
else
-#endif
{
c = _filbuf(stream);
-#if defined __BORLANDC__ || defined _WIN32_WCE
+#if defined __BORLANDC__
if ((c == EOF) && (errno == EPIPE)) {
clearerr(stream);
}
@@ -3798,12 +3796,10 @@ rb_w32_getc(FILE* stream)
int
rb_w32_putc(int c, FILE* stream)
{
-#ifndef _WIN32_WCE
if (enough_to_put(stream->FILE_COUNT)) {
c = (unsigned char)(*stream->FILE_READPTR++ = (char)c);
}
else
-#endif
{
c = _flsbuf(c, stream);
catch_interrupt();
@@ -4195,7 +4191,7 @@ rb_w32_pipe(int fds[2])
return _pipe(fds, 65536L, _O_NOINHERIT);
p = strchr(name, '0');
- snprintf(p, strlen(p) + 1, "%x-%x", rb_w32_getpid(), serial++);
+ snprintf(p, strlen(p) + 1, "%x-%lx", rb_w32_getpid(), serial++);
sec.nLength = sizeof(sec);
sec.lpSecurityDescriptor = NULL;
@@ -4443,8 +4439,8 @@ rb_w32_write(int fd, const void *buf, size_t size)
memset(&ol, 0, sizeof(ol));
if (!(_osfile(fd) & (FDEV | FPIPE))) {
LONG high = 0;
- DWORD low = SetFilePointer((HANDLE)_osfhnd(fd), 0, &high,
- FILE_CURRENT);
+ DWORD method = _osfile(fd) & FAPPEND ? FILE_END : FILE_CURRENT;
+ DWORD low = SetFilePointer((HANDLE)_osfhnd(fd), 0, &high, method);
#ifndef INVALID_SET_FILE_POINTER
#define INVALID_SET_FILE_POINTER ((DWORD)-1)
#endif
@@ -4670,7 +4666,7 @@ rb_w32_unlink(const char *path)
return ret;
}
-#if !defined(__BORLANDC__) && !defined(_WIN32_WCE)
+#if !defined(__BORLANDC__)
int
rb_w32_isatty(int fd)
{
diff --git a/wince/Makefile.sub b/wince/Makefile.sub
deleted file mode 100644
index d8f595a6bf..0000000000
--- a/wince/Makefile.sub
+++ /dev/null
@@ -1,47 +0,0 @@
-# -*- makefile -*-
-
-CROSS_COMPILING = 1
-LARGEFILE_SUPPORT = 0
-
-!ifndef win_srcdir
-win_srcdir = $(srcdir)/wince
-!endif
-
-!if !defined(OS) || !defined(RT)
-OS = mswince
-RT = $(OS)
-!endif
-
-!if !defined(WARNFLAGS)
-WARNFLAGS = -w
-!endif
-ARCHDEFS = $(CECPUDEF) -DUNDER_CE -D_WIN32_WCE=$(SUBSYSVERSION:.=) \
- -DFILENAME_MAX=MAX_PATH -DTLS_OUT_OF_INDEXES=0xFFFFFFFF \
- -DBUFSIZ=512 -D_UNICODE -DUNICODE
-!if !defined(LDFLAGS)
-LDFLAGS = -link -incremental:yes -pdb:none -machine:$(MACHINE) -subsystem:$(SUBSYSTEM)
-!endif
-!if !defined(XLDFLAGS)
-XLDFLAGS = -stack:$(STACK) -subsystem:$(SUBSYSTEM)
-!endif
-LIBS = coredll.lib ceshell.lib winsock.lib $(EXTLIBS)
-MISSING = acosh.obj cbrt.obj crypt.obj dup2.obj erf.obj hypot.obj \
- isinf.obj isnan.obj lgamma.obj strftime.obj strlcat.obj strlcpy.obj
- tgamma.obj win32.obj \
- assert.obj direct.obj errno.obj io_wce.obj process_wce.obj \
- signal_wce.obj stdio.obj stdlib.obj string_wce.obj \
- time_wce.obj wince.obj winsock2.obj \
- stat.obj timeb.obj utime.obj
-LIBOBJS = isinf.obj isnan.obj
-COMMON_LIBS = coredll winsock
-COMMON_MACROS = WIN32_LEAN_AND_MEAN
-COMMON_HEADERS = winsock.h windows.h
-
-XCFLAGS = -I$(srcdir)/wince
-
-!if !defined(STACK_COMMIT)
-STACK_COMMIT = 0x10000
-!endif
-WINMAINOBJ = wincemain.$(OBJEXT)
-
-!include $(srcdir)/win32/Makefile.sub
diff --git a/wince/README.wince b/wince/README.wince
deleted file mode 100644
index b4c8de2e09..0000000000
--- a/wince/README.wince
+++ /dev/null
@@ -1,122 +0,0 @@
-=begin
-
-= How to build ruby using eMbedded Visual C++
-
-== Requirement
-
-(1) eMbedded Visual C++ 3.0 or later.
-
-(2) ruby executable on the compiling host environment.
-
-(3) Please set environment variable (({INCLUDE})), (({LIB})), (({PATH})),
- (({CE_TOOLS_DIR})), (({EMBEDDED_TOOLS_DIR})) to run required commands
- properly from the command line.
-
- Note: building ruby requires following commands.
- * nmake
- * clarm or clmips or shcl
- * lib
- * dumpbin
-
-== How to compile and install
-
-(1) Execute wince\configure.bat on your build directory.
- You can specify the target platform as an argument.
- For example, run `((%configure arm-hpc2k-wince%))'
- You can also specify the install directory.
- For example, run `((%configure --prefix=<install_directory>%))'
- Default of the install directory is /usr .
-
-(2) Change ((|RUBY_INSTALL_NAME|)) and ((|RUBY_SO_NAME|)) in (({Makefile}))
- if you want to change the name of the executable files.
-
-(3) Run `((%nmake%))'
-
-(4) Run `((%nmake DESTDIR=<install_directory> install%))'
-
- This command will create following directories and copy (not install :-P)
- files onto them.
- * <install_directory>\bin
- * <install_directory>\lib
- * <install_directory>\lib\ruby
- * <install_directory>\lib\ruby\<MAJOR>.<MINOR>
- * <install_directory>\lib\ruby\<MAJOR>.<MINOR>\<PLATFORM>
- * <install_directory>\lib\ruby\site_ruby
- * <install_directory>\lib\ruby\site_ruby\<MAJOR>.<MINOR>
- * <install_directory>\lib\ruby\site_ruby\<MAJOR>.<MINOR>\<PLATFORM>
- * <install_directory>\man\man1
- If Ruby's version is `x.y.z', the ((|<MAJOR>|)) is `x' and the ((|<MINOR>|)) is `y'.
- In case of `mips-hpc2k-wince', The ((|<PLATFORM>|)) is `(({mips-mswince}))'.
-
-(5) Copy <install_directory> to your WindowsCE machine.
-
-== Icons
-
-Any icon files(*.ico) in the build directory, directories specified with
-((|icondirs|)) make variable and (({win32})) directory under the ruby
-source directory will be included in DLL or executable files, according
-to their base names.
- $(RUBY_INSTALL_NAME).ico or ruby.ico --> $(RUBY_INSTALL_NAME).exe
- $(RUBYW_INSTALL_NAME).ico or rubyw.ico --> $(RUBYW_INSTALL_NAME).exe
- the others --> $(RUBY_SO_NAME).dll
-
-Although no icons are distributed with the ruby source or in the official
-site, you can use anything you like. For example, followings are written
-in Japanese, but you can download at least.
-
-* ((<URL:http://member.nifty.ne.jp/ueivu/rubyico.html>)) or
- ((<zipped icons|URL:http://member.nifty.ne.jp/ueivu/Ruby_ico.zip>))
-* ((<URL:http://homepage1.nifty.com/a_nakata/ruby/>)) or
- ((<icon itself|URL:http://homepage1.nifty.com/a_nakata/ruby/RubyIcon.ico>))
-
-== Build examples
-
-* Build on the ruby source directory.
-
- ex.)
- ruby source directory: C:\ruby
- build directory: C:\ruby
- install directory: C:\usr\local
-
- C:
- cd \ruby
- win32\configure --prefix=/usr/local
- nmake
- nmake install
-
-* Build on the relative directory from the ruby source directory.
-
- ex.)
- ruby source directory: C:\ruby
- build directory: C:\ruby\mswin32
- install directory: C:\usr\local
-
- C:
- cd \ruby
- mkdir mswin32
- cd mswin32
- ..\win32\configure --prefix=/usr/local
- nmake
- nmake install
-
-* Build on the different drive.
-
- ex.)
- ruby source directory: C:\src\ruby
- build directory: D:\build\ruby
- install directory: C:\usr\local
-
- D:
- cd D:\build\ruby
- C:\src\ruby\win32\configure --prefix=C:/usr/local
- nmake
- nmake install
-
-== Bugs
-
-You can ((*NOT*)) use a path name contains any white space characters as
-the ruby source directory, this restriction comes from the behavior of
-(({!INCLUDE})) directives of (({NMAKE})).
-((- you may call it a bug. -))
-
-=end
diff --git a/wince/assert.c b/wince/assert.c
deleted file mode 100644
index 0f4be68497..0000000000
--- a/wince/assert.c
+++ /dev/null
@@ -1,11 +0,0 @@
-#include <windows.h>
-#include <tchar.h>
-#include "assert.h"
-
-
-void assert( int expression )
-{
- if( expression==0 )
- exit(2);
-}
-
diff --git a/wince/assert.h b/wince/assert.h
deleted file mode 100644
index c2a4e3ebb7..0000000000
--- a/wince/assert.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASSERT_H_
-#define _ASSERT_H_
-
-void assert( int expression );
-
-#endif
diff --git a/wince/configure.bat b/wince/configure.bat
deleted file mode 100755
index dadfb2fa83..0000000000
--- a/wince/configure.bat
+++ /dev/null
@@ -1,109 +0,0 @@
-@echo off
-::: Don't set environment variable in batch file other than autoexec.bat
-::: to avoid "Out of environment space" problem on Windows 95/98.
-::: set TMPMAKE=~tmp~.mak
-
-echo> ~tmp~.mak ####
-echo>> ~tmp~.mak conf = %0
-echo>> ~tmp~.mak $(conf:\=/): nul
-echo>> ~tmp~.mak @del ~tmp~.mak
-echo>> ~tmp~.mak @-$(MAKE) -l$(MAKEFLAGS) -f $(@D)/setup.mak \
-:loop
-if "%1" == "" goto :end
-if "%1" == "--prefix" goto :prefix
-if "%1" == "--srcdir" goto :srcdir
-if "%1" == "srcdir" goto :srcdir
-if "%1" == "--target" goto :target
-if "%1" == "target" goto :target
-if "%1" == "--with-static-linked-ext" goto :extstatic
-if "%1" == "--program-suffix" goto :suffix
-if "%1" == "--program-name" goto :progname
-if "%1" == "--enable-install-doc" goto :enable-rdoc
-if "%1" == "--disable-install-doc" goto :disable-rdoc
-if "%1" == "--extout" goto :extout
-if "%1" == "--with-baseruby" goto :baseruby
-if "%1" == "-h" goto :help
-if "%1" == "--help" goto :help
-if "%1" == "CC" goto :define
-if "%1" == "EMBEDDED_TOOLS_DIR" goto :define
-if "%1" == "CE_TOOLS_DIR" goto :define
-if "%1" == "EMBEDDED_TOOLS4_DIR" goto :define
-if "%1" == "CE_TOOLS4_DIR" goto :define
- echo>> ~tmp~.mak "%1" \
- shift
-goto :loop
-:srcdir
- echo>> ~tmp~.mak "srcdir=%2" \
- shift
- shift
-goto :loop
-:prefix
- echo>> ~tmp~.mak "prefix=%2" \
- shift
- shift
-goto :loop
-:suffix
- echo>> ~tmp~.mak "RUBY_SUFFIX=%2" \
- shift
- shift
-goto :loop
-:installname
- echo>> ~tmp~.mak "RUBY_INSTALL_NAME=%2" \
- shift
- shift
-goto :loop
-:soname
- echo>> ~tmp~.mak "RUBY_SO_NAME=%2" \
- shift
- shift
-goto :loop
-:define
- echo>> ~tmp~.mak "%1=%2" \
- shift
- shift
-goto :loop
-:target
- echo>> ~tmp~.mak "%2" \
- shift
- shift
-goto :loop
-:extstatic
- echo>> ~tmp~.mak "EXTSTATIC=static" \
- shift
-goto :loop
-:enable-rdoc
- echo>> ~tmp~.mak "RDOCTARGET=install-doc" \
- shift
-goto :loop
-:disable-rdoc
- echo>> ~tmp~.mak "RDOCTARGET=install-nodoc" \
- shift
-goto :loop
-:extout
- echo>> ~tmp~.mak "EXTOUT=%2" \
- shift
- shift
-goto :loop
-:baseruby
- echo>> ~tmp~.mak "BASERUBY=%2" \
- shift
- shift
-goto :loop
-:help
- echo Configuration:
- echo --help display this help
- echo --srcdir=DIR find the sources in DIR [configure dir or `..']
- echo Installation directories:
- echo --prefix=PREFIX install files in PREFIX []
- echo System types:
- echo --target=TARGET configure for TARGET [i386-mswin32]
- echo Optional Package:
- echo --with-baseruby=RUBY use RUBY as baseruby [ruby]
- echo --with-static-linked-ext link external modules statically
- echo --enable-install-doc install rdoc indexes during install
- del ~tmp~.mak
-goto :exit
-:end
-echo>> ~tmp~.mak WIN32DIR=$(@D)
-nmake -alf ~tmp~.mak
-:exit
diff --git a/wince/direct.c b/wince/direct.c
deleted file mode 100644
index bf0d7cd224..0000000000
--- a/wince/direct.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/***************************************************************
- direct.c
-***************************************************************/
-
-#include <windows.h>
-#include <tchar.h>
-#include <direct.h>
-#include "wince.h" /* for wce_mbtowc */
-
-/* global for chdir, getcwd */
-char _currentdir[MAX_PATH+1];
-
-
-char *getcwd(char* buffer, int maxlen)
-{
- strcpy( buffer, _currentdir );
- return buffer;
-}
-
-int _chdir(const char * dirname)
-{
- if( MAX_PATH < strlen(dirname) )
- return -1;
-
- strcpy( _currentdir, dirname );
- return 0;
-}
-
-int _rmdir(const char * dir)
-{
- wchar_t *wdir;
- BOOL rc;
-
- /* replace with RemoveDirectory. */
- wdir = wce_mbtowc(dir);
- rc = RemoveDirectoryW(wdir);
- free(wdir);
-
- return rc==TRUE ? 0 : -1;
-}
-
-int _mkdir(const char * dir)
-{
- wchar_t* wdir;
- BOOL rc;
-
- /* replace with CreateDirectory. */
- wdir = wce_mbtowc(dir);
- rc = CreateDirectoryW(wdir, NULL);
- free(wdir);
-
- return rc==TRUE ? 0 : -1;
-}
-
diff --git a/wince/direct.h b/wince/direct.h
deleted file mode 100644
index 7c859b9d3b..0000000000
--- a/wince/direct.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef DIRECT_H
-#define DIRECT_H 1
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-char *getcwd(char* buffer, int maxlen);
-int _chdir(const char * dirname);
-int _rmdir(const char * dir);
-int _mkdir(const char * dir);
-
-#ifdef __cplusplus
-};
-#endif
-
-#define chdir _chdir
-#define rmdir _rmdir
-#define mkdir _mkdir
-
-#endif
diff --git a/wince/errno.c b/wince/errno.c
deleted file mode 100644
index 705b25428e..0000000000
--- a/wince/errno.c
+++ /dev/null
@@ -1,11 +0,0 @@
-/***************************************************************
- errno.c
-***************************************************************/
-
-#include <errno.h>
-
-
-int errno;
-int _doserrno;
-int _sys_nerr;
-
diff --git a/wince/errno.h b/wince/errno.h
deleted file mode 100644
index 2fdd325b32..0000000000
--- a/wince/errno.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef ERRNO_H
-#define ERRNO_H 1
-
-
-#define EPERM 1
-#define ENOENT 2
-#define ESRCH 3
-#define EINTR 4
-#define EIO 5
-#define ENXIO 6
-#define E2BIG 7
-#define ENOEXEC 8
-#define EBADF 9
-#define ECHILD 10
-#define EAGAIN 11
-#define ENOMEM 12
-#define EACCES 13
-#define EFAULT 14
-#define EOSERR 15 // rk
-#define EBUSY 16
-#define EEXIST 17
-#define EXDEV 18
-#define ENODEV 19
-#define ENOTDIR 20
-#define EISDIR 21
-#define EINVAL 22
-#define ENFILE 23
-#define EMFILE 24
-#define ENOTTY 25
-#define EFBIG 27
-#define ENOSPC 28
-#define ESPIPE 29
-#define EROFS 30
-#define EMLINK 31
-#define EPIPE 32
-#define EDOM 33
-#define ERANGE 34
-#define EDEADLK 36
-#define ENOSYS 37
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern int errno;
-extern int _doserrno;
-extern int _sys_nerr;
-
-#define sys_nerr _sys_nerr
-
-#ifdef __cplusplus
-};
-#endif
-
-#endif
diff --git a/wince/fcntl.h b/wince/fcntl.h
deleted file mode 100644
index 5a6bdc71e6..0000000000
--- a/wince/fcntl.h
+++ /dev/null
@@ -1,42 +0,0 @@
-
-#ifndef FCNTL_H
-#define FCNTL_H 1
-
-
-#define F_SETFL 1
-#define F_SETFD 2
-#define F_GETFL 3
-
-#define _O_RDONLY 0x0000 /* open for reading only */
-#define _O_WRONLY 0x0001 /* open for writing only */
-#define _O_RDWR 0x0002 /* open for reading and writing */
-
-#define _O_NONBLOCK 0x0004
-
-#define _O_APPEND 0x0008 /* writes done at eof */
-#define _O_CREAT 0x0100 /* create and open file */
-#define _O_TRUNC 0x0200 /* open and truncate */
-#define _O_EXCL 0x0400 /* open only if file doesn't already exist */
-#define _O_TEXT 0x4000 /* file mode is text (translated) */
-#define _O_BINARY 0x8000 /* file mode is binary (untranslated) */
-#define _O_ACCMODE 0x10000
-
-#define _O_NOINHERIT 0
-#define O_NOINHERIT _O_NOINHERIT
-
-#define O_RDONLY _O_RDONLY
-#define O_WRONLY _O_WRONLY
-#define O_RDWR _O_RDWR
-
-#define O_NONBLOCK _O_NONBLOCK
-
-#define O_APPEND _O_APPEND
-#define O_CREAT _O_CREAT
-#define O_TRUNC _O_TRUNC
-#define O_EXCL _O_EXCL
-#define O_TEXT _O_TEXT
-#define O_BINARY _O_BINARY
-#define O_ACCMODE _O_ACCMODE
-
-
-#endif
diff --git a/wince/io.h b/wince/io.h
deleted file mode 100644
index eb355a4916..0000000000
--- a/wince/io.h
+++ /dev/null
@@ -1,76 +0,0 @@
-
-#ifndef _IO_WINCE_H_
-#define _IO_WINCE_H_
-
-#ifndef _TIME_T_DEFINED
-typedef unsigned long time_t;
-#define _TIME_T_DEFINED
-#endif
-
-#ifndef _FSIZE_T_DEFINED
-typedef unsigned long _fsize_t; /* Could be 64 bits for Win32 */
-#define _FSIZE_T_DEFINED
-#endif
-
-#ifndef _FINDDATA_T_DEFINED
-struct _finddata_t {
- unsigned attrib;
- time_t time_create; /* -1 for FAT file systems */
- time_t time_access; /* -1 for FAT file systems */
- time_t time_write;
- _fsize_t size;
- char name[260];
-};
-#define _FINDDATA_T_DEFINED
-#endif
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int _chsize(int handle, long size);
-int _rename (const char *oldname, const char *newname);
-int _unlink(const char *file);
-int _umask(int cmask);
-int _chmod(const char *path, int mode);
-int dup( int handle );
-//int dup2( int handle1, int handle2 );
-int _isatty(int fd);
-int _pipe(int *phandles, unsigned int psize, int textmode);
-int _access(const char *filename, int flags);
-int _open_osfhandle ( long osfhandle, int flags);
-long _get_osfhandle( int filehandle );
-int _open(const char *file, int mode,...);
-int close(int fd);
-int _read(int fd, void *buffer, int length);
-int _write(int fd, const void *buffer, unsigned count);
-long _lseek(int handle, long offset, int origin);
-long _findfirst( char *filespec, struct _finddata_t *fileinfo );
-int _findnext( long handle, struct _finddata_t *fileinfo );
-int _findclose( long handle );
-
-#ifdef __cplusplus
-};
-#endif
-
-#define chmod _chmod
-#define chsize _chsize
-#define rename _rename
-#define unlink _unlink
-#define open _open
-//#define close _close
-#define read _read
-#define write _write
-#define umask _umask
-//#define dup _dup
-#define isatty _isatty
-#define access _access
-#define pipe _pipe
-#define setmode _setmode
-#define lseek _lseek
-
-#define _close close
-
-#endif
-
diff --git a/wince/io_wce.c b/wince/io_wce.c
deleted file mode 100644
index 613934aa66..0000000000
--- a/wince/io_wce.c
+++ /dev/null
@@ -1,230 +0,0 @@
-/***************************************************************
- io.c
-
- author : uema2
- date : Nov 30, 2002
-
- You can freely use, copy, modify, and redistribute
- the whole contents.
-***************************************************************/
-
-#include <windows.h>
-#include <stdlib.h>
-#include <io.h>
-#include <fcntl.h>
-#include <time.h>
-#include <errno.h>
-#include "wince.h" /* for wce_mbtowc */
-
-extern int _errno;
-
-
-int _rename(const char *oldname, const char *newname)
-{
- wchar_t *wold, *wnew;
- BOOL rc;
-
- wold = wce_mbtowc(oldname);
- wnew = wce_mbtowc(newname);
-
- /* replace with MoveFile. */
- rc = MoveFileW(wold, wnew);
-
- free(wold);
- free(wnew);
-
- return rc==TRUE ? 0 : -1;
-}
-
-int _unlink(const char *file)
-{
- wchar_t *wfile;
- BOOL rc;
-
- /* replace with DeleteFile. */
- wfile = wce_mbtowc(file);
- rc = DeleteFileW(wfile);
- free(wfile);
-
- return rc==TRUE ? 0 : -1;
-}
-
-/* replace "open" with "CreateFile", etc. */
-int _open(const char *file, int mode, va_list arg)
-{
- wchar_t *wfile;
- DWORD access=0, share=0, create=0;
- HANDLE h;
-
- if( (mode&_O_RDWR) != 0 )
- access = GENERIC_READ|GENERIC_WRITE;
- else if( (mode&_O_RDONLY) != 0 )
- access = GENERIC_READ;
- else if( (mode&_O_WRONLY) != 0 )
- access = GENERIC_WRITE;
-
- if( (mode&_O_CREAT) != 0 )
- create = CREATE_ALWAYS;
- else
- create = OPEN_ALWAYS;
-
- wfile = wce_mbtowc(file);
-
- h = CreateFileW(wfile, access, share, NULL,
- create, 0, NULL );
-
- free(wfile);
- return (int)h;
-}
-
-int close(int fd)
-{
- CloseHandle( (HANDLE)fd );
- return 0;
-}
-
-int _read(int fd, void *buffer, int length)
-{
- DWORD dw;
- ReadFile( (HANDLE)fd, buffer, length, &dw, NULL );
- return (int)dw;
-}
-
-int _write(int fd, const void *buffer, unsigned count)
-{
- DWORD dw;
- WriteFile( (HANDLE)fd, buffer, count, &dw, NULL );
- return (int)dw;
-}
-
-long _lseek(int handle, long offset, int origin)
-{
- DWORD flag, ret;
-
- switch(origin)
- {
- case SEEK_SET: flag = FILE_BEGIN; break;
- case SEEK_CUR: flag = FILE_CURRENT; break;
- case SEEK_END: flag = FILE_END; break;
- default: flag = FILE_CURRENT; break;
- }
-
- ret = SetFilePointer( (HANDLE)handle, offset, NULL, flag );
- return ret==0xFFFFFFFF ? -1 : 0;
-}
-
-/* _findfirst, _findnext, _findclose. */
-/* replace them with FindFirstFile, etc. */
-long _findfirst( char *file, struct _finddata_t *fi )
-{
- HANDLE h;
- WIN32_FIND_DATAA fda;
-
- h = FindFirstFileA( file, &fda );
- if( h==NULL )
- {
- errno = EINVAL; return -1;
- }
-
- fi->attrib = fda.dwFileAttributes;
- fi->time_create = wce_FILETIME2time_t( &fda.ftCreationTime );
- fi->time_access = wce_FILETIME2time_t( &fda.ftLastAccessTime );
- fi->time_write = wce_FILETIME2time_t( &fda.ftLastWriteTime );
- fi->size = fda.nFileSizeLow + (fda.nFileSizeHigh<<32);
- strcpy( fi->name, fda.cFileName );
-
- return (long)h;
-}
-
-int _findnext( long handle, struct _finddata_t *fi )
-{
- WIN32_FIND_DATAA fda;
- BOOL b;
-
- b = FindNextFileA( (HANDLE)handle, &fda );
-
- if( b==FALSE )
- {
- errno = ENOENT; return -1;
- }
-
- fi->attrib = fda.dwFileAttributes;
- fi->time_create = wce_FILETIME2time_t( &fda.ftCreationTime );
- fi->time_access = wce_FILETIME2time_t( &fda.ftLastAccessTime );
- fi->time_write = wce_FILETIME2time_t( &fda.ftLastWriteTime );
- fi->size = fda.nFileSizeLow + (fda.nFileSizeHigh<<32);
- strcpy( fi->name, fda.cFileName );
-
- return 0;
-}
-
-int _findclose( long handle )
-{
- BOOL b;
- b = FindClose( (HANDLE)handle );
- return b==FALSE ? -1 : 0;
-}
-
-/* below functions unsupported... */
-/* I have no idea how to replace... */
-int _chsize(int handle, long size)
-{
- errno = EACCES;
- return -1;
-}
-
-int _umask(int cmask)
-{
- return 0;
-}
-
-int _chmod(const char *path, int mode)
-{
- return 0;
-}
-
-/* WinCE doesn't have dup and dup2. */
-/* so, we cannot use missing/dup2.c. */
-int dup( int handle )
-{
- errno = EBADF;
- return -1;
-}
-/*
-int dup2( int handle1, int handle2 )
-{
- errno = EBADF;
- return -1;
-}
-*/
-int _isatty(int fd)
-{
- if( fd==(int)_fileno(stdin) ||
- fd==(int)_fileno(stdout)||
- fd==(int)_fileno(stderr) )
- return 1;
- else
- return 0;
-}
-
-int _pipe(int *phandles, unsigned int psize, int textmode)
-{
- return -1;
-}
-
-int _access(const char *filename, int flags)
-{
- return 0;
-}
-
-int _open_osfhandle( long osfhandle, int flags)
-{
-/* return 0; */
- return (int)osfhandle;
-}
-
-long _get_osfhandle( int filehandle )
-{
-/* return 0; */
- return (long)filehandle;
-}
diff --git a/wince/process.h b/wince/process.h
deleted file mode 100644
index 2ef72a4ac1..0000000000
--- a/wince/process.h
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef PROCESS_H
-#define PROCESS_H 1
-
-
-#define _P_WAIT 0
-#define _P_NOWAIT 1
-#define _P_OVERLAY 2
-#define _P_DETACH 4
-
-#define P_WAIT _P_WAIT
-#define P_NOWAIT _P_NOWAIT
-#define P_DETACH _P_DETACH
-#define P_OVERLAY _P_OVERLAY
-
-#ifndef _INTPTR_T_DEFINED
-typedef int intptr_t;
-#define _INTPTR_T_DEFINED
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int _getpid(void);
-
-int _cwait(int *, int, int);
-void abort(void);
-
-int _execl(const char *, const char *, ...);
-//int _execv(const char *, const char * const *);
-int execv(const char *path, char *const argv[]);
-
-intptr_t _spawnle(int, const char *, const char *, ...);
-intptr_t _spawnvpe(int, const char *, const char * const *,
- const char * const *);
-
-#ifdef __cplusplus
-};
-#endif
-
-//#define getpid _getpid
-#define execl _execl
-#define execv _execv
-
-
-#endif
diff --git a/wince/process_wce.c b/wince/process_wce.c
deleted file mode 100644
index 4415ad024e..0000000000
--- a/wince/process_wce.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/***************************************************************
- process.c
-***************************************************************/
-
-#include <windows.h>
-#include "process.h"
-
-int _getpid(void)
-{
- return (int)GetCurrentProcessId();
-}
-
-/* I wonder _exec and _swawn should be replaced with CreateProcess... */
-int _execl(const char *cmdname, const char *arg0,
- va_list va_args)
-{
- return 0;
-}
-
-int execv(const char *path, char *const argv[])
-{
- return 0;
-}
-
-void abort(void)
-{
-}
-
-int _cwait( int *termstat, int procHandle, int action )
-{
- return 0;
-}
-
-intptr_t _spawnle(int mode,
- const char *cmdname, const char *arg0,
- va_list va_argn)
-{
- return 0;
-}
-
-intptr_t _spawnvpe(int mode,
- const char *cmdname, const char *const *argv,
- const char *const *envp)
-{
- return 0;
-}
-
diff --git a/wince/setup.mak b/wince/setup.mak
deleted file mode 100644
index 96151c7da7..0000000000
--- a/wince/setup.mak
+++ /dev/null
@@ -1,254 +0,0 @@
-# -*- makefile -*-
-
-!if "$(srcdir)" != ""
-WIN32DIR = $(srcdir)/win32
-!elseif "$(WIN32DIR)" == "win32"
-srcdir = .
-!elseif "$(WIN32DIR)" == "$(WIN32DIR:/win32=)/win32"
-srcdir = $(WIN32DIR:/win32=)
-!else
-srcdir = $(WIN32DIR)/..
-!endif
-!ifndef prefix
-prefix = /usr
-!endif
-OS = mswince
-RT = msvcrt
-INCLUDE = !include
-APPEND = echo>>$(MAKEFILE)
-!ifdef MAKEFILE
-MAKE = $(MAKE) -f $(MAKEFILE)
-!else
-MAKEFILE = Makefile
-!endif
-ARCH = PROCESSOR_ARCHITECTURE
-CPU = PROCESSOR_LEVEL
-CPP = cl -nologo -EP
-
-all: -prologue- -generic- -epilogue-
-i386-$(OS): -prologue- -i386- -epilogue-
-i486-$(OS): -prologue- -i486- -epilogue-
-i586-$(OS): -prologue- -i586- -epilogue-
-i686-$(OS): -prologue- -i686- -epilogue-
-alpha-$(OS): -prologue- -alpha- -epilogue-
-
-# CE
-mips-hpc2k-wince: -prologue- -mips- -hpc2k- -epilogue-
-mips-ppc-wince: -prologue- -mips- -ppc- -epilogue-
-mips-hpcpro-wince: -prologue- -mips- -hpcpro- -epilogue-
-arm-hpc2k-wince: -prologue- -arm- -hpc2k- -epilogue-
-arm-ppc-wince: -prologue- -arm- -ppc- -epilogue-
-arm-hpcpro-wince: -prologue- -arm- -hpcpro- -epilogue-
-sh3-ppc-wince: -prologue- -sh3- -ppc- -epilogue-
-sh3-hpcpro-wince: -prologue- -sh3- -hpcpro- -epilogue-
-sh4-hpcpro-wince: -prologue- -sh4- -hpcpro- -epilogue-
-armv4-.net41-wince: -prologue- -armv4- -.net41- -epilogue-
-armv4t-.net41-wince: -prologue- -armv4t- -.net41- -epilogue-
-armv4i-sig3-wince: -prologue- -armv4i- -sig3- -epilogue-
-
--prologue-: nul
- @type << > $(MAKEFILE)
-### Makefile for ruby $(OS) ###
-srcdir = $(srcdir:\=/)
-prefix = $(prefix:\=/)
-EXTSTATIC = $(EXTSTATIC)
-!if defined(RDOCTARGET)
-RDOCTARGET = $(RDOCTARGET)
-!endif
-!if defined(EXTOUT)
-EXTOUT = $(EXTOUT)
-!endif
-!if defined(BASERUBY)
-BASERUBY = $(BASERUBY)
-!endif
-<<
- @$(CPP) -I$(srcdir) <<"Creating $(MAKEFILE)" >> $(MAKEFILE)
-#define RUBY_REVISION 0
-#include "version.h"
-MAJOR = RUBY_VERSION_MAJOR
-MINOR = RUBY_VERSION_MINOR
-TEENY = RUBY_VERSION_TEENY
-MSC_VER = _MSC_VER
-<<
-
--generic-: nul
-!if defined($(ARCH)) || defined($(CPU))
- @type << >>$(MAKEFILE)
-!if defined($(ARCH))
-$(ARCH) = $(PROCESSOR_ARCHITECTURE)
-!endif
-!if defined($(CPU))
-$(CPU) = $(PROCESSOR_LEVEL)
-!endif
-
-<<
-!endif
-
--alpha-: nul
- @$(APPEND) $(ARCH) = alpha
--ix86-: nul
- @$(APPEND) $(ARCH) = x86
-
--i386-: -ix86-
- @$(APPEND) $(CPU) = 3
--i486-: -ix86-
- @$(APPEND) $(CPU) = 4
--i586-: -ix86-
- @$(APPEND) $(CPU) = 5
--i686-: -ix86-
- @$(APPEND) $(CPU) = 6
-
-# CE
--mips- -arm- -sh3- -sh4-::
- @$(APPEND) $(ARCH) = $(@:-=)
--mips- -arm-::
- @$(APPEND) CC = cl$(@:-=)
--sh3- -sh4-::
- @$(APPEND) CC = shcl
--armv4- -armv4i-::
- @$(APPEND) CC = clarm
- @$(APPEND) ARCHFOLDER = $(@:-=)
--armv4t-::
- @$(APPEND) CC = clthumb
- @$(APPEND) ARCHFOLDER = $(@:-=)
-
--arm-::
- @$(APPEND) CECPUDEF = -DARM -D_ARM_
--mips-::
- @$(APPEND) CECPUDEF = -DMIPS -D_MIPS_
--sh3-::
- @$(APPEND) CECPUDEF = -DSHx -DSH3 -D_SH3_
--sh4-::
- @$(APPEND) CECPUDEF = -DSHx -DSH4 -D_SH4_
- @$(APPEND) QSH4 = -Qsh4
--armv4-::
- @$(APPEND) CECPUDEF = -DARM -D_ARM_ -DARMV4
- @$(APPEND) $(ARCH) = ARM
--armv4t- -armv4i-::
- @$(APPEND) CECPUDEF = -DARM -D_ARM_ -DARMV4T -DTHUMB -D_THUMB_
- @$(APPEND) $(ARCH) = THUMB
-
-
--hpc2k-: -hpc2000-
--ppc-: "-MS Pocket PC-"
--hpcpro2-: "-MS HPC Pro-"
--hpcpro-: "-MS HPC Pro--"
-
--mswin32-:
- @type << >>$(MAKEFILE)
-OS = mswin32
-RT = msvcrt
-<<
-
--mswince-:
- @type << >>$(MAKEFILE)
-!ifdef CE_TOOLS_DIR
-CE_TOOLS_DIR = $(CE_TOOLS_DIR)
-!endif
-!ifdef EMBEDDED_TOOLS_DIR
-EMBEDDED_TOOLS_DIR = $(EMBEDDED_TOOLS_DIR)
-!endif
-
-OS = mswince
-RT = $$(OS)
-<<
-
--mswince4-:
- @type << >>$(MAKEFILE)
-!ifdef CE_TOOLS4_DIR
-CE_TOOLS4_DIR = $(CE_TOOLS4_DIR)
-!endif
-!ifdef EMBEDDED_TOOLS4_DIR
-EMBEDDED_TOOLS4_DIR = $(EMBEDDED_TOOLS4_DIR)
-!endif
-
-OS = mswince
-RT = $$(OS)
-<<
-
-
--mswince-3.00 -mswince-2.11: -mswince-
- @type << >>$(MAKEFILE)
-SUBSYSVERSION = $(@:-mswince-=)
-PATH = $$(EMBEDDED_TOOLS_DIR)/common/evc/bin;$$(EMBEDDED_TOOLS_DIR)/EVC/WCE$$(SUBSYSVERSION:.=)/bin
-<<
-
--mswince-4.10: -mswince4-
- @type << >>$(MAKEFILE)
-SUBSYSVERSION = $(@:-mswince-=)
-EXTLIBS = ws2.lib
-PATH = $$(EMBEDDED_TOOLS4_DIR)/common/evc/bin;$$(EMBEDDED_TOOLS4_DIR)/EVC/WCE$$(SUBSYSVERSION:.=)/bin
-<<
-
--hpc2000- "-MS Pocket PC-": -mswince-3.00
-"-MS HPC Pro-" "-MS HPC Pro--": -mswince-2.11
--.net41- -sig3-: -mswince-4.10
-
--hpc2000-:
- @type << >>$(MAKEFILE)
-SUBSYSTEM = windowsce,3.0
-INCLUDE = $$(CE_TOOLS_DIR)/wce$$(SUBSYSVERSION:.=)/$(@:-=)/include
-LIB = $$(CE_TOOLS_DIR)/wce$$(SUBSYSVERSION:.=)/$(@:-=)/lib/$$(PROCESSOR_ARCHITECTURE)
-<<
-
-"-MS Pocket PC-":
- @type << >>$(MAKEFILE)
-SUBSYSTEM = windowsce,3.0
-INCLUDE = $$(CE_TOOLS_DIR)/wce$$(SUBSYSVERSION:.=)/MS Pocket PC/include
-LIB = $$(CE_TOOLS_DIR)/wce$$(SUBSYSVERSION:.=)/MS Pocket PC/lib/$$(PROCESSOR_ARCHITECTURE)
-<<
-
-
-"-MS HPC Pro--":
- @type << >>$(MAKEFILE)
-SUBSYSTEM = windowsce,2.11
-INCLUDE = $$(CE_TOOLS_DIR)/wce$$(SUBSYSVERSION:.=)/MS HPC Pro/include
-LIB = $$(CE_TOOLS_DIR)/wce$$(SUBSYSVERSION:.=)/MS HPC Pro/lib/$$(PROCESSOR_ARCHITECTURE)
-<<
-
--.net41-:
- @type << >>$(MAKEFILE)
-SUBSYSTEM = windowsce,4.1
-INCLUDE = $$(CE_TOOLS4_DIR)/wce400/STANDARDSDK/include/$$(ARCHFOLDER)
-LIB = $$(CE_TOOLS4_DIR)/wce400/STANDARDSDK/lib/$$(ARCHFOLDER)
-<<
-
--sig3-:
- @type << >>$(MAKEFILE)
-SUBSYSTEM = windowsce,4.1
-INCLUDE = $$(CE_TOOLS4_DIR)/wce410/sigmarionIII SDK/include/$$(ARCHFOLDER)
-LIB = $$(CE_TOOLS4_DIR)/wce410/sigmarionIII SDK/lib/$$(ARCHFOLDER)
-<<
-
--epilogue-: -encs-
-
--encs-: nul
- @$(MAKE) -l -f $(srcdir)/win32/enc-setup.mak srcdir="$(srcdir)" MAKEFILE=$(MAKEFILE)
-
--epilogue-: nul
- @type << >>$(MAKEFILE)
-!ifdef RUBY_INSTALL_NAME
-RUBY_INSTALL_NAME = $(RUBY_INSTALL_NAME)
-!else ifdef RUBY_SUFFIX
-RUBY_INSTALL_NAME = ruby$(RUBY_SUFFIX)
-!endif
-!ifdef RUBY_SO_NAME
-RUBY_SO_NAME = $(RUBY_SO_NAME)
-!else
-# RUBY_SO_NAME = $$(RT)-$$(RUBY_INSTALL_NAME)$$(MAJOR)$$(MINOR)
-!endif
-# CFLAGS = -nologo $$(DEBUGFLAGS) $$(OPTFLAGS) $$(PROCESSOR_FLAG)
-CPPFLAGS = -I. -I$$(srcdir) -I$$(srcdir)/missing -I$$(srcdir)/wince \
- $$(CECPUDEF) -DUNDER_CE -D_WIN32_WCE=$$(SUBSYSVERSION:.=) \
- -DFILENAME_MAX=MAX_PATH -DTLS_OUT_OF_INDEXES=0xFFFFFFFF \
- -DBUFSIZ=512 -D_UNICODE -DUNICODE $$(QSH4)
-# STACK = 0x10000,0x1000
-# LDFLAGS = $$(CFLAGS) -Fm
-# XLDFLAGS =
-# RFLAGS = -r
-# EXTLIBS =
-
-$(INCLUDE) $$(srcdir)/wince/Makefile.sub
-<<
- @$(srcdir:/=\)\win32\rm.bat config.h config.status
- @echo type `$(MAKE)' to make ruby for $(OS).
diff --git a/wince/signal.h b/wince/signal.h
deleted file mode 100644
index 95f857dd88..0000000000
--- a/wince/signal.h
+++ /dev/null
@@ -1,71 +0,0 @@
-#ifndef SIGNAL_H
-#define SIGNAL_H 1
-
-#include <sys/types.h>
-
-#define SIGHUP 1
-#define SIGINT 2
-#define SIGQUIT 3
-#define SIGILL 4
-#define SIGPIPE 5
-#define SIGFPE 8
-#define SIGUSR1 10
-#define SIGSEGV 11
-#define SIGUSR2 12
-#define SIGTERM 15
-#define SIGCHLD 17
-#define SIGTSTP 20
-#define SIGBREAK 21
-#define SIGABRT 22
-#define NSIG 22
-
-#define SA_NOCLDSTOP 1
-#define SA_SHIRQ 0x04000000
-#define SA_STACK 0x08000000
-#define SA_RESTART 0x10000000
-#define SA_INTERRUPT 0x20000000
-#define SA_NOMASK 0x40000000
-#define SA_ONESHOT 0x80000000
-
-/* signal action codes */
-
-#define SIG_DFL (void (*)(int))0 /* default signal action */
-#define SIG_IGN (void (*)(int))1 /* ignore signal */
-#define SIG_SGE (void (*)(int))3 /* signal gets error */
-#define SIG_ACK (void (*)(int))4 /* acknowledge */
-#define SIG_ERR (void (*)(int))-1 /* signal error value */
-
-#define SIG_BLOCK 0 /* for blocking signals */
-#define SIG_UNBLOCK 1 /* for unblocking signals */
-#define SIG_SETMASK 2 /* for setting the signal mask */
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef void (* SIGHANDLER)(int);
-typedef void (* sighandler_t)(int);
-
-typedef int sig_atomic_t;
-typedef unsigned int sigset_t;
-
-struct sigaction{
- sighandler_t sa_handler;
- sigset_t sa_mask;
- unsigned long sa_flags;
- void (*sa_restorer)(void);
-};
-
-int raise(int sig);
-//#ifndef _WIN32_WCE_EMULATION
- void (* signal(int sig, void (__cdecl *func)(int)))(int);
-//#else
-// void (* signal(int sig, void (*func)));
-//#endif
-
-#ifdef __cplusplus
-};
-#endif
-
-#endif
diff --git a/wince/signal_wce.c b/wince/signal_wce.c
deleted file mode 100644
index 95f85e0ac8..0000000000
--- a/wince/signal_wce.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/***************************************************************
- signal.c
-***************************************************************/
-
-#include <windows.h>
-#include "signal.h"
-
-/* lazy replacement... (^^; */
-int raise(int sig)
-{
- return 0;
-}
-
-//#ifdef _WIN32_WCE
-//#ifdef _WIN32_WCE_EMULATION
-//void (* signal(int sig, void (*func)))
-//{
-// return sig;
-//}
-//#else
-void (* signal(int sig, void (__cdecl *func)(int)))(int)
-{
- return sig;
-}
-//#endif
-//#endif
diff --git a/wince/stddef.h b/wince/stddef.h
deleted file mode 100644
index 227725020e..0000000000
--- a/wince/stddef.h
+++ /dev/null
@@ -1,5 +0,0 @@
-
-#ifndef _STDDEF_H_
-#define _STDDEF_H_
-
-#endif
diff --git a/wince/stdio.c b/wince/stdio.c
deleted file mode 100644
index 877408d417..0000000000
--- a/wince/stdio.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/***************************************************************
- stdio.c
-***************************************************************/
-
-#include <windows.h>
-#include "wince.h" /* for wce_mbtowc */
-
-
-FILE *freopen(const char *filename, const char *mode, FILE *file)
-{
- wchar_t *wfilename, *wmode;
- FILE *fp;
-
- wfilename = wce_mbtowc(filename);
- wmode = wce_mbtowc(mode);
-
- fp = _wfreopen(wfilename, wmode, file);
-
- free(wfilename);
- free(wmode);
-
- return fp;
-}
-
-FILE *fdopen( int handle, const char *mode )
-{
- wchar_t *wmode;
- FILE* fp;
-
- wmode = wce_mbtowc(mode);
- fp = _wfdopen( (void*)handle, wmode );
-
- free(wmode);
- return fp;
-}
-
diff --git a/wince/stdlib.c b/wince/stdlib.c
deleted file mode 100644
index d371b12f88..0000000000
--- a/wince/stdlib.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/***************************************************************
- stdlib.c
-***************************************************************/
-
-#include <windows.h>
-
-char **environ;
-extern char * rb_w32_getenv(const char *);
-
-/* getenv should replace with rb_w32_getenv. */
-char *getenv(const char *env)
-{
- return rb_w32_getenv(env);
-}
-
-char *_fullpath(char *absPath, const char *relPath,
- size_t maxLength)
-{
- strcpy( absPath, relPath );
- return absPath;
-}
-
-int mblen(const char *mbstr, size_t count)
-{
- const char *p = mbstr;
- size_t i;
- int n=0;
-
- for( i=0; i<count; i++ )
- {
- if( *p=='\0' ) break;
- if( IsDBCSLeadByteEx( CP_ACP, *p ) )
- n+=2, p+=2;
- else
- n+=1, p+=1;
- }
-
- return n;
-}
-
-void *bsearch( const void *key, const void *base,
- size_t num, size_t width,
- int ( __cdecl *compare )(const void *, const void *))
-{
- size_t i;
- const void* p = base;
- const char* px;
-
- for( i=0; i<num; i++ )
- {
- if( 0==compare( key, p ) )
- return (void*)p;
- px = (const char*)p; px+=width; p=(const void*)px;
- }
- return NULL;
-}
-
diff --git a/wince/string_wce.c b/wince/string_wce.c
deleted file mode 100644
index 257eee101d..0000000000
--- a/wince/string_wce.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/***************************************************************
- string.c
-***************************************************************/
-
-#include <windows.h>
-#include "wince.h" /* for wce_mbtowc */
-
-/* _strdup already exists in stdlib.h? */
-char *strdup(const char * str)
-{
- char *p;
-
- p = malloc( strlen(str)+1 );
- strcpy( p, str );
- return p;
-}
-
-char* strerror(int errno)
-{
- static char buf[32]="wince::strerror called.";
- return buf;
-}
-
-/* strnicmp already exists in stdlib.h? */
-int strnicmp( const char *s1, const char *s2, size_t count )
-{
- wchar_t *w1, *w2;
- int n;
-
- w1 = wce_mbtowc(s1);
- w2 = wce_mbtowc(s2);
-
- n = wcsnicmp(w1, w2, count);
-
- free(w1);
- free(w2);
-
- return n;
-}
-
-#if _WIN32_WCE < 300
-#include "..\missing\strtoul.c"
-
-char *strrchr( const char *p, int c )
-{
- char *pp;
- for( pp=(char*)p+strlen(p); pp!=p; pp-- )
- {
- if( *pp==c ) break;
- }
- return pp==p ? NULL : pp;
-}
-
-int stricmp( const char *s1, const char *s2 )
-{
- wchar_t *w1, *w2;
- int n;
-
- w1 = wce_mbtowc(s1);
- w2 = wce_mbtowc(s2);
-
- n = wcsicmp(w1, w2);
-
- free(w1);
- free(w2);
-
- return n;
-}
-
-char *strpbrk(const char *str, const char *cs)
-{
- wchar_t *wstr, *wcs, *w;
- char *s = NULL;
-
- wstr = wce_mbtowc(str);
- wcs = wce_mbtowc(cs);
-
- w = wcspbrk(wstr, wcs);
-
- if( w!=NULL )
- s = str + (wcs-wstr)/sizeof(wchar_t);
-
- free(wstr);
- free(wcs);
-
- return s;
-}
-
-#endif
diff --git a/wince/sys/stat.c b/wince/sys/stat.c
deleted file mode 100644
index 5d51dbf426..0000000000
--- a/wince/sys/stat.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/***************************************************************
- stat.c
-
- author : uema2
- date : Nov 30, 2002
-
- You can freely use, copy, modify, and redistribute
- the whole contents.
-***************************************************************/
-
-#include <windows.h>
-#include <sys/stat.h>
-#include <time.h>
-#include "..\wince.h" /* for wce_mbtowc */
-
-
-int _stat(const char *filename, struct _stat *st)
-{
- DWORD dwAttribute;
- HANDLE h;
- DWORD dwSizeLow=0, dwSizeHigh=0, dwError=0;
- WIN32_FIND_DATAW fd;
- wchar_t *wfilename;
-
-// wfilename = wce_mbtowc(filename);
- wfilename = wce_replaceRelativeDir(filename);
-
- dwAttribute = GetFileAttributesW(wfilename);
- if(dwAttribute==0xFFFFFFFF)
- {
- free(wfilename);
- return -1;
- }
-
- st->st_mode = 0;
- if((dwAttribute & FILE_ATTRIBUTE_DIRECTORY) != 0)
- st->st_mode += S_IFDIR;
- else
- st->st_mode += S_IFREG;
-
- /* initialize */
- st->st_atime = 0;
- st->st_mtime = 0;
- st->st_ctime = 0;
- st->st_size = 0;
- st->st_dev = 0;
-
- h = FindFirstFileW(wfilename, &fd);
- if(h == INVALID_HANDLE_VALUE)
- {
- if(wfilename[wcslen(wfilename)-1] == L'\\')
- {
- wfilename[wcslen(wfilename)-1] = L'\0';
- h = FindFirstFileW(wfilename, &fd);
- if(h == INVALID_HANDLE_VALUE)
- {
- free(wfilename);
- return 0;
- }
- }
- else
- {
- free(wfilename);
- return 0;
- }
- }
-
- /* FILETIME -> time_t */
- st->st_atime = wce_FILETIME2time_t(&fd.ftLastAccessTime);
- st->st_mtime = wce_FILETIME2time_t(&fd.ftLastWriteTime);
- st->st_ctime = wce_FILETIME2time_t(&fd.ftCreationTime);
- st->st_size = fd.nFileSizeLow;
-
- FindClose( h );
- free(wfilename);
- return 0;
-}
-
-int fstat(int file, struct stat *sbuf)
-{
- /* GetFileSize & GetFileTime */
- DWORD dwSize;
- FILETIME ctime, atime, mtime;
-
- dwSize = GetFileSize( (HANDLE)file, NULL );
- if( dwSize == 0xFFFFFFFF )
- return -1;
-
- sbuf->st_size = dwSize;
- sbuf->st_dev = 0;
- sbuf->st_rdev = 0;
- sbuf->st_mode = _S_IFREG;
- sbuf->st_nlink= 1;
-
- GetFileTime( (HANDLE)file, &ctime, &atime, &mtime );
- sbuf->st_ctime = wce_FILETIME2time_t(&ctime);
- sbuf->st_atime = wce_FILETIME2time_t(&atime);
- sbuf->st_mtime = wce_FILETIME2time_t(&mtime);
-
- return 0;
-}
-
diff --git a/wince/sys/stat.h b/wince/sys/stat.h
deleted file mode 100644
index e3cdf8b8e7..0000000000
--- a/wince/sys/stat.h
+++ /dev/null
@@ -1,68 +0,0 @@
-#ifndef SYS_STAT_H
-#define SYS_STAT_H 1
-
-#include <sys/types.h>
-
-#define _S_IFMT 0170000 /* file type mask */
-#define _S_IFDIR 0040000 /* directory */
-#define _S_IFCHR 0020000 /* character special */
-#define _S_IFIFO 0010000 /* pipe */
-#define _S_IFREG 0100000 /* regular */
-#define _S_IREAD 0000400 /* read permission, owner */
-#define _S_IWRITE 0000200 /* write permission, owner */
-#define _S_IEXEC 0000100 /* execute/search permission, owner */
-
-#define S_IFMT _S_IFMT
-#define S_IFREG _S_IFREG
-#define S_IFCHR _S_IFCHR
-#define S_IFDIR _S_IFDIR
-#define S_IREAD _S_IREAD
-#define S_IWRITE _S_IWRITE
-#define S_IEXEC _S_IEXEC
-
-#ifndef S_ISDIR
-#define S_ISDIR(X) (((X) & S_IFMT) == S_IFDIR)
-#endif
-#ifndef S_ISREG
-#define S_ISREG(X) (((X) & S_IFMT) == S_IFREG)
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// in sys/types.h
-//typedef unsigned int _dev_t;
-//typedef long _off_t;
-//typedef unsigned short _ino_t;
-
-#ifndef _STAT_DEFINED
-struct stat
-{
- dev_t st_dev;
- ino_t st_ino;
- unsigned short st_mode;
- short st_nlink;
- short st_uid;
- short st_gid;
- dev_t st_rdev;
- off_t st_size;
- time_t st_atime;
- time_t st_mtime;
- time_t st_ctime;
-};
-#define _STAT_DEFINED
-#endif /* _STAT_DEFINED */
-
-#define _stat stat
-
-int _stat(const char *filename, struct _stat *stat);
-int fstat(int file, struct stat *sbuf);
-
-
-#ifdef __cplusplus
-};
-#endif
-
-
-#endif
diff --git a/wince/sys/timeb.c b/wince/sys/timeb.c
deleted file mode 100644
index 838ae0798d..0000000000
--- a/wince/sys/timeb.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/***************************************************************
- timeb.c
-***************************************************************/
-
-#include <windows.h>
-#include <time.h>
-#include <sys/timeb.h>
-
-
-int ftime(struct timeb *tp)
-{
- SYSTEMTIME s;
- FILETIME f;
-
- GetLocalTime(&s);
- SystemTimeToFileTime( &s, &f );
-
- tp->dstflag = 0;
- tp->timezone = _timezone/60;
- tp->time = wce_FILETIME2time_t(&f);
- tp->millitm = s.wMilliseconds;
-
- return 0;
-}
-
diff --git a/wince/sys/timeb.h b/wince/sys/timeb.h
deleted file mode 100644
index e051b9058c..0000000000
--- a/wince/sys/timeb.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifndef SYS_TIMEB_H
-#define SYS_TIMEB_H 1
-
-#include <sys/types.h>
-
-struct _timeb {
- time_t time;
- unsigned short millitm;
- short timezone;
- short dstflag;
-};
-
-#define timeb _timeb
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int ftime(struct timeb *tp);
-
-#ifdef __cplusplus
-};
-#endif
-
-
-#endif
diff --git a/wince/sys/types.h b/wince/sys/types.h
deleted file mode 100644
index 541d5e8361..0000000000
--- a/wince/sys/types.h
+++ /dev/null
@@ -1,60 +0,0 @@
-#ifndef SYS_TYPES_H
-#define SYS_TYPES_H 1
-
-#define BIG_ENDIAN 1234
-#define LITTLE_ENDIAN 4321
-
-#ifdef MIPS
-#define BYTE_ORDER LITTLE_ENDIAN
-#endif
-
-//#if UNDER_CE > 201
-// typedef unsigned long time_t;
-// #define _TIME_T_DEFINED_
-//#endif
-typedef unsigned long dev_t;
-typedef unsigned long ino_t;
-#ifndef _MODE_T_DEFINED_
- typedef unsigned long mode_t;
- #define _MODE_T_DEFINED_
-#endif
-
-typedef long clock_t;
-
-#ifndef _PTRDIFF_T_DEFINED
-typedef long ptrdiff_t;
-#define _PTRDIFF_T_DEFINED
-#endif
-
-typedef long off_t;
-
-//typedef unsigned char u_char;
-//typedef unsigned short u_short;
-
-#ifndef _CADDR_T_DEFINED_
-typedef unsigned char * caddr_t;
-#define _CADDR_T_DEFINED_
-#endif
-
-#ifndef _SIZE_T_DEFINED_
-typedef unsigned int size_t;
-#define _SIZE_T_DEFINED_
-#endif
-
-//typedef unsigned char u_int8_t;
-
-//typedef short int16_t;
-//typedef unsigned short u_int16_t;
-
-//typedef int int32_t;
-//typedef unsigned int u_int32_t;
-
-//typedef unsigned long u_long;
-//typedef unsigned int u_int;
-
-//#ifndef _TIME_T_DEFINED_
-//typedef unsigned long time_t;
-//#define _TIME_T_DEFINED_
-//#endif
-
-#endif
diff --git a/wince/sys/utime.c b/wince/sys/utime.c
deleted file mode 100644
index 0139c13828..0000000000
--- a/wince/sys/utime.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/***************************************************************
- utime.c
-***************************************************************/
-
-#include <windows.h>
-#include <sys/utime.h>
-#include "..\wince.h" /* for wce_mbtowc */
-
-
-#ifdef _WIN32_WCE
- #if _WIN32_WCE < 300
- #define Int32x32To64(a, b) ((LONGLONG)((LONG)(a)) * (LONGLONG)((LONG)(b)))
-/* #define Int32x32To64(a, b) ((__int64)((LONG)(a)) * (__int64)((LONG)(b))) */
- #endif
-#endif
-
-int utime(const char *f, struct utimbuf *t)
-{
- HANDLE h;
- FILETIME atime={0}, mtime={0};
- __int64 time64;
- BOOL rc;
- wchar_t *w;
-
- w = wce_mbtowc(f);
- h = CreateFileW(w, GENERIC_WRITE,
- FILE_SHARE_READ|FILE_SHARE_WRITE,
- NULL, OPEN_EXISTING, 0, 0);
- free(w);
-
- if( h==INVALID_HANDLE_VALUE )
- return -1;
-
- time64 = Int32x32To64(t->actime, 10000000) + 116444736000000000;
- atime.dwLowDateTime = (DWORD)time64;
- atime.dwHighDateTime = (DWORD)(time64 >> 32);
- time64 = Int32x32To64(t->modtime, 10000000) + 116444736000000000;
- mtime.dwLowDateTime = (DWORD)time64;
- mtime.dwHighDateTime = (DWORD)(time64 >> 32);
-
- rc = SetFileTime(h, NULL, &atime, &mtime);
- return rc==TRUE ? 0 : -1;
-}
-
diff --git a/wince/sys/utime.h b/wince/sys/utime.h
deleted file mode 100644
index b644f02a61..0000000000
--- a/wince/sys/utime.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef SYS_UTIME_H
-#define SYS_UTIME_H 1
-
-#include <time.h>
-
-struct utimbuf
-{
- time_t actime;
- time_t modtime;
-};
-
-#define _utimbuf utimbuf
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int utime(const char *f, struct utimbuf *t);
-
-#ifdef __cplusplus
-};
-#endif
-
-//#define utime _utime
-
-#endif
diff --git a/wince/time.h b/wince/time.h
deleted file mode 100644
index 531b2aacfd..0000000000
--- a/wince/time.h
+++ /dev/null
@@ -1,63 +0,0 @@
-#ifndef _TIME_WINCE_H
-#define _TIME_WINCE_H 1
-
-#include <winbase.h>
-#include <sys/types.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern int daylight;
-extern int _timezone, timezone;
-extern char *tzname[2];
-
-#if 0
-#define _DAY_SEC (24L * 60L * 60L) /* secs in a day */
-#define _YEAR_SEC (365L * _DAY_SEC) /* secs in a year */
-#define _FOUR_YEAR_SEC (1461L * _DAY_SEC) /* secs in a 4 year interval */
-#define _DEC_SEC 315532800L /* secs in 1970-1979 */
-#define _BASE_YEAR 70L /* 1970 is the base year */
-#define _BASE_DOW 4 /* 01-01-70 was a Thursday */
-#define _LEAP_YEAR_ADJUST 17L /* Leap years 1900 - 1970 */
-#define _MAX_YEAR 138L /* 2038 is the max year */
-#endif
-
-#ifndef _TM_DEFINED
-struct tm {
- int tm_sec; /* seconds after the minute - [0,59] */
- int tm_min; /* minutes after the hour - [0,59] */
- int tm_hour; /* hours since midnight - [0,23] */
- int tm_mday; /* day of the month - [1,31] */
- int tm_mon; /* months since January - [0,11] */
- int tm_year; /* years since 1900 */
- int tm_wday; /* days since Sunday - [0,6] */
- int tm_yday; /* days since January 1 - [0,365] */
- int tm_isdst; /* daylight savings time flag */
-};
-#define _TM_DEFINED
-#endif
-
-
-typedef struct {
- int yr; // year of interest
- int yd; // day of year
- long ms; // milli-seconds in the day
-} transitionTime;
-
-time_t mktime(struct tm* pt);
-time_t time( time_t *timer );
-struct tm *localtime(const time_t *ptime);
-struct tm *gmtime(const time_t *tod);
-char* ctime( const time_t *t );
-char* asctime(const struct tm *tptr);
-void tzset();
-int clock(void);
-time_t wce_FILETIME2time_t(const FILETIME* pf);
-
-
-#ifdef __cplusplus
-};
-#endif
-
-#endif
diff --git a/wince/time_wce.c b/wince/time_wce.c
deleted file mode 100644
index ed9b3386bd..0000000000
--- a/wince/time_wce.c
+++ /dev/null
@@ -1,301 +0,0 @@
-/***************************************************************
- time.c
-
- author : uema2
- date : Nov 30, 2002
-
- You can freely use, copy, modify, and redistribute
- the whole contents.
-***************************************************************/
-
-/*#define __SCRATCH_TIMEC_DEBUG__ */
-
-#include <windows.h>
-#include <tchar.h>
-#include <time.h>
-
-/* globals */
-const __int64 _onesec_in100ns = (__int64)10000000;
-int timezone, _timezone, altzone;
-int daylight;
-char *tzname[2];
-
-
-/* __int64 <--> FILETIME */
-static __int64 wce_FILETIME2int64(FILETIME f)
-{
- __int64 t;
-
- t = f.dwHighDateTime;
- t <<= 32;
- t |= f.dwLowDateTime;
- return t;
-}
-
-static FILETIME wce_int642FILETIME(__int64 t)
-{
- FILETIME f;
-
- f.dwHighDateTime = (DWORD)((t >> 32) & 0x00000000FFFFFFFF);
- f.dwLowDateTime = (DWORD)( t & 0x00000000FFFFFFFF);
- return f;
-}
-
-/* FILETIME utility */
-static FILETIME wce_getFILETIMEFromYear(WORD year)
-{
- SYSTEMTIME s={0};
- FILETIME f;
-
- s.wYear = year;
- s.wMonth = 1;
- s.wDayOfWeek = 1;
- s.wDay = 1;
-
- SystemTimeToFileTime( &s, &f );
- return f;
-}
-
-static time_t wce_getYdayFromSYSTEMTIME(const SYSTEMTIME* s)
-{
- __int64 t;
- FILETIME f1, f2;
-
- f1 = wce_getFILETIMEFromYear( s->wYear );
- SystemTimeToFileTime( s, &f2 );
-
- t = wce_FILETIME2int64(f2)-wce_FILETIME2int64(f1);
-
- return (time_t)((t/_onesec_in100ns)/(60*60*24));
-}
-
-/* tm <--> SYSTEMTIME */
-static SYSTEMTIME wce_tm2SYSTEMTIME(struct tm *t)
-{
- SYSTEMTIME s;
-
- s.wYear = t->tm_year + 1900;
- s.wMonth = t->tm_mon + 1;
- s.wDayOfWeek = t->tm_wday;
- s.wDay = t->tm_mday;
- s.wHour = t->tm_hour;
- s.wMinute = t->tm_min;
- s.wSecond = t->tm_sec;
- s.wMilliseconds = 0;
-
- return s;
-}
-
-static struct tm wce_SYSTEMTIME2tm(SYSTEMTIME *s)
-{
- struct tm t;
-
- t.tm_year = s->wYear - 1900;
- t.tm_mon = s->wMonth- 1;
- t.tm_wday = s->wDayOfWeek;
- t.tm_mday = s->wDay;
- t.tm_yday = wce_getYdayFromSYSTEMTIME(s);
- t.tm_hour = s->wHour;
- t.tm_min = s->wMinute;
- t.tm_sec = s->wSecond;
- t.tm_isdst = 0;
-
- return t;
-}
-
-/* FILETIME <--> time_t */
-time_t wce_FILETIME2time_t(const FILETIME* f)
-{
- FILETIME f1601, f1970;
- __int64 t, offset;
-
- f1601 = wce_getFILETIMEFromYear(1601);
- f1970 = wce_getFILETIMEFromYear(1970);
-
- offset = wce_FILETIME2int64(f1970) - wce_FILETIME2int64(f1601);
-
- t = wce_FILETIME2int64(*f);
-
- t -= offset;
- return (time_t)(t / _onesec_in100ns);
-}
-
-FILETIME wce_time_t2FILETIME(const time_t t)
-{
- FILETIME f, f1970;
- __int64 time;
-
- f1970 = wce_getFILETIMEFromYear(1970);
-
- time = t;
- time *= _onesec_in100ns;
- time += wce_FILETIME2int64(f1970);
-
- f = wce_int642FILETIME(time);
-
- return f;
-}
-
-/* time.h difinition */
-time_t time( time_t *timer )
-{
- SYSTEMTIME s;
- FILETIME f;
-
- if( timer==NULL ) return 0;
-
- GetSystemTime( &s );
-
- SystemTimeToFileTime( &s, &f );
-
- *timer = wce_FILETIME2time_t(&f);
- return *timer;
-}
-
-struct tm *localtime( const time_t *timer )
-{
- SYSTEMTIME ss, ls, s;
- FILETIME sf, lf, f;
- __int64 t, diff;
- static struct tm tms;
-
- GetSystemTime(&ss);
- GetLocalTime(&ls);
-
- SystemTimeToFileTime( &ss, &sf );
- SystemTimeToFileTime( &ls, &lf );
-
- diff = wce_FILETIME2int64(sf) - wce_FILETIME2int64(lf);
-
- f = wce_time_t2FILETIME(*timer);
- t = wce_FILETIME2int64(f) - diff;
- f = wce_int642FILETIME(t);
-
- FileTimeToSystemTime( &f, &s );
-
- tms = wce_SYSTEMTIME2tm(&s);
-
- return &tms;
-}
-
-time_t mktime(struct tm* pt)
-{
- SYSTEMTIME ss, ls, s;
- FILETIME sf, lf, f;
- __int64 diff;
-
- GetSystemTime(&ss);
- GetLocalTime(&ls);
- SystemTimeToFileTime( &ss, &sf );
- SystemTimeToFileTime( &ls, &lf );
-
- diff = (wce_FILETIME2int64(lf)-wce_FILETIME2int64(sf))/_onesec_in100ns;
-
- s = wce_tm2SYSTEMTIME(pt);
- SystemTimeToFileTime( &s, &f );
- return wce_FILETIME2time_t(&f) - (time_t)diff;
-}
-
-struct tm *gmtime(const time_t *t)
-{
- FILETIME f;
- SYSTEMTIME s;
- static struct tm tms;
-
- f = wce_time_t2FILETIME(*t);
- FileTimeToSystemTime(&f, &s);
- tms = wce_SYSTEMTIME2tm(&s);
- return &tms;
-}
-
-char* ctime( const time_t *t )
-{
- // Wed Jan 02 02:03:55 1980\n\0
- static char buf[30]={0};
- char week[] = "Sun Mon Tue Wed Thr Fri Sat ";
- char month[]= "Jan Feb Mar Apl May Jun Jul Aug Sep Oct Nov Dec ";
- struct tm tms;
-
- tms = *localtime(t);
-
- strncpy( buf, week+tms.tm_wday*4, 4 );
- strncpy( buf+4, month+tms.tm_mon*4, 4 );
- sprintf( buf+8, "%02d ", tms.tm_mday );
- sprintf( buf+11, "%02d:%02d:%02d %d\n",
- tms.tm_hour, tms.tm_min, tms.tm_sec, tms.tm_year+1900 );
- return buf;
-}
-
-char *asctime(const struct tm *pt)
-{
- static char buf[30]={0};
- char week[] = "Sun Mon Tue Wed Thr Fri Sat ";
- char month[]= "Jan Feb Mar Apl May Jun Jul Aug Sep Oct Nov Dec ";
-
- strncpy( buf, week+pt->tm_wday*4, 4 );
- strncpy( buf+4, month+pt->tm_mon*4, 4 );
- sprintf( buf+8, "%02d ", pt->tm_mday );
- sprintf( buf+11, "%02d:%02d:%02d %d\n",
- pt->tm_hour, pt->tm_min, pt->tm_sec, pt->tm_year+1900 );
- return buf;
-}
-
-void tzset()
-{
- daylight = 1;
- _timezone = 28800;
- timezone = 28800;
-}
-
-int clock(void)
-{
- return 1;
-}
-
-//---------------------------------------------------------------
-#ifdef __SCRATCH_TIMEC_DEBUG__
-
-int main()
-{
- time_t t1, t2;
- struct tm tm1, tm2;
-
- time( &t1 );
- tm1 = *localtime(&t1);
- t1 = mktime(&tm1);
- tm1 = *gmtime(&t1);
-
- _time( &t2 );
- tm2 = *_localtime(&t2);
- t2 = _mktime(&tm2);
- tm2 = *_gmtime(&t2);
-
- // time, mktime
- if( t1==t2 )
- OutputDebugString( "ok\n" );
- else
- {
- static char buf[128];
- wsprintf( buf, "ng : %d, %d\n", t1, t2 );
- OutputDebugString( buf );
- }
-
- // localtime, gmtime
- if( 0==memcmp( &tm1, &tm2, sizeof(struct tm) ) )
- OutputDebugString( "ok\n" );
- else
- OutputDebugString( "ng\n" );
-
- // ctime
- OutputDebugString( ctime(&t1) );
- OutputDebugString( _ctime(&t2) );
-
- // asctime
- OutputDebugString( asctime(&tm1) );
- OutputDebugString( _asctime(&tm2) );
-
- return 0;
-}
-
-#endif
-
diff --git a/wince/varargs.h b/wince/varargs.h
deleted file mode 100644
index 2d1d476ccd..0000000000
--- a/wince/varargs.h
+++ /dev/null
@@ -1,34 +0,0 @@
-
-#ifndef VARARGS_H
-#define VARARGS_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef _VA_LIST_DEFINED
-typedef char *va_list;
-#define _VA_LIST_DEFINED
-#endif
-
-//#ifdef MIPS
-#define va_alist __va_alist, __va_alist2, __va_alist3, __va_alist4
-#define va_dcl int __va_alist, __va_alist2, __va_alist3, __va_alist4;
-#define va_start(list) list = (char *) &__va_alist
-#define va_end(list)
-#define va_arg(list, mode) ((mode *)(list =\
- (char *) ((((int)list + (__builtin_alignof(mode)<=4?3:7)) &\
- (__builtin_alignof(mode)<=4?-4:-8))+sizeof(mode))))[-1]
-#else
-#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
-#define va_dcl va_list va_alist;
-#define va_start(ap) ap = (va_list)&va_alist
-#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
-#define va_end(ap) ap = (va_list)0
-//#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/wince/wince.c b/wince/wince.c
deleted file mode 100644
index c1a950c1c1..0000000000
--- a/wince/wince.c
+++ /dev/null
@@ -1,583 +0,0 @@
-/***************************************************************
- wince.c
-
- author : uema2
- date : Nov 30, 2002
-
- You can freely use, copy, modify, and redistribute
- the whole contents.
-***************************************************************/
-
-#include <windows.h>
-#include <tchar.h>
-#include "wince.h"
-
-/* global for GetCommandLineA */
-char *_commandLine;
-
-extern char _currentdir[];
-
-/* make up Win32API except wce_* functions. */
-
-DWORD GetModuleFileNameA(
- HMODULE hModule, LPSTR lpFileName,
- DWORD size )
-{
- LPWSTR lpFileNameW;
- LPSTR mb;
- size_t ret;
-
- if( size==0 ) return 0;
-
- lpFileNameW = (LPWSTR)malloc( size*sizeof(wchar_t) );
- ret = GetModuleFileNameW( hModule, lpFileNameW, size );
- mb = wce_wctomb(lpFileNameW);
- strcpy(lpFileName, mb);
- free(mb);
- free(lpFileNameW);
-
- return ret;
-}
-
-#if _WIN32_WCE < 300
-FARPROC GetProcAddressA(HMODULE hModule, LPCSTR lpProcName)
-{
- FARPROC p;
- LPWSTR lpwProcName;
-
- lpwProcName = wce_mbtowc( lpProcName );
- p = GetProcAddressW( hModule, lpwProcName );
- free( lpwProcName );
- return p;
-}
-#endif
-
-char * GetCommandLineA(void)
-{
- return _commandLine;
-}
-
-/* this is not Win32API. GetCommandLineA helper. */
-void wce_SetCommandLine(LPCWSTR wcmd)
-{
- char* acmd;
-
- acmd = wce_wctomb( wcmd );
- _commandLine = (char*)malloc( strlen(acmd)+5 );
- sprintf( _commandLine, "ruby %s", acmd );
- free(acmd);
-}
-
-/* this is not Win32API. GetCommandLineA helper. */
-void wce_FreeCommandLine(void)
-{
- free(_commandLine);
- _commandLine = NULL;
-}
-
-/* I have no idea how to replace this. */
-BOOL GetProcessTimes(HANDLE hprocess,
- LPFILETIME lpCreationTime, LPFILETIME lpExitTime,
- LPFILETIME lpKernelTime, LPFILETIME lpUserTime)
-{
- return 0;
-}
-
-/* -------------- file attributes functions. ------------------- */
-DWORD GetFileAttributesA(LPCSTR lpFileName)
-{
- LPWSTR lpwFileName;
- DWORD dw;
-
- lpwFileName = wce_mbtowc(lpFileName);
- dw = GetFileAttributesW(lpwFileName);
- free(lpwFileName);
- return dw;
-}
-
-BOOL SetFileAttributesA(
- LPCSTR lpFileName, DWORD attributes)
-{
- LPWSTR lpwFileName;
- BOOL b;
-
- lpwFileName = wce_mbtowc(lpFileName);
- b = SetFileAttributesW(lpwFileName, attributes);
- free(lpwFileName);
- return b;
-}
-
-/* --------------- move and remove functions. ------------------- */
-BOOL MoveFileA(LPCSTR fn1, LPCSTR fn2)
-{
- LPWSTR wfn1, wfn2;
- BOOL b;
-
- wfn1 = wce_mbtowc(fn1);
- wfn2 = wce_mbtowc(fn2);
- b = MoveFileW(wfn1, wfn2);
- free(wfn1);
- free(wfn2);
- return 0;
-}
-
-BOOL MoveFileEx(LPCSTR oldname, LPCSTR newname, DWORD dwFlags)
-{
- LPWSTR woldname, wnewname;
- BOOL b;
-
- woldname = wce_mbtowc(oldname);
- wnewname = wce_mbtowc(newname);
-
- if( (dwFlags&MOVEFILE_REPLACE_EXISTING)!=0 )
- DeleteFileW( wnewname );
-
- b = MoveFileW( woldname, wnewname );
-
- free(woldname);
- free(wnewname);
-
- return b;
-}
-
-BOOL DeleteFileA(LPCSTR path)
-{
- LPWSTR wpath;
- BOOL b;
-
- wpath = wce_mbtowc(path);
- b = DeleteFileW(wpath);
- free(wpath);
- return 0;
-}
-
-/* --------------- EnvironmentVariable functions. ----------------- */
-DWORD GetEnvironmentVariable(
- LPCSTR name, LPSTR value, DWORD size)
-{
- /* use registry instead of "environment valuable". */
- HKEY hk;
- LONG lret;
- LPBYTE lpData;
- DWORD dwType=REG_SZ, cbData;
- TCHAR buf[MAX_PATH]={0};
- LPWSTR wname;
- LPSTR avalue;
-
- lret = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
- _T("Software\\ruby_mswince"),
- 0, KEY_QUERY_VALUE, &hk );
-
- if ( lret != ERROR_SUCCESS )
- {
- strcpy( value, "" );
- return 0;
- }
-
- lpData = (LPBYTE)buf;
- cbData = MAX_PATH*sizeof(*buf);
- wname = wce_mbtowc( name );
-
- lret = RegQueryValueEx( hk, wname,
- NULL, &dwType, lpData, &cbData );
- RegCloseKey( hk );
-
- if ( lret != ERROR_SUCCESS )
- {
- strcpy( value, "" );
- free( wname );
- return 0;
- }
-
- avalue = wce_wctomb( (LPCTSTR)lpData );
- strcpy( value, avalue );
- free( avalue );
- free( wname );
-
- return strlen(value);
-}
-
-BOOL SetEnvironmentVariable(LPCSTR name, LPCSTR value)
-{
- /* use registry instead of "environment valuable". */
- HKEY hk;
- LONG lret;
- LPBYTE lpData;
- DWORD ret, dwType=REG_SZ, cbData;
- LPWSTR wname, wvalue;
-
- lret = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
- _T("Software\\ruby_mswince"),
- 0, _T(""), 0,
- 0, NULL, &hk, &ret );
- if( lret != ERROR_SUCCESS )
- return FALSE;
-
- wname = wce_mbtowc(name);
- wvalue = wce_mbtowc(value);
-
- lpData = (LPBYTE)wvalue;
- cbData = (wcslen(wvalue) + 1) * sizeof(*wvalue);
- lret = RegSetValueEx( hk, wname,
- 0, dwType, lpData, cbData );
- RegCloseKey( hk );
- free(wname);
- free(wvalue);
- return lret == ERROR_SUCCESS;
-}
-
-LPVOID GetEnvironmentStrings(VOID)
-{
- return NULL;
-}
-
-BOOL FreeEnvironmentStrings(LPSTR lpszEnvironmentBlock)
-{
- return FALSE;
-}
-
-/* DuplicateHandle, LockFile, etc... */
-/* I have no idea... */
-BOOL GenerateConsoleCtrlEvent(DWORD dwCtrlEvent,
- DWORD dwProcessGroupID)
-{
- return 0;
-}
-
-BOOL DuplicateHandle(
- HANDLE source_process, HANDLE source,
- HANDLE dest_process, HANDLE *dest,
- DWORD access, BOOL inherit, DWORD options)
-{
- return 0;
-}
-
-BOOL LockFile(HANDLE hFile,
- DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
- DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh)
-{
- return FALSE;
-}
-
-BOOL LockFileEx(HANDLE hFile,
- DWORD dwFlags, DWORD dwReserved,
- DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh,
- LPOVERLAPPED lpOverlapped)
-{
- return FALSE;
-}
-
-BOOL UnlockFile( HFILE hFile,
- DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
- DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh)
-{
- return FALSE;
-}
-
-BOOL UnlockFileEx(HANDLE hFile,
- DWORD dwReserved, DWORD nNumberOfBytesToUnlockLow,
- DWORD nNumberOfBytesToUnlockHigh, LPOVERLAPPED lpOverlapped)
-{
- return FALSE;
-}
-
-/* --------------------- etc, etc, etc... ----------------------- */
-BOOL GetVersionExA(OSVERSIONINFOA *v)
-{
- OSVERSIONINFOW wv;
- BOOL b;
- LPSTR mb;
-
- b = GetVersionExW(&wv);
- mb = wce_wctomb(wv.szCSDVersion);
-
- strcpy( v->szCSDVersion, mb );
- free(mb);
- return b;
-}
-
-DWORD WaitForMultipleObjectsEx(DWORD count,
- const HANDLE *handles, BOOL wait_all,
- DWORD timeout, BOOL alertable)
-{
- return WaitForMultipleObjects(
- count, handles, wait_all,
- timeout );
-}
-
-BOOL CreateProcessA(LPCSTR appname, LPCSTR commandline,
- LPSECURITY_ATTRIBUTES att, LPSECURITY_ATTRIBUTES threadatt,
- BOOL bOpt, DWORD dwFlag, LPVOID lpEnv, LPSTR dir,
- LPSTARTUPINFO lpsi, LPPROCESS_INFORMATION lppi)
-{
- LPWSTR wappname, wcommandline, wdir;
- BOOL b;
-
- wappname = wce_mbtowc(appname);
- wcommandline = wce_mbtowc(commandline);
- wdir = wce_mbtowc(dir);
-
- b = CreateProcessW(wappname, wcommandline,
- att, threadatt, bOpt, dwFlag, lpEnv,
- wdir, lpsi, lppi);
-
- free(wappname);
- free(wcommandline);
- free(wdir);
-
- return b;
-}
-
-HANDLE CreateEventA(SECURITY_ATTRIBUTES *sa,
- BOOL manual_reset, BOOL initial_state, LPCSTR name)
-{
- HANDLE h;
- LPWSTR wname;
-
- wname = wce_mbtowc(name);
- h = CreateEventW(sa, manual_reset,
- initial_state, wname);
- free(wname);
-
- return h;
-}
-
-DWORD FormatMessageA(DWORD dwFlags, LPCVOID lpSource,
- DWORD dwMessageId, DWORD dwLanguageId, LPSTR lpBuffer,
- DWORD nSize, va_list* args)
-{
- DWORD dw;
- LPWSTR lpWBuffer;
-
- lpWBuffer = wce_mbtowc(lpBuffer);
- dw = FormatMessageW( dwFlags, lpSource,
- dwMessageId, dwLanguageId,
- lpWBuffer, nSize, (va_list*)args );
- free(lpWBuffer);
- return dw;
-}
-
-/*---------------- FindFirstFile, FindNextFile ------------------ */
-HANDLE FindFirstFileA(LPCSTR path,
- WIN32_FIND_DATAA *data)
-{
- LPWSTR wpath;
- LPSTR mb;
- HANDLE h;
- WIN32_FIND_DATAW wdata;
-
- wpath = wce_mbtowc(path);
- h = FindFirstFileW( wpath, &wdata );
- free(wpath);
-
- mb = wce_wctomb( wdata.cFileName );
- strcpy( data->cFileName, mb );
- free(mb);
-
- return h;
-}
-
-BOOL FindNextFileA(HANDLE handle,
- WIN32_FIND_DATAA *data)
-{
- BOOL b;
- WIN32_FIND_DATAW wdata;
- LPSTR mb1;
-
- b = FindNextFileW(handle, &wdata);
-
- mb1 = wce_wctomb( wdata.cFileName );
- strcpy( data->cFileName, mb1 );
- free(mb1);
-
- return b;
-}
-
-/* CreateFile doesn't support SECURITY_ATTRIBUTES in WinCE. */
-/* it must be NULL. */
-HANDLE CreateFileA(LPCSTR filename, DWORD access,
- DWORD sharing, LPSECURITY_ATTRIBUTES sa,
- DWORD creation, DWORD attributes, HANDLE template)
-{
- LPWSTR wfilename;
- HANDLE h;
-
- wfilename = wce_mbtowc(filename);
- h = CreateFileW(wfilename, access, sharing,
- NULL, creation, 0, NULL);
- free(wfilename);
-
- return 0;
-}
-
-/* ---------------- CharNext, CharPrev. ---------------------*/
-LPSTR CharNextA(LPCSTR a)
-{
- char *p=(char *)a;
- if( TRUE==IsDBCSLeadByteEx(CP_ACP, (BYTE)*a) )
- p+=2;
- else
- p++;
-
- return p;
-}
-
-LPSTR CharPrevA(LPCSTR start, LPCSTR ptr)
-{
- if( start==ptr ) return (LPSTR)start;
- else if( start+1==ptr ) return (LPSTR)start;
- else if( TRUE==IsDBCSLeadByteEx(CP_ACP, (BYTE)*(ptr-2)) )
- return (LPSTR)(ptr-2);
- else
- return (LPSTR)(ptr-1);
-}
-
-/* WinCE doesn't have "drives". */
-DWORD GetLogicalDrives(VOID)
-{
- return 0;
-}
-
-/* WinCE doesn't have "user name". */
-BOOL GetUserName(LPSTR lpBuffer, LPDWORD nSize)
-{
- return 0;
-}
-
-/*------------------- LoadLibrary -----------------------*/
-HINSTANCE LoadLibraryA(LPCSTR libname)
-{
- HINSTANCE h;
- LPWSTR wlibname;
-
- // if starts ".\", replace current directory.
-// wlibname = wce_replaceRelativeDir(libname);
-
- wlibname = wce_mbtowc(libname);
- h = LoadLibraryW(wlibname);
- free(wlibname);
- return h;
-}
-
-HINSTANCE LoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile,
- DWORD dwFlags)
-{
- HINSTANCE h;
- LPWSTR wlibname;
-
- wlibname = wce_mbtowc(lpLibFileName);
-// wlibname = wce_replaceRelativeDir(lpLibFileName);
-
-#if _WIN32_WCE < 300
- h = LoadLibraryW(wlibname);
-#else
- h = LoadLibraryExW(wlibname, hFile, dwFlags);
-#endif
- free(wlibname);
- return h;
-}
-
-/* WinCE doesn't have "CreatePipe". */
-BOOL CreatePipe(PHANDLE hReadPipe, PHANDLE hWritePipe,
- LPSECURITY_ATTRIBUTES lpPipeAttributes, DWORD nSize)
-{
- return FALSE;
-}
-
-/* WinCE doesn't have "Standard Devices". */
-HANDLE GetStdHandle(DWORD nStdHandle)
-{
- return NULL;
-}
-
-BOOL SetStdHandle(DWORD nStdHandle, HANDLE h)
-{
- return FALSE;
-}
-
-#if _WIN32_WCE < 300
-VOID ZeroMemory(PVOID p, DWORD length)
-{
- memset(p,0,length);
-}
-#endif
-
-
-/* need in ruby/io.c. */
-int ReadDataPending()
-{
- return 0;
-}
-
-/*---------------- helper functions. ---------------------------- */
-FILE *wce_fopen( const char *fname, const char *mode )
-{
- TCHAR* tfname = wce_replaceRelativeDir(fname);
- TCHAR* tmode = wce_mbtowc(mode);
- FILE* fp = _tfopen(tfname, tmode);
- free(tfname); free(tmode);
- return fp;
-}
-
-void wce_SetCurrentDir()
-{
- WCHAR tbuf[MAX_PATH+1]={0};
- WCHAR *tp;
- char *buf;
-
- GetModuleFileNameW( NULL, tbuf, MAX_PATH );
- tp = _tcsrchr( tbuf, '\\' );
- if( tp!=NULL ) *tp=_T('\0');
- buf = wce_wctomb(tbuf);
- strcpy( _currentdir, buf );
- free(buf);
-}
-
-TCHAR *wce_replaceRelativeDir(const char* str)
-{
- TCHAR *tbuf;
-
- if( 2<=strlen(str) && str[0]=='.' &&
- (str[1]=='/' || str[1]=='\\') )
- {
- char *buf;
- int len = strlen(str) + strlen(_currentdir);
- buf = malloc( len+1 );
- sprintf(buf, "%s%s", _currentdir, &str[1]);
- tbuf = wce_mbtowc(buf);
- free(buf);
- }
- else
- tbuf = wce_mbtowc(str);
- return tbuf;
-}
-
-/* char -> wchar_t */
-wchar_t* wce_mbtowc(const char* a)
-{
- int length;
- wchar_t *wbuf;
-
- length = MultiByteToWideChar(CP_ACP, 0,
- a, -1, NULL, 0);
- wbuf = (wchar_t*)malloc( (length+1)*sizeof(wchar_t) );
- MultiByteToWideChar(CP_ACP, 0,
- a, -1, wbuf, length);
-
- return wbuf;
-}
-
-/* wchar_t -> char */
-char* wce_wctomb(const wchar_t* w)
-{
- DWORD charlength;
- char* pChar;
-
- charlength = WideCharToMultiByte(CP_ACP, 0, w,
- -1, NULL, 0, NULL, NULL);
- pChar = (char*)malloc(charlength+1);
- WideCharToMultiByte(CP_ACP, 0, w,
- -1, pChar, charlength, NULL, NULL);
-
- return pChar;
-}
diff --git a/wince/wince.h b/wince/wince.h
deleted file mode 100644
index 7a562f702a..0000000000
--- a/wince/wince.h
+++ /dev/null
@@ -1,191 +0,0 @@
-
-#ifndef _EXT_CE_
-#define _EXT_CE_
-
-/* unique difinition in wince platform. */
-
-#ifndef _MIPS_
- #define CONTEXT_FLOATING_POINT 0x00000002L
-#endif
-
-/* LockFile difinition. */
-#define LOCKFILE_FAIL_IMMEDIATELY 0x00000001
-#define LOCKFILE_EXCLUSIVE_LOCK 0x00000002
-
-/* Dual Mode difinition. */
-#define STARTF_USESHOWWINDOW 0x00000001
-#define STARTF_USESIZE 0x00000002
-#define STARTF_USEPOSITION 0x00000004
-#define STARTF_USECOUNTCHARS 0x00000008
-#define STARTF_USEFILLATTRIBUTE 0x00000010
-#define STARTF_RUNFULLSCREEN 0x00000020
-#define STARTF_FORCEONFEEDBACK 0x00000040
-#define STARTF_FORCEOFFFEEDBACK 0x00000080
-#define STARTF_USESTDHANDLES 0x00000100
-/* #define STARTF_USEHOTKEY 0x00000200 */
-
-#define STD_INPUT_HANDLE (DWORD)-10
-#define STD_OUTPUT_HANDLE (DWORD)-11
-#define STD_ERROR_HANDLE (DWORD)-12
-
-#define NORMAL_PRIORITY_CLASS 0x00000020
-#define IDLE_PRIORITY_CLASS 0x00000040
-#define HIGH_PRIORITY_CLASS 0x00000080
-#define REALTIME_PRIORITY_CLASS 0x00000100
-
-
-/* WINSOCK.H? */
-#define SO_SYNCHRONOUS_NONALERT 0x20
-
-/* MoveFileEx definition. */
-#define MOVEFILE_REPLACE_EXISTING 0x00000001
-/*
-#define MOVEFILE_COPY_ALLOWED 0x00000002
-#define MOVEFILE_DELAY_UNTIL_REBOOT 0x00000004
-#define MOVEFILE_WRITE_THROUGH 0x00000008
-#define MOVEFILE_CREATE_HARDLINK 0x00000010
-#define MOVEFILE_FAIL_IF_NOT_TRACKABLE 0x00000020
-*/
-
-#define _fgetc fgetc
-#define _fputc fputc
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Win32 API redifinition. */
-
-#undef GetCommandLine
-#define GetCommandLine GetCommandLineA
-
-#undef SetFileAttributes
-#define SetFileAttributes SetFileAttributesA
-
-#undef GetFileAttributes
-#define GetFileAttributes GetFileAttributesA
-
-#undef FormatMessage
-#define FormatMessage FormatMessageA
-
-#undef GetModuleFileName
-#define GetModuleFileName GetModuleFileNameA
-
-#undef CreateFile
-#define CreateFile CreateFileA
-
-#undef MoveFile
-#define MoveFile MoveFileA
-
-#undef DeleteFile
-#define DeleteFile DeleteFileA
-
-#undef CreateProcess
-#define CreateProcess CreateProcessA
-
-#undef CharNext
-#define CharNext CharNextA
-
-#undef CharPrev
-#define CharPrev CharPrevA
-
-#undef WIN32_FIND_DATA
-#define WIN32_FIND_DATA WIN32_FIND_DATAA
-
-#undef FindFirstFile
-#define FindFirstFile FindFirstFileA
-
-#undef FindNextFile
-#define FindNextFile FindNextFileA
-
-/* stdio.c */
-FILE *freopen(const char *filename, const char *mode, FILE *file);
-FILE *fdopen( int handle, const char *mode );
-
-//#define fdopen _fdopen
-
-/* stdlib.c */
-char *getenv(const char *charstuff);
-char *_fullpath(char *absPath, const char *relPath, size_t maxLength);
-
-/* string.c */
-char *strdup(const char * str);
-/* char *strerror(int errno); */
-int strnicmp( const char *s1, const char *s2, size_t count );
-
-//#define strnicmp _strnicmp
-#define stricmp _stricmp
-
-/* for win32.c */
-FARPROC GetProcAddressX(HMODULE hModule, LPCSTR lpProcName);
-
-BOOL MoveFileEx(LPCSTR oldname, LPCSTR newname, DWORD dwFlags);
-BOOL DuplicateHandle(
- HANDLE source_process, HANDLE source,
- HANDLE dest_process, HANDLE *dest,
- DWORD access, BOOL inherit, DWORD options);
-BOOL LockFile(HANDLE hFile,
- DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
- DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh);
-BOOL LockFileEx(HANDLE hFile,
- DWORD dwFlags, DWORD dwReserved,
- DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh,
- LPOVERLAPPED lpOverlapped);
-BOOL UnlockFile( HFILE hFile,
- DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
- DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh);
-BOOL UnlockFileEx(HANDLE hFile,
- DWORD dwReserved, DWORD nNumberOfBytesToUnlockLow,
- DWORD nNumberOfBytesToUnlockHigh, LPOVERLAPPED lpOverlapped);
-BOOL GetUserName(LPSTR lpBuffer, LPDWORD nSize);
-BOOL CreatePipe(PHANDLE hReadPipe, PHANDLE hWritePipe,
- LPSECURITY_ATTRIBUTES lpPipeAttributes, DWORD nSize);
-HANDLE GetStdHandle(DWORD nStdHandle);
-BOOL SetStdHandle(DWORD nStdHandle, HANDLE h);
-DWORD GetLogicalDrives(VOID);
-DWORD WaitForMultipleObjectsEx(DWORD count,
- const HANDLE *handles, BOOL wait_all,
- DWORD timeout, BOOL alertable);
-DWORD GetEnvironmentVariable(LPCSTR name, LPSTR value, DWORD size);
-LPVOID GetEnvironmentStrings(VOID);
-BOOL FreeEnvironmentStrings(LPSTR lpszEnvironmentBlock);
-BOOL GenerateConsoleCtrlEvent(DWORD dwCtrlEvent,
- DWORD dwProcessGroupID);
-BOOL GetProcessTimes(HANDLE hprocess,
- LPFILETIME lpCreationTime, LPFILETIME lpExitTime,
- LPFILETIME lpKernelTime, LPFILETIME lpUserTime);
-
-/* char -> wchar_t, wchar_t -> char */
-wchar_t* wce_mbtowc(const char* a);
-char* wce_wctomb(const wchar_t* w);
-/* other helpers. */
-void wce_SetCommandLine(LPCWSTR wcmd);
-void wce_FreeCommandLine(void);
-TCHAR *wce_replaceRelativeDir(const char* str);
-void wce_SetCurrentDir();
-
-#if _WIN32_WCE < 300
- /* for Handheld PC Pro. */
- char *strrchr( const char *p, int c );
- int stricmp( const char *p1, const char *p2 );
- VOID ZeroMemory(PVOID p, DWORD length);
-
- #define isascii(c) ( (c>=0x00&&c<=0x7f)?1:0 )
- #define isspace(c) ( ((c>=0x09&&c<=0x0d)||c==0x20)?1:0 )
- #define isdigit(c) ( (c>=0x00&&c<=0x09)?1:0 )
- #define isupper(c) ( (c>='A'&&c<='Z')?1:0 )
- #define isalpha(c) ( ((c>='A'&&c<='Z')||(c>='a'&&c<='z'))?1:0 )
- #define isprint(c) ( (c>=0x20&&c<=0x7e)?1:0 )
- #define isalnum(c) ( (isalpha(c)||isdigit(c))?1:0 )
- #define iscntrl(c) ( ((c>=0x00&&c<=0x1f)||c==0x7f)?1:0 )
- #define islower(c) ( (c>='a'&&c<='z')?1:0 )
- #define ispunct(c) ( !(isalnum(c)||isspace(c))?1:0 )
- #define isxdigit(c) ( ((c>=0&&c<=9)||(c>='A'&&c<='F')||(c>='a'&&c<='f'))?1:0 )
-#endif
-
-#ifdef __cplusplus
-};
-#endif
-
-
-#endif /* _EXT_CE_ */
diff --git a/wince/wincemain.c b/wince/wincemain.c
deleted file mode 100644
index 5122b57d02..0000000000
--- a/wince/wincemain.c
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <windows.h>
-#include <stdio.h>
-#include "wince.h"
-
-extern int main(int, char**);
-
-
-int WINAPI
-WinMain(HINSTANCE current, HINSTANCE prev, LPWSTR wcmd, int showcmd)
-{
- /* wchar_t -> char */
- wce_SetCommandLine(wcmd);
-
- wce_SetCurrentDir();
-
- /* main. */
- return main(0, NULL);
-}
diff --git a/wince/wincon.h b/wince/wincon.h
deleted file mode 100644
index ea50c6ebc6..0000000000
--- a/wince/wincon.h
+++ /dev/null
@@ -1,7 +0,0 @@
-
-#ifndef _WINCON_H_
-#define _WINCON_H_
-
-#define CTRL_C_EVENT 0
-
-#endif
diff --git a/wince/winsock2.c b/wince/winsock2.c
deleted file mode 100644
index 9b2a5be600..0000000000
--- a/wince/winsock2.c
+++ /dev/null
@@ -1,338 +0,0 @@
-/***************************************************************
- winsock2.c
-***************************************************************/
-
-//#define _WINSOCK2_C_DEBUG_MAIN_
-
-#include <windows.h>
-#include "wince.h"
-#ifdef _WINSOCK2_C_DEBUG_MAIN_
- #include <winsock.h>
-#endif
-
-#ifndef _WINSOCK2_C_DEBUG_MAIN_
-struct servent{
- char* s_name; /* official service name */
- char** s_aliases; /* alias list */
- short s_port; /* port # */
- char* s_proto; /* protocol to use */
-};
-struct protoent{
- char* p_name; /* official protocol name */
- char** p_aliases; /* alias list */
- short p_proto; /* protocol # */
-};
-#endif
-
-struct sproto{
- short num;
- char name[10];
-};
-struct sserv{
- short num;
- char protoname[10];
- char servname[20];
-};
-
-static struct sproto _proto_table[11]={
- 0, "ip",
- 1, "icmp",
- 3, "ggp",
- 6, "tcp",
- 8, "egp",
- 12, "pup",
- 17, "udp",
- 20, "hmp",
- 22, "xns-idp",
- 27, "rdp",
- 66, "rvd",
-};
-
-static struct sserv _serv_table[142]={
- 7, "tcp", "echo",
- 7, "udp", "echo",
- 9, "tcp", "discard",
- 9, "udp", "discard",
- 11, "tcp", "systat",
- 11, "udp", "systat",
- 13, "tcp", "daytime",
- 13, "udp", "daytime",
- 15, "tcp", "netstat",
- 17, "tcp", "qotd",
- 17, "udp", "qotd",
- 19, "tcp", "chargen",
- 19, "udp", "chargen",
- 20, "tcp", "ftp-data",
- 21, "tcp", "ftp",
- 23, "tcp", "telnet",
- 25, "tcp", "smtp",
- 37, "tcp", "time",
- 37, "udp", "time",
- 39, "udp", "rlp",
- 42, "tcp", "name",
- 42, "udp", "name",
- 43, "tcp", "whois",
- 53, "tcp", "domain",
- 53, "udp", "domain",
- 53, "tcp", "nameserver",
- 53, "udp", "nameserver",
- 57, "tcp", "mtp",
- 67, "udp", "bootp",
- 69, "udp", "tftp",
- 77, "tcp", "rje",
- 79, "tcp", "finger",
- 87, "tcp", "link",
- 95, "tcp", "supdup",
- 101, "tcp", "hostnames",
- 102, "tcp", "iso-tsap",
- 103, "tcp", "dictionary",
- 103, "tcp", "x400",
- 104, "tcp", "x400-snd",
- 105, "tcp", "csnet-ns",
- 109, "tcp", "pop",
- 109, "tcp", "pop2",
- 110, "tcp", "pop3",
- 111, "tcp", "portmap",
- 111, "udp", "portmap",
- 111, "tcp", "sunrpc",
- 111, "udp", "sunrpc",
- 113, "tcp", "auth",
- 115, "tcp", "sftp",
- 117, "tcp", "path",
- 117, "tcp", "uucp-path",
- 119, "tcp", "nntp",
- 123, "udp", "ntp",
- 137, "udp", "nbname",
- 138, "udp", "nbdatagram",
- 139, "tcp", "nbsession",
- 144, "tcp", "NeWS",
- 153, "tcp", "sgmp",
- 158, "tcp", "tcprepo",
- 161, "tcp", "snmp",
- 162, "tcp", "snmp-trap",
- 170, "tcp", "print-srv",
- 175, "tcp", "vmnet",
- 315, "udp", "load",
- 400, "tcp", "vmnet0",
- 500, "udp", "sytek",
- 512, "udp", "biff",
- 512, "tcp", "exec",
- 513, "tcp", "login",
- 513, "udp", "who",
- 514, "tcp", "shell",
- 514, "udp", "syslog",
- 515, "tcp", "printer",
- 517, "udp", "talk",
- 518, "udp", "ntalk",
- 520, "tcp", "efs",
- 520, "udp", "route",
- 525, "udp", "timed",
- 526, "tcp", "tempo",
- 530, "tcp", "courier",
- 531, "tcp", "conference",
- 531, "udp", "rvd-control",
- 532, "tcp", "netnews",
- 533, "udp", "netwall",
- 540, "tcp", "uucp",
- 543, "tcp", "klogin",
- 544, "tcp", "kshell",
- 550, "udp", "new-rwho",
- 556, "tcp", "remotefs",
- 560, "udp", "rmonitor",
- 561, "udp", "monitor",
- 600, "tcp", "garcon",
- 601, "tcp", "maitrd",
- 602, "tcp", "busboy",
- 700, "udp", "acctmaster",
- 701, "udp", "acctslave",
- 702, "udp", "acct",
- 703, "udp", "acctlogin",
- 704, "udp", "acctprinter",
- 704, "udp", "elcsd",
- 705, "udp", "acctinfo",
- 706, "udp", "acctslave2",
- 707, "udp", "acctdisk",
- 750, "tcp", "kerberos",
- 750, "udp", "kerberos",
- 751, "tcp", "kerberos_master",
- 751, "udp", "kerberos_master",
- 752, "udp", "passwd_server",
- 753, "udp", "userreg_server",
- 754, "tcp", "krb_prop",
- 888, "tcp", "erlogin",
- 1109, "tcp", "kpop",
- 1167, "udp", "phone",
- 1524, "tcp", "ingreslock",
- 1666, "udp", "maze",
- 2049, "udp", "nfs",
- 2053, "tcp", "knetd",
- 2105, "tcp", "eklogin",
- 5555, "tcp", "rmt",
- 5556, "tcp", "mtb",
- 9535, "tcp", "man",
- 9536, "tcp", "w",
- 9537, "tcp", "mantst",
- 10000, "tcp", "bnews",
- 10000, "udp", "rscs0",
- 10001, "tcp", "queue",
- 10001, "udp", "rscs1",
- 10002, "tcp", "poker",
- 10002, "udp", "rscs2",
- 10003, "tcp", "gateway",
- 10003, "udp", "rscs3",
- 10004, "tcp", "remp",
- 10004, "udp", "rscs4",
- 10005, "udp", "rscs5",
- 10006, "udp", "rscs6",
- 10007, "udp", "rscs7",
- 10008, "udp", "rscs8",
- 10009, "udp", "rscs9",
- 10010, "udp", "rscsa",
- 10011, "udp", "rscsb",
- 10012, "tcp", "qmaster",
- 10012, "udp", "qmaster",
-};
-
-/* WinCE doesn't have /etc/protocols. */
-struct protoent* getprotobyname(const char* name)
-{
- static struct protoent pe;
- int i;
- int len = strlen(name);
-
- memset( &pe, 0, sizeof(struct protoent) );
-
- for(i=0; i<9; i++)
- {
- if( 0==strnicmp(_proto_table[i].name, name, len) )
- {
- pe.p_name = _proto_table[i].name;
- pe.p_proto= _proto_table[i].num;
- break;
- }
- }
-
- return &pe;
-}
-
-struct protoent* getprotobynumber(int proto)
-{
- static struct protoent pe={0};
- int i;
-
- memset( &pe, 0, sizeof(struct protoent) );
-
- for(i=0; i<9; i++)
- {
- if( proto == _proto_table[i].num )
- {
- pe.p_name = _proto_table[i].name;
- pe.p_proto= _proto_table[i].num;
- break;
- }
- }
-
- return &pe;
-}
-
-/* WinCE doesn't have /etc/services. */
-struct servent* getservbyname(const char* name,
- const char* proto)
-{
- static struct servent se;
- int i;
- int slen = strlen(name), plen = strlen(proto);
-
- memset( &se, 0, sizeof(struct servent) );
-
- if( proto==NULL ) return NULL;
- if( 0!=strnicmp( proto, "tcp", 3 ) &&
- 0!=strnicmp( proto, "udp", 3 ) )
- return NULL;
-
- for( i=0; i<142; i++ )
- {
- if( 0==strnicmp( name, _serv_table[i].servname, slen ) &&
- 0==strnicmp( proto, _serv_table[i].protoname, plen ) )
- {
- char hc, lc;
- se.s_name = _serv_table[i].servname;
- se.s_proto= _serv_table[i].protoname;
- hc = (_serv_table[i].num&0xFF00)>>8;
- lc = _serv_table[i].num&0xFF;
- se.s_port = (lc<<8) + hc;
- break;
- }
- }
-
- return &se;
-}
-
-struct servent* getservbyport(int port, const char* proto)
-{
- static struct servent se;
- int i;
- int plen = strlen(proto);
- short sport;
- char lc, hc;
-
- hc = (port&0xFF00)>>8;
- lc = port&0xFF;
-
- sport = (lc<<8) + hc;
-
- memset( &se, 0, sizeof(struct servent) );
-
- if( proto==NULL ) return NULL;
- if( 0!=strnicmp( proto, "tcp", 3 ) &&
- 0!=strnicmp( proto, "udp", 3 ) )
- return NULL;
-
- for( i=0; i<142; i++ )
- {
- if( sport == _serv_table[i].num &&
- 0==strnicmp( proto, _serv_table[i].protoname, plen ) )
- {
- se.s_name = _serv_table[i].servname;
- se.s_proto= _serv_table[i].protoname;
- se.s_port = port;
- break;
- }
- }
-
- return &se;
-}
-
-
-#ifdef _WINSOCK2_C_DEBUG_MAIN_
-
-int main()
-{
- WORD wVersionRequested = MAKEWORD(1,1);
- WSADATA wsaData;
- int nErrorStatus;
- struct protoent pe1, pe2;
- struct servent se1, se2;
-
- nErrorStatus = WSAStartup(wVersionRequested, &wsaData);
- if(nErrorStatus != 0)
- return -1;
-
- pe1 = *getprotobyname("UDP");
- pe2 = *_getprotobyname("UDP");
-
-// pe1 = *getprotobynumber(17);
-// pe2 = *_getprotobynumber(17);
-
-// se1 = *getservbyname("gateway", "tcp");
-// se2 = *_getservbyname("gateway", "tcp");
-
- se1 = *getservbyport(0x1327, "tcp");
- se2 = *_getservbyport(0x1327, "tcp");
-
- WSACleanup();
-
- return 0;
-}
-
-#endif
diff --git a/x68/_dtos18.c b/x68/_dtos18.c
deleted file mode 100644
index 4712a66bf7..0000000000
--- a/x68/_dtos18.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * PROJECT C Library, X68000 PROGRAMMING INTERFACE DEFINITION
- * --------------------------------------------------------------------
- * This file is written by the Project C Library Group, and completely
- * in public domain. You can freely use, copy, modify, and redistribute
- * the whole contents, without this notice.
- * --------------------------------------------------------------------
- * $Id$
- */
-
-/* System headers */
-#include <stdlib.h>
-#include <sys/xstdlib.h>
-
-/*
-** 本関数は浮動小数点を倍精度整数に変換してから文字列にするため、精度的には
-** 倍精度整数に格納できる桁数までしか扱うことができない。したがって最高精度
-** は18桁である。
-*/
-
-/* File scope variables */
-static double _pos1[32] = {
- 1.0e+17, /* + 0 */
- 1.0e+18, /* + 1 */
- 1.0e+19, /* + 2 */
- 1.0e+20, /* + 3 */
- 1.0e+21, /* + 4 */
- 1.0e+22, /* + 5 */
- 1.0e+23, /* + 6 */
- 1.0e+24, /* + 7 */
- 1.0e+25, /* + 8 */
- 1.0e+26, /* + 9 */
- 1.0e+27, /* +10 */
- 1.0e+28, /* +11 */
- 1.0e+29, /* +12 */
- 1.0e+30, /* +13 */
- 1.0e+31, /* +14 */
- 1.0e+32, /* +15 */
- 1.0e+33, /* +16 */
- 1.0e+34, /* +17 */
- 1.0e+35, /* +18 */
- 1.0e+36, /* +19 */
- 1.0e+37, /* +20 */
- 1.0e+38, /* +21 */
- 1.0e+39, /* +22 */
- 1.0e+40, /* +23 */
- 1.0e+41, /* +24 */
- 1.0e+42, /* +25 */
- 1.0e+43, /* +26 */
- 1.0e+44, /* +27 */
- 1.0e+45, /* +28 */
- 1.0e+46, /* +29 */
- 1.0e+47, /* +30 */
- 1.0e+48, /* +31 */
-};
-
-/* File scope variables */
-static double _neg1[32] = {
- 1.0e+17, /* - 0 */
- 1.0e+16, /* - 1 */
- 1.0e+15, /* - 2 */
- 1.0e+14, /* - 3 */
- 1.0e+13, /* - 4 */
- 1.0e+12, /* - 5 */
- 1.0e+11, /* - 6 */
- 1.0e+10, /* - 7 */
- 1.0e+9, /* - 8 */
- 1.0e+8, /* - 9 */
- 1.0e+7, /* -10 */
- 1.0e+6, /* -11 */
- 1.0e+5, /* -12 */
- 1.0e+4, /* -13 */
- 1.0e+3, /* -14 */
- 1.0e+2, /* -15 */
- 1.0e+1, /* -16 */
- 1.0e+0, /* -17 */
- 1.0e-1, /* -18 */
- 1.0e-2, /* -19 */
- 1.0e-3, /* -20 */
- 1.0e-4, /* -21 */
- 1.0e-5, /* -22 */
- 1.0e-6, /* -23 */
- 1.0e-7, /* -24 */
- 1.0e-8, /* -25 */
- 1.0e-9, /* -26 */
- 1.0e-10, /* -27 */
- 1.0e-11, /* -28 */
- 1.0e-12, /* -29 */
- 1.0e-13, /* -30 */
- 1.0e-14, /* -31 */
-};
-
-/* File scope variables */
-static double _pos2[10] = {
- 1.0e+0, /* 000 */
- 1.0e+32, /* 001 */
- 1.0e+64, /* 010 */
- 1.0e+96, /* 011 */
- 1.0e+128, /* 100 */
- 1.0e+160, /* 101 */
- 1.0e+192, /* 110 */
- 1.0e+224, /* 111 */
- 1.0e+256, /* 1000 */
- 1.0e+288, /* 1001 */
-};
-
-/* File scope variables */
-static double _neg2[10] = {
- 1.0e-0, /* 000 */
- 1.0e-32, /* 001 */
- 1.0e-64, /* 010 */
- 1.0e-96, /* 011 */
- 1.0e-128, /* 100 */
- 1.0e-160, /* 101 */
- 1.0e-192, /* 110 */
- 1.0e-224, /* 111 */
- 1.0e-256, /* 1000 */
- 1.0e-288, /* 1001 */
-};
-
-/* File scope functions */
-static int _cmpd (double x, double y)
-{
- unsigned long vx, vy, rc;
- unsigned long *x_ptr = (unsigned long *) &x;
- unsigned long *y_ptr = (unsigned long *) &y;
-
- /* xの指数ビットを取り出す */
- vx = x_ptr[0] & 0x7FF00000;
-
- /* yの指数ビットを取り出す */
- vy = y_ptr[0] & 0x7FF00000;
-
- /* 指数ビットだけで判断する */
- if ((rc = vy - vx) != 0)
- return rc;
-
- /* xの有効数字の上位ビットを取り出す */
- vx = x_ptr[0] & 0x000FFFFF;
-
- /* yの有効数字の上位ビットを取り出す */
- vy = y_ptr[0] & 0x000FFFFF;
-
- /* 上位ビットだけで判断する */
- if ((rc = vy - vx) != 0)
- return rc;
-
- /* xの有効数字の下位ビットを取り出す */
- vx = x_ptr[1];
-
- /* yの有効数字の下位ビットを取り出す */
- vy = y_ptr[1];
-
- /* 最終判断 */
- return vy - vx;
-}
-
-/* Functions */
-void _dtos18 (double x, int *decpt, int *sign, char *buffer)
-{
- short e2;
- int e, n;
-
- /* 基数2の指数を求める(バイアスなしの状態) */
- e2 = (((unsigned short *) &x)[0] & 0x7FF0U) >> 4;
-
- /* 指数が0の場合は±0.0チェック */
- if (e2 == 0) {
-
- unsigned long hi = ((unsigned long *) &x)[0] & 0xFFFFF;
- unsigned long lo = ((unsigned long *) &x)[1];
-
- /* 有効数字が全部0かどうか */
- if (hi == 0 && lo == 0) {
-
- /* 文字列を設定 */
- buffer[0] = '0';
-
- /* NULを設定 */
- buffer[1] = '\0';
-
- /* 小数点位置を計算 */
- *decpt = 1;
-
- /* 符号を計算 */
- /* *sign = hi & 0x80000000UL; */
- *sign = 0;
-
- /* 確定 */
- return;
-
- }
-
- }
-
- /* 2の指数にバイアスをかけてから10の指数を概算 (approx. log10(2)) */
- e = ((int) ((e2 - 1023) * 77)) >> 8;
-
- /* 指数が正の場合 */
- if (e >= 0) {
-
- /* 指数が32より小さい場合はテーブル1から */
- if (e < 32)
- x *= _neg1[e];
-
- /* 指数が32より大きい場合はテーブル1,2から */
- else
- x *= _neg1[e & 31] * _neg2[e >> 5];
-
- }
-
- /* 指数が負の場合 */
- else {
-
- /* 絶対値を計算 */
- n = -e;
-
- /* 絶対値が32より小さい場合はテーブル1から */
- if (n < 32)
- x *= _pos1[n];
-
- /* 絶対値が32より大きい場合はテーブル1,2から */
- else {
- x *= _pos1[n & 31];
- x *= _pos2[n >> 5];
- }
-
- }
-
- /* スケーリングしすぎた場合は戻す */
- if (_cmpd (1.0e+18, x) >= 0) {
- e++;
- x *= 1.0e-1;
- }
-
- /* スケーリングし足りない場合は追加 */
- else if (_cmpd (1.0e+17, x) < 0) {
- e--;
- x *= 1.0e+1;
- }
-
- /* 小数点位置を計算 */
- *decpt = e + 1;
-
- /* 符号を計算 */
- *sign = ((unsigned char *) &x)[0] & 0x80U;
-
- /* 文字列に変換 */
- _ulltoa ((unsigned long long) x, buffer);
-}
diff --git a/x68/_round.c b/x68/_round.c
deleted file mode 100644
index 761930fb8c..0000000000
--- a/x68/_round.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * PROJECT C Library, X68000 PROGRAMMING INTERFACE DEFINITION
- * --------------------------------------------------------------------
- * This file is written by the Project C Library Group, and completely
- * in public domain. You can freely use, copy, modify, and redistribute
- * the whole contents, without this notice.
- * --------------------------------------------------------------------
- * $Id$
- */
-/* changed 1997.2.2 by K.Okabe */
-
-/* System headers */
-#include <stdlib.h>
-#include <sys/xstdlib.h>
-
-/* Functions */
-int _round (char *top, char *cur, int undig)
-{
- char *ptr;
-
- /* 最後が5未満なら丸めは必要ない */
- if (undig < '5')
- return 0;
-
- /* ポインタ設定 */
- ptr = cur - 1;
-
- /* 先頭まで戻りながら丸め処理 */
- while (ptr >= top) {
-
- /* 繰り上がらなければそれで終わり */
- if (++(*ptr) <= '9')
- return 0;
-
- /* その桁を0に戻す */
- *ptr-- = '0';
-
- }
-
- /* 先頭を1にする */
- *++ptr = '1';
-
- /* 繰り上がりをしらせる */
- return 1;
-}
diff --git a/x68/fconvert.c b/x68/fconvert.c
deleted file mode 100644
index 9a0bc0e088..0000000000
--- a/x68/fconvert.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * PROJECT C Library, X68000 PROGRAMMING INTERFACE DEFINITION
- * --------------------------------------------------------------------
- * This file is written by the Project C Library Group, and completely
- * in public domain. You can freely use, copy, modify, and redistribute
- * the whole contents, without this notice.
- * --------------------------------------------------------------------
- * $Id$
- */
-/* changed 1997.2.3 by K.Okabe */
-
-/* System headers */
-#include <stdlib.h>
-#include <sys/xstdlib.h>
-
-/* Functions */
-char *fconvert (double x, int ndigit, int *decpt, int *sign, char *buffer)
-{
- int pos, n;
- char *src, *dst;
- char string[24];
- int figup;
-
- /* 18桁の文字列に変換 */
- _dtos18 (x, decpt, sign, string);
-
- /* コピー元アドレスを設定 */
- src = string;
-
- /* コピー先アドレスを設定 */
- dst = buffer;
-
- /* 小数点位置を得る */
- pos = *decpt;
-
- /* 小数点位置が負なら */
- if (pos < 0) {
-
- /* 埋める桁数を計算 */
- n = min (-pos, ndigit);
-
- /* 先頭を0で埋める */
- while (n-- > 0)
- *dst++ = '0';
-
- /* 小数点位置は0になる */
- *decpt = 0;
-
- }
-
- /* 残りのコピー桁数 */
- n = ndigit + pos;
-
- /* 格納先にコピー */
- while (n-- > 0) {
-
- /* 足りない部分は0で埋める */
- if (*src == '\0') {
- while (n-- >= 0)
- *dst++ = '0';
- break;
- }
-
- /* 変換文字列からコピー */
- *dst++ = *src++;
-
- }
-
- /* 丸める */
- *decpt += (figup = _round (buffer, dst, *src));
-
- /* 繰り上がりがあれば末尾に0を追加する */
- if (figup)
- *dst++ = '0';
-
- /* 終端に NUL を打つ */
- *dst = '\0';
-
- /* アドレスを返す */
- return buffer;
-}
diff --git a/x68/select.c b/x68/select.c
deleted file mode 100644
index b4bf464032..0000000000
--- a/x68/select.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * PROJECT C Library, X68000 PROGRAMMING INTERFACE DEFINITION
- * --------------------------------------------------------------------
- * This file is written by the Project C Library Group, and completely
- * in public domain. You can freely use, copy, modify, and redistribute
- * the whole contents, without this notice.
- * --------------------------------------------------------------------
- * $Id$
- */
-
-#ifndef __IOCS_INLINE__
-#define __IOCS_INLINE__
-#define __DOS_INLINE__
-#define __DOS_DOSCALL__
-#endif
-
-/* System headers */
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <sys/dos.h>
-#include <sys/iocs.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#if 0
-#include <sys/select.h>
-#include <sys/xsocket.h>
-#endif
-#include <sys/xunistd.h>
-
-/* Macros */
-#define XFD_ISSET(fd,fds) ((fds) && FD_ISSET ((fd), (fds)))
-#define isreadable(mode) ((mode) == O_RDONLY || (mode) == O_RDWR)
-#define iswritable(mode) ((mode) == O_WRONLY || (mode) == O_RDWR)
-#ifndef _POSIX_FD_SETSIZE
-#define _POSIX_FD_SETSIZE OPEN_MAX
-#endif
-
-/* Functions */
-int
-select (int fds, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timeval *timeout)
-{
- fd_set oread, owrite, oexcept;
- int ticks, start;
- int nfds;
-
- if (fds > _POSIX_FD_SETSIZE)
- {
- errno = EINVAL;
- return -1;
- }
-
- FD_ZERO (&oread);
- FD_ZERO (&owrite);
- FD_ZERO (&oexcept);
-
- nfds = 0;
- ticks = -1;
-
- if (timeout)
- {
- ticks = timeout->tv_sec * 100 + timeout->tv_usec / 10000;
- if (ticks < 0)
- {
- errno = EINVAL;
- return -1;
- }
- }
-
- start = _iocs_ontime ();
- for (;;)
- {
- {
- int fd;
-
- for (fd = 0; fd < fds; fd++)
- {
- int accmode;
-
- if (_fddb[fd].inuse == _FD_NOTUSED)
- continue;
-
- accmode = _fddb[fd].oflag & O_ACCMODE;
-
- if (isatty (fd))
- {
- if (XFD_ISSET (fd, rfds) && isreadable (accmode) && _dos_k_keysns ())
- {
- FD_SET (fd, &oread);
- nfds++;
- }
-
- if (XFD_ISSET (fd, wfds) && iswritable (accmode))
- {
- FD_SET (fd, &owrite);
- nfds++;
- }
- }
-#if 0
- else if (_fddb[fd].sockno >= 0)
- {
- if (XFD_ISSET (fd, rfds) && _socklen (_fddb[fd].sockno, 0))
- {
- FD_SET (fd, &oread);
- nfds++;
- }
-
- if (XFD_ISSET (fd, wfds) /* && _socklen (_fddb[fd].sockno, 1) == 0 */)
- {
- FD_SET (fd, &owrite);
- nfds++;
- }
- }
-#endif
- else
- {
- if (XFD_ISSET (fd, rfds) && isreadable (accmode) && _dos_ioctrlis (fd))
- {
- FD_SET (fd, &oread);
- nfds++;
- }
-
- if (XFD_ISSET (fd, wfds) && iswritable (accmode) && _dos_ioctrlos (fd))
- {
- FD_SET (fd, &owrite);
- nfds++;
- }
- }
- }
- }
-
- {
- int rest;
-
- if ((rest = (_iocs_ontime () - start) % 8640000) < 0)
- rest += 8640000;
-
- if (nfds != 0)
- {
- if (ticks >= 0)
- {
- int left;
-
- if ((left = ticks - rest) < 0)
- left = 0;
-
- timeout->tv_sec = left / 100;
- timeout->tv_usec = (left % 100) * 10000;
- }
-
- if (rfds)
- *rfds = oread;
- if (wfds)
- *wfds = owrite;
- if (efds)
- *efds = oexcept;
-
- return nfds;
- }
-
- if (ticks >= 0 && rest > ticks)
- return 0;
- }
-
- _dos_change_pr ();
- }
-}